Commit 542f9b0d authored by Jonathan.Wage's avatar Jonathan.Wage

Further model loading refactoring and refactored merge() in Doctrine_Record

parent 0ac4d757
...@@ -441,13 +441,13 @@ final class Doctrine ...@@ -441,13 +441,13 @@ final class Doctrine
private static $_debug = false; private static $_debug = false;
/** /**
* _loadedModels * _loadedModelFiles
* *
* Array of all the loaded models and the path to each one for autoloading * Array of all the loaded models and the path to each one for autoloading
* *
* @var array * @var array
*/ */
private static $_loadedModels = array(); private static $_loadedModelFiles = array();
/** /**
* _validators * _validators
...@@ -517,13 +517,44 @@ final class Doctrine ...@@ -517,13 +517,44 @@ final class Doctrine
foreach ($it as $file) { foreach ($it as $file) {
$e = explode('.', $file->getFileName()); $e = explode('.', $file->getFileName());
if (end($e) === 'php' && strpos($file->getFileName(), '.inc') === false) { 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 ...@@ -541,57 +572,51 @@ final class Doctrine
{ {
if ($classes === null) { if ($classes === null) {
$classes = get_declared_classes(); $classes = get_declared_classes();
$classes = array_merge($classes, array_keys(self::$_loadedModels)); $classes = array_merge($classes, array_keys(self::$_loadedModelFiles));
} }
$loadedModels = array(); 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) { foreach ((array) $classes as $name) {
try { if (self::isValidModelClass($name) && !in_array($name, $validModels)) {
$declaredBefore = get_declared_classes(); $validModels[] = $name;
$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 $validModels;
}
/** /**
* isValidModelClass * 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 * @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 * @return boolean
*/ */
public static function isValidModelClass($class) 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) { if ($class instanceof ReflectionClass) {
// Skip the following classes // Skip the following classes
// - abstract classes // - abstract classes
...@@ -600,13 +625,14 @@ final class Doctrine ...@@ -600,13 +625,14 @@ final class Doctrine
if (!$class->isAbstract() && if (!$class->isAbstract() &&
$class->isSubClassOf('Doctrine_Record') && $class->isSubClassOf('Doctrine_Record') &&
$class->hasMethod('setTableDefinition')) { $class->hasMethod('setTableDefinition')) {
return true; return true;
} }
} }
return false; return false;
} }
/** /**
* getConnectionByTableName * getConnectionByTableName
* *
...@@ -1001,7 +1027,7 @@ final class Doctrine ...@@ -1001,7 +1027,7 @@ final class Doctrine
return true; return true;
} }
$loadedModels = self::$_loadedModels; $loadedModels = self::$_loadedModelFiles;
if (isset($loadedModels[$className]) && file_exists($loadedModels[$className])) { if (isset($loadedModels[$className]) && file_exists($loadedModels[$className])) {
require_once($loadedModels[$className]); require_once($loadedModels[$className]);
......
...@@ -670,12 +670,11 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator ...@@ -670,12 +670,11 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
* @param string $array * @param string $array
* @return void * @return void
*/ */
public function fromArray($array, $deep = true)
public function fromArray($array)
{ {
$data = array(); $data = array();
foreach ($array as $rowKey => $row) { foreach ($array as $rowKey => $row) {
$this[$rowKey]->fromArray($row); $this[$rowKey]->fromArray($row, $deep);
} }
} }
......
...@@ -274,7 +274,7 @@ class Doctrine_Data ...@@ -274,7 +274,7 @@ class Doctrine_Data
*/ */
public function purge($models = array()) public function purge($models = array())
{ {
$models = Doctrine::getLoadedModels($models); $models = Doctrine::filterInvalidModels($models);
foreach ($models as $model) foreach ($models as $model)
{ {
......
...@@ -1124,7 +1124,7 @@ class Doctrine_Export extends Doctrine_Connection_Module ...@@ -1124,7 +1124,7 @@ class Doctrine_Export extends Doctrine_Connection_Module
*/ */
public function exportClassesSql(array $classes) public function exportClassesSql(array $classes)
{ {
$models = Doctrine::getLoadedModels($classes); $models = Doctrine::filterInvalidModels($classes);
$sql = array(); $sql = array();
......
...@@ -1174,7 +1174,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count ...@@ -1174,7 +1174,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
* @param boolean $deep - Return also the relations * @param boolean $deep - Return also the relations
* @return array * @return array
*/ */
public function toArray($deep = false, $prefixKey = false) public function toArray($deep = true, $prefixKey = false)
{ {
$a = array(); $a = array();
...@@ -1184,10 +1184,12 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count ...@@ -1184,10 +1184,12 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
} }
$a[$column] = $value; $a[$column] = $value;
} }
if ($this->_table->getIdentifierType() == Doctrine::IDENTIFIER_AUTOINC) { if ($this->_table->getIdentifierType() == Doctrine::IDENTIFIER_AUTOINC) {
$i = $this->_table->getIdentifier(); $i = $this->_table->getIdentifier();
$a[$i] = $this->getIncremented(); $a[$i] = $this->getIncremented();
} }
if ($deep) { if ($deep) {
foreach ($this->_references as $key => $relation) { foreach ($this->_references as $key => $relation) {
if ( ! $relation instanceof Doctrine_Null) { if ( ! $relation instanceof Doctrine_Null) {
...@@ -1195,21 +1197,59 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count ...@@ -1195,21 +1197,59 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
} }
} }
} }
return array_merge($a, $this->_values); 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)) { if (is_array($array)) {
foreach ($array as $key => $value) { foreach ($array as $key => $value) {
if ($this->getTable()->hasRelation($key)) { if ($this->getTable()->hasRelation($key) && $deep) {
$this->$key->fromArray($value); $this->$key->fromArray($value, $deep);
} else if($this->getTable()->hasColumn($key)) { } else if($this->getTable()->hasColumn($key)) {
$this->set($key, $value); $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') { if ($type == 'array') {
return $this->toArray($deep); return $this->toArray($deep);
...@@ -1217,6 +1257,15 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count ...@@ -1217,6 +1257,15 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
return Doctrine_Parser::dump($this->toArray($deep, true), $type); 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) public function importFrom($type, $data)
{ {
if ($type == 'array') { if ($type == 'array') {
...@@ -1294,12 +1343,8 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count ...@@ -1294,12 +1343,8 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
* *
* @return Doctrine_Record * @return Doctrine_Record
*/ */
public function copy($deep = false) public function copy($deep = true)
{ {
if ($deep) {
return $this->copyDeep();
}
$data = $this->_data; $data = $this->_data;
if ($this->_table->getIdentifierType() === Doctrine::IDENTIFIER_AUTOINC) { if ($this->_table->getIdentifierType() === Doctrine::IDENTIFIER_AUTOINC) {
...@@ -1315,30 +1360,21 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count ...@@ -1315,30 +1360,21 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
if ( ! ($val instanceof Doctrine_Null)) { if ( ! ($val instanceof Doctrine_Null)) {
$ret->_modified[] = $key; $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 ($deep) {
if ($value instanceof Doctrine_Collection) { foreach ($this->_references as $key => $value) {
foreach ($value as $record) { if ($value instanceof Doctrine_Collection) {
$copy->{$key}[] = $record->copyDeep(); 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 ...@@ -1476,66 +1512,6 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
$this->_references[$name] = $rel->fetchRelatedFor($this); $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 * call
* *
......
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