From 542f9b0d727d86447994450a2e85ced42cd01f94 Mon Sep 17 00:00:00 2001 From: "Jonathan.Wage" Date: Tue, 27 Nov 2007 18:23:13 +0000 Subject: [PATCH] Further model loading refactoring and refactored merge() in Doctrine_Record --- lib/Doctrine.php | 116 ++++++++++++++++----------- lib/Doctrine/Collection.php | 5 +- lib/Doctrine/Data.php | 2 +- lib/Doctrine/Export.php | 2 +- lib/Doctrine/Record.php | 156 +++++++++++++++--------------------- 5 files changed, 141 insertions(+), 140 deletions(-) diff --git a/lib/Doctrine.php b/lib/Doctrine.php index c6b7a30ae..75ba511ad 100644 --- a/lib/Doctrine.php +++ b/lib/Doctrine.php @@ -441,13 +441,13 @@ final class Doctrine private static $_debug = false; /** - * _loadedModels + * _loadedModelFiles * * Array of all the loaded models and the path to each one for autoloading * * @var array */ - private static $_loadedModels = array(); + private static $_loadedModelFiles = array(); /** * _validators @@ -517,13 +517,44 @@ final class Doctrine foreach ($it as $file) { $e = explode('.', $file->getFileName()); if (end($e) === 'php' && strpos($file->getFileName(), '.inc') === false) { - self::$_loadedModels[$e[0]] = $file->getPathName(); + self::$_loadedModelFiles[$e[0]] = $file->getPathName(); + } + } + } + + $loadedModels = array(); + + $modelFiles = array_keys(self::$_loadedModelFiles); + + foreach ($modelFiles as $name) { + if (class_exists($name)) { + $declaredBefore = get_declared_classes(); + + if (self::isValidModelClass($name) && !in_array($name, $loadedModels)) { + $loadedModels[] = $name; + } + } else { + // Determine class names by the actual inclusion of the model file + // The possibility exists that the class name(s) contained in the model + // file is not the same as the actual model file name itself + if (isset(self::$_loadedModelFiles[$name])) { + require_once self::$_loadedModelFiles[$name]; + $declaredAfter = get_declared_classes(); + // Using array_slice since array_diff is broken is some versions + $foundClasses = array_slice($declaredAfter, count($declaredBefore) - 1); + if ($foundClasses) { + foreach ($foundClasses as $name) { + if (self::isValidModelClass($name) && !in_array($name, $loadedModels)) { + $loadedModels[] = $name; + } + } + } } } } } - return self::getLoadedModels(array_keys(self::$_loadedModels)); + return self::filterInvalidModels($loadedModels); } /** @@ -541,57 +572,51 @@ final class Doctrine { if ($classes === null) { $classes = get_declared_classes(); - $classes = array_merge($classes, array_keys(self::$_loadedModels)); + $classes = array_merge($classes, array_keys(self::$_loadedModelFiles)); } - $loadedModels = array(); - - foreach ((array) $classes as $name) { - try { - $declaredBefore = get_declared_classes(); - $class = new ReflectionClass($name); - if (self::isValidModelClass($class)) { - $loadedModels[] = $name; - } - } catch (Exception $e) { - // Determine class names by the actual inclusion of the model file - // The possibility exists that the class name(s) contained in the model - // file is not the same as the actual model file name itself - if (isset(self::$_loadedModels[$name])) { - try { - require_once self::$_loadedModels[$name]; - $declaredAfter = get_declared_classes(); - // Using array_slice since array_diff is broken is some versions - $foundClasses = array_slice($declaredAfter, count($declaredBefore)-1); - if ($foundClasses) { - foreach ($foundClasses as $name) { - $class = new ReflectionClass($name); - if (self::isValidModelClass($class)) { - $loadedModels[] = $name; - } - } - } - } catch (Exception $e) { - continue; - } - } - } - - } - return $loadedModels; + return self::filterInvalidModels($classes); } + /** + * filterInvalidModels + * + * Filter through an array of classes and return all the classes that are valid models + * + * @param classes Array of classes to filter through, otherwise uses get_declared_classes() + * @return array $loadedModels + */ + public static function filterInvalidModels($classes) + { + $validModels = array(); + + foreach ((array) $classes as $name) { + if (self::isValidModelClass($name) && !in_array($name, $validModels)) { + $validModels[] = $name; + } + } + + return $validModels; + } /** * isValidModelClass * - * Checks whether a reflection class is a valid Doctrine model class + * Checks if what is passed is a valid Doctrine_Record * - * @param class A reflection class to validate - * @return boolean + * @param mixed $class Can be a string named after the class, an instance of the class, or an instance of the class reflected + * @return boolean */ public static function isValidModelClass($class) { + if ($class instanceof Doctrine_Record) { + $class = get_class($class); + } + + if (is_string($class) && class_exists($class)) { + $class = new ReflectionClass($class); + } + if ($class instanceof ReflectionClass) { // Skip the following classes // - abstract classes @@ -600,13 +625,14 @@ final class Doctrine if (!$class->isAbstract() && $class->isSubClassOf('Doctrine_Record') && $class->hasMethod('setTableDefinition')) { + return true; } } + return false; } - /** * getConnectionByTableName * @@ -1001,7 +1027,7 @@ final class Doctrine return true; } - $loadedModels = self::$_loadedModels; + $loadedModels = self::$_loadedModelFiles; if (isset($loadedModels[$className]) && file_exists($loadedModels[$className])) { require_once($loadedModels[$className]); diff --git a/lib/Doctrine/Collection.php b/lib/Doctrine/Collection.php index 805fa63ec..d550d0b5e 100644 --- a/lib/Doctrine/Collection.php +++ b/lib/Doctrine/Collection.php @@ -670,12 +670,11 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator * @param string $array * @return void */ - - public function fromArray($array) + public function fromArray($array, $deep = true) { $data = array(); foreach ($array as $rowKey => $row) { - $this[$rowKey]->fromArray($row); + $this[$rowKey]->fromArray($row, $deep); } } diff --git a/lib/Doctrine/Data.php b/lib/Doctrine/Data.php index 561432f2c..8fc07b65b 100644 --- a/lib/Doctrine/Data.php +++ b/lib/Doctrine/Data.php @@ -274,7 +274,7 @@ class Doctrine_Data */ public function purge($models = array()) { - $models = Doctrine::getLoadedModels($models); + $models = Doctrine::filterInvalidModels($models); foreach ($models as $model) { diff --git a/lib/Doctrine/Export.php b/lib/Doctrine/Export.php index 2907778ec..81904d100 100644 --- a/lib/Doctrine/Export.php +++ b/lib/Doctrine/Export.php @@ -1124,7 +1124,7 @@ class Doctrine_Export extends Doctrine_Connection_Module */ public function exportClassesSql(array $classes) { - $models = Doctrine::getLoadedModels($classes); + $models = Doctrine::filterInvalidModels($classes); $sql = array(); diff --git a/lib/Doctrine/Record.php b/lib/Doctrine/Record.php index 2ed076bed..338317364 100644 --- a/lib/Doctrine/Record.php +++ b/lib/Doctrine/Record.php @@ -1174,7 +1174,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count * @param boolean $deep - Return also the relations * @return array */ - public function toArray($deep = false, $prefixKey = false) + public function toArray($deep = true, $prefixKey = false) { $a = array(); @@ -1184,10 +1184,12 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count } $a[$column] = $value; } + if ($this->_table->getIdentifierType() == Doctrine::IDENTIFIER_AUTOINC) { $i = $this->_table->getIdentifier(); $a[$i] = $this->getIncremented(); } + if ($deep) { foreach ($this->_references as $key => $relation) { if ( ! $relation instanceof Doctrine_Null) { @@ -1195,21 +1197,59 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count } } } + return array_merge($a, $this->_values); } - public function fromArray($array) + + /** + * merge + * + * merges this record with an array of values + * or with another existing instance of this object + * + * @param mixed $data Data to merge. Either another instance of this model or an array + * @param bool $deep Bool value for whether or not to merge the data deep + * @return void + */ + public function merge($data, $deep = true) + { + if ($data instanceof $this) { + $array = $data->toArray($deep); + } else if (is_array($data)) { + $array = $data; + } + + return $this->fromArray($array, $deep); + } + + /** + * fromArray + * + * @param string $array + * @param bool $deep Bool value for whether or not to merge the data deep + * @return void + */ + public function fromArray($array, $deep = true) { if (is_array($array)) { foreach ($array as $key => $value) { - if ($this->getTable()->hasRelation($key)) { - $this->$key->fromArray($value); + if ($this->getTable()->hasRelation($key) && $deep) { + $this->$key->fromArray($value, $deep); } else if($this->getTable()->hasColumn($key)) { $this->set($key, $value); } } } } - public function exportTo($type, $deep = false) + + /** + * exportTo + * + * @param string $type + * @param string $deep + * @return void + */ + public function exportTo($type, $deep = true) { if ($type == 'array') { return $this->toArray($deep); @@ -1217,6 +1257,15 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count return Doctrine_Parser::dump($this->toArray($deep, true), $type); } } + + /** + * importFrom + * + * @param string $type + * @param string $data + * @return void + * @author Jonathan H. Wage + */ public function importFrom($type, $data) { if ($type == 'array') { @@ -1294,12 +1343,8 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count * * @return Doctrine_Record */ - public function copy($deep = false) + public function copy($deep = true) { - if ($deep) { - return $this->copyDeep(); - } - $data = $this->_data; if ($this->_table->getIdentifierType() === Doctrine::IDENTIFIER_AUTOINC) { @@ -1315,30 +1360,21 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count if ( ! ($val instanceof Doctrine_Null)) { $ret->_modified[] = $key; } - } + } - return $ret; - } - - /** - * copyDeep - * returns a copy of this object and all its related objects - * - * @return Doctrine_Record - */ - public function copyDeep() { - $copy = $this->copy(); - - foreach ($this->_references as $key => $value) { - if ($value instanceof Doctrine_Collection) { - foreach ($value as $record) { - $copy->{$key}[] = $record->copyDeep(); + if ($deep) { + foreach ($this->_references as $key => $value) { + if ($value instanceof Doctrine_Collection) { + foreach ($value as $record) { + $rt->{$key}[] = $record->copy($deep); + } + } else { + $rt->set($key, $value->copy($deep)); } - } else { - $copy->set($key, $value->copyDeep()); } } - return $copy; + + return $ret; } /** @@ -1476,66 +1512,6 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count $this->_references[$name] = $rel->fetchRelatedFor($this); } - /** - * merge - * merges this record with an array of values - * - * @param array $values - * @return void - */ - public function merge(array $values) - { - foreach ($this->_table->getFieldNames() as $fieldName) { - try { - if (isset($values[$fieldName])) { - $this->set($fieldName, $values[$fieldName]); - } - } catch (Doctrine_Exception $e) { - // silence all exceptions - } - } - } - - /** - * mergeDeep - * merges this record with an array of values - * - * @pre it is expected that the array keys representing a hasMany - * relationship are the keyColumn set with INDEXBY - * - * @param array $values - * @param $rmFromCollection if some records are not found in the array, - * they are removed from the collection<->relation - * @return void - */ - public function mergeDeep(array $values, $rmFromCollection = false) - { - $this->merge($values); - - foreach ($values as $rel_name => $rel_data) { - if ($this->getTable()->hasRelation($rel_name)) { - $rel = $this->get($rel_name); - if ($rel instanceof Doctrine_Collection) { - foreach ($rel as $key => $record) { - if (isset($rel_data[$key])) { - $record->mergeDeep($rel_data[$key], $rmFromCollection); - unset($rel_data[$key]); - } elseif ($rmFromCollection) { - $rel->remove($key); - } - } - foreach ($rel_data as $key => $new_data) { - $new_record = $rel->getTable()->create(); - $new_record->mergeDeep($new_data); - $rel->add($new_record, $key); - } - } else { - $rel->mergeDeep($rel_data); - } - } - } - } - /** * call *