Update vendor

This commit is contained in:
Frederic Guillot 2015-01-27 20:13:16 -05:00
parent b0c1f57213
commit d2cfc7fd15
33 changed files with 994 additions and 462 deletions

View File

@ -5,7 +5,7 @@
"require": { "require": {
"fguillot/simple-validator": "dev-master", "fguillot/simple-validator": "dev-master",
"fguillot/json-rpc": "dev-master", "fguillot/json-rpc": "dev-master",
"fguillot/picodb": "dev-master", "fguillot/picodb": "0.0.2",
"fguillot/picofeed": "dev-master", "fguillot/picofeed": "dev-master",
"fguillot/picofarad": "dev-master" "fguillot/picofarad": "dev-master"
}, },

View File

@ -57,9 +57,9 @@ function get_favicons(array $feed_ids)
} }
return Database::get('db') return Database::get('db')
->table('favicons') ->hashtable('favicons')
->in('feed_id', $feed_ids) ->in('feed_id', $feed_ids)
->hashmap('feed_id', 'icon'); ->getAll('feed_id', 'icon');
} }
// Get all favicons for a list of items // Get all favicons for a list of items
@ -82,8 +82,8 @@ function get_all_favicons()
} }
return Database::get('db') return Database::get('db')
->table('favicons') ->hashtable('favicons')
->hashmap('feed_id', 'icon'); ->getAll('feed_id', 'icon');
} }
// Update feed information // Update feed information
@ -290,7 +290,7 @@ function get_ids($limit = LIMIT_ALL)
$query->limit((int) $limit); $query->limit((int) $limit);
} }
return $query->hashmap('id', 'id'); return $query->findAllByColumn('id');
} }
// get number of feeds with errors // get number of feeds with errors

View File

@ -68,10 +68,10 @@ function get_everything_since($timestamp)
function get_all_status() function get_all_status()
{ {
return Database::get('db') return Database::get('db')
->table('items') ->hashtable('items')
->in('status', array('read', 'unread')) ->in('status', array('read', 'unread'))
->orderBy('updated', 'desc') ->orderBy('updated', 'desc')
->hashmap('id', 'status'); ->getAll('id', 'status');
} }
// Get all items by status // Get all items by status

2
vendor/autoload.php vendored
View File

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer' . '/autoload_real.php'; require_once __DIR__ . '/composer' . '/autoload_real.php';
return ComposerAutoloaderInita3275f8a3fafdaf0ccb719369aca304a::getLoader(); return ComposerAutoloaderInit489790cbd05fef7749a4adcb52f440da::getLoader();

View File

@ -14,6 +14,7 @@ return array(
'PicoDb\\Driver\\Mysql' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Driver/Mysql.php', 'PicoDb\\Driver\\Mysql' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Driver/Mysql.php',
'PicoDb\\Driver\\Postgres' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Driver/Postgres.php', 'PicoDb\\Driver\\Postgres' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Driver/Postgres.php',
'PicoDb\\Driver\\Sqlite' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Driver/Sqlite.php', 'PicoDb\\Driver\\Sqlite' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Driver/Sqlite.php',
'PicoDb\\Hashtable' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Hashtable.php',
'PicoDb\\Schema' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Schema.php', 'PicoDb\\Schema' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Schema.php',
'PicoDb\\Table' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Table.php', 'PicoDb\\Table' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Table.php',
'PicoFeed\\Client\\Client' => $vendorDir . '/fguillot/picofeed/lib/PicoFeed/Client/Client.php', 'PicoFeed\\Client\\Client' => $vendorDir . '/fguillot/picofeed/lib/PicoFeed/Client/Client.php',
@ -65,6 +66,7 @@ return array(
'SimpleValidator\\Validators\\Date' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Date.php', 'SimpleValidator\\Validators\\Date' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Date.php',
'SimpleValidator\\Validators\\Email' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Email.php', 'SimpleValidator\\Validators\\Email' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Email.php',
'SimpleValidator\\Validators\\Equals' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Equals.php', 'SimpleValidator\\Validators\\Equals' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Equals.php',
'SimpleValidator\\Validators\\Exists' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Exists.php',
'SimpleValidator\\Validators\\GreaterThan' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/GreaterThan.php', 'SimpleValidator\\Validators\\GreaterThan' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/GreaterThan.php',
'SimpleValidator\\Validators\\InArray' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/InArray.php', 'SimpleValidator\\Validators\\InArray' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/InArray.php',
'SimpleValidator\\Validators\\Integer' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Integer.php', 'SimpleValidator\\Validators\\Integer' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Integer.php',
@ -73,6 +75,7 @@ return array(
'SimpleValidator\\Validators\\MacAddress' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/MacAddress.php', 'SimpleValidator\\Validators\\MacAddress' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/MacAddress.php',
'SimpleValidator\\Validators\\MaxLength' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/MaxLength.php', 'SimpleValidator\\Validators\\MaxLength' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/MaxLength.php',
'SimpleValidator\\Validators\\MinLength' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/MinLength.php', 'SimpleValidator\\Validators\\MinLength' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/MinLength.php',
'SimpleValidator\\Validators\\NotEquals' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/NotEquals.php',
'SimpleValidator\\Validators\\NotInArray' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/NotInArray.php', 'SimpleValidator\\Validators\\NotInArray' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/NotInArray.php',
'SimpleValidator\\Validators\\Numeric' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Numeric.php', 'SimpleValidator\\Validators\\Numeric' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Numeric.php',
'SimpleValidator\\Validators\\Range' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Range.php', 'SimpleValidator\\Validators\\Range' => $vendorDir . '/fguillot/simple-validator/src/SimpleValidator/Validators/Range.php',

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer // autoload_real.php @generated by Composer
class ComposerAutoloaderInita3275f8a3fafdaf0ccb719369aca304a class ComposerAutoloaderInit489790cbd05fef7749a4adcb52f440da
{ {
private static $loader; private static $loader;
@ -19,9 +19,9 @@ class ComposerAutoloaderInita3275f8a3fafdaf0ccb719369aca304a
return self::$loader; return self::$loader;
} }
spl_autoload_register(array('ComposerAutoloaderInita3275f8a3fafdaf0ccb719369aca304a', 'loadClassLoader'), true, true); spl_autoload_register(array('ComposerAutoloaderInit489790cbd05fef7749a4adcb52f440da', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(); self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInita3275f8a3fafdaf0ccb719369aca304a', 'loadClassLoader')); spl_autoload_unregister(array('ComposerAutoloaderInit489790cbd05fef7749a4adcb52f440da', 'loadClassLoader'));
$map = require __DIR__ . '/autoload_namespaces.php'; $map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) { foreach ($map as $namespace => $path) {
@ -42,14 +42,14 @@ class ComposerAutoloaderInita3275f8a3fafdaf0ccb719369aca304a
$includeFiles = require __DIR__ . '/autoload_files.php'; $includeFiles = require __DIR__ . '/autoload_files.php';
foreach ($includeFiles as $file) { foreach ($includeFiles as $file) {
composerRequirea3275f8a3fafdaf0ccb719369aca304a($file); composerRequire489790cbd05fef7749a4adcb52f440da($file);
} }
return $loader; return $loader;
} }
} }
function composerRequirea3275f8a3fafdaf0ccb719369aca304a($file) function composerRequire489790cbd05fef7749a4adcb52f440da($file)
{ {
require $file; require $file;
} }

View File

@ -1,43 +1,4 @@
[ [
{
"name": "fguillot/simple-validator",
"version": "dev-master",
"version_normalized": "9999999-dev",
"source": {
"type": "git",
"url": "https://github.com/fguillot/simpleValidator.git",
"reference": "3bfa1ef0062906c83824ce8db1219914996d9bd4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fguillot/simpleValidator/zipball/3bfa1ef0062906c83824ce8db1219914996d9bd4",
"reference": "3bfa1ef0062906c83824ce8db1219914996d9bd4",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"time": "2014-11-25 22:58:14",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-0": {
"SimpleValidator": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Frédéric Guillot",
"homepage": "http://fredericguillot.com"
}
],
"description": "The most easy to use validator library for PHP :)",
"homepage": "https://github.com/fguillot/simpleValidator"
},
{ {
"name": "fguillot/picofarad", "name": "fguillot/picofarad",
"version": "dev-master", "version": "dev-master",
@ -116,6 +77,45 @@
"description": "A simple Json-RPC client/server library that just works", "description": "A simple Json-RPC client/server library that just works",
"homepage": "https://github.com/fguillot/JsonRPC" "homepage": "https://github.com/fguillot/JsonRPC"
}, },
{
"name": "fguillot/simple-validator",
"version": "dev-master",
"version_normalized": "9999999-dev",
"source": {
"type": "git",
"url": "https://github.com/fguillot/simpleValidator.git",
"reference": "9e9502c88ce239901c0fee12a1f504948342ab42"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fguillot/simpleValidator/zipball/9e9502c88ce239901c0fee12a1f504948342ab42",
"reference": "9e9502c88ce239901c0fee12a1f504948342ab42",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"time": "2015-01-21 02:00:33",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-0": {
"SimpleValidator": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Frédéric Guillot",
"homepage": "http://fredericguillot.com"
}
],
"description": "The most easy to use validator library for PHP :)",
"homepage": "https://github.com/fguillot/simpleValidator"
},
{ {
"name": "fguillot/picofeed", "name": "fguillot/picofeed",
"version": "dev-master", "version": "dev-master",
@ -123,18 +123,18 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/fguillot/picoFeed.git", "url": "https://github.com/fguillot/picoFeed.git",
"reference": "8858f63e5380e8b1df4d8a4bbc5618931cddde7d" "reference": "83e406cbfbd188dbfbc0330c0757b037a87b0928"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/fguillot/picoFeed/zipball/8858f63e5380e8b1df4d8a4bbc5618931cddde7d", "url": "https://api.github.com/repos/fguillot/picoFeed/zipball/83e406cbfbd188dbfbc0330c0757b037a87b0928",
"reference": "8858f63e5380e8b1df4d8a4bbc5618931cddde7d", "reference": "83e406cbfbd188dbfbc0330c0757b037a87b0928",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.3.0" "php": ">=5.3.0"
}, },
"time": "2015-01-18 02:06:19", "time": "2015-01-28 01:01:28",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {
@ -157,23 +157,23 @@
}, },
{ {
"name": "fguillot/picodb", "name": "fguillot/picodb",
"version": "dev-master", "version": "v0.0.2",
"version_normalized": "9999999-dev", "version_normalized": "0.0.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/fguillot/picoDb.git", "url": "https://github.com/fguillot/picoDb.git",
"reference": "9588cf60e74dd6ff63d96f7eb91c4f74b47a11b1" "reference": "b3ef5f79e7e5e33729fdbf9c02c8a252a3d76b6b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/fguillot/picoDb/zipball/9588cf60e74dd6ff63d96f7eb91c4f74b47a11b1", "url": "https://api.github.com/repos/fguillot/picoDb/zipball/b3ef5f79e7e5e33729fdbf9c02c8a252a3d76b6b",
"reference": "9588cf60e74dd6ff63d96f7eb91c4f74b47a11b1", "reference": "b3ef5f79e7e5e33729fdbf9c02c8a252a3d76b6b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.3.0" "php": ">=5.3.0"
}, },
"time": "2015-01-20 00:52:01", "time": "2015-01-25 16:20:14",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {

View File

@ -39,4 +39,5 @@ Thumbs.db
# App specific # # App specific #
################ ################
example.php example.php
vendor

View File

@ -7,8 +7,9 @@ PicoDb is a minimalist database query builder for PHP.
Features Features
-------- --------
- No dependency - Easy to use, easy to hack, fast and very lightweight
- Easy to use, fast and very lightweight - Supported drivers: Sqlite, Mysql, Postgresql
- Requires only PDO
- Use prepared statements - Use prepared statements
- Handle schema versions (migrations) - Handle schema versions (migrations)
- License: [WTFPL](http://www.wtfpl.net) - License: [WTFPL](http://www.wtfpl.net)
@ -26,110 +27,149 @@ Documentation
### Installation ### Installation
```bash ```bash
composer require fguillot/picodb dev-master composer require fguillot/picodb @stable
``` ```
### Connect to your database ### Connect to your database
```php ```php
use PicoDb\Database; use PicoDb\Database;
// Sqlite driver // Sqlite driver
$db = new Database(['driver' => 'sqlite', 'filename' => ':memory:']); $db = new Database(['driver' => 'sqlite', 'filename' => ':memory:']);
// Mysql driver // Mysql driver
// Optional options: "schema_table" (the default table name is "schema_version") // Optional options: "schema_table" (the default table name is "schema_version")
$db = new Database(array( $db = new Database(array(
'driver' => 'mysql', 'driver' => 'mysql',
'hostname' => 'localhost', 'hostname' => 'localhost',
'username' => 'root', 'username' => 'root',
'password' => '', 'password' => '',
'database' => 'my_db_name', 'database' => 'my_db_name',
'charset' => 'utf8', 'charset' => 'utf8',
)); ));
``` ```
### Execute a SQL request ### Execute a SQL request
```php ```php
$db->execute('CREATE TABLE toto (column1 TEXT)'); $db->execute('CREATE TABLE toto (column1 TEXT)');
``` ```
### Insert some data ### Insert some data
```php ```php
$db->table('toto')->save(['column1' => 'hey']); $db->table('toto')->save(['column1' => 'test']);
``` ```
### Transations or
```php ```php
$db->transaction(function($db) { $db->table('toto')->insert(['column1' => 'test']);
$db->table('toto')->save(['column1' => 'foo']); ```
$db->table('toto')->save(['column1' => 'bar']);
}); ### Transactions
```php
$db->transaction(function ($db) {
$db->table('toto')->save(['column1' => 'foo']);
$db->table('toto')->save(['column1' => 'bar']);
});
```
or
```php
$db->startTransaction();
// Do something...
$db->closeTransaction();
// Rollback
$db->cancelTransaction();
``` ```
### Fetch all data ### Fetch all data
```php ```php
$records = $db->table('toto')->findAll(); $records = $db->table('toto')->findAll();
foreach ($records as $record) { foreach ($records as $record) {
var_dump($record['column1']); var_dump($record['column1']);
} }
``` ```
### Update something ### Update something
$db->table('toto')->eq('id', 1)->save(['column1' => 'hey']); ```php
$db->table('toto')->eq('id', 1)->save(['column1' => 'hey']);
```
You just need to add a condition to perform an update. You just need to add a condition to perform an update.
### Remove rows ### Remove rows
```php ```php
$db->table('toto')->lowerThan('column1', 10)->remove(); $db->table('toto')->lowerThan('column1', 10)->remove();
``` ```
### Sorting ### Sorting
```php ```php
$db->table('toto')->asc('column1')->findAll(); $db->table('toto')->asc('column1')->findAll();
``` ```
or or
```php ```php
$db->table('toto')->desc('column1')->findAll(); $db->table('toto')->desc('column1')->findAll();
```
or
```php
#db->table('toto')->orderBy('column1', 'ASC')->findAll();
``` ```
### Limit and offset ### Limit and offset
```php ```php
$db->table('toto')->limit(10)->offset(5)->findAll(); $db->table('toto')->limit(10)->offset(5)->findAll();
``` ```
### Fetch only some columns ### Fetch only some columns
```php ```php
$db->table('toto')->columns('column1', 'column2')->findAll(); $db->table('toto')->columns('column1', 'column2')->findAll();
```
### Fetch only one column
Many rows:
```php
$db->table('toto')->findAllByColumn('column1');
```
One row:
```php
$db->table('toto')->findOneColumn('column1');
``` ```
### Equals condition ### Equals condition
```php ```php
$db->table('toto') $db->table('toto')
->equals('column1', 'hey') ->equals('column1', 'hey')
->findAll(); ->findAll();
``` ```
or or
```php ```php
$db->table('toto') $db->table('toto')
->eq('column1', 'hey') ->eq('column1', 'hey')
->findAll(); ->findAll();
``` ```
Yout got: 'SELECT * FROM toto WHERE column1=?' Yout got: 'SELECT * FROM toto WHERE column1=?'
@ -137,9 +177,9 @@ Yout got: 'SELECT * FROM toto WHERE column1=?'
### IN condition ### IN condition
```php ```php
$db->table('toto') $db->table('toto')
->in('column1', ['hey', 'bla']) ->in('column1', ['hey', 'bla'])
->findAll(); ->findAll();
``` ```
### Like condition ### Like condition
@ -147,81 +187,81 @@ Yout got: 'SELECT * FROM toto WHERE column1=?'
Case-sensitive (only Mysql and Postgres): Case-sensitive (only Mysql and Postgres):
```php ```php
$db->table('toto') $db->table('toto')
->like('column1', '%Foo%') ->like('column1', '%Foo%')
->findAll(); ->findAll();
``` ```
Not case-sensitive: Not case-sensitive:
```php ```php
$db->table('toto') $db->table('toto')
->ilike('column1', '%foo%') ->ilike('column1', '%foo%')
->findAll(); ->findAll();
``` ```
### Lower than ### Lower than
```php ```php
$db->table('toto') $db->table('toto')
->lowerThan('column1', 2) ->lowerThan('column1', 2)
->findAll(); ->findAll();
``` ```
or or
```php ```php
$db->table('toto') $db->table('toto')
->lt('column1', 2) ->lt('column1', 2)
->findAll(); ->findAll();
``` ```
### Lower than or equals ### Lower than or equals
```php ```php
$db->table('toto') $db->table('toto')
->lowerThanOrEquals('column1', 2) ->lowerThanOrEquals('column1', 2)
->findAll(); ->findAll();
``` ```
or or
```php ```php
$db->table('toto') $db->table('toto')
->lte('column1', 2) ->lte('column1', 2)
->findAll(); ->findAll();
``` ```
### Greater than ### Greater than
```php ```php
$db->table('toto') $db->table('toto')
->greaterThan('column1', 3) ->greaterThan('column1', 3)
->findAll(); ->findAll();
``` ```
or or
```php ```php
$db->table('toto') $db->table('toto')
->gt('column1', 3) ->gt('column1', 3)
->findAll(); ->findAll();
``` ```
### Greater than or equals ### Greater than or equals
```php ```php
$db->table('toto') $db->table('toto')
->greaterThanOrEquals('column1', 3) ->greaterThanOrEquals('column1', 3)
->findAll(); ->findAll();
``` ```
or or
```php ```php
$db->table('toto') $db->table('toto')
->gte('column1', 3) ->gte('column1', 3)
->findAll(); ->findAll();
``` ```
### Multiple conditions ### Multiple conditions
@ -229,22 +269,113 @@ or
Each condition is joined by a AND. Each condition is joined by a AND.
```php ```php
$db->table('toto') $db->table('toto')
->like('column2', '%toto') ->like('column2', '%toto')
->gte('column1', 3) ->gte('column1', 3)
->findAll(); ->findAll();
``` ```
How to make a OR condition: How to make a OR condition:
```php ```php
$db->table('toto') $db->table('toto')
->beginOr() ->beginOr()
->like('column2', '%toto') ->like('column2', '%toto')
->gte('column1', 3) ->gte('column1', 3)
->closeOr() ->closeOr()
->eq('column5', 'titi') ->eq('column5', 'titi')
->findAll(); ->findAll();
```
### Debugging
Log generated queries:
```php
$db->log_queries = true;
```
Mesure each query time:
```php
$db->stopwatch = true;
```
Get the number of queries executed:
```php
echo $db->nb_queries;
```
Get log messages:
```php
print_r($db->getLogMessages());
```
### Hashtable (key/value store)
How to use a table as a key/value store:
```php
$db->execute(
'CREATE TABLE toto (
column1 TEXT NOT NULL UNIQUE,
column2 TEXT default NULL
)'
);
$db->table('toto')->insert(['column1' => 'option1', 'column2' => 'value1']);
```
Add/Replace some values:
```php
$db->hashtable('toto')
->columnKey('column1')
->columnValue('column2')
->put(['option1' => 'new value', 'option2' => 'value2']));
```
Get all values:
```php
$result = $db->hashtable('toto')->columnKey('column1')->columnValue('column2')->get();
print_r($result);
Array
(
[option2] => value2
[option1] => new value
)
```
or
```php
$result = $db->hashtable('toto')->getAll('column1', 'column2');
```
Get a specific value:
```php
$db->hashtable('toto')
->columnKey('column1')
->columnValue('column2')
->put(['option3' => 'value3']);
$result = $db->hashtable('toto')
->columnKey('column1')
->columnValue('column2')
->get('option1', 'option3');
print_r($result);
Array
(
[option1] => new value
[option3] => value3
)
``` ```
### Schema migrations ### Schema migrations
@ -258,30 +389,30 @@ How to make a OR condition:
Example: Example:
```php ```php
namespace Schema; namespace Schema;
function version_1($pdo) function version_1($pdo)
{ {
$pdo->exec(' $pdo->exec('
CREATE TABLE users ( CREATE TABLE users (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
name TEXT UNIQUE, name TEXT UNIQUE,
email TEXT UNIQUE, email TEXT UNIQUE,
password TEXT password TEXT
) )
'); ');
} }
function version_2($pdo) function version_2($pdo)
{ {
$pdo->exec(' $pdo->exec('
CREATE TABLE tags ( CREATE TABLE tags (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
name TEXT UNIQUE name TEXT UNIQUE
) )
'); ');
} }
``` ```
#### Run schema update automatically #### Run schema update automatically
@ -294,21 +425,21 @@ Example:
Example: Example:
```php ```php
$last_schema_version = 5; $last_schema_version = 5;
$db = new PicoDb\Database(array( $db = new PicoDb\Database(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'filename' => '/tmp/mydb.sqlite' 'filename' => '/tmp/mydb.sqlite'
)); ));
if ($db->schema()->check($last_schema_version)) { if ($db->schema()->check($last_schema_version)) {
// Do something... // Do something...
} }
else { else {
die('Unable to migrate database schema.'); die('Unable to migrate database schema.');
} }
``` ```
### Use a singleton to handle database instances ### Use a singleton to handle database instances
@ -316,24 +447,24 @@ Example:
Setup a new instance: Setup a new instance:
```php ```php
PicoDb\Database::bootstrap('myinstance', function() { PicoDb\Database::bootstrap('myinstance', function() {
$db = new PicoDb\Database(array( $db = new PicoDb\Database(array(
'driver' => 'sqlite', 'driver' => 'sqlite',
'filename' => DB_FILENAME 'filename' => DB_FILENAME
)); ));
if ($db->schema()->check(DB_VERSION)) { if ($db->schema()->check(DB_VERSION)) {
return $db; return $db;
} }
else { else {
die('Unable to migrate database schema.'); die('Unable to migrate database schema.');
} }
}); });
``` ```
Get this instance anywhere in your code: Get this instance anywhere in your code:
```php ```php
PicoDb\Database::get('myinstance')->table(...) PicoDb\Database::get('myinstance')->table(...)
``` ```

View File

@ -190,15 +190,20 @@ class Database
* *
* @access public * @access public
* @param string $value Value * @param string $value Value
* @param string $table Table name
* @return string * @return string
*/ */
public function escapeIdentifier($value) public function escapeIdentifier($value, $table = '')
{ {
// Do not escape custom query // Do not escape custom query
if (strpos($value, '.') !== false || strpos($value, ' ') !== false) { if (strpos($value, '.') !== false || strpos($value, ' ') !== false) {
return $value; return $value;
} }
if (! empty($table)) {
return $this->pdo->escapeIdentifier($table).'.'.$this->pdo->escapeIdentifier($value);
}
return $this->pdo->escapeIdentifier($value); return $this->pdo->escapeIdentifier($value);
} }
@ -311,6 +316,19 @@ class Database
return new Table($this, $table_name); return new Table($this, $table_name);
} }
/**
* Get a hashtable instance
*
* @access public
* @return Picodb\Hashtable
*/
public function hashtable($table_name)
{
require_once __DIR__.'/Table.php';
require_once __DIR__.'/Hashtable.php';
return new Hashtable($this, $table_name);
}
/** /**
* Get a schema instance * Get a schema instance
* *

View File

@ -0,0 +1,144 @@
<?php
namespace PicoDb;
use PDO;
class Hashtable extends Table
{
private $column_key = 'key';
private $column_value = 'value';
/**
* Set the key column
*
* @access public
* @param string $column
* @return \PicoDb\Table
*/
public function columnKey($column)
{
$this->column_key = $column;
return $this;
}
/**
* Set the value column
*
* @access public
* @param string $column
* @return \PicoDb\Table
*/
public function columnValue($column)
{
$this->column_value = $column;
return $this;
}
/**
* Insert or update
*
* @access public
* @param array $data
* @return boolean
*/
public function put(array $data)
{
switch ($this->db->getConnection()->getAttribute(PDO::ATTR_DRIVER_NAME)) {
case 'mysql':
$sql = sprintf(
'REPLACE INTO %s (%s) VALUES %s',
$this->db->escapeIdentifier($this->table_name),
"$this->column_key, $this->column_value",
implode(', ', array_fill(0, count($data), '(?, ?)'))
);
foreach ($data as $key => $value) {
$this->values[] = $key;
$this->values[] = $value;
}
$this->db->execute($sql, $this->values);
break;
case 'sqlite': // multi insert (see mysql) requires sqlite library > 3.7.11 (bundled with PHP 5.5.11+)
// all or nothing
$this->db->startTransaction();
foreach($data as $key => $value) {
$sql = sprintf(
'INSERT OR REPLACE INTO %s (%s) VALUES (?, ?)',
$this->db->escapeIdentifier($this->table_name),
$this->db->escapeIdentifier($this->column_key).', '.$this->db->escapeIdentifier($this->column_value)
);
$this->db->execute($sql, array($key, $value));
}
break;
default: // no upsert available, need to make a select/update/insert limbo
// all or nothing
$this->db->startTransaction();
foreach($data as $key => $value) {
// check if the key exists
$this->eq($this->column_key, $key);
if ($this->count() === 1) {
// update the record
$this->update(array($this->column_key => $key, $this->column_value => $value));
}
else {
// insert the record
$this->insert(array($this->column_key => $key, $this->column_value => $value));
}
}
}
$this->db->closeTransaction();
return true;
}
/**
* Hashmap result [ [column1 => column2], [], ...]
*
* @access public
* @return array
*/
public function get()
{
$hashmap = array();
// setup where condition
if (func_num_args() > 0) {
$this->in($this->column_key, func_get_args());
}
// setup to select columns in case that there are more than two
$this->columns($this->column_key, $this->column_value);
$rq = $this->db->execute($this->buildSelectQuery(), $this->values);
$rows = $rq->fetchAll(PDO::FETCH_NUM);
foreach ($rows as $row) {
$hashmap[$row[0]] = $row[1];
}
return $hashmap;
}
/**
* Shortcut method to get a hashmap result
*
* @access public
* @param string $key Key column
* @param string $value Value column
* @return array
*/
public function getAll($key, $value)
{
$this->column_key = $key;
$this->column_value = $value;
return $this->get();
}
}

View File

@ -9,7 +9,10 @@ class Table
const SORT_ASC = 'ASC'; const SORT_ASC = 'ASC';
const SORT_DESC = 'DESC'; const SORT_DESC = 'DESC';
private $table_name = ''; protected $db;
protected $table_name = '';
protected $values = array();
private $sql_limit = ''; private $sql_limit = '';
private $sql_offset = ''; private $sql_offset = '';
private $sql_order = ''; private $sql_order = '';
@ -18,11 +21,9 @@ class Table
private $or_conditions = array(); private $or_conditions = array();
private $is_or_condition = false; private $is_or_condition = false;
private $columns = array(); private $columns = array();
private $values = array();
private $distinct = false; private $distinct = false;
private $group_by = array(); private $group_by = array();
private $filter_callback = null; private $filter_callback = null;
private $db;
/** /**
* Constructor * Constructor
@ -130,30 +131,6 @@ class Table
return $result->rowCount() > 0; return $result->rowCount() > 0;
} }
/**
* Hashmap result [ [column1 => column2], [], ...]
*
* @access public
* @param string $key Column 1
* @param string $value Column 2
* @return array
*/
public function hashmap($key, $value)
{
$listing = array();
$this->columns($key, $value);
$rq = $this->db->execute($this->buildSelectQuery(), $this->values);
$rows = $rq->fetchAll(PDO::FETCH_NUM);
foreach ($rows as $row) {
$listing[$row[0]] = $row[1];
}
return $listing;
}
/** /**
* Add callback to alter the resultset * Add callback to alter the resultset
* *
@ -241,7 +218,7 @@ class Table
public function buildSelectQuery() public function buildSelectQuery()
{ {
foreach ($this->columns as $key => $value) { foreach ($this->columns as $key => $value) {
$this->columns[$key] = $this->db->escapeIdentifier($value); $this->columns[$key] = $this->db->escapeIdentifier($value, $this->table_name);
} }
return sprintf( return sprintf(
@ -267,7 +244,7 @@ class Table
public function count() public function count()
{ {
$sql = sprintf( $sql = sprintf(
'SELECT COUNT(*) FROM %s'.$this->conditions().$this->sql_order.$this->sql_limit.$this->sql_offset, 'SELECT COUNT(*) FROM %s '.implode(' ', $this->joins).$this->conditions().$this->sql_order.$this->sql_limit.$this->sql_offset,
$this->db->escapeIdentifier($this->table_name) $this->db->escapeIdentifier($this->table_name)
); );

View File

@ -157,14 +157,47 @@ abstract class Client
*/ */
protected $status_code = 0; protected $status_code = 0;
/**
* HTTP response body
*
* @access protected
* @var string
*/
protected $body = '';
/**
* Body size
*
* @access protected
* @var integer
*/
protected $body_length = 0;
/**
* HTTP response headers
*
* @access protected
* @var array
*/
protected $headers = array();
/**
* Counter on the number of header received
*
* @access protected
* @var integer
*/
protected $headers_counter = 0;
/** /**
* Do the HTTP request * Do the HTTP request
* *
* @abstract * @abstract
* @access public * @access public
* @param bool $follow_location Flag used when there is an open_basedir restriction
* @return array * @return array
*/ */
abstract public function doRequest(); abstract public function doRequest($follow_location = true);
/** /**
* Get client instance: curl or stream driver * Get client instance: curl or stream driver
@ -262,6 +295,48 @@ abstract class Client
} }
} }
/**
* Handle manually redirections when there is an open base dir restriction
*
* @access private
* @param string $location Redirected URL
* @return array
*/
public function handleRedirection($location)
{
$nb_redirects = 0;
$result = array();
$this->url = Url::resolve($location, $this->url);
$this->body = '';
$this->body_length = 0;
$this->headers = array();
$this->headers_counter = 0;
while (true) {
$nb_redirects++;
if ($nb_redirects >= $this->max_redirects) {
throw new MaxRedirectException('Maximum number of redirections reached');
}
$result = $this->doRequest(false);
if ($result['status'] == 301 || $result['status'] == 302) {
$this->url = $result['headers']['Location'];
$this->body = '';
$this->body_length = 0;
$this->headers = array();
$this->headers_counter = 0;
}
else {
break;
}
}
return $result;
}
/** /**
* Check if a request has been modified according to the parameters * Check if a request has been modified according to the parameters
* *

View File

@ -12,38 +12,6 @@ use PicoFeed\Logging\Logger;
*/ */
class Curl extends Client class Curl extends Client
{ {
/**
* HTTP response body
*
* @access private
* @var string
*/
private $body = '';
/**
* Body size
*
* @access private
* @var integer
*/
private $body_length = 0;
/**
* HTTP response headers
*
* @access private
* @var array
*/
private $headers = array();
/**
* Counter on the number of header received
*
* @access private
* @var integer
*/
private $headers_counter = 0;
/** /**
* cURL callback to read the HTTP body * cURL callback to read the HTTP body
* *
@ -260,48 +228,6 @@ class Curl extends Client
return $follow_location && ini_get('open_basedir') !== '' && ($status == 301 || $status == 302); return $follow_location && ini_get('open_basedir') !== '' && ($status == 301 || $status == 302);
} }
/**
* Handle manually redirections when there is an open base dir restriction
*
* @access private
* @param string $location Redirected URL
* @return array
*/
private function handleRedirection($location)
{
$nb_redirects = 0;
$result = array();
$this->url = $location;
$this->body = '';
$this->body_length = 0;
$this->headers = array();
$this->headers_counter = 0;
while (true) {
$nb_redirects++;
if ($nb_redirects >= $this->max_redirects) {
throw new MaxRedirectException('Maximum number of redirections reached');
}
$result = $this->doRequest(false);
if ($result['status'] == 301 || $result['status'] == 302) {
$this->url = $result['headers']['Location'];
$this->body = '';
$this->body_length = 0;
$this->headers = array();
$this->headers_counter = 0;
}
else {
break;
}
}
return $result;
}
/** /**
* Handle cURL errors (throw individual exceptions) * Handle cURL errors (throw individual exceptions)
* *

View File

@ -61,7 +61,7 @@ class Stream extends Client
'method' => 'GET', 'method' => 'GET',
'protocol_version' => 1.1, 'protocol_version' => 1.1,
'timeout' => $this->timeout, 'timeout' => $this->timeout,
'max_redirects' => $this->max_redirects, 'follow_location' => 0,
) )
); );
@ -89,9 +89,10 @@ class Stream extends Client
* Do the HTTP request * Do the HTTP request
* *
* @access public * @access public
* @return array HTTP response ['body' => ..., 'status' => ..., 'headers' => ...] * @param bool $follow_location Flag used when there is an open_basedir restriction
* @return array HTTP response ['body' => ..., 'status' => ..., 'headers' => ...]
*/ */
public function doRequest() public function doRequest($follow_location = false)
{ {
// Create context // Create context
$context = stream_context_create($this->prepareContext()); $context = stream_context_create($this->prepareContext());
@ -121,6 +122,12 @@ class Stream extends Client
fclose($stream); fclose($stream);
// Do redirect manual to get only the headers of the last request and
// the final url
if ($status == 301 || $status == 302) {
return $this->handleRedirection($headers['Location']);
}
return array( return array(
'status' => $status, 'status' => $status,
'body' => $this->decodeBody($body, $headers), 'body' => $this->decodeBody($body, $headers),

View File

@ -55,13 +55,13 @@ class Url
* *
* @static * @static
* @access public * @access public
* @param string $item_url Unknown url (can be relative or not) * @param mixed $item_url Unknown url (can be relative or not)
* @param mixed $website_url Website url * @param mixed $website_url Website url
* @return string * @return string
*/ */
public static function resolve($item_url, $website_url) public static function resolve($item_url, $website_url)
{ {
$link = new Url($item_url); $link = is_string($item_url) ? new Url($item_url) : $item_url;
$website = is_string($website_url) ? new Url($website_url) : $website_url; $website = is_string($website_url) ? new Url($website_url) : $website_url;
if ($link->isRelativeUrl()) { if ($link->isRelativeUrl()) {
@ -172,7 +172,7 @@ class Url
$path = $this->isRelativePath() ? '/' : ''; $path = $this->isRelativePath() ? '/' : '';
$path .= substr($current_path, -1) === '/' ? $current_path : dirname($current_path); $path .= substr($current_path, -1) === '/' ? $current_path : dirname($current_path);
return str_replace('//', '/', $path.'/'); return preg_replace('/\\\\\/|\/\//', '/', $path.'/');
} }
/** /**

View File

@ -159,6 +159,7 @@ class Encoding
return $input; return $input;
case 'windows-1251': case 'windows-1251':
case 'windows-1255': case 'windows-1255':
case 'windows-1256':
return iconv($encoding, 'UTF-8//TRANSLIT', $input); return iconv($encoding, 'UTF-8//TRANSLIT', $input);
default: default:
return self::toUTF8($input); return self::toUTF8($input);

View File

@ -198,8 +198,10 @@ class XmlParser
$p1 = strpos($data, 'encoding='); $p1 = strpos($data, 'encoding=');
$p2 = strpos($data, '"', $p1 + 10); $p2 = strpos($data, '"', $p1 + 10);
$encoding = substr($data, $p1 + 10, $p2 - $p1 - 10); if ($p1 !== false && $p2 !== false) {
$encoding = strtolower($encoding); $encoding = substr($data, $p1 + 10, $p2 - $p1 - 10);
$encoding = strtolower($encoding);
}
} }
return $encoding; return $encoding;

View File

@ -172,7 +172,7 @@ class Favicon
} }
foreach ($icons as $icon_link) { foreach ($icons as $icon_link) {
$icon_link = $this->convertLink($website, new Url($icon_link)); $icon_link = Url::resolve($icon_link, $website);
$resource = $this->download($icon_link); $resource = $this->download($icon_link);
$this->content = $resource->getContent(); $this->content = $resource->getContent();
$this->content_type = $resource->getContentType(); $this->content_type = $resource->getContentType();
@ -187,28 +187,6 @@ class Favicon
return ''; return '';
} }
/**
* Convert icon links to absolute url
*
* @access public
* @param \PicoFeed\Client\Url $website Website url
* @param \PicoFeed\Client\Url $icon Icon url
* @return string
*/
public function convertLink(Url $website, Url $icon)
{
$base_url = '';
if ($icon->isRelativeUrl()) {
$base_url = $website->getBaseUrl();
}
else if ($icon->isProtocolRelative()) {
$icon->setScheme($website->getScheme());
}
return $icon->getAbsoluteUrl($base_url);
}
/** /**
* Extract the icon links from the HTML * Extract the icon links from the HTML
* *

View File

@ -29,6 +29,7 @@ class CurlTest extends PHPUnit_Framework_TestCase
$this->assertEquals(200, $result['status']); $this->assertEquals(200, $result['status']);
$this->assertEquals('<!DOCTYPE', substr($result['body'], 0, 9)); $this->assertEquals('<!DOCTYPE', substr($result['body'], 0, 9));
$this->assertEquals('text/html; charset=utf-8', $result['headers']['Content-Type']); $this->assertEquals('text/html; charset=utf-8', $result['headers']['Content-Type']);
$this->assertEquals('http://miniflux.net/', $client->getUrl());
} }
/** /**

View File

@ -30,12 +30,14 @@ class StreamTest extends PHPUnit_Framework_TestCase
public function testRedirect() public function testRedirect()
{ {
$client = new Stream; $client = new Stream;
$client->setUrl('http://github.com/fguillot/picoFeed'); $client->setUrl('http://www.miniflux.net/index.html');
$result = $client->doRequest(); $result = $client->doRequest();
$this->assertTrue(is_array($result));
$this->assertEquals(200, $result['status']); $this->assertEquals(200, $result['status']);
$this->assertEquals('<!DOCTYPE html>', substr(trim($result['body']), 0, 15)); $this->assertEquals('<!DOCTYPE', substr($result['body'], 0, 9));
$this->assertEquals('text/html; charset=utf-8', $result['headers']['Content-Type']); $this->assertEquals('text/html; charset=utf-8', $result['headers']['Content-Type']);
$this->assertEquals('http://miniflux.net/', $client->getUrl());
} }
/** /**

View File

@ -217,39 +217,76 @@ AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
public function testResolve() public function testResolve()
{ {
// relative link
$this->assertEquals( $this->assertEquals(
'http://www.la-grange.net/2014/08/03/4668-noisettes', 'http://miniflux.net/assets/img/favicon.png',
Url::resolve('/2014/08/03/4668-noisettes', 'http://www.la-grange.net') Url::resolve('assets/img/favicon.png', 'http://miniflux.net')
); );
// relative link + HTTPS
$this->assertEquals( $this->assertEquals(
'http://www.la-grange.net/2014/08/03/4668-noisettes', 'https://miniflux.net/assets/img/favicon.png',
Url::resolve('/2014/08/03/4668-noisettes', 'http://www.la-grange.net/') Url::resolve('assets/img/favicon.png', 'https://miniflux.net')
); );
// absolute link
$this->assertEquals( $this->assertEquals(
'http://www.la-grange.net/2014/08/03/4668-noisettes', 'http://miniflux.net/assets/img/favicon.png',
Url::resolve('/2014/08/03/4668-noisettes', 'http://www.la-grange.net/feed.atom') Url::resolve('/assets/img/favicon.png', 'http://miniflux.net')
); );
// absolute link + HTTPS
$this->assertEquals( $this->assertEquals(
'http://what-if.xkcd.com/imgs/a/112/driving.png', 'https://miniflux.net/assets/img/favicon.png',
Url::resolve('/imgs/a/112/driving.png', 'http://what-if.xkcd.com/feed.atom') Url::resolve('/assets/img/favicon.png', 'https://miniflux.net')
); );
// Protocol relative link
$this->assertEquals( $this->assertEquals(
'http://website/subfolder/img/foo.png', 'http://google.com/assets/img/favicon.png',
Url::resolve('img/foo.png', 'http://website/subfolder/') Url::resolve('//google.com/assets/img/favicon.png', 'http://miniflux.net')
); );
// Protocol relative link + HTTPS
$this->assertEquals( $this->assertEquals(
'http://website/img/foo.png', 'https://google.com/assets/img/favicon.png',
Url::resolve('/img/foo.png', 'http://website/subfolder/') Url::resolve('//google.com/assets/img/favicon.png', 'https://miniflux.net')
); );
// URL same fqdn
$this->assertEquals( $this->assertEquals(
'http://www.lofibucket.com/articles/img/quakescope.jpg', 'http://miniflux.net/assets/img/favicon.png',
Url::resolve('img/quakescope.jpg', 'http://www.lofibucket.com/articles/oscilloscope_quake.html') Url::resolve('http://miniflux.net/assets/img/favicon.png', 'https://miniflux.net')
);
// URL different fqdn
$this->assertEquals(
'https://www.google.com/assets/img/favicon.png',
Url::resolve('https://www.google.com/assets/img/favicon.png', 'https://miniflux.net')
);
// HTTPS URL
$this->assertEquals(
'https://miniflux.net/assets/img/favicon.png',
Url::resolve('https://miniflux.net/assets/img/favicon.png', 'https://miniflux.net')
);
// empty string on missing website parameter
$this->assertEquals(
'',
Url::resolve('favicon.png', '')
);
// website only on missing icon parameter
$this->assertEquals(
'https://miniflux.net/',
Url::resolve('', 'https://miniflux.net')
);
// empty string on missing website and icon parameter
$this->assertEquals(
'',
Url::resolve('', '')
); );
} }
} }

View File

@ -13,6 +13,7 @@ class XmlParserTest extends PHPUnit_Framework_TestCase
$this->assertEquals('utf-8', XmlParser::getEncodingFromXmlTag("<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet")); $this->assertEquals('utf-8', XmlParser::getEncodingFromXmlTag("<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet"));
$this->assertEquals('utf-8', XmlParser::getEncodingFromXmlTag('<?xml version="1.0" encoding="UTF-8"?><feed xml:')); $this->assertEquals('utf-8', XmlParser::getEncodingFromXmlTag('<?xml version="1.0" encoding="UTF-8"?><feed xml:'));
$this->assertEquals('windows-1251', XmlParser::getEncodingFromXmlTag('<?xml version="1.0" encoding="Windows-1251"?><rss version="2.0">')); $this->assertEquals('windows-1251', XmlParser::getEncodingFromXmlTag('<?xml version="1.0" encoding="Windows-1251"?><rss version="2.0">'));
$this->assertEquals('', XmlParser::getEncodingFromXmlTag("<?xml version='1.0'?><?xml-stylesheet"));
} }
public function testScanForXEE() public function testScanForXEE()

View File

@ -87,83 +87,6 @@ class FaviconTest extends PHPUnit_Framework_TestCase
$this->assertFalse($favicon->exists('')); $this->assertFalse($favicon->exists(''));
} }
public function testConvertLink()
{
$favicon = new Favicon;
// relative link
$this->assertEquals(
'http://miniflux.net/assets/img/favicon.png',
$favicon->convertLink(new Url('http://miniflux.net'), new Url('assets/img/favicon.png'))
);
// relative link + HTTPS
$this->assertEquals(
'https://miniflux.net/assets/img/favicon.png',
$favicon->convertLink(new Url('https://miniflux.net'), new Url('assets/img/favicon.png'))
);
// absolute link
$this->assertEquals(
'http://miniflux.net/assets/img/favicon.png',
$favicon->convertLink(new Url('http://miniflux.net'), new Url('/assets/img/favicon.png'))
);
// absolute link + HTTPS
$this->assertEquals(
'https://miniflux.net/assets/img/favicon.png',
$favicon->convertLink(new Url('https://miniflux.net'), new Url('/assets/img/favicon.png'))
);
// Protocol relative link
$this->assertEquals(
'http://google.com/assets/img/favicon.png',
$favicon->convertLink(new Url('http://miniflux.net'), new Url('//google.com/assets/img/favicon.png'))
);
// Protocol relative link + HTTPS
$this->assertEquals(
'https://google.com/assets/img/favicon.png',
$favicon->convertLink(new Url('https://miniflux.net'), new Url('//google.com/assets/img/favicon.png'))
);
// URL same fqdn
$this->assertEquals(
'http://miniflux.net/assets/img/favicon.png',
$favicon->convertLink(new Url('https://miniflux.net'), new Url('http://miniflux.net/assets/img/favicon.png'))
);
// URL different fqdn
$this->assertEquals(
'https://www.google.com/assets/img/favicon.png',
$favicon->convertLink(new Url('https://miniflux.net'), new Url('https://www.google.com/assets/img/favicon.png'))
);
// HTTPS URL
$this->assertEquals(
'https://miniflux.net/assets/img/favicon.png',
$favicon->convertLink(new Url('https://miniflux.net'), new Url('https://miniflux.net/assets/img/favicon.png'))
);
// empty string on missing website parameter
$this->assertEquals(
'',
$favicon->convertLink(new Url(''), new Url('favicon.png'))
);
// website only on missing icon parameter
$this->assertEquals(
'https://miniflux.net/',
$favicon->convertLink(new Url('https://miniflux.net'), new Url(''))
);
// empty string on missing website and icon parameter
$this->assertEquals(
'',
$favicon->convertLink(new Url(''), new Url(''))
);
}
public function testFind_inMeta() public function testFind_inMeta()
{ {
$favicon = new Favicon; $favicon = new Favicon;

View File

@ -35,4 +35,6 @@ Thumbs.db
*.swp *.swp
*~ *~
*.lock *.lock
.buildpath
.project
vendor vendor

View File

@ -28,7 +28,7 @@ Frédéric Guillot: [http://fredericguillot.com](http://fredericguillot.com)
Source code Source code
----------- -----------
On Github: [https://github.com/fguillot/simpleLogger](https://github.com/fguillot/simpleValidator) On Github: [https://github.com/fguillot/simpleValidator](https://github.com/fguillot/simpleValidator)
License License
@ -109,6 +109,28 @@ The specified field must exists.
new Validators\Required($field, $error_message); new Validators\Required($field, $error_message);
### Equals
The specified fields must be equals.
new Validators\Equals($field, $field2, $error_message);
### NotEquals
The specified fields must not be equals.
new Validators\NotEquals($field, $field2, $error_message);
### Exists
Check inside a database if the column value exists or not.
new Validators\Exists($field, $error_message, PDO $pdo, $table, $key = '');
`$pdo` must be an PDO instance, `$table` is the table name.
By default the key used in the table is the value of `$field`, but it can be override if the field doesn't have the same name in the database.
### Unique ### Unique
Check inside a database if the column value is unique or not. Check inside a database if the column value is unique or not.
@ -116,5 +138,36 @@ Check inside a database if the column value is unique or not.
new Validators\Unique($field, $error_message, PDO $pdo, $table, $primary_key = 'id'); new Validators\Unique($field, $error_message, PDO $pdo, $table, $primary_key = 'id');
`$pdo` must be an PDO instance, `$table` is the table name and by default the primary key is "id". `$pdo` must be an PDO instance, `$table` is the table name and by default the primary key is "id".
`$field` can either be a string or an array of string to check inside a database if a value from several columns is unique or not.
If the primary key value is not null, we don't check the uniqueness of the column for this row. If the primary key value is not null, we don't check the uniqueness of the column for this row.
It's useful if you perform validation for an update. It's useful if you perform validation for an update.
Contributors
----------
### Install the latest version of PHPUnit
Simply download the PHPUnit PHAR et copy the file somewhere in your $PATH:
wget https://phar.phpunit.de/phpunit.phar
chmod +x phpunit.phar
sudo mv phpunit.phar /usr/local/bin/phpunit
phpunit --version
PHPUnit 4.2.6 by Sebastian Bergmann.
### Running unit tests
Sqlite tests use a in-memory database, nothing is written on the filesystem.
Example:
phpunit --bootstrap vendor/autoload.php tests
PHPUnit 4.4.2 by Sebastian Bergmann.
............
Time: 69 ms, Memory: 3.75Mb
OK (12 tests, 149 assertions)

View File

@ -39,6 +39,9 @@ abstract class Base
public function getField() public function getField()
{ {
if (is_array($this->field)) {
return $this->field[0];
}
return $this->field; return $this->field;
} }
} }

View File

@ -0,0 +1,58 @@
<?php
/*
* This file is part of Simple Validator.
*
* (c) Frédéric Guillot <contact@fredericguillot.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace SimpleValidator\Validators;
use SimpleValidator\Base;
/**
* @author Olivier Maridat
*/
class Exists extends Base
{
private $pdo;
private $key;
private $table;
public function __construct($field, $error_message, \PDO $pdo, $table, $key = '')
{
parent::__construct($field, $error_message);
$this->pdo = $pdo;
$this->table = $table;
$this->key = $key;
}
public function execute(array $data)
{
if (! isset($data[$this->field]) || '' === $data[$this->field]) {
return true;
}
if ($this->key === '') {
$this->key = $this->field;
}
$rq = $this->pdo->prepare('SELECT COUNT(*) FROM '.$this->table.' WHERE '.$this->key.'=?');
$rq->execute(array(
$data[$this->field]
));
$result = $rq->fetch(\PDO::FETCH_NUM);
if (isset($result[0]) && $result[0] >= '1') {
return true;
}
return false;
}
}

View File

@ -0,0 +1,43 @@
<?php
/*
* This file is part of Simple Validator.
*
* (c) Frédéric Guillot <contact@fredericguillot.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace SimpleValidator\Validators;
use SimpleValidator\Base;
/**
* @author Olivier Maridat
*/
class NotEquals extends Base
{
private $field2;
public function __construct($field1, $field2, $error_message)
{
parent::__construct($field1, $error_message);
$this->field2 = $field2;
}
public function execute(array $data)
{
if (isset($data[$this->field]) && $data[$this->field] !== '') {
if (! isset($data[$this->field2])) return true;
return $data[$this->field] !== $data[$this->field2];
}
return true;
}
}

View File

@ -15,6 +15,7 @@ use SimpleValidator\Base;
/** /**
* @author Frédéric Guillot <contact@fredericguillot.com> * @author Frédéric Guillot <contact@fredericguillot.com>
* @author Olivier Maridat
*/ */
class Unique extends Base class Unique extends Base
{ {
@ -35,44 +36,35 @@ class Unique extends Base
public function execute(array $data) public function execute(array $data)
{ {
if (isset($data[$this->field]) && $data[$this->field] !== '') { if (! is_array($this->field)) {
$this->field = array($this->field);
}
$fields = array();
$parameters = array();
foreach($this->field AS $field) {
if (! isset($data[$field]) || $data[$field] === '') {
return true;
}
$fields[] = $field;
$parameters[] = $data[$field];
}
if (isset($data[$this->primary_key])) {
$parameters[] = $data[$this->primary_key];
}
if (! isset($data[$this->primary_key])) { $rq = $this->pdo->prepare(
'SELECT COUNT(*) FROM '.$this->table.' WHERE '.implode('=? AND ', $fields).'=?'.(isset($data[$this->primary_key]) ? ' AND '.$this->primary_key.'!=?' : '')
$rq = $this->pdo->prepare('SELECT COUNT(*) FROM '.$this->table.' WHERE '.$this->field.'=?'); );
$rq->execute(array( $rq->execute($parameters);
$data[$this->field]
)); $result = $rq->fetch(\PDO::FETCH_NUM);
$result = $rq->fetch(\PDO::FETCH_NUM); if (isset($result[0]) && $result[0] === '1') {
return false;
if (isset($result[0]) && $result[0] === '1') { }
return false; return true;
}
}
else {
$rq = $this->pdo->prepare(
'SELECT COUNT(*) FROM '.$this->table.'
WHERE '.$this->field.'=? AND '.$this->primary_key.' != ?'
);
$rq->execute(array(
$data[$this->field],
$data[$this->primary_key]
));
$result = $rq->fetch(\PDO::FETCH_NUM);
if (isset($result[0]) && $result[0] === '1') {
return false;
}
}
}
return true;
} }
} }

View File

@ -0,0 +1,74 @@
<?php
require_once 'src/SimpleValidator/Base.php';
require_once 'src/SimpleValidator/Validators/Unique.php';
require_once 'src/SimpleValidator/Validators/Exists.php';
use SimpleValidator\Validators\Exists;
class ExistsValidatorTest extends PHPUnit_Framework_TestCase
{
public function testValidator()
{
$pdo = new PDO('sqlite::memory:');
$pdo->exec('CREATE TABLE mytable (id INTEGER, toto TEXT)');
$message = 'toto doesn\'t exist';
$v = new Exists('id', $message, $pdo, 'mytable');
$this->assertEquals($message, $v->getErrorMessage());
$this->assertTrue($v->execute(array('id' => '')));
$this->assertTrue($v->execute(array('id' => null)));
$this->assertFalse($v->execute(array('id' => '1')));
$pdo->exec("INSERT INTO mytable VALUES ('1', 'truc')");
$this->assertTrue($v->execute(array('id' => '1')));
$this->assertFalse($v->execute(array('id' => '0')));
$this->assertTrue($v->execute(array('id' => '')));
$this->assertTrue($v->execute(array('id' => null)));
$pdo->exec("INSERT INTO mytable VALUES ('2', 'muche')");
$this->assertTrue($v->execute(array('id' => '2')));
$this->assertTrue($v->execute(array('id' => '1')));
$this->assertFalse($v->execute(array('id' => '0')));
$this->assertTrue($v->execute(array('id' => '')));
$this->assertTrue($v->execute(array('id' => null)));
}
public function testValidatorWithDifferentKey()
{
$pdo = new PDO('sqlite::memory:');
$pdo->exec('CREATE TABLE mytable (id INTEGER, toto TEXT)');
$message = 'toto doesn\'t exist';
$v = new Exists('toto_id', $message, $pdo, 'mytable', 'id');
$this->assertEquals($message, $v->getErrorMessage());
$this->assertTrue($v->execute(array('toto_id' => '')));
$this->assertTrue($v->execute(array('toto_id' => null)));
$this->assertFalse($v->execute(array('toto_id' => '1')));
$pdo->exec("INSERT INTO mytable VALUES ('1', 'truc')");
$this->assertTrue($v->execute(array('toto_id' => '1')));
$this->assertFalse($v->execute(array('toto_id' => '0')));
$this->assertTrue($v->execute(array('toto_id' => '')));
$this->assertTrue($v->execute(array('toto_id' => null)));
$pdo->exec("INSERT INTO mytable VALUES ('2', 'muche')");
$this->assertTrue($v->execute(array('toto_id' => '2')));
$this->assertTrue($v->execute(array('toto_id' => '1')));
$this->assertFalse($v->execute(array('toto_id' => '0')));
$this->assertTrue($v->execute(array('toto_id' => '')));
$this->assertTrue($v->execute(array('toto_id' => null)));
}
}

View File

@ -0,0 +1,35 @@
<?php
require_once 'src/SimpleValidator/Base.php';
require_once 'src/SimpleValidator/Validators/Email.php';
use SimpleValidator\Validators\NotEquals;
class EmailValidatorTest extends PHPUnit_Framework_TestCase
{
public function testValidator()
{
$message = 'should not be equal';
$v = new NotEquals('toto', 'titi', $message);
$this->assertEquals($message, $v->getErrorMessage());
$this->assertFalse($v->execute(array('toto' => 'test', 'titi' => 'test')));
$this->assertTrue($v->execute(array('toto' => 'test', 'titi' => 'testest')));
$this->assertTrue($v->execute(array('toto' => 'test')));
$this->assertTrue($v->execute(array('toto' => 'test', 'titi' => '')));
$this->assertTrue($v->execute(array('toto' => 'test', 'titi' => null)));
$this->assertTrue($v->execute(array('toto' => 'test')));
$this->assertTrue($v->execute(array('toto' => '', 'titi' => 'test')));
$this->assertTrue($v->execute(array('toto' => null, 'titi' => 'test')));
$this->assertTrue($v->execute(array('titi' => 'test')));
$this->assertTrue($v->execute(array()));
$this->assertTrue($v->execute(array('toto' => '')));
$this->assertTrue($v->execute(array('toto' => null)));
$this->assertTrue($v->execute(array('titi' => '')));
$this->assertTrue($v->execute(array('titi' => null)));
}
}

View File

@ -35,4 +35,49 @@ class UniqueValidatorTest extends PHPUnit_Framework_TestCase
$this->assertFalse($v->execute(array('toto' => 'truc', 'id' => '2'))); $this->assertFalse($v->execute(array('toto' => 'truc', 'id' => '2')));
} }
public function testValidatorWithArray()
{
$pdo = new PDO('sqlite::memory:');
$pdo->exec('CREATE TABLE mytable (id INTEGER, toto TEXT, tata TEXT)');
$message = 'field must be unique';
$v = new Unique(array('toto', 'tata'), $message, $pdo, 'mytable');
$this->assertEquals($message, $v->getErrorMessage());
$this->assertTrue($v->execute(array('toto' => '')));
$this->assertTrue($v->execute(array('toto' => null)));
$this->assertTrue($v->execute(array('toto' => 'bidule')));
$this->assertTrue($v->execute(array('toto' => 'bidule', 'tata' => 'machin')));
$this->assertTrue($v->execute(array('toto' => 'bidule', 'toutou' => 'machin')));
$pdo->exec("INSERT INTO mytable VALUES ('1', 'truc', 'muche')");
$this->assertTrue($v->execute(array('toto' => 'truc')));
$this->assertTrue($v->execute(array('toto' => 'bidule')));
$this->assertTrue($v->execute(array('toto' => 'bidule', 'tata' => 'miouch')));
$this->assertTrue($v->execute(array('toto' => 'bidule', 'tata' => 'muche')));
$this->assertTrue($v->execute(array('toto' => 'bidule', 'toutou' => 'muche')));
$this->assertFalse($v->execute(array('toto' => 'truc', 'tata' => 'muche')));
$this->assertTrue($v->execute(array('toto' => 'truc', 'tata' => 'miouch')));
$pdo->exec("INSERT INTO mytable VALUES ('2', 'bidule', 'machin')");
$this->assertTrue($v->execute(array('toto' => 'bidule')));
$this->assertTrue($v->execute(array('toto' => 'truc')));
$this->assertTrue($v->execute(array('toto' => 'bidule', 'tata' => 'muche')));
$this->assertFalse($v->execute(array('toto' => 'bidule', 'tata' => 'machin')));
$this->assertTrue($v->execute(array('toto' => 'bidule', 'tata' => 'muche', 'id' => '2')));
$this->assertTrue($v->execute(array('toto' => 'bidule', 'tata' => 'machin', 'id' => '2')));
$this->assertTrue($v->execute(array('toto' => 'truc', 'id' => '2')));
$this->assertFalse($v->execute(array('toto' => 'truc', 'tata' => 'muche', 'id' => '2')));
$this->assertTrue($v->execute(array('toto' => 'truc', 'tata' => 'miouch', 'id' => '2')));
}
} }