From cb79b1d995d0a7b0dead4b7f8ed3df4c5d84d6da Mon Sep 17 00:00:00 2001 From: doctrine Date: Sun, 16 Apr 2006 20:38:17 +0000 Subject: [PATCH] --- classes/Collection.class.php | 50 +++++++++++++++++----- classes/Collection/Batch.class.php | 10 +++++ classes/Collection/Immediate.class.php | 10 +++-- classes/Configurable.class.php | 15 +++++-- classes/DQL/Parser.class.php | 24 +++++++---- classes/Doctrine.class.php | 6 ++- classes/IndexGenerator.php | 26 ++++++++++++ classes/Record.class.php | 2 +- classes/Sensei/Sensei.class.php | 12 +++--- classes/Table.class.php | 11 ++++- tests/CollectionTestCase.class.php | 57 +++++++++++++++++++++++++- tests/ConfigurableTestCase.class.php | 23 +++++++++++ tests/SenseiTestCase.class.php | 3 +- tests/classes.php | 2 +- tests/run.php | 10 +++-- 15 files changed, 219 insertions(+), 42 deletions(-) create mode 100644 classes/IndexGenerator.php diff --git a/classes/Collection.class.php b/classes/Collection.class.php index 8167bc229..9e7bbc9aa 100644 --- a/classes/Collection.class.php +++ b/classes/Collection.class.php @@ -33,12 +33,21 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator * @var boolean $expanded whether or not this collection has been expanded */ protected $expanded = false; + /** + * @var mixed $generator + */ + protected $generator; /** * constructor */ public function __construct(Doctrine_Table $table) { $this->table = $table; + + $name = $table->getAttribute(Doctrine::ATTR_COLL_KEY); + if($name !== null) { + $this->generator = new Doctrine_IndexGenerator($name); + } } /** * @return object Doctrine_Table @@ -46,6 +55,25 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator public function getTable() { return $this->table; } + /** + * @param Doctrine_IndexGenerator $generator + * @return void + */ + public function setGenerator($generator) { + $this->generator = $generator; + } + /** + * @return Doctrine_IndexGenerator + */ + public function getGenerator() { + return $this->generator; + } + /** + * @return array + */ + public function getData() { + return $this->data; + } /** * @param array $data */ @@ -214,7 +242,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator /** * count * this class implements interface countable - * @return integer number of data access objects in this collection + * @return integer number of records in this collection */ public function count() { return count($this->data); @@ -231,11 +259,11 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator $this->data[$key] = $record; } + /** - * add - * adds a dao instance to this collection - * @param Doctrine_Record $record data access object to be added - * @param string $key optional key for the DAO + * adds a record to collection + * @param Doctrine_Record $record record to be added + * @param string $key optional key for the record * @return boolean */ public function add(Doctrine_Record $record,$key = null) { @@ -243,27 +271,29 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator $record->rawSet($this->reference_field,$this->reference); if(isset($key)) { - if(isset($this->data[$key])) return false; $this->data[$key] = $record; } - $this->data[] = $record; + if(isset($this->generator)) { + $key = $this->generator->getIndex($record); + $this->data[$key] = $record; + } else + $this->data[] = $record; return true; - } /** * save - * saves all data access objects + * saves all records */ public function save() { $this->table->getSession()->saveCollection($this); } /** * single shot delete - * deletes all dao instances from this collection + * deletes all records from this collection * uses only one database query to perform this operation * @return boolean */ diff --git a/classes/Collection/Batch.class.php b/classes/Collection/Batch.class.php index 07250a11d..6c3424df3 100644 --- a/classes/Collection/Batch.class.php +++ b/classes/Collection/Batch.class.php @@ -23,10 +23,19 @@ class Doctrine_Collection_Batch extends Doctrine_Collection { public function __construct(Doctrine_DQL_Parser $graph,$key) { parent::__construct($graph->getTable($key)); + $this->data = $graph->getData($key); if( ! is_array($this->data)) $this->data = array(); + if(isset($this->generator)) { + foreach($this->data as $k => $v) { + $record = $this->get($k); + $i = $this->generator->getIndex($record); + $this->data[$i] = $record; + unset($this->data[$k]); + } + } $this->batchSize = $this->getTable()->getAttribute(Doctrine::ATTR_BATCH_SIZE); } @@ -138,6 +147,7 @@ class Doctrine_Collection_Batch extends Doctrine_Collection { if( ! isset($this->data[$key])) $this->data[$key] = $this->table->create(); + } diff --git a/classes/Collection/Immediate.class.php b/classes/Collection/Immediate.class.php index cea26206a..2858e7d33 100644 --- a/classes/Collection/Immediate.class.php +++ b/classes/Collection/Immediate.class.php @@ -13,16 +13,18 @@ class Doctrine_Collection_Immediate extends Doctrine_Collection { * @param integer $key */ public function __construct(Doctrine_DQL_Parser $graph,$key) { - parent::__construct($graph->getTable($key)); - - $name = $this->table->getComponentName(); + $table = $graph->getTable($key); + parent::__construct($table); + + $name = $table->getComponentName(); $data = $graph->getData($name); if(is_array($data)) { foreach($data as $k=>$v): - $this->table->setData($v); + $table->setData($v); $this->add($this->table->getRecord()); endforeach; } + } } ?> diff --git a/classes/Configurable.class.php b/classes/Configurable.class.php index c61623bec..77bad322e 100644 --- a/classes/Configurable.class.php +++ b/classes/Configurable.class.php @@ -86,16 +86,25 @@ abstract class Doctrine_Configurable { break; case Doctrine::ATTR_CREATE_TABLES: $value = (bool) $value; + break; + case Doctrine::ATTR_COLL_KEY: + if( ! ($this instanceof Doctrine_Table)) + throw new Doctrine_Exception("This attribute can only be set at table level."); + + if( ! $this->hasColumn($value)) + throw new Doctrine_Exception("Couldn't set collection key attribute. No such column '$value'"); + + break; case Doctrine::ATTR_VLD: break; case Doctrine::ATTR_CACHE: if($value != Doctrine::CACHE_SQLITE && $value != Doctrine::CACHE_NONE) - throw new Doctrine_Exception("Unknown cache container. See Doctrine::CACHE_* constants for availible containers."); + throw new Doctrine_Exception("Unknown cache container. See Doctrine::CACHE_* constants for availible containers."); break; default: - throw new Exception("Unknown attribute."); + throw new Doctrine_Exception("Unknown attribute."); endswitch; $this->attributes[$attribute] = $value; @@ -115,7 +124,7 @@ abstract class Doctrine_Configurable { final public function getAttribute($attribute) { $attribute = (int) $attribute; - if($attribute < 1 || $attribute > 14) + if($attribute < 1 || $attribute > 15) throw new InvalidKeyException(); if( ! isset($this->attributes[$attribute])) { diff --git a/classes/DQL/Parser.class.php b/classes/DQL/Parser.class.php index 3077de70f..8df9c98e6 100644 --- a/classes/DQL/Parser.class.php +++ b/classes/DQL/Parser.class.php @@ -128,6 +128,18 @@ class Doctrine_DQL_Parser { } } } + /** + * @param integer $limit + */ + final public function setLimit($limit) { + $this->limit = $limit; + } + /** + * @param integer $offset + */ + final public function setOffset($offset) { + $this->offset = $offset; + } /** * @return integer */ @@ -422,7 +434,7 @@ class Doctrine_DQL_Parser { if($this->aggregate) { $keys = array_keys($this->tnames); $query = $this->getQuery(); - $stmt = $this->tnames[$keys[0]]->getSession()->select($query); + $stmt = $this->tnames[$keys[0]]->getSession()->select($query,$this->limit,$this->offset); $data = $stmt->fetch(PDO::FETCH_ASSOC); if(count($data) == 1) { return current($data); @@ -454,7 +466,7 @@ class Doctrine_DQL_Parser { case "order": $p = $part; $i = $k+1; - if(isset($e[$i]) AND strtolower($e[$i]) == "by") { + if(isset($e[$i]) && strtolower($e[$i]) == "by") { $parts[$part] = array(); } break; @@ -633,7 +645,7 @@ class Doctrine_DQL_Parser { * @param string $e2 the second bracket, usually ')' */ public static function bracketTrim($str,$e1,$e2) { - if(substr($str,0,1) == $e1 AND substr($str,-1) == $e2) + if(substr($str,0,1) == $e1 && substr($str,-1) == $e2) return substr($str,1,-1); else return $str; @@ -781,10 +793,8 @@ class Doctrine_DQL_Parser { $this->tnames[$name] = $objTable; } - } catch(Doctrine_Exception $e) { - throw new DQLException(); - } catch(InvalidKeyException $e) { - throw new DQLException(); + } catch(Exception $e) { + throw new DQLException($e->getMessage(),$e->getCode()); } } return $objTable; diff --git a/classes/Doctrine.class.php b/classes/Doctrine.class.php index f20a2bdce..4fd7dbfac 100644 --- a/classes/Doctrine.class.php +++ b/classes/Doctrine.class.php @@ -116,6 +116,10 @@ final class Doctrine { * create tables attribute */ const ATTR_CREATE_TABLES = 14; + /** + * collection key attribute + */ + const ATTR_COLL_KEY = 15; @@ -189,7 +193,7 @@ final class Doctrine { public static function getPath() { if(! self::$path) self::$path = dirname(__FILE__); - + return self::$path; } /** diff --git a/classes/IndexGenerator.php b/classes/IndexGenerator.php new file mode 100644 index 000000000..033d5bdc5 --- /dev/null +++ b/classes/IndexGenerator.php @@ -0,0 +1,26 @@ +name = $name; + } + /** + * @param Doctrine_Record $record + * @return mixed + */ + public function getIndex(Doctrine_Record $record) { + $value = $record->get($this->name); + if($value === null) + throw new Doctrine_Exception("Couldn't create collection index. Record field '".$this->name."' was null."); + + return $value; + } +} +?> + diff --git a/classes/Record.class.php b/classes/Record.class.php index c570e89ff..e944dd64e 100644 --- a/classes/Record.class.php +++ b/classes/Record.class.php @@ -957,7 +957,7 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite * @return void */ final public function hasColumn($name, $type, $length = 20, $options = "") { - $this->table->hasColumn($name, $type, $length, $options); + $this->table->setColumn($name, $type, $length, $options); } /** * returns a string representation of this object diff --git a/classes/Sensei/Sensei.class.php b/classes/Sensei/Sensei.class.php index 793eaa833..fbc514e37 100644 --- a/classes/Sensei/Sensei.class.php +++ b/classes/Sensei/Sensei.class.php @@ -12,15 +12,15 @@ class Sensei_Entity extends Doctrine_Record { } } class Sensei_Variable extends Doctrine_Record { + public function setUp() { + //$this->setAttribute(Doctrine::ATTR_COLL_KEY, "name"); + } public function setTableDefinition() { - $this->hasColumn("name","string",50); + $this->hasColumn("name","string",50,"unique"); $this->hasColumn("value","string",10000); $this->hasColumn("session_id","integer"); } } - -class Sensei_Entity_Var extends Sensei_Variable { } -class Sensei_Session_Var extends Doctrine_Record { } class Sensei_Session extends Doctrine_Record { public function setUp() { $this->ownsMany("Sensei_variable","Sensei_variable.session_id"); @@ -159,17 +159,17 @@ class Sensei extends Doctrine_Access { return true; } private function read($id) { - $coll = $this->session->query("FROM Sensei_Session WHERE Sensei_Session.session_id = ?",array($id)); + $coll = $this->session->query("FROM Sensei_Session, Sensei_Session.Sensei_Variable WHERE Sensei_Session.session_id = ?",array($id)); $this->record = $coll[0]; $this->record->user_agent = $_SERVER['HTTP_USER_AGENT']; $this->record->updated = time(); $this->record->session_id = $id; + $this->vars = $this->record->Sensei_variable; if($this->record->getState() == Doctrine_Record::STATE_TDIRTY) { $this->record->created = time(); $this->record->save(); } - $this->vars = $this->record->Sensei_variable; return ""; } public function write($id,$sess_data) { diff --git a/classes/Table.class.php b/classes/Table.class.php index a5151c668..a82741c97 100644 --- a/classes/Table.class.php +++ b/classes/Table.class.php @@ -201,14 +201,14 @@ class Doctrine_Table extends Doctrine_Configurable { endswitch; } /** - * hasColumn + * setColumn * @param string $name * @param string $type * @param integer $length * @param mixed $options * @return void */ - final public function hasColumn($name, $type, $length, $options = "") { + final public function setColumn($name, $type, $length, $options = "") { $this->columns[$name] = array($type,$length,$options); $e = explode("|",$options); @@ -216,6 +216,13 @@ class Doctrine_Table extends Doctrine_Configurable { $this->primaryKeys[] = $name; } } + /** + * hasColumn + * @return boolean + */ + final public function hasColumn($name) { + return isset($this->columns[$name]); + } /** * returns all primary keys * @return array diff --git a/tests/CollectionTestCase.class.php b/tests/CollectionTestCase.class.php index 05ffb8c65..f0cb3c7c5 100644 --- a/tests/CollectionTestCase.class.php +++ b/tests/CollectionTestCase.class.php @@ -1,7 +1,60 @@ objTable); + $coll->add(new User()); + $this->assertEqual($coll->count(),1); + $coll->add(new User()); + $this->assertTrue($coll->count(),2); + + $this->assertEqual($coll->getKeys(), array(0,1)); + + $coll[2] = new User(); + + $this->assertTrue($coll->count(),3); + $this->assertEqual($coll->getKeys(), array(0,1,2)); + } + public function testExpand() { + $users = $this->session->query("FROM User, User.Phonenumber-l WHERE User.Phonenumber.phonenumber LIKE '%123%'"); + + $this->assertTrue($users instanceof Doctrine_Collection); + $this->assertTrue($users[1] instanceof User); + + $data = $users[1]->Phonenumber->getData(); + + $coll = $users[1]->Phonenumber; + + $this->assertEqual(count($data), 1); + + $coll[1]; + + $this->assertEqual(count($coll), 3); + + $this->assertTrue($coll[2]->getState() == Doctrine_Record::STATE_PROXY); + + $generator = new Doctrine_IndexGenerator("id"); + $coll->setGenerator($generator); + $generator = $coll->getGenerator(); + $this->assertEqual($generator->getIndex($this->old), 4); + } + public function testGenerator() { + $generator = new Doctrine_IndexGenerator("name"); + $coll = new Doctrine_Collection($this->objTable); + $coll->setGenerator($generator); + + $user = new User(); + $user->name = "name"; + $coll->add($user); + + $this->assertEqual($coll["name"], $user); + + + $this->session->getTable("email")->setAttribute(Doctrine::ATTR_COLL_KEY,"address"); + $emails = $this->session->getTable("email")->findAll(); + foreach($emails as $k => $v) { + $this->assertTrue(gettype($k), "string"); + } + + } } ?> diff --git a/tests/ConfigurableTestCase.class.php b/tests/ConfigurableTestCase.class.php index 985d2653c..c42370862 100644 --- a/tests/ConfigurableTestCase.class.php +++ b/tests/ConfigurableTestCase.class.php @@ -54,6 +54,29 @@ class Doctrine_ConfigurableTestCase extends Doctrine_UnitTestCase { $this->assertTrue($e instanceof Exception); $this->session->commit(); } + + $e = false; + try { + $this->manager->setAttribute(Doctrine::ATTR_COLL_KEY, "name"); + } catch(Exception $e) { + } + $this->assertTrue($e instanceof Exception); + + $e = false; + try { + $this->objTable->setAttribute(Doctrine::ATTR_COLL_KEY, "unknown"); + } catch(Exception $e) { + } + $this->assertTrue($e instanceof Exception); + + $e = true; + try { + $this->objTable->setAttribute(Doctrine::ATTR_COLL_KEY, "name"); + } catch(Exception $e) { + } + $this->assertTrue($e); + + $e = false; try { $this->session->beginTransaction(); $this->session->setAttribute(Doctrine::ATTR_LOCKMODE, Doctrine::LOCK_PESSIMISTIC); diff --git a/tests/SenseiTestCase.class.php b/tests/SenseiTestCase.class.php index bc9246ba6..49d8f7ef4 100644 --- a/tests/SenseiTestCase.class.php +++ b/tests/SenseiTestCase.class.php @@ -52,8 +52,7 @@ class Sensei_UnitTestCase extends UnitTestCase { $this->init(); } - public function testConstructor() { - + public function testConstructor() { $this->assertTrue($this->record instanceof Sensei_Session); if(isset($_COOKIE["PHPSESSID"])) { diff --git a/tests/classes.php b/tests/classes.php index 9aba371f9..15fedca5a 100644 --- a/tests/classes.php +++ b/tests/classes.php @@ -7,7 +7,7 @@ class Entity extends Doctrine_Record { } public function setTableDefinition() { $this->hasColumn("name","string",50); - $this->hasColumn("loginname","string",20); + $this->hasColumn("loginname","string",20,"unique"); $this->hasColumn("password","string",16); $this->hasColumn("type","integer",1); $this->hasColumn("created","integer",11); diff --git a/tests/run.php b/tests/run.php index b4008dfae..4bfb13307 100644 --- a/tests/run.php +++ b/tests/run.php @@ -11,6 +11,7 @@ require_once("RecordTestCase.class.php"); require_once("DQLParserTestCase.class.php"); require_once("AccessTestCase.class.php"); require_once("ValidatorTestCase.class.php"); +require_once("CollectionTestCase.class.php"); require_once("CacheSqliteTestCase.class.php"); require_once("SenseiTestCase.class.php"); @@ -24,7 +25,7 @@ $test = new GroupTest("Doctrine Framework Unit Tests"); -/** + $test->addTestCase(new Doctrine_RecordTestCase()); $test->addTestCase(new Doctrine_SessionTestCase()); @@ -34,16 +35,19 @@ $test->addTestCase(new Doctrine_ManagerTestCase()); $test->addTestCase(new Doctrine_TableTestCase()); $test->addTestCase(new Doctrine_AccessTestCase()); -$test->addTestCase(new Doctrine_ConfigurableTestCase()); + $test->addTestCase(new Doctrine_EventListenerTestCase()); $test->addTestCase(new Doctrine_DQL_ParserTestCase()); $test->addTestCase(new Doctrine_BatchIteratorTestCase()); -*/ + +$test->addTestCase(new Doctrine_CollectionTestCase()); +$test->addTestCase(new Doctrine_ConfigurableTestCase()); $test->addTestCase(new Sensei_UnitTestCase()); + //$test->addTestCase(new Doctrine_Cache_FileTestCase()); //$test->addTestCase(new Doctrine_Cache_SqliteTestCase());