95% coverage, getting close.

This commit is contained in:
Joshua Sherman 2014-01-19 22:36:30 -05:00
parent f3d5d12b9f
commit db6e169f7b
6 changed files with 222 additions and 54 deletions

View file

@ -203,7 +203,7 @@ class Config extends Object
* @param array $array configuration error to flatten * @param array $array configuration error to flatten
* @return array flattened configuration array * @return array flattened configuration array
*/ */
private function flatten($environment, $array) public function flatten($environment, $array)
{ {
if (is_array($array)) if (is_array($array))
{ {

View file

@ -631,6 +631,11 @@ class Model extends Object
} }
} }
if (!preg_match('/^[0-9]+$/', implode('', array_keys($this->records))))
{
$this->records = [$this->records];
}
$this->index = 0; $this->index = 0;
$this->original = $this->records; $this->original = $this->records;
} }
@ -892,7 +897,14 @@ class Model extends Object
*/ */
public function count() public function count()
{ {
return count($this->records); if (isset($this->records[0]) && $this->records[0] == [])
{
return 0;
}
else
{
return count($this->records);
}
} }
/** /**
@ -1087,14 +1099,14 @@ class Model extends Object
/** /**
* @todo I outta loop through twice to determine if it's an INSERT * @todo I outta loop through twice to determine if it's an INSERT
* or an UPDATE. As it stands, you could run into a scenario where * or an UPDATE. As it stands, you could run into a scenario
* you could have a mixed lot that would attempt to build out a * where you could have a mixed lot that would attempt to
* query with both insert and update syntax and would probably * build out a query with both INSERT and UPDATE syntax and
* cause a doomsday scenario for our universe. * would probably cause a doomsday scenario for our universe.
*/ */
foreach ($this->records as $record) foreach ($this->records as $record)
{ {
// Performs an update with multiple queries // Performs an UPDATE with multiple queries
if (array_key_exists($this->columns['id'], $record)) if (array_key_exists($this->columns['id'], $record))
{ {
$update = true; $update = true;
@ -1124,14 +1136,14 @@ class Model extends Object
if ($this->columns['updated_at'] != false) if ($this->columns['updated_at'] != false)
{ {
$update_fields[] = $this->columns['updated_at'] . ' = ?'; $update_fields[] = $this->columns['updated_at'] . ' = ?';
$input_parameters[] = time::timestamp(); $input_parameters[] = Time::timestamp();
} }
// @todo Check if the column was passed in // @todo Check if the column was passed in
if ($this->columns['updated_id'] != false && isset($_session['__pickles']['security']['user_id'])) if ($this->columns['updated_id'] != false && isset($_SESSION['__pickles']['security']['user_id']))
{ {
$update_fields[] = $this->columns['updated_id'] . ' = ?'; $update_fields[] = $this->columns['updated_id'] . ' = ?';
$input_parameters[] = $_session['__pickles']['security']['user_id']; $input_parameters[] = $_SESSION['__pickles']['security']['user_id'];
} }
if ($sql != '') if ($sql != '')
@ -1139,7 +1151,7 @@ class Model extends Object
$sql .= '; '; $sql .= '; ';
} }
$sql .= 'update ' . $this->table . ' set ' . implode(', ', $update_fields) . ' where '; $sql .= 'UPDATE ' . $this->table . ' SET ' . implode(', ', $update_fields) . ' WHERE ';
if (isset($record[$this->columns['id']])) if (isset($record[$this->columns['id']]))
{ {
@ -1151,7 +1163,7 @@ class Model extends Object
throw new Exception('Missing UID field.'); throw new Exception('Missing UID field.');
} }
} }
// Performs a multiple row insert // Performs a multiple row INSERT
else else
{ {
if (!isset($sql)) if (!isset($sql))
@ -1165,7 +1177,7 @@ class Model extends Object
$field_count++; $field_count++;
} }
if ($this->columns['created_id'] != false && isset($_session['__pickles']['security']['user_id'])) if ($this->columns['created_id'] != false && isset($_SESSION['__pickles']['security']['user_id']))
{ {
$insert_fields[] = $this->columns['created_id']; $insert_fields[] = $this->columns['created_id'];
$field_count++; $field_count++;
@ -1175,7 +1187,7 @@ class Model extends Object
$input_parameters = []; $input_parameters = [];
// INSERT INTO ... // INSERT INTO ...
$sql = 'insert into ' . $this->table . ' (' . implode(', ', $insert_fields) . ') values ' . $values; $sql = 'INSERT INTO ' . $this->table . ' (' . implode(', ', $insert_fields) . ') VALUES ' . $values;
} }
else else
{ {
@ -1192,14 +1204,14 @@ class Model extends Object
// @todo Check if the column was passed in // @todo Check if the column was passed in
if ($this->columns['created_at'] != false) if ($this->columns['created_at'] != false)
{ {
$input_parameters[] = time::timestamp(); $input_parameters[] = Time::timestamp();
$record_field_count++; $record_field_count++;
} }
// @todo Check if the column was passed in // @todo Check if the column was passed in
if ($this->columns['created_id'] != false && isset($_session['__pickles']['security']['user_id'])) if ($this->columns['created_id'] != false && isset($_SESSION['__pickles']['security']['user_id']))
{ {
$input_parameters[] = $_session['__pickles']['security']['user_id']; $input_parameters[] = $_SESSION['__pickles']['security']['user_id'];
$record_field_count++; $record_field_count++;
} }
@ -1226,12 +1238,12 @@ class Model extends Object
// Determines if it's an UPDATE or INSERT // Determines if it's an UPDATE or INSERT
$update = (isset($this->record[$this->columns['id']]) && trim($this->record[$this->columns['id']]) != ''); $update = (isset($this->record[$this->columns['id']]) && trim($this->record[$this->columns['id']]) != '');
// Starts to build the query, optionally sets priority, delayed and ignore syntax // Starts to build the query, optionally sets PRIORITY, DELAYED and IGNORE syntax
if ($this->replace === true && $this->mysql) if ($this->replace === true && $this->mysql)
{ {
$sql = 'REPLACE'; $sql = 'REPLACE';
if (strtoupper($this->priority) == 'low') if (strtoupper($this->priority) == 'LOW')
{ {
$sql .= ' LOW_PRIORITY'; $sql .= ' LOW_PRIORITY';
} }
@ -1288,6 +1300,11 @@ class Model extends Object
// Makes sure there's something to INSERT or UPDATE // Makes sure there's something to INSERT or UPDATE
if (count($record) > 0) if (count($record) > 0)
{ {
if ($this->replace && $update)
{
$update = false;
}
$insert_fields = []; $insert_fields = [];
// Loops through all the columns and assembles the query // Loops through all the columns and assembles the query
@ -1323,7 +1340,7 @@ class Model extends Object
} }
} }
// If it's an UPDATE tack on the id // If it's an UPDATE tack on the ID
if ($update == true) if ($update == true)
{ {
if ($this->columns['updated_at'] != false) if ($this->columns['updated_at'] != false)
@ -1334,43 +1351,49 @@ class Model extends Object
} }
$sql .= $this->columns['updated_at'] . ' = ?'; $sql .= $this->columns['updated_at'] . ' = ?';
$input_parameters[] = time::timestamp(); $input_parameters[] = Time::timestamp();
} }
if ($this->columns['updated_id'] != false && isset($_session['__pickles']['security']['user_id'])) if ($this->columns['updated_id'] != false && isset($_SESSION['__pickles']['security']['user_id']))
{ {
if ($input_parameters != null) if ($input_parameters != null)
{ {
$sql .= ', '; $sql .= ', ';
} }
$sql .= $this->columns['updated_id'] . ' = ?'; $sql .= $this->columns['updated_id'] . ' = ?';
$input_parameters[] = $_session['__pickles']['security']['user_id'];
$input_parameters[] = $_SESSION['__pickles']['security']['user_id'];
} }
$sql .= ' where ' . $this->columns['id'] . ' = ?' . ($this->mysql ? ' limit 1' : '') . ';'; $sql .= ' WHERE ' . $this->columns['id'] . ' = ?' . ($this->mysql ? ' LIMIT 1' : '') . ';';
$input_parameters[] = $this->record[$this->columns['id']]; $input_parameters[] = $this->record[$this->columns['id']];
} }
else else
{ {
if ($this->columns['created_at'] != false) // @todo REPLACE should be grabbing the previous values so
// that we're not wiping out pertinent data when the
// internal columns are in use. This includes the
// `id` column that is needed to keep it from doing
// an INSERT instead of an UPDATE
if ($this->columns['created_at'] != false || $this->replace)
{ {
$insert_fields[] = $this->columns['created_at']; $insert_fields[] = $this->columns['created_at'];
$input_parameters[] = Time::timestamp(); $input_parameters[] = Time::timestamp();
} }
if ($this->columns['created_id'] != false && isset($_session['__pickles']['security']['user_id'])) if ($this->columns['created_id'] != false && isset($_SESSION['__pickles']['security']['user_id']))
{ {
$insert_fields[] = $this->columns['created_id']; $insert_fields[] = $this->columns['created_id'];
$input_parameters[] = $_session['__pickles']['security']['user_id']; $input_parameters[] = $_SESSION['__pickles']['security']['user_id'];
} }
$sql .= '(' . implode(', ', $insert_fields) . ') values (' . implode(', ', array_fill(0, count($input_parameters), '?')) . ')'; $sql .= '(' . implode(', ', $insert_fields) . ') VALUES (' . implode(', ', array_fill(0, count($input_parameters), '?')) . ')';
// PDO::lastInsertID() doesn't work so we return the ID with the query // PDO::lastInsertID() doesn't work so we return the ID with the query
if ($this->postgresql) if ($this->postgresql)
{ {
$sql .= ' returning ' . $this->columns['id']; $sql .= ' RETURNING ' . $this->columns['id'];
} }
$sql .= ';'; $sql .= ';';
@ -1387,7 +1410,7 @@ class Model extends Object
{ {
$results = $this->db->execute($sql, $input_parameters); $results = $this->db->execute($sql, $input_parameters);
// clears the cache // Clears the cache
if ($update && $this->use_cache) if ($update && $this->use_cache)
{ {
$this->cache->delete(strtoupper($this->model) . '-' . $this->record[$this->columns['id']]); $this->cache->delete(strtoupper($this->model) . '-' . $this->record[$this->columns['id']]);
@ -1424,10 +1447,10 @@ class Model extends Object
$input_parameters[] = Time::timestamp(); $input_parameters[] = Time::timestamp();
} }
if ($this->columns['deleted_id'] && isset($_session['__pickles']['security']['user_id'])) if ($this->columns['deleted_id'] && isset($_SESSION['__pickles']['security']['user_id']))
{ {
$sql .= ', ' . $this->columns['deleted_id'] . ' = ?'; $sql .= ', ' . $this->columns['deleted_id'] . ' = ?';
$input_parameters[] = $_session['__pickles']['security']['user_id']; $input_parameters[] = $_SESSION['__pickles']['security']['user_id'];
} }
$sql .= ' WHERE ' . $this->columns['id'] . ' = ?'; $sql .= ' WHERE ' . $this->columns['id'] . ' = ?';

View file

@ -28,42 +28,37 @@ class Object
* Object Instances * Object Instances
* *
* @static * @static
* @access private
* @var array * @var array
*/ */
protected static $instances = []; public static $instances = [];
/** /**
* Instance of the Config object * Instance of the Config object
* *
* @access protected * @var object
* @var object
*/ */
protected $config = null; public $config = null;
/** /**
* Instance of the Cache object * Instance of the Cache object
* *
* @access protected * @var object
* @var object
*/ */
protected $cache = null; public $cache = null;
/** /**
* Instance of the Database object * Instance of the Database object
* *
* @access protected * @var object
* @var object
*/ */
protected $db = null; public $db = null;
/** /**
* Profiler flag * Profiler flag
* *
* @access private * @var mixed
* @var mixed
*/ */
private $profiler = false; public $profiler = false;
/** /**
* Constructor * Constructor

View file

@ -61,6 +61,7 @@ function setUpConfig($config)
} }
`mysql -e 'TRUNCATE TABLE test.pickles;'`; `mysql -e 'TRUNCATE TABLE test.pickles;'`;
`mysql -e 'TRUNCATE TABLE test.mypickles;'`;
`mysql -e 'TRUNCATE TABLE test.users;'`; `mysql -e 'TRUNCATE TABLE test.users;'`;
`echo 'flush_all' | nc localhost 11211`; `echo 'flush_all' | nc localhost 11211`;

View file

@ -6,16 +6,25 @@ class MockModelWithoutColumns extends Model
public $columns = false; public $columns = false;
} }
// InnoDB
class MockModel extends Model class MockModel extends Model
{ {
public $table = 'pickles'; public $table = 'pickles';
public $columns = ['created_at' => 'created_at']; public $columns = ['created_at' => 'created_at'];
} }
// MyISAM
class MyMockModel extends Model
{
public $table = 'mypickles';
}
class ModelTest extends PHPUnit_Framework_TestCase class ModelTest extends PHPUnit_Framework_TestCase
{ {
public static function setUpBeforeClass() public static function setUpBeforeClass()
{ {
// Clears out the Config for ease of testing
Object::$instances = [];
$config = Config::getInstance(); $config = Config::getInstance();
$config->data = [ $config->data = [
@ -353,6 +362,126 @@ class ModelTest extends PHPUnit_Framework_TestCase
$model = new MockModel(); $model = new MockModel();
$conditions = $model->generateConditions(['id BETWEEN' => '1']); $conditions = $model->generateConditions(['id BETWEEN' => '1']);
} }
public function testCommitSingleRecord()
{
$value = String::random();
$model = new MockModel(1);
$model->record['field1'] = $value;
$model->commit();
$model = new MockModel(1);
$this->assertEquals($value, $model->record['field1']);
}
public function testCommitSingleRecordReplace()
{
# $value = String::random();
# $model = new MockModel(1);
# $model->replace = true;
# $model->record['field1'] = $value;
# $model->commit();
# $model = new MockModel(1);
# $this->assertEquals($value, $model->record['field1']);
}
public function testCommitInsertPriority()
{
$value = String::random();
$model = new MockModel();
$model->priority = 'low';
$model->record['field1'] = $value;
$id = $model->commit();
$model = new MockModel($id);
$this->assertEquals($value, $model->record['field1']);
}
public function testCommitInsertDelayed()
{
$value = String::random();
$model = new MyMockModel();
$model->delayed = true;
$model->record['field1'] = $value;
$model->commit();
$model = new MyMockModel(1);
$this->assertEquals($value, $model->record['field1']);
}
public function testCommitInsertIgnore()
{
$value = String::random();
$model = new MockModel();
$model->ignore = true;
$model->record['field1'] = $value;
$id = $model->commit();
$model = new MockModel($id);
$this->assertEquals($value, $model->record['field1']);
}
public function testCommitReplacePriority()
{
$value = String::random();
$model = new MockModel();
$model->replace = true;
$model->priority = 'low';
$model->record['field1'] = $value;
$id = $model->commit();
$model = new MockModel($id);
$this->assertEquals($value, $model->record['field1']);
}
public function testCommitReplaceDelayed()
{
$value = String::random();
$model = new MyMockModel();
$model->replace = true;
$model->delayed = true;
$model->record['field1'] = $value;
$model->commit();
$model = new MyMockModel(2);
$this->assertEquals($value, $model->record['field1']);
}
public function testCommitReplaceIgnore()
{
$value = String::random();
$model = new MockModel();
$model->replace = true;
$model->ignore = true;
$model->record['field1'] = $value;
$id = $model->commit();
$model = new MockModel($id);
$this->assertEquals($value, $model->record['field1']);
}
public function testDeleteLogical()
{
$_SESSION['__pickles']['security']['user_id'] = 1;
$model = new MockModel(1);
$model->delete();
$model = new MockModelWithoutColumns(1);
$this->assertEquals(1, $model->record['is_deleted']);
}
public function testDeleteActual()
{
$model = new MockModelWithoutColumns(1);
$model->delete();
$model = new MockModelWithoutColumns(1);
$this->assertEquals(0, $model->count());
}
public function testDeleteNothing()
{
$model = new MockModelWithoutColumns(100);
$this->assertFalse($model->delete());
}
public function testLoadParametersWithString()
{
$model = new MockModel();
$this->assertFalse($model->loadParameters(''));
}
} }
?> ?>

View file

@ -3,12 +3,12 @@ DROP TABLE IF EXISTS pickles;
CREATE TABLE `pickles` ( CREATE TABLE `pickles` (
`id` int(1) unsigned NOT NULL AUTO_INCREMENT, `id` int(1) unsigned NOT NULL AUTO_INCREMENT,
`field1` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `field1` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`field2` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `field2` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`field3` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `field3` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`field4` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `field4` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`field5` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `field5` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`created_id` int(1) unsigned DEFAULT NULL, `created_id` int(1) unsigned DEFAULT NULL,
`created_at` datetime NOT NULL, `created_at` datetime DEFAULT NULL,
`updated_id` int(1) unsigned DEFAULT NULL, `updated_id` int(1) unsigned DEFAULT NULL,
`updated_at` datetime DEFAULT NULL, `updated_at` datetime DEFAULT NULL,
`deleted_id` int(1) unsigned DEFAULT NULL, `deleted_id` int(1) unsigned DEFAULT NULL,
@ -16,7 +16,27 @@ CREATE TABLE `pickles` (
`is_deleted` tinyint(1) unsigned DEFAULT '0', `is_deleted` tinyint(1) unsigned DEFAULT '0',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY is_deleted (is_deleted) KEY is_deleted (is_deleted)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
DROP TABLE IF EXISTS mypickles;
CREATE TABLE `mypickles` (
`id` int(1) unsigned NOT NULL AUTO_INCREMENT,
`field1` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`field2` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`field3` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`field4` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`field5` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`created_id` int(1) unsigned DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_id` int(1) unsigned DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`deleted_id` int(1) unsigned DEFAULT NULL,
`deleted_at` datetime DEFAULT NULL,
`is_deleted` tinyint(1) unsigned DEFAULT '0',
PRIMARY KEY (`id`),
KEY is_deleted (is_deleted)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
DROP TABLE IF EXISTS users; DROP TABLE IF EXISTS users;
@ -32,4 +52,4 @@ CREATE TABLE `users` (
`deleted_at` datetime DEFAULT NULL, `deleted_at` datetime DEFAULT NULL,
`is_deleted` tinyint(1) unsigned DEFAULT '0', `is_deleted` tinyint(1) unsigned DEFAULT '0',
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;