diff --git a/lib/Doctrine/Compiler.php b/lib/Doctrine/Compiler.php index 16ad716bb..14ee1c144 100644 --- a/lib/Doctrine/Compiler.php +++ b/lib/Doctrine/Compiler.php @@ -34,20 +34,38 @@ class Doctrine_Compiler { private static $classes = array( "Doctrine", "Configurable", + "Overloadable", + "Access", + "Manager", - "Session", "Table", + "Table_Exception", "Iterator", "Exception", - "Access", + "Null", "Identifier", "Repository", "Record", + "Record_Exception", "Record_Iterator", "Collection", "Collection_Immediate", "Validator", + "Validator_Exception", + "Validator_Notnull", + "Validator_Nospace", + "Validator_Range", + "Validator_Regexp", + "Validator_Country", + "Validator_Notblank", + "Validator_Creditcard", + "Validator_Date", + "Validator_Ip", + "Validator_Unique", + "Validator_Usstate", + "Validator_Htmlcolor", + "Validator_Email", "Hydrate", "Query", "Query_Part", @@ -57,17 +75,21 @@ class Doctrine_Compiler { "Query_Condition", "Query_Where", "Query_Having", + "Query_Exception", "RawSql", + "RawSql_Exception", "EventListener_Interface", "EventListener", "EventListener_Empty", + "EventListener_Chain", "Relation", - "ForeignKey", - "LocalKey", - "Association", + "Relation_ForeignKey", + "Relation_LocalKey", + "Relation_Association", "DB", "DBStatement", "Connection", + "Connection_Exception", "Connection_UnitOfWork", "Connection_Transaction"); diff --git a/lib/Doctrine/Export.php b/lib/Doctrine/Export.php index b32bc78da..c4de44852 100644 --- a/lib/Doctrine/Export.php +++ b/lib/Doctrine/Export.php @@ -27,5 +27,19 @@ * @license LGPL */ class Doctrine_Export { - public function export() { } + public function export() { + $parent = new ReflectionClass('Doctrine_Record'); + $conn = Doctrine_Manager::getInstance()->getCurrentConnection(); + $old = $conn->getAttribute(Doctrine::ATTR_CREATE_TABLES); + + $conn->setAttribute(Doctrine::ATTR_CREATE_TABLES, true); + + foreach(get_declared_classes() as $name) { + $class = new ReflectionClass($name); + + if($class->isSubclassOf($parent) && ! $class->isAbstract()) + $obj = new $class(); + } + $conn->setAttribute(Doctrine::ATTR_CREATE_TABLES, $old); + } } diff --git a/lib/Doctrine/Export/Exception.php b/lib/Doctrine/Export/Exception.php new file mode 100644 index 000000000..5849eac78 --- /dev/null +++ b/lib/Doctrine/Export/Exception.php @@ -0,0 +1,29 @@ +. + */ +Doctrine::autoload('Doctrine_Exception'); +/** + * Doctrine_Export_Exception + * + * @package Doctrine ORM + * @url www.phpdoctrine.com + * @license LGPL + */ +class Doctrine_Export_Exception extends Doctrine_Exception { } diff --git a/lib/Doctrine/Hydrate.php b/lib/Doctrine/Hydrate.php index 385eea636..ea485f899 100644 --- a/lib/Doctrine/Hydrate.php +++ b/lib/Doctrine/Hydrate.php @@ -382,18 +382,15 @@ abstract class Doctrine_Hydrate extends Doctrine_Access { } else { $pointer = $this->joins[$name]; + $path = array_search($name, $this->tableAliases); $tmp = explode(".", $path); $alias = end($tmp); unset($tmp); $fk = $this->tables[$pointer]->getRelation($alias); + $last = $prev[$pointer]->getLast(); if($fk->isOneToOne()) { - - // one-to-one relation - if($fk instanceof Doctrine_Relation_LocalKey) - $last->set($fk->getLocal(), $record->getIncremented(), false); - $last->set($fk->getAlias(), $record); $prev[$name] = $record; @@ -404,9 +401,8 @@ abstract class Doctrine_Hydrate extends Doctrine_Access { $prev[$name] = $this->getCollection($name); $last->initReference($prev[$name], $fk); - //$last->set($fk->getAlias(), $this->getCollection($name)); } else { - // previous entry found from identityMap + // previous entry found from memory $prev[$name] = $last->get($alias); } @@ -422,6 +418,8 @@ abstract class Doctrine_Hydrate extends Doctrine_Access { return $coll; endswitch; } + + /** * hydrateHolders * diff --git a/lib/Doctrine/Manager.php b/lib/Doctrine/Manager.php index 7d54a3939..19329d741 100644 --- a/lib/Doctrine/Manager.php +++ b/lib/Doctrine/Manager.php @@ -131,24 +131,6 @@ class Doctrine_Manager extends Doctrine_Configurable implements Countable, Itera public static function connection(PDO $dbh) { return Doctrine_Manager::getInstance()->openConnection($dbh); } - /** - * install - * - * @return void - */ - final public function install() { - $parent = new ReflectionClass('Doctrine_Record'); - $old = $this->getAttribute(Doctrine::ATTR_CREATE_TABLES); - - $this->attributes[Doctrine::ATTR_CREATE_TABLES] = true; - foreach(get_declared_classes() as $name) { - $class = new ReflectionClass($name); - - if($class->isSubclassOf($parent)) - $obj = new $class(); - } - $this->attributes[Doctrine::ATTR_CREATE_TABLES] = $old; - } /** * openConnection * opens a new connection and saves it to Doctrine_Manager->connections diff --git a/lib/Doctrine/RawSql.php b/lib/Doctrine/RawSql.php index c59b4685b..481f3a4d8 100644 --- a/lib/Doctrine/RawSql.php +++ b/lib/Doctrine/RawSql.php @@ -18,7 +18,7 @@ * and is licensed under the LGPL. For more information, see * . */ - +Doctrine::autoload('Doctrine_Hydrate'); /** * Doctrine_RawSql * @@ -41,7 +41,7 @@ class Doctrine_RawSql extends Doctrine_Hydrate { */ public function __call($name, $args) { if( ! isset($this->parts[$name])) - throw new Doctrine_Exception("Unknown overload method"); + throw new Doctrine_RawSql_Exception("Unknown overload method $name. Availible overload methods are ".implode(" ",array_keys($this->parts))); if($name == 'select') { preg_match_all('/{([^}{]*)}/U', $args[0], $m); @@ -57,8 +57,8 @@ class Doctrine_RawSql extends Doctrine_Hydrate { * get */ public function get($name) { - if( ! isset($this->parts[$name])) - throw new Doctrine_Exception('Unknown query part '.$name); + if( ! isset($this->parts[$name])) + throw new Doctrine_RawSql_Exception('Unknown query part '.$name); return $this->parts[$name]; } @@ -126,13 +126,13 @@ class Doctrine_RawSql extends Doctrine_Hydrate { foreach($this->fields as $field) { $e = explode(".", $field); if( ! isset($e[1])) - throw new Doctrine_Exception("All selected fields in Sql query must be in format tableAlias.fieldName"); + throw new Doctrine_RawSql_Exception("All selected fields in Sql query must be in format tableAlias.fieldName"); if( ! isset($this->tables[$e[0]])) { try { $this->addComponent($e[0], ucwords($e[0])); } catch(Doctrine_Exception $exception) { - throw new Doctrine_Exception("The associated component for table alias $e[0] couldn't be found."); + throw new Doctrine_RawSql_Exception("The associated component for table alias $e[0] couldn't be found."); } } diff --git a/lib/Doctrine/RawSql/Exception.php b/lib/Doctrine/RawSql/Exception.php new file mode 100644 index 000000000..7e386d082 --- /dev/null +++ b/lib/Doctrine/RawSql/Exception.php @@ -0,0 +1,29 @@ +. + */ +Doctrine::autoload('Doctrine_Exception'); +/** + * Doctrine_RawSql_Exception + * + * @package Doctrine ORM + * @url www.phpdoctrine.com + * @license LGPL + */ +class Doctrine_RawSql_Exception extends Doctrine_Exception { } diff --git a/lib/Doctrine/Record.php b/lib/Doctrine/Record.php index 9cdfaf639..a5759652d 100644 --- a/lib/Doctrine/Record.php +++ b/lib/Doctrine/Record.php @@ -744,33 +744,28 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite // one-to-many or one-to-one relation if($rel instanceof Doctrine_Relation_ForeignKey || $rel instanceof Doctrine_Relation_LocalKey) { - switch($rel->getType()) { - case Doctrine_Relation::MANY_COMPOSITE: - case Doctrine_Relation::MANY_AGGREGATE: - // one-to-many relation found - if( ! ($value instanceof Doctrine_Collection)) - throw new Doctrine_Record_Exception("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Collection when setting one-to-many references."); + if( ! $rel->isOneToOne()) { + // one-to-many relation found + if( ! ($value instanceof Doctrine_Collection)) + throw new Doctrine_Record_Exception("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Collection when setting one-to-many references."); - $value->setReference($this,$rel); - break; - case Doctrine_Relation::ONE_COMPOSITE: - case Doctrine_Relation::ONE_AGGREGATE: - // one-to-one relation found - if( ! ($value instanceof Doctrine_Record)) - throw new Doctrine_Record_Exception("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Record when setting one-to-one references."); + $value->setReference($this,$rel); + } else { + // one-to-one relation found + if( ! ($value instanceof Doctrine_Record)) + throw new Doctrine_Record_Exception("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Record when setting one-to-one references."); - if($rel->getLocal() == $this->table->getIdentifier()) { - $value->set($rel->getForeign(), $this, false); - } else { - $this->set($rel->getLocal(),$value); - } - break; + if($rel instanceof Doctrine_Relation_LocalKey) { + $this->set($rel->getLocal(), $value, false); + } else { + $value->set($rel->getForeign(), $this, false); + } } } elseif($rel instanceof Doctrine_Relation_Association) { // join table relation found if( ! ($value instanceof Doctrine_Collection)) - throw new Doctrine_Record_Exception("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Collection when setting one-to-many references."); + throw new Doctrine_Record_Exception("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Collection when setting many-to-many references."); } @@ -1177,6 +1172,10 @@ abstract class Doctrine_Record extends Doctrine_Access implements Countable, Ite } return false; } + + public function lazyInitRelated(Doctrine_Collection $coll, Doctrine_Relation $connector) { + + } /** * addReference * @param Doctrine_Record $record diff --git a/lib/Doctrine/Repository.php b/lib/Doctrine/Repository.php index 00719b063..9a087cea1 100644 --- a/lib/Doctrine/Repository.php +++ b/lib/Doctrine/Repository.php @@ -28,7 +28,7 @@ * @url www.phpdoctrine.com * @license LGPL */ -class Doctrine_Repository implements Countable, IteratorAggregate { +class Doctrine_Table_Repository implements Countable, IteratorAggregate { /** * @var object Doctrine_Table $table */ @@ -74,11 +74,11 @@ class Doctrine_Repository implements Countable, IteratorAggregate { /** * get * @param integer $oid - * @throws InvalidKeyException + * @throws Doctrine_Table_Repository_Exception */ public function get($oid) { if( ! isset($this->registry[$oid])) - throw new InvalidKeyException(); + throw new Doctrine_Table_Repository_Exception("Unknown object identifier"); return $this->registry[$oid]; } diff --git a/lib/Doctrine/Statement.php b/lib/Doctrine/Statement.php deleted file mode 100644 index 41c12745c..000000000 --- a/lib/Doctrine/Statement.php +++ /dev/null @@ -1,187 +0,0 @@ -query = $query; - $this->stmt = $stmt; - } - public function set($name, $value) { } - public function get($name) { } - /** - * getCollection - * returns Doctrine_Collection object - * - * @parma string $name component name - * @param integer $index - * @return Doctrine_Collection - */ - private function getCollection($name) { - $table = $this->connection->getTable($name); - switch($this->fetchModes[$name]): - case Doctrine::FETCH_BATCH: - $coll = new Doctrine_Collection_Batch($table); - break; - case Doctrine::FETCH_LAZY: - $coll = new Doctrine_Collection_Lazy($table); - break; - case Doctrine::FETCH_OFFSET: - $coll = new Doctrine_Collection_Offset($table); - break; - case Doctrine::FETCH_IMMEDIATE: - $coll = new Doctrine_Collection_Immediate($table); - break; - case Doctrine::FETCH_LAZY_OFFSET: - $coll = new Doctrine_Collection_LazyOffset($table); - break; - endswitch; - - $coll->populate($this); - return $coll; - } - /** - * execute - * executes the dql query, populates all collections - * and returns the root collection - * - * @param array $params - * @return Doctrine_Collection - */ - public function execute($params = array()) { - switch(count($this->tables)): - case 0: - throw new DQLException(); - break; - case 1: - $query = $this->getQuery(); - - $keys = array_keys($this->tables); - - $name = $this->tables[$keys[0]]->getComponentName(); - $stmt = $this->connection->execute($query,$params); - - while($data = $stmt->fetch(PDO::FETCH_ASSOC)): - foreach($data as $key => $value): - $e = explode("__",$key); - if(count($e) > 1) { - $data[$e[1]] = $value; - } else { - $data[$e[0]] = $value; - } - unset($data[$key]); - endforeach; - $this->data[$name][] = $data; - endwhile; - - return $this->getCollection($keys[0]); - break; - default: - $query = $this->getQuery(); - - $keys = array_keys($this->tables); - $root = $keys[0]; - $stmt = $this->connection->execute($query,$params); - - $previd = array(); - - $coll = $this->getCollection($root); - - $array = $this->parseData($stmt); - - foreach($array as $data): - - /** - * remove duplicated data rows and map data into objects - */ - foreach($data as $key => $row): - if(empty($row)) - continue; - - $key = ucwords($key); - $name = $this->tables[$key]->getComponentName(); - - if( ! isset($previd[$name])) - $previd[$name] = array(); - - - if($previd[$name] !== $row) { - $this->tables[$name]->setData($row); - $record = $this->tables[$name]->getRecord(); - - if($name == $root) { - $this->tables[$name]->setData($row); - $record = $this->tables[$name]->getRecord(); - $coll->add($record); - } else { - $last = $coll->getLast(); - - if( ! $last->hasReference($name)) { - $last->initReference($this->getCollection($name),$this->connectors[$name]); - } - $last->addReference($record); - } - } - - $previd[$name] = $row; - endforeach; - endforeach; - - return $coll; - endswitch; - } - /** - * parseData - * parses the data returned by PDOStatement - * - * @param PDOStatement $stmt - * @return array - */ - public function parseData(PDOStatement $stmt) { - $array = array(); - while($data = $stmt->fetch(PDO::FETCH_ASSOC)): - /** - * parse the data into two-dimensional array - */ - foreach($data as $key => $value): - $e = explode("__",$key); - - if(count($e) > 1) { - $data[$e[0]][$e[1]] = $value; - } else { - $data[0][$e[0]] = $value; - } - unset($data[$key]); - endforeach; - $array[] = $data; - endwhile; - $stmt->closeCursor(); - return $array; - } -} - diff --git a/lib/Doctrine/Table.php b/lib/Doctrine/Table.php index 93be6fb34..9fe3087c0 100644 --- a/lib/Doctrine/Table.php +++ b/lib/Doctrine/Table.php @@ -83,7 +83,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable { */ private $identityMap = array(); /** - * @var Doctrine_Repository $repository record repository + * @var Doctrine_Table_Repository $repository record repository */ private $repository; @@ -250,10 +250,12 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable { if( ! $this->connection->addTable($this)) throw new Doctrine_Table_Exception(); - $this->repository = new Doctrine_Repository($this); + $this->repository = new Doctrine_Table_Repository($this); } /** - * @return Doctrine_Repository + * getRepository + * + * @return Doctrine_Table_Repository */ public function getRepository() { return $this->repository; diff --git a/lib/Doctrine/Table/Repository.php b/lib/Doctrine/Table/Repository.php new file mode 100644 index 000000000..9a087cea1 --- /dev/null +++ b/lib/Doctrine/Table/Repository.php @@ -0,0 +1,137 @@ +. + */ +/** + * Doctrine_Repository + * each record is added into Doctrine_Repository at the same time they are created, + * loaded from the database or retrieved from the cache + * + * @author Konsta Vesterinen + * @package Doctrine ORM + * @url www.phpdoctrine.com + * @license LGPL + */ +class Doctrine_Table_Repository implements Countable, IteratorAggregate { + /** + * @var object Doctrine_Table $table + */ + private $table; + /** + * @var array $registry + * an array of all records + * keys representing record object identifiers + */ + private $registry = array(); + /** + * constructor + * + * @param Doctrine_Table $table + */ + public function __construct(Doctrine_Table $table) { + $this->table = $table; + } + /** + * getTable + * + * @return object Doctrine_Table + */ + public function getTable() { + return $this->table; + } + /** + * add + * + * @param Doctrine_Record $record record to be added into registry + * @return boolean + */ + public function add(Doctrine_Record $record) { + $oid = $record->getOID(); + + if(isset($this->registry[$oid])) + return false; + + $this->registry[$oid] = $record; + + return true; + } + /** + * get + * @param integer $oid + * @throws Doctrine_Table_Repository_Exception + */ + public function get($oid) { + if( ! isset($this->registry[$oid])) + throw new Doctrine_Table_Repository_Exception("Unknown object identifier"); + + return $this->registry[$oid]; + } + /** + * count + * Doctrine_Registry implements interface Countable + * @return integer the number of records this registry has + */ + public function count() { + return count($this->registry); + } + /** + * @param integer $oid object identifier + * @return boolean whether ot not the operation was successful + */ + public function evict($oid) { + if( ! isset($this->registry[$oid])) + return false; + + unset($this->registry[$oid]); + return true; + } + /** + * @return integer number of records evicted + */ + public function evictAll() { + $evicted = 0; + foreach($this->registry as $oid=>$record) { + if($this->evict($oid)) + $evicted++; + } + return $evicted; + } + /** + * getIterator + * @return ArrayIterator + */ + public function getIterator() { + return new ArrayIterator($this->registry); + } + /** + * contains + * @param integer $oid object identifier + */ + public function contains($oid) { + return isset($this->registry[$oid]); + } + /** + * loadAll + * @return void + */ + public function loadAll() { + $this->table->findAll(); + } +} + diff --git a/lib/Doctrine/Table/Repository/Exception.php b/lib/Doctrine/Table/Repository/Exception.php new file mode 100644 index 000000000..ab305da0c --- /dev/null +++ b/lib/Doctrine/Table/Repository/Exception.php @@ -0,0 +1,29 @@ +. + */ +Doctrine::autoload('Doctrine_Exception'); +/** + * Doctrine_Table_Repository_Exception + * + * @package Doctrine ORM + * @url www.phpdoctrine.com + * @license LGPL + */ +class Doctrine_Table_Repository_Exception extends Doctrine_Exception { }