From a9ccd9dc1e464898b2fe2bac4afebab61a5db0d8 Mon Sep 17 00:00:00 2001 From: doctrine Date: Wed, 7 Jun 2006 09:07:38 +0000 Subject: [PATCH] Validator: support for array and object types, better handling of null valued columns --- Doctrine/DB.php | 1 + Doctrine/Manager.php | 1 + Doctrine/Record.php | 30 +++++++++----- Doctrine/Session.php | 2 +- Doctrine/Validator.php | 83 +++++++++++++++++++++++-------------- tests/ValidatorTestCase.php | 23 +++++++++- tests/classes.php | 9 ++++ tests/run.php | 1 - 8 files changed, 105 insertions(+), 45 deletions(-) diff --git a/Doctrine/DB.php b/Doctrine/DB.php index 46809dfd4..13bb36faf 100644 --- a/Doctrine/DB.php +++ b/Doctrine/DB.php @@ -131,6 +131,7 @@ class Doctrine_DBStatement extends PDOStatement { */ public function execute(array $params = null) { $time = microtime(); + $result = parent::execute($params); $exectime = (microtime() - $time); diff --git a/Doctrine/Manager.php b/Doctrine/Manager.php index 4e27cf8da..3704853d8 100644 --- a/Doctrine/Manager.php +++ b/Doctrine/Manager.php @@ -41,6 +41,7 @@ class Doctrine_Manager extends Doctrine_Configurable implements Countable, Itera Doctrine_Record::initNullObject($this->null); Doctrine_Collection::initNullObject($this->null); Doctrine_Record_Iterator::initNullObject($this->null); + Doctrine_Validator::initNullObject($this->null); } /** * @return Doctrine_Null diff --git a/Doctrine/Record.php b/Doctrine/Record.php index 910bfa998..42ec0d7ad 100644 --- a/Doctrine/Record.php +++ b/Doctrine/Record.php @@ -98,8 +98,8 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite */ private static $index = 1; /** - * @var Doctrine_Null $nullObject a Doctrine_Null object used for extremely fast - * SQL null value testing + * @var Doctrine_Null $null a Doctrine_Null object used for extremely fast + * null value testing */ private static $null; /** @@ -208,10 +208,12 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite * modifies data array * example: * - * $data = array("name"=>"John","lastname"=> null,"id"=>1,"unknown"=>"unknown"); - * $names = array("name","lastname","id"); + * $data = array("name"=>"John","lastname"=> null, "id" => 1,"unknown" => "unknown"); + * $names = array("name", "lastname", "id"); * $data after operation: - * $data = array("name"=>"John","lastname" => array(),"id"=>1); + * $data = array("name"=>"John","lastname" => Object(Doctrine_Null)); + * + * here column 'id' is removed since its auto-incremented primary key (protected) */ private function cleanData() { $tmp = $this->data; @@ -219,14 +221,21 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite $this->data = array(); foreach($this->table->getColumnNames() as $name) { + $type = $this->table->getTypeOf($name); + if( ! isset($tmp[$name])) { - $this->data[$name] = self::$null; + if($type == 'array') { + $this->data[$name] = array(); + $this->modified[] = $name; + } else + $this->data[$name] = self::$null; } else { - switch($this->table->getTypeOf($name)): + switch($type): case "array": case "object": if($tmp[$name] !== self::$null) $this->data[$name] = unserialize($tmp[$name]); + break; default: $this->data[$name] = $tmp[$name]; @@ -235,8 +244,9 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite } } /** - * prepares identifiers + * prepares identifiers for later use * + * @param boolean $exists whether or not this record exists in persistent data store * @return void */ private function prepareIdentifiers($exists = true) { @@ -706,9 +716,9 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite foreach($this->modified as $k => $v) { $type = $this->table->getTypeOf($v); - + if($type == 'array' || - $type == 'object') { + $type == 'object') { $a[$v] = serialize($this->data[$v]); continue; diff --git a/Doctrine/Session.php b/Doctrine/Session.php index e917d1010..c80fdb640 100644 --- a/Doctrine/Session.php +++ b/Doctrine/Session.php @@ -747,7 +747,7 @@ abstract class Doctrine_Session extends Doctrine_Configurable implements Countab * @return boolean */ private function update(Doctrine_Record $record) { - $array = $record->getModified(); + $array = $record->getPrepared(); if(empty($array)) return false; diff --git a/Doctrine/Validator.php b/Doctrine/Validator.php index e3548c9de..75488537b 100644 --- a/Doctrine/Validator.php +++ b/Doctrine/Validator.php @@ -31,7 +31,7 @@ class Doctrine_Validator { /** * constant for blank validation error */ - const ERR_BLANK = 4; + const ERR_NOTBLANK = 4; /** * constant for date validation error */ @@ -39,7 +39,7 @@ class Doctrine_Validator { /** * constant for null validation error */ - const ERR_NULL = 6; + const ERR_NOTNULL = 6; /** * constant for enum validation error */ @@ -53,13 +53,27 @@ class Doctrine_Validator { /** - * @var array $stack error stack + * @var array $stack error stack */ private $stack = array(); /** - * @var array $validators an array of validator objects + * @var array $validators an array of validator objects */ private static $validators = array(); + /** + * @var Doctrine_Null $null a Doctrine_Null object used for extremely fast + * null value testing + */ + private static $null; + /** + * initNullObject + * + * @param Doctrine_Null $null + * @return void + */ + public static function initNullObject(Doctrine_Null $null) { + self::$null = $null; + } /** * returns a validator object * @@ -86,24 +100,35 @@ class Doctrine_Validator { * @return void */ public function validateRecord(Doctrine_Record $record) { - $modified = $record->getModified(); $columns = $record->getTable()->getColumns(); $name = $record->getTable()->getComponentName(); + switch($record->getState()): + case Doctrine_Record::STATE_TDIRTY: + case Doctrine_Record::STATE_TCLEAN: + $data = $record->getData(); + break; + default: + $data = $record->getModified(); + endswitch; + $err = array(); - foreach($modified as $key => $value) { + + foreach($data as $key => $value) { + if($value === self::$null) + $value = null; + $column = $columns[$key]; + if($column[0] == 'array' || $column[0] == 'object') { + $value = serialize($value); + } + if(strlen($value) > $column[1]) { $err[$key] = Doctrine_Validator::ERR_LENGTH; continue; } - if(self::gettype($value) !== $column[0]) { - $err[$key] = Doctrine_Validator::ERR_TYPE; - continue; - } - $e = explode("|",$column[2]); foreach($e as $k => $arg) { @@ -116,28 +141,22 @@ class Doctrine_Validator { $validator = self::getValidator($args[0]); if( ! $validator->validate($record, $key, $value, $args[1])) { - switch(strtolower($args[0])): - case "unique": - $err[$key] = Doctrine_Validator::ERR_UNIQUE; - break; - case "notnull": - $err[$key] = Doctrine_Validator::ERR_NULL; - break; - case "notblank": - $err[$key] = Doctrine_Validator::ERR_BLANK; - break; - case "enum": - $err[$key] = Doctrine_Validator::ERR_VALID; - break; - default: - $err[$key] = Doctrine_Validator::ERR_VALID; - break; - endswitch; - } - - // errors found quit validation looping for this column - if(isset($err[$key])) + + $constant = 'Doctrine_Validator::ERR_'.strtoupper($args[0]); + + if(defined($constant)) + $err[$key] = constant($constant); + else + $err[$key] = Doctrine_Validator::ERR_VALID; + + // errors found quit validation looping for this column break; + } + } + + if(self::gettype($value) !== $column[0] && self::gettype($value) != 'NULL') { + $err[$key] = Doctrine_Validator::ERR_TYPE; + continue; } } diff --git a/tests/ValidatorTestCase.php b/tests/ValidatorTestCase.php index 96ae2f58f..ddcb97952 100644 --- a/tests/ValidatorTestCase.php +++ b/tests/ValidatorTestCase.php @@ -1,5 +1,27 @@ tables[] = "Validator_Test"; + parent::prepareTables(); + } + public function testValidate2() { + $test = new Validator_Test(); + $test->mymixed = "message"; + + $validator = new Doctrine_Validator(); + $validator->validateRecord($test); + + $stack = $validator->getErrorStack(); + + $this->assertTrue(is_array($stack)); + + $stack = $stack['Validator_Test'][0]; + $this->assertEqual($stack['mystring'], Doctrine_Validator::ERR_NOTNULL); + + $test->mystring = 'str'; + + $test->save(); + } public function testValidate() { $user = $this->session->getTable("User")->find(4); @@ -71,6 +93,5 @@ class Doctrine_ValidatorTestCase extends Doctrine_UnitTestCase { $this->assertEqual($a["User"][0]["name"], Doctrine_Validator::ERR_LENGTH); $this->manager->setAttribute(Doctrine::ATTR_VLD, false); } - } ?> diff --git a/tests/classes.php b/tests/classes.php index 1178553de..791bcec13 100644 --- a/tests/classes.php +++ b/tests/classes.php @@ -313,4 +313,13 @@ class Log_Status extends Doctrine_Record { $this->hasColumn("name", "string", 255); } } +class Validator_Test extends Doctrine_Record { + public function setTableDefinition() { + $this->hasColumn("mymixed","string", 100); + $this->hasColumn("mystring","string", 100, "notnull|unique"); + $this->hasColumn("myarray", "array", 1000); + $this->hasColumn("myobject", "object", 1000); + $this->hasColumn("myinteger", "integer", 11); + } +} ?> diff --git a/tests/run.php b/tests/run.php index 91a8333cc..c2696e43a 100644 --- a/tests/run.php +++ b/tests/run.php @@ -15,7 +15,6 @@ require_once("CollectionTestCase.php"); require_once("CacheSqliteTestCase.php"); require_once("CollectionOffsetTestCase.php"); -require_once("SenseiTestCase.php"); require_once("QueryTestCase.php"); error_reporting(E_ALL);