Commit a9ccd9dc authored by doctrine's avatar doctrine

Validator: support for array and object types, better handling of null valued columns

parent d1ed73c6
...@@ -131,6 +131,7 @@ class Doctrine_DBStatement extends PDOStatement { ...@@ -131,6 +131,7 @@ class Doctrine_DBStatement extends PDOStatement {
*/ */
public function execute(array $params = null) { public function execute(array $params = null) {
$time = microtime(); $time = microtime();
$result = parent::execute($params); $result = parent::execute($params);
$exectime = (microtime() - $time); $exectime = (microtime() - $time);
......
...@@ -41,6 +41,7 @@ class Doctrine_Manager extends Doctrine_Configurable implements Countable, Itera ...@@ -41,6 +41,7 @@ class Doctrine_Manager extends Doctrine_Configurable implements Countable, Itera
Doctrine_Record::initNullObject($this->null); Doctrine_Record::initNullObject($this->null);
Doctrine_Collection::initNullObject($this->null); Doctrine_Collection::initNullObject($this->null);
Doctrine_Record_Iterator::initNullObject($this->null); Doctrine_Record_Iterator::initNullObject($this->null);
Doctrine_Validator::initNullObject($this->null);
} }
/** /**
* @return Doctrine_Null * @return Doctrine_Null
......
...@@ -98,8 +98,8 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite ...@@ -98,8 +98,8 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
*/ */
private static $index = 1; private static $index = 1;
/** /**
* @var Doctrine_Null $nullObject a Doctrine_Null object used for extremely fast * @var Doctrine_Null $null a Doctrine_Null object used for extremely fast
* SQL null value testing * null value testing
*/ */
private static $null; private static $null;
/** /**
...@@ -208,10 +208,12 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite ...@@ -208,10 +208,12 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
* modifies data array * modifies data array
* example: * example:
* *
* $data = array("name"=>"John","lastname"=> null,"id"=>1,"unknown"=>"unknown"); * $data = array("name"=>"John","lastname"=> null, "id" => 1,"unknown" => "unknown");
* $names = array("name","lastname","id"); * $names = array("name", "lastname", "id");
* $data after operation: * $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() { private function cleanData() {
$tmp = $this->data; $tmp = $this->data;
...@@ -219,14 +221,21 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite ...@@ -219,14 +221,21 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite
$this->data = array(); $this->data = array();
foreach($this->table->getColumnNames() as $name) { foreach($this->table->getColumnNames() as $name) {
$type = $this->table->getTypeOf($name);
if( ! isset($tmp[$name])) { if( ! isset($tmp[$name])) {
if($type == 'array') {
$this->data[$name] = array();
$this->modified[] = $name;
} else
$this->data[$name] = self::$null; $this->data[$name] = self::$null;
} else { } else {
switch($this->table->getTypeOf($name)): switch($type):
case "array": case "array":
case "object": case "object":
if($tmp[$name] !== self::$null) if($tmp[$name] !== self::$null)
$this->data[$name] = unserialize($tmp[$name]); $this->data[$name] = unserialize($tmp[$name]);
break; break;
default: default:
$this->data[$name] = $tmp[$name]; $this->data[$name] = $tmp[$name];
...@@ -235,8 +244,9 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite ...@@ -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 * @return void
*/ */
private function prepareIdentifiers($exists = true) { private function prepareIdentifiers($exists = true) {
......
...@@ -747,7 +747,7 @@ abstract class Doctrine_Session extends Doctrine_Configurable implements Countab ...@@ -747,7 +747,7 @@ abstract class Doctrine_Session extends Doctrine_Configurable implements Countab
* @return boolean * @return boolean
*/ */
private function update(Doctrine_Record $record) { private function update(Doctrine_Record $record) {
$array = $record->getModified(); $array = $record->getPrepared();
if(empty($array)) if(empty($array))
return false; return false;
......
...@@ -31,7 +31,7 @@ class Doctrine_Validator { ...@@ -31,7 +31,7 @@ class Doctrine_Validator {
/** /**
* constant for blank validation error * constant for blank validation error
*/ */
const ERR_BLANK = 4; const ERR_NOTBLANK = 4;
/** /**
* constant for date validation error * constant for date validation error
*/ */
...@@ -39,7 +39,7 @@ class Doctrine_Validator { ...@@ -39,7 +39,7 @@ class Doctrine_Validator {
/** /**
* constant for null validation error * constant for null validation error
*/ */
const ERR_NULL = 6; const ERR_NOTNULL = 6;
/** /**
* constant for enum validation error * constant for enum validation error
*/ */
...@@ -60,6 +60,20 @@ class Doctrine_Validator { ...@@ -60,6 +60,20 @@ class Doctrine_Validator {
* @var array $validators an array of validator objects * @var array $validators an array of validator objects
*/ */
private static $validators = array(); 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 * returns a validator object
* *
...@@ -86,21 +100,32 @@ class Doctrine_Validator { ...@@ -86,21 +100,32 @@ class Doctrine_Validator {
* @return void * @return void
*/ */
public function validateRecord(Doctrine_Record $record) { public function validateRecord(Doctrine_Record $record) {
$modified = $record->getModified();
$columns = $record->getTable()->getColumns(); $columns = $record->getTable()->getColumns();
$name = $record->getTable()->getComponentName(); $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(); $err = array();
foreach($modified as $key => $value) {
foreach($data as $key => $value) {
if($value === self::$null)
$value = null;
$column = $columns[$key]; $column = $columns[$key];
if(strlen($value) > $column[1]) { if($column[0] == 'array' || $column[0] == 'object') {
$err[$key] = Doctrine_Validator::ERR_LENGTH; $value = serialize($value);
continue;
} }
if(self::gettype($value) !== $column[0]) { if(strlen($value) > $column[1]) {
$err[$key] = Doctrine_Validator::ERR_TYPE; $err[$key] = Doctrine_Validator::ERR_LENGTH;
continue; continue;
} }
...@@ -116,31 +141,25 @@ class Doctrine_Validator { ...@@ -116,31 +141,25 @@ class Doctrine_Validator {
$validator = self::getValidator($args[0]); $validator = self::getValidator($args[0]);
if( ! $validator->validate($record, $key, $value, $args[1])) { if( ! $validator->validate($record, $key, $value, $args[1])) {
switch(strtolower($args[0])):
case "unique": $constant = 'Doctrine_Validator::ERR_'.strtoupper($args[0]);
$err[$key] = Doctrine_Validator::ERR_UNIQUE;
break; if(defined($constant))
case "notnull": $err[$key] = constant($constant);
$err[$key] = Doctrine_Validator::ERR_NULL; else
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; $err[$key] = Doctrine_Validator::ERR_VALID;
break;
endswitch;
}
// errors found quit validation looping for this column // errors found quit validation looping for this column
if(isset($err[$key]))
break; break;
} }
} }
if(self::gettype($value) !== $column[0] && self::gettype($value) != 'NULL') {
$err[$key] = Doctrine_Validator::ERR_TYPE;
continue;
}
}
if( ! empty($err)) { if( ! empty($err)) {
$this->stack[$name][] = $err; $this->stack[$name][] = $err;
return false; return false;
......
<?php <?php
class Doctrine_ValidatorTestCase extends Doctrine_UnitTestCase { class Doctrine_ValidatorTestCase extends Doctrine_UnitTestCase {
public function prepareTables() {
$this->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() { public function testValidate() {
$user = $this->session->getTable("User")->find(4); $user = $this->session->getTable("User")->find(4);
...@@ -71,6 +93,5 @@ class Doctrine_ValidatorTestCase extends Doctrine_UnitTestCase { ...@@ -71,6 +93,5 @@ class Doctrine_ValidatorTestCase extends Doctrine_UnitTestCase {
$this->assertEqual($a["User"][0]["name"], Doctrine_Validator::ERR_LENGTH); $this->assertEqual($a["User"][0]["name"], Doctrine_Validator::ERR_LENGTH);
$this->manager->setAttribute(Doctrine::ATTR_VLD, false); $this->manager->setAttribute(Doctrine::ATTR_VLD, false);
} }
} }
?> ?>
...@@ -313,4 +313,13 @@ class Log_Status extends Doctrine_Record { ...@@ -313,4 +313,13 @@ class Log_Status extends Doctrine_Record {
$this->hasColumn("name", "string", 255); $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);
}
}
?> ?>
...@@ -15,7 +15,6 @@ require_once("CollectionTestCase.php"); ...@@ -15,7 +15,6 @@ require_once("CollectionTestCase.php");
require_once("CacheSqliteTestCase.php"); require_once("CacheSqliteTestCase.php");
require_once("CollectionOffsetTestCase.php"); require_once("CollectionOffsetTestCase.php");
require_once("SenseiTestCase.php");
require_once("QueryTestCase.php"); require_once("QueryTestCase.php");
error_reporting(E_ALL); error_reporting(E_ALL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment