Commit 3cd7b954 authored by romanb's avatar romanb

Refactorings. Merged hydrator fixes from 0.11/1.0

parent 4d752746
...@@ -24,9 +24,8 @@ ...@@ -24,9 +24,8 @@
/** /**
* A <tt>ClassMetadata</tt> instance holds all the information (metadata) of an entity and * A <tt>ClassMetadata</tt> instance holds all the information (metadata) of an entity and
* it's associations and how they're mapped to the relational database. * it's associations and how they're mapped to the relational database.
* It is the backbone of Doctrine's metadata mapping.
* *
* @package Doctrine
* @subpackage ClassMetadata
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @since 2.0 * @since 2.0
*/ */
...@@ -115,8 +114,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -115,8 +114,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
protected $_generators = array(); protected $_generators = array();
/** /**
* The mapped columns and their mapping definitions. * The field mappings of the class.
* Keys are column names and values are mapping definitions. * Keys are field names and values are mapping definitions.
* *
* The mapping definition array has at least the following values: * The mapping definition array has at least the following values:
* *
...@@ -128,9 +127,9 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -128,9 +127,9 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
* -- values enum values * -- values enum values
* ... many more * ... many more
* *
* @var array $columns * @var array
*/ */
protected $_mappedColumns = array(); protected $_fieldMappings = array();
/** /**
* The mapped embedded values (value objects). * The mapped embedded values (value objects).
...@@ -283,6 +282,28 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -283,6 +282,28 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
protected $_invokedMethods = array(); protected $_invokedMethods = array();
/**
* The cached lifecycle listeners. There is only one instance of each
* listener class at any time.
*
* @var array
*/
protected $_lifecycleListenerInstances = array();
/**
* The registered lifecycle callbacks for Entities of this class.
*
* @var array
*/
protected $_lifecycleCallbacks = array();
/**
* The registered lifecycle listeners for Entities of this class.
*
* @var array
*/
protected $_lifecycleListeners = array();
/** /**
* Constructs a new ClassMetadata instance. * Constructs a new ClassMetadata instance.
...@@ -374,7 +395,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -374,7 +395,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function isUniqueField($fieldName) public function isUniqueField($fieldName)
{ {
$mapping = $this->getColumnMapping($fieldName); $mapping = $this->getFieldMapping($fieldName);
if ($mapping !== false) { if ($mapping !== false) {
return isset($mapping['unique']) && $mapping['unique'] == true; return isset($mapping['unique']) && $mapping['unique'] == true;
...@@ -391,7 +412,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -391,7 +412,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function isNotNull($fieldName) public function isNotNull($fieldName)
{ {
$mapping = $this->getColumnMapping($fieldName); $mapping = $this->getFieldMapping($fieldName);
if ($mapping !== false) { if ($mapping !== false) {
return isset($mapping['notnull']) && $mapping['notnull'] == true; return isset($mapping['notnull']) && $mapping['notnull'] == true;
...@@ -542,10 +563,10 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -542,10 +563,10 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
return $this->getColumnMapping($columnName); return $this->getColumnMapping($columnName);
} }
public function getColumnMapping($columnName) public function getFieldMapping($fieldName)
{ {
return isset($this->_mappedColumns[$columnName]) ? return isset($this->_fieldMappings[$fieldName]) ?
$this->_mappedColumns[$columnName] : false; $this->_fieldMappings[$fieldName] : false;
} }
/** /**
...@@ -593,6 +614,10 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -593,6 +614,10 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
* found on this class mapping. * found on this class mapping.
* This lookup on subclasses is costly but happens only *once* for a column * This lookup on subclasses is costly but happens only *once* for a column
* during hydration because the hydrator caches effectively. * during hydration because the hydrator caches effectively.
*
* @return string The field name.
* @throws Doctrine::ORM::Exceptions::ClassMetadataException if the field name could
* not be found.
*/ */
public function lookupFieldName($lcColumnName) public function lookupFieldName($lcColumnName)
{ {
...@@ -626,7 +651,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -626,7 +651,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
} }
/** /**
* Maps a column of the class' database table to a field of the entity. * Maps a field of the class to a database column.
* *
* @param string $name The name of the column to map. Syntax: columnName [as propertyName]. * @param string $name The name of the column to map. Syntax: columnName [as propertyName].
* The property name is optional. If not used the column will be * The property name is optional. If not used the column will be
...@@ -639,7 +664,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -639,7 +664,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
* *
* @throws Doctrine_ClassMetadata_Exception If trying use wrongly typed parameter. * @throws Doctrine_ClassMetadata_Exception If trying use wrongly typed parameter.
*/ */
public function mapColumn($name, $type, $length = null, $options = array(), $prepend = false) public function mapColumn($name, $type, $length = null, $options = array())
{ {
// converts 0 => 'primary' to 'primary' => true etc. // converts 0 => 'primary' to 'primary' => true etc.
foreach ($options as $k => $option) { foreach ($options as $k => $option) {
...@@ -661,18 +686,14 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -661,18 +686,14 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
$columnName = $parts[0]; $columnName = $parts[0];
$lcColumnName = strtolower($parts[0]); $lcColumnName = strtolower($parts[0]);
if (isset($this->_mappedColumns[$columnName])) { if (isset($this->_fieldMappings[$fieldName])) {
return; return;
} }
// Fill column name <-> field name lookup maps // Fill column name <-> field name lookup maps
if ($prepend) {
$this->_columnNames = array_merge(array($fieldName => $columnName), $this->_columnNames);
$this->_fieldNames = array_merge(array($columnName => $fieldName), $this->_fieldNames);
} else {
$this->_columnNames[$fieldName] = $columnName; $this->_columnNames[$fieldName] = $columnName;
$this->_fieldNames[$columnName] = $fieldName; $this->_fieldNames[$columnName] = $fieldName;
} $this->_lcColumnToFieldNames[$lcColumnName] = $fieldName;
$this->_lcColumnToFieldNames[$lcColumnName] = $fieldName; $this->_lcColumnToFieldNames[$lcColumnName] = $fieldName;
...@@ -701,11 +722,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -701,11 +722,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
$options['immutable'] = false; $options['immutable'] = false;
}*/ }*/
if ($prepend) { $this->_fieldMappings[$fieldName] = $options;
$this->_mappedColumns = array_merge(array($columnName => $options), $this->_mappedColumns);
} else {
$this->_mappedColumns[$columnName] = $options;
}
$this->_columnCount++; $this->_columnCount++;
} }
...@@ -753,24 +770,6 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -753,24 +770,6 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
//... //...
} }
/**
* setColumn
*
* @param string $name
* @param string $type
* @param integer $length
* @param mixed $options
* @param boolean $prepend Whether to prepend or append the new column to the column list.
* By default the column gets appended.
* @throws Doctrine_Table_Exception if trying use wrongly typed parameter
* @return void
* @deprecated Use mapColumn()
*/
public function setColumn($name, $type, $length = null, $options = array(), $prepend = false)
{
return $this->mapColumn($name, $type, $length, $options, $prepend);
}
/** /**
* Gets the names of all validators that are applied on a field. * Gets the names of all validators that are applied on a field.
* *
...@@ -779,9 +778,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -779,9 +778,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function getFieldValidators($fieldName) public function getFieldValidators($fieldName)
{ {
$columnName = $this->getColumnName($fieldName); return isset($this->_fieldMappings[$fieldName]['validators']) ?
return isset($this->_mappedColumns[$columnName]['validators']) ? $this->_fieldMappings[$fieldName]['validators'] : array();
$this->_mappedColumns[$columnName]['validators'] : array();
} }
/** /**
...@@ -803,12 +801,11 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -803,12 +801,11 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function getDefaultValueOf($fieldName) public function getDefaultValueOf($fieldName)
{ {
$columnName = $this->getColumnName($fieldName); if ( ! isset($this->_fieldMappings[$fieldName])) {
if ( ! isset($this->_mappedColumns[$columnName])) { throw new Doctrine_Table_Exception("Couldn't get default value. Column ".$fieldName." doesn't exist.");
throw new Doctrine_Table_Exception("Couldn't get default value. Column ".$columnName." doesn't exist.");
} }
if (isset($this->_mappedColumns[$columnName]['default'])) { if (isset($this->_fieldMappings[$fieldName]['default'])) {
return $this->_mappedColumns[$columnName]['default']; return $this->_fieldMappings[$fieldName]['default'];
} else { } else {
return null; return null;
} }
...@@ -867,12 +864,12 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -867,12 +864,12 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function hasColumn($columnName) public function hasColumn($columnName)
{ {
return isset($this->_mappedColumns[$columnName]); return isset($this->_fieldNames[$columnName]);
} }
public function hasMappedColumn($columnName) public function hasMappedColumn($columnName)
{ {
return isset($this->_mappedColumns[$columnName]); return isset($this->_fieldNames[$columnName]);
} }
/** /**
...@@ -890,9 +887,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -890,9 +887,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function getEnumValues($fieldName) public function getEnumValues($fieldName)
{ {
$columnName = $this->getColumnName($fieldName); if (isset($this->_fieldMappings[$fieldName]['values'])) {
if (isset($this->_mappedColumns[$columnName]['values'])) { return $this->_fieldMappings[$fieldName]['values'];
return $this->_mappedColumns[$columnName]['values'];
} else { } else {
return array(); return array();
} }
...@@ -917,8 +913,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -917,8 +913,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
$columnName = $this->getColumnName($fieldName); $columnName = $this->getColumnName($fieldName);
if ( ! $this->_em->getAttribute(Doctrine::ATTR_USE_NATIVE_ENUM) && if ( ! $this->_em->getAttribute(Doctrine::ATTR_USE_NATIVE_ENUM) &&
isset($this->_mappedColumns[$columnName]['values'][$index])) { isset($this->_fieldMappings[$fieldName]['values'][$index])) {
$enumValue = $this->_mappedColumns[$columnName]['values'][$index]; $enumValue = $this->_fieldMappings[$fieldName]['values'][$index];
} else { } else {
$enumValue = $index; $enumValue = $index;
} }
...@@ -973,9 +969,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -973,9 +969,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function getCustomAccessor($fieldName) public function getCustomAccessor($fieldName)
{ {
$columnName = $this->getColumnName($fieldName); return isset($this->_fieldMappings[$fieldName]['accessor']) ?
return isset($this->_mappedColumns[$columnName]['accessor']) ? $this->_fieldMappings[$fieldName]['accessor'] : null;
$this->_mappedColumns[$columnName]['accessor'] : null;
} }
/** /**
...@@ -985,9 +980,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -985,9 +980,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function getCustomMutator($fieldName) public function getCustomMutator($fieldName)
{ {
$columnName = $this->getColumnName($fieldName); return isset($this->_fieldMappings[$fieldName]['mutator']) ?
return isset($this->_mappedColumns[$columnName]['mutator']) ? $this->_fieldMappings[$fieldName]['mutator'] : null;
$this->_mappedColumns[$columnName]['mutator'] : null;
} }
/** /**
...@@ -998,7 +992,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -998,7 +992,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function getColumns() public function getColumns()
{ {
return $this->_mappedColumns; return $this->_fieldMappings;
} }
/** /**
...@@ -1008,7 +1002,12 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -1008,7 +1002,12 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function getMappedColumns() public function getMappedColumns()
{ {
return $this->_mappedColumns; return $this->_fieldMappings;
}
public function getFieldMappings()
{
return $this->_fieldMappings;
} }
/** /**
...@@ -1023,8 +1022,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -1023,8 +1022,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
unset($this->_fieldNames[$columnName]); unset($this->_fieldNames[$columnName]);
if (isset($this->_mappedColumns[$columnName])) { if (isset($this->_fieldMappings[$fieldName])) {
unset($this->_mappedColumns[$columnName]); unset($this->_fieldMappings[$fieldName]);
return true; return true;
} }
$this->_columnCount--; $this->_columnCount--;
...@@ -1040,7 +1039,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -1040,7 +1039,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
public function getColumnNames(array $fieldNames = null) public function getColumnNames(array $fieldNames = null)
{ {
if ($fieldNames === null) { if ($fieldNames === null) {
return array_keys($this->_mappedColumns); return array_keys($this->_fieldNames);
} else { } else {
$columnNames = array(); $columnNames = array();
foreach ($fieldNames as $fieldName) { foreach ($fieldNames as $fieldName) {
...@@ -1092,8 +1091,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -1092,8 +1091,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function getMappingForField($fieldName) public function getMappingForField($fieldName)
{ {
$columnName = $this->getColumnName($fieldName); return $this->_fieldMappings[$fieldName];
return $this->getColumnDefinition($columnName);
} }
/** /**
...@@ -1104,6 +1102,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -1104,6 +1102,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function getTypeOf($fieldName) public function getTypeOf($fieldName)
{ {
return $this->getTypeOfColumn($this->getColumnName($fieldName)); return $this->getTypeOfColumn($this->getColumnName($fieldName));
} }
...@@ -1115,7 +1114,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -1115,7 +1114,8 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function getTypeOfField($fieldName) public function getTypeOfField($fieldName)
{ {
return $this->getTypeOfColumn($this->getColumnName($fieldName)); return isset($this->_fieldMappings[$fieldName]) ?
$this->_fieldMappings[$fieldName]['type'] : false;
} }
/** /**
...@@ -1125,7 +1125,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -1125,7 +1125,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function getTypeOfColumn($columnName) public function getTypeOfColumn($columnName)
{ {
return isset($this->_mappedColumns[$columnName]) ? $this->_mappedColumns[$columnName]['type'] : false; return $this->getTypeOfField($this->getFieldName($columnName));
} }
/** /**
...@@ -1133,7 +1133,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -1133,7 +1133,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function getFieldLength($fieldName) public function getFieldLength($fieldName)
{ {
return $this->_mappedColumns[$this->getColumnName($fieldName)]['length']; return $this->_fieldMappings[$fieldName]['length'];
} }
/** /**
...@@ -1683,7 +1683,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -1683,7 +1683,7 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
*/ */
public function isInheritedField($fieldName) public function isInheritedField($fieldName)
{ {
return isset($this->_mappedColumns[$this->getColumnName($fieldName)]['inherited']); return isset($this->_fieldMappings[$fieldName]['inherited']);
} }
/** /**
...@@ -1913,6 +1913,86 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable ...@@ -1913,6 +1913,86 @@ class Doctrine_ClassMetadata implements Doctrine_Configurable, Serializable
} }
/**
* Dispatches the lifecycle event of the given Entity to the registered
* lifecycle callbacks and lifecycle listeners.
*
* @param string $event The lifecycle event.
* @param Entity $entity The Entity on which the event occured.
*/
public function invokeLifecycleCallbacks($lifecycleEvent, Doctrine_Entity $entity)
{
foreach ($this->getLifecycleCallbacks($lifecycleEvent) as $callback) {
$entity->$callback();
}
foreach ($this->getLifecycleListeners($lifecycleEvent) as $className => $callback) {
if ( ! isset($this->_lifecycleListenerInstances[$className])) {
$this->_lifecycleListenerInstances[$className] = new $className;
}
$this->_lifecycleListenerInstances[$className]->$callback($entity);
}
}
/**
* Gets the registered lifecycle callbacks for an event.
*
* @param string $event
* @return array
*/
public function getLifecycleCallbacks($event)
{
return isset($this->_lifecycleCallbacks[$event]) ?
$this->_lifecycleCallbacks[$event] : array();
}
/**
* Gets the registered lifecycle listeners for an event.
*
* @param string $event
* @return array
*/
public function getLifecycleListeners($event)
{
return isset($this->_lifecycleListeners[$event]) ?
$this->_lifecycleListeners[$event] : array();
}
/**
* Adds a lifecycle listener for Entities this class.
*
* Note: If the same listener class is registered more than once, the old
* one will be overridden.
*
* @param string $listenerClass
* @param array $callbacks
*/
public function addLifecycleListener($listenerClass, array $callbacks)
{
$this->_lifecycleListeners[$event][$listenerClass] = array();
foreach ($callbacks as $method => $event) {
$this->_lifecycleListeners[$event][$listenerClass][] = $method;
}
}
/**
* Adds a lifecycle callback for Entities of this class.
*
* Note: If a the same callback is registered more than once, the old one
* will be overridden.
*
* @param string $callback
* @param string $event
*/
public function addLifecycleCallback($callback, $event)
{
if ( ! isset($this->_lifecycleCallbacks[$event])) {
$this->_lifecycleCallbacks[$event] = array();
}
if ( ! in_array($callback, $this->_lifecycleCallbacks[$event])) {
$this->_lifecycleCallbacks[$event][$callback] = $callback;
}
}
/** /**
* @todo Implementation. Immutable entities can not be updated or deleted once * @todo Implementation. Immutable entities can not be updated or deleted once
* they are created. This means the entity can only be modified as long as it's * they are created. This means the entity can only be modified as long as it's
......
...@@ -34,12 +34,19 @@ ...@@ -34,12 +34,19 @@
*/ */
class Doctrine_ClassMetadata_CodeDriver class Doctrine_ClassMetadata_CodeDriver
{ {
/**
* Name of the callback method.
*
* @todo We could make the name of the callback methods customizable for users.
*/
const CALLBACK_METHOD = 'initMetadata';
/** /**
* Loads the metadata for the specified class into the provided container. * Loads the metadata for the specified class into the provided container.
*/ */
public function loadMetadataForClass($className, Doctrine_ClassMetadata $metadata) public function loadMetadataForClass($className, Doctrine_ClassMetadata $metadata)
{ {
if ( ! method_exists($className, 'initMetadata')) { if ( ! method_exists($className, self::CALLBACK_METHOD)) {
throw new Doctrine_ClassMetadata_Exception("Unable to load metadata for class" throw new Doctrine_ClassMetadata_Exception("Unable to load metadata for class"
. " '$className'. Callback method 'initMetadata' not found."); . " '$className'. Callback method 'initMetadata' not found.");
} }
......
...@@ -133,7 +133,10 @@ class Doctrine_ClassMetadata_Factory ...@@ -133,7 +133,10 @@ class Doctrine_ClassMetadata_Factory
foreach ($parentClass->getColumns() as $name => $definition) { foreach ($parentClass->getColumns() as $name => $definition) {
$fullName = "$name as " . $parentClass->getFieldName($name); $fullName = "$name as " . $parentClass->getFieldName($name);
$definition['inherited'] = true; $definition['inherited'] = true;
$subClass->mapColumn($fullName, $definition['type'], $definition['length'], $subClass->mapColumn(
$fullName,
$definition['type'],
$definition['length'],
$definition); $definition);
} }
} }
...@@ -154,11 +157,6 @@ class Doctrine_ClassMetadata_Factory ...@@ -154,11 +157,6 @@ class Doctrine_ClassMetadata_Factory
protected function _loadMetadata(Doctrine_ClassMetadata $class, $name) protected function _loadMetadata(Doctrine_ClassMetadata $class, $name)
{ {
if ( ! class_exists($name) || empty($name)) { if ( ! class_exists($name) || empty($name)) {
/*try {
throw new Exception();
} catch (Exception $e) {
echo $e->getTraceAsString();
}*/
throw new Doctrine_Exception("Couldn't find class " . $name . "."); throw new Doctrine_Exception("Couldn't find class " . $name . ".");
} }
...@@ -175,11 +173,6 @@ class Doctrine_ClassMetadata_Factory ...@@ -175,11 +173,6 @@ class Doctrine_ClassMetadata_Factory
} while ($className = get_parent_class($className)); } while ($className = get_parent_class($className));
if ($className === false) { if ($className === false) {
try {
throw new Exception();
} catch (Exception $e) {
echo $e->getTraceAsString() . "<br />";
}
throw new Doctrine_ClassMetadata_Factory_Exception("Unknown component '$className'."); throw new Doctrine_ClassMetadata_Factory_Exception("Unknown component '$className'.");
} }
...@@ -207,10 +200,11 @@ class Doctrine_ClassMetadata_Factory ...@@ -207,10 +200,11 @@ class Doctrine_ClassMetadata_Factory
protected function _initIdentifier(Doctrine_ClassMetadata $class) protected function _initIdentifier(Doctrine_ClassMetadata $class)
{ {
switch (count((array)$class->getIdentifier())) { switch (count((array)$class->getIdentifier())) {
case 0: case 0: // No identifier in the class mapping yet
// If its a subclass, inherit the identifier from the parent.
if ($class->getInheritanceType() == Doctrine::INHERITANCE_TYPE_JOINED && if ($class->getInheritanceType() == Doctrine::INHERITANCE_TYPE_JOINED &&
count($class->getParentClasses()) > 0) { count($class->getParentClasses()) > 0) {
$parents = $class->getParentClasses(); $parents = $class->getParentClasses();
$root = end($parents); $root = end($parents);
$rootClass = $class->getConnection()->getMetadata($root); $rootClass = $class->getConnection()->getMetadata($root);
...@@ -237,17 +231,20 @@ class Doctrine_ClassMetadata_Factory ...@@ -237,17 +231,20 @@ class Doctrine_ClassMetadata_Factory
$definition, true); $definition, true);
} }
} else { } else {
throw Doctrine_MappingException::identifierRequired($class->getClassName());
/* Legacy behavior of auto-adding an id field
$definition = array('type' => 'integer', $definition = array('type' => 'integer',
'length' => 20, 'length' => 20,
'autoincrement' => true, 'autoincrement' => true,
'primary' => true); 'primary' => true);
$class->setColumn('id', $definition['type'], $definition['length'], $definition, true); $class->mapColumn('id', $definition['type'], $definition['length'], $definition, true);
$class->setIdentifier(array('id')); $class->setIdentifier(array('id'));
$class->setIdentifierType(Doctrine::IDENTIFIER_AUTOINC); $class->setIdentifierType(Doctrine::IDENTIFIER_AUTOINC);
*/
} }
break; break;
case 1: case 1: // A single identifier is in the mapping
foreach ((array)$class->getIdentifier() as $pk) { foreach ($class->getIdentifier() as $pk) {
$columnName = $class->getColumnName($pk); $columnName = $class->getColumnName($pk);
$thisColumns = $class->getColumns(); $thisColumns = $class->getColumns();
$e = $thisColumns[$columnName]; $e = $thisColumns[$columnName];
...@@ -294,7 +291,7 @@ class Doctrine_ClassMetadata_Factory ...@@ -294,7 +291,7 @@ class Doctrine_ClassMetadata_Factory
$class->setIdentifier(array($pk)); $class->setIdentifier(array($pk));
break; break;
default: default: // Multiple identifiers are in the mapping so its a composite id
$class->setIdentifierType(Doctrine::IDENTIFIER_COMPOSITE); $class->setIdentifierType(Doctrine::IDENTIFIER_COMPOSITE);
} }
} }
......
...@@ -83,7 +83,7 @@ class Doctrine_Connection_UnitOfWork ...@@ -83,7 +83,7 @@ class Doctrine_Connection_UnitOfWork
protected $_removedEntities = array(); protected $_removedEntities = array();
/** /**
* The EntityManager the unit of work belongs to. * The EntityManager the UnitOfWork belongs to.
*/ */
protected $_em; protected $_em;
...@@ -98,7 +98,7 @@ class Doctrine_Connection_UnitOfWork ...@@ -98,7 +98,7 @@ class Doctrine_Connection_UnitOfWork
/** /**
* Constructor. * Constructor.
* Created a new UnitOfWork. * Creates a new UnitOfWork.
* *
* @param Doctrine_EntityManager $em * @param Doctrine_EntityManager $em
*/ */
...@@ -111,6 +111,7 @@ class Doctrine_Connection_UnitOfWork ...@@ -111,6 +111,7 @@ class Doctrine_Connection_UnitOfWork
* Commits the unit of work, executing all operations that have been postponed * Commits the unit of work, executing all operations that have been postponed
* up to this point. * up to this point.
* *
* @todo Impl
*/ */
public function commit() public function commit()
{ {
...@@ -191,7 +192,7 @@ class Doctrine_Connection_UnitOfWork ...@@ -191,7 +192,7 @@ class Doctrine_Connection_UnitOfWork
*/ */
public function registerRemoved(Doctrine_Entity $entity) public function registerRemoved(Doctrine_Entity $entity)
{ {
if ($entity->isTransient()) { if ($entity->isNew()) {
return; return;
} }
$this->unregisterIdentity($entity); $this->unregisterIdentity($entity);
...@@ -511,4 +512,229 @@ class Doctrine_Connection_UnitOfWork ...@@ -511,4 +512,229 @@ class Doctrine_Connection_UnitOfWork
return isset($this->_identityMap[$rootClassName][$idHash]); return isset($this->_identityMap[$rootClassName][$idHash]);
} }
public function save(Doctrine_Entity $entity)
{
switch ($entity->_state()) {
case Doctrine_Entity::STATE_CLEAN:
//nothing to do
// ignore $entity but cascade
break;
case Doctrine_Entity::STATE_DIRTY:
// update
$this->registerDirty($entity);
// todo:cascade
break;
case Doctrine_Entity::STATE_TCLEAN:
case Doctrine_Entity::STATE_TDIRTY:
// insert
// if identifier type IDENTITY:
// cascade
// if no transaction is started yet, do it
// force insert (directly to persister)
// else
// cascade
// get & assign the identifier, then registerNew()
break;
}
}
private function _cascadeSave(Doctrine_Entity $entity)
{
}
private function _cascadeDelete(Doctrine_Entity $entity)
{
}
// Stuff from 0.11/1.0 that we will need later (need to modify it though)
/**
* Collects all records that need to be deleted by applying defined
* application-level delete cascades.
*
* @param array $deletions Map of the records to delete. Keys=Oids Values=Records.
*/
/*private function _collectDeletions(Doctrine_Record $record, array &$deletions)
{
if ( ! $record->exists()) {
return;
}
$deletions[$record->getOid()] = $record;
$this->_cascadeDelete($record, $deletions);
}*/
/**
* Cascades an ongoing delete operation to related objects. Applies only on relations
* that have 'delete' in their cascade options.
* This is an application-level cascade. Related objects that participate in the
* cascade and are not yet loaded are fetched from the database.
* Exception: many-valued relations are always (re-)fetched from the database to
* make sure we have all of them.
*
* @param Doctrine_Record The record for which the delete operation will be cascaded.
* @throws PDOException If something went wrong at database level
* @return void
*/
/*protected function _cascadeDelete(Doctrine_Record $record, array &$deletions)
{
foreach ($record->getTable()->getRelations() as $relation) {
if ($relation->isCascadeDelete()) {
$fieldName = $relation->getAlias();
// if it's a xToOne relation and the related object is already loaded
// we don't need to refresh.
if ( ! ($relation->getType() == Doctrine_Relation::ONE && isset($record->$fieldName))) {
$record->refreshRelated($relation->getAlias());
}
$relatedObjects = $record->get($relation->getAlias());
if ($relatedObjects instanceof Doctrine_Record && $relatedObjects->exists()
&& ! isset($deletions[$relatedObjects->getOid()])) {
$this->_collectDeletions($relatedObjects, $deletions);
} else if ($relatedObjects instanceof Doctrine_Collection && count($relatedObjects) > 0) {
// cascade the delete to the other objects
foreach ($relatedObjects as $object) {
if ( ! isset($deletions[$object->getOid()])) {
$this->_collectDeletions($object, $deletions);
}
}
}
}
}
}*/
/**
* Executes the deletions for all collected records during a delete operation
* (usually triggered through $record->delete()).
*
* @param array $deletions Map of the records to delete. Keys=Oids Values=Records.
*/
/*private function _executeDeletions(array $deletions)
{
// collect class names
$classNames = array();
foreach ($deletions as $record) {
$classNames[] = $record->getTable()->getComponentName();
}
$classNames = array_unique($classNames);
// order deletes
$executionOrder = $this->buildFlushTree($classNames);
// execute
try {
$this->conn->beginInternalTransaction();
for ($i = count($executionOrder) - 1; $i >= 0; $i--) {
$className = $executionOrder[$i];
$table = $this->conn->getTable($className);
// collect identifiers
$identifierMaps = array();
$deletedRecords = array();
foreach ($deletions as $oid => $record) {
if ($record->getTable()->getComponentName() == $className) {
$veto = $this->_preDelete($record);
if ( ! $veto) {
$identifierMaps[] = $record->identifier();
$deletedRecords[] = $record;
unset($deletions[$oid]);
}
}
}
if (count($deletedRecords) < 1) {
continue;
}
// extract query parameters (only the identifier values are of interest)
$params = array();
$columnNames = array();
foreach ($identifierMaps as $idMap) {
while (list($fieldName, $value) = each($idMap)) {
$params[] = $value;
$columnNames[] = $table->getColumnName($fieldName);
}
}
$columnNames = array_unique($columnNames);
// delete
$tableName = $table->getTableName();
$sql = "DELETE FROM " . $this->conn->quoteIdentifier($tableName) . " WHERE ";
if ($table->isIdentifierComposite()) {
$sql .= $this->_buildSqlCompositeKeyCondition($columnNames, count($identifierMaps));
$this->conn->exec($sql, $params);
} else {
$sql .= $this->_buildSqlSingleKeyCondition($columnNames, count($params));
$this->conn->exec($sql, $params);
}
// adjust state, remove from identity map and inform postDelete listeners
foreach ($deletedRecords as $record) {
// currently just for bc!
$this->_deleteCTIParents($table, $record);
//--
$record->state(Doctrine_Record::STATE_TCLEAN);
$record->getTable()->removeRecord($record);
$this->_postDelete($record);
}
}
$this->conn->commit();
// trigger postDelete for records skipped during the deletion (veto!)
foreach ($deletions as $skippedRecord) {
$this->_postDelete($skippedRecord);
}
return true;
} catch (Exception $e) {
$this->conn->rollback();
throw $e;
}
}*/
/**
* Builds the SQL condition to target multiple records who have a single-column
* primary key.
*
* @param Doctrine_Table $table The table from which the records are going to be deleted.
* @param integer $numRecords The number of records that are going to be deleted.
* @return string The SQL condition "pk = ? OR pk = ? OR pk = ? ..."
*/
/*private function _buildSqlSingleKeyCondition($columnNames, $numRecords)
{
$idColumn = $this->conn->quoteIdentifier($columnNames[0]);
return implode(' OR ', array_fill(0, $numRecords, "$idColumn = ?"));
}*/
/**
* Builds the SQL condition to target multiple records who have a composite primary key.
*
* @param Doctrine_Table $table The table from which the records are going to be deleted.
* @param integer $numRecords The number of records that are going to be deleted.
* @return string The SQL condition "(pk1 = ? AND pk2 = ?) OR (pk1 = ? AND pk2 = ?) ..."
*/
/*private function _buildSqlCompositeKeyCondition($columnNames, $numRecords)
{
$singleCondition = "";
foreach ($columnNames as $columnName) {
$columnName = $this->conn->quoteIdentifier($columnName);
if ($singleCondition === "") {
$singleCondition .= "($columnName = ?";
} else {
$singleCondition .= " AND $columnName = ?";
}
}
$singleCondition .= ")";
$fullCondition = implode(' OR ', array_fill(0, $numRecords, $singleCondition));
return $fullCondition;
}*/
} }
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
#namespace Doctrine::ORM; #namespace Doctrine::ORM;
/** /**
* Doctrine_Entity * Base class for all Entities (objects with persistent state in a RDBMS that are
* All record classes should inherit this super class. * managed by Doctrine).
* *
* NOTE: Methods that are intended for internal use only but must be public * NOTE: Methods that are intended for internal use only but must be public
* are marked INTERNAL: and begin with an underscore "_" to indicate that they * are marked INTERNAL: and begin with an underscore "_" to indicate that they
...@@ -37,8 +37,10 @@ ...@@ -37,8 +37,10 @@
* @link www.phpdoctrine.org * @link www.phpdoctrine.org
* @since 2.0 * @since 2.0
* @version $Revision: 4342 $ * @version $Revision: 4342 $
* @todo Split up into "Entity" and "ActiveEntity (extends Entity)"??? * @todo Split up into "Entity" and "ActiveEntity" (extends Entity)
* @todo Remove as many methods as possible. * @todo Move entity states into a separate enumeration (EntityStates).
* They do not need to be exposed to users in such a way. The states are mainly
* for internal use.
*/ */
abstract class Doctrine_Entity extends Doctrine_Access implements Serializable abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
{ {
...@@ -47,6 +49,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -47,6 +49,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
* An Entity is in dirty state when its properties are changed. * An Entity is in dirty state when its properties are changed.
*/ */
const STATE_DIRTY = 1; const STATE_DIRTY = 1;
const STATE_MANAGED_DIRTY = 1;
/** /**
* TDIRTY STATE * TDIRTY STATE
...@@ -54,6 +57,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -54,6 +57,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
* fields are modified but it is NOT yet persisted into database. * fields are modified but it is NOT yet persisted into database.
*/ */
const STATE_TDIRTY = 2; const STATE_TDIRTY = 2;
const STATE_NEW_DIRTY = 2;
/** /**
* CLEAN STATE * CLEAN STATE
...@@ -61,19 +65,17 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -61,19 +65,17 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
* and none of its properties are changed. * and none of its properties are changed.
*/ */
const STATE_CLEAN = 3; const STATE_CLEAN = 3;
const STATE_MANAGED_CLEAN = 3;
/**
* PROXY STATE
* An Entity is in proxy state when its properties are not fully loaded.
*/
//const STATE_PROXY = 4;
/** /**
* NEW TCLEAN * NEW TCLEAN
* An Entity is in transient clean state when it is created and none of its * An Entity is in transient clean state when it is created and none of its
* fields are modified. * fields are modified.
* @todo Do we need this state? Just STATE_NEW may be enough without differentiating
* clean/dirty. A new entity is always "dirty".
*/ */
const STATE_TCLEAN = 5; const STATE_TCLEAN = 5;
const STATE_NEW_CLEAN = 5;
/** /**
* LOCKED STATE * LOCKED STATE
...@@ -81,9 +83,25 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -81,9 +83,25 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
* *
* This state is used internally to ensure that circular deletes * This state is used internally to ensure that circular deletes
* and saves will not cause infinite loops. * and saves will not cause infinite loops.
* @todo Not sure this is a good idea. It is a problematic solution because
* it hides the original state while the locked state is active.
*/ */
const STATE_LOCKED = 6; const STATE_LOCKED = 6;
/**
* A detached Entity is an instance with a persistent identity that is not
* (or no longer) associated with an EntityManager (and a UnitOfWork).
* This means its no longer in the identity map.
*/
const STATE_DETACHED = 7;
/**
* A removed Entity instance is an instance with a persistent identity,
* associated with an EntityManager, that is scheduled for removal from the
* database.
*/
const STATE_DELETED = 8;
/** /**
* Index used for creating object identifiers (oid's). * Index used for creating object identifiers (oid's).
* *
...@@ -205,114 +223,16 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -205,114 +223,16 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
self::$_useAutoAccessorOverride = true; self::$_useAutoAccessorOverride = true;
} }
/**
* _index
*
* @return integer
*/
/*public static function _index()
{
return self::$_index;
}*/
/** /**
* Returns the object identifier. * Returns the object identifier.
* *
* @return integer * @return integer
*/ */
public function getOid() final public function getOid()
{ {
return $this->_oid; return $this->_oid;
} }
/**
* Empty template method to provide concrete Record classes with the possibility
* to hook into the serializing procedure.
*/
public function preSerialize()
{ }
/**
* Empty template method to provide concrete Record classes with the possibility
* to hook into the serializing procedure.
*/
public function postSerialize()
{ }
/**
* Empty template method to provide concrete Record classes with the possibility
* to hook into the serializing procedure.
*/
public function preUnserialize()
{ }
/**
* Empty template method to provide concrete Record classes with the possibility
* to hook into the serializing procedure.
*/
public function postUnserialize()
{ }
/**
* Empty template method to provide concrete Record classes with the possibility
* to hook into the saving procedure.
*/
public function preSave()
{ }
/**
* Empty template method to provide concrete Record classes with the possibility
* to hook into the saving procedure.
*/
public function postSave()
{ }
/**
* Empty template method to provide concrete Record classes with the possibility
* to hook into the deletion procedure.
*/
public function preDelete()
{ }
/**
* Empty template method to provide concrete Record classes with the possibility
* to hook into the deletion procedure.
*/
public function postDelete()
{ }
/**
* Empty template method to provide concrete Record classes with the possibility
* to hook into the saving procedure only when the record is going to be
* updated.
*/
public function preUpdate()
{ }
/**
* Empty template method to provide concrete Record classes with the possibility
* to hook into the saving procedure only when the record is going to be
* updated.
*/
public function postUpdate()
{ }
/**
* Empty template method to provide concrete Record classes with the possibility
* to hook into the saving procedure only when the record is going to be
* inserted into the data store the first time.
*/
public function preInsert()
{ }
/**
* Empty template method to provide concrete Record classes with the possibility
* to hook into the saving procedure only when the record is going to be
* inserted into the data store the first time.
*/
public function postInsert()
{ }
/** /**
* setDefaultValues * setDefaultValues
* sets the default values for records internal data * sets the default values for records internal data
...@@ -345,46 +265,15 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -345,46 +265,15 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
}*/ }*/
/** /**
* cleanData
* leaves the $data array only with values whose key is a field inside this
* record and returns the values that were removed from $data. Also converts
* any values of 'null' to objects of type Doctrine_Null.
*
* @param array $data data array to be cleaned
* @return array $tmp values cleaned from data
* @todo Remove. Should not be necessary. Slows down instantiation.
*/
/*public function cleanData(&$data)
{
$tmp = $data;
$data = array();
$fieldNames = $this->_em->getEntityPersister($this->_entityName)->getFieldNames();
foreach ($fieldNames as $fieldName) {
if (isset($tmp[$fieldName])) {
$data[$fieldName] = $tmp[$fieldName];
} else if (array_key_exists($fieldName, $tmp)) {
$data[$fieldName] = Doctrine_Null::$INSTANCE;
} else if ( ! isset($this->_data[$fieldName])) {
$data[$fieldName] = Doctrine_Null::$INSTANCE;
}
unset($tmp[$fieldName]);
}
return $tmp;
}*/
/**
* hydrate
* hydrates this object from given array * hydrates this object from given array
* *
* @param array $data * @param array $data
* @return boolean * @return boolean
*/ */
public function hydrate(array $data) final public function hydrate(array $data)
{ {
$this->_data = array_merge($this->_data, $data); $this->_data = array_merge($this->_data, $data);
//$this->_extractIdentifier(true); $this->_extractIdentifier();
} }
/** /**
...@@ -437,8 +326,8 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -437,8 +326,8 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
*/ */
public function serialize() public function serialize()
{ {
//$event = new Doctrine_Event($this, Doctrine_Event::RECORD_SERIALIZE); //$this->_em->getEventManager()->dispatchEvent(Event::preSerialize);
//$this->preSerialize($event); //$this->_class->dispatchLifecycleEvent(Event::preSerialize, $this);
$vars = get_object_vars($this); $vars = get_object_vars($this);
...@@ -533,7 +422,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -533,7 +422,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
/** /**
* INTERNAL: * INTERNAL:
* returns / assigns the state of this record * Gets or sets the state of this Entity.
* *
* @param integer|string $state if set, this method tries to set the record state to $state * @param integer|string $state if set, this method tries to set the record state to $state
* @see Doctrine_Entity::STATE_* constants * @see Doctrine_Entity::STATE_* constants
...@@ -577,7 +466,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -577,7 +466,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
* this record represents does not exist anymore) * this record represents does not exist anymore)
* @return boolean * @return boolean
* @todo Implementation to EntityManager. * @todo Implementation to EntityManager.
* @todo ActiveEntity method. * @todo Move to ActiveEntity (extends Entity).
*/ */
public function refresh($deep = false) public function refresh($deep = false)
{ {
...@@ -674,9 +563,10 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -674,9 +563,10 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
}*/ }*/
/** /**
* INTERNAL: (Usage from within extending classes is fine) * INTERNAL: (Usage from within extending classes is intended)
*
* Gets the value of a field (regular field or reference). * Gets the value of a field (regular field or reference).
* If the property is not yet loaded this method does NOT load it. * If the field is not yet loaded this method does NOT load it.
* *
* NOTE: Use of this method from outside the scope of an extending class * NOTE: Use of this method from outside the scope of an extending class
* is strongly discouraged. * is strongly discouraged.
...@@ -684,6 +574,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -684,6 +574,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
* @param $name name of the property * @param $name name of the property
* @throws Doctrine_Entity_Exception if trying to get an unknown field * @throws Doctrine_Entity_Exception if trying to get an unknown field
* @return mixed * @return mixed
* @todo Rename to _get()
*/ */
final public function _rawGet($fieldName) final public function _rawGet($fieldName)
{ {
...@@ -697,7 +588,8 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -697,7 +588,8 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
} }
/** /**
* INTERNAL: (Usage from within extending classes is fine) * INTERNAL: (Usage from within extending classes is intended)
*
* Sets the value of a field (regular field or reference). * Sets the value of a field (regular field or reference).
* If the field is not yet loaded this method does NOT load it. * If the field is not yet loaded this method does NOT load it.
* *
...@@ -707,6 +599,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -707,6 +599,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
* @param $name name of the field * @param $name name of the field
* @throws Doctrine_Entity_Exception if trying to get an unknown field * @throws Doctrine_Entity_Exception if trying to get an unknown field
* @return mixed * @return mixed
* @todo Rename to _set
*/ */
final public function _rawSet($fieldName, $value) final public function _rawSet($fieldName, $value)
{ {
...@@ -805,7 +698,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -805,7 +698,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
} }
if (isset($this->_references[$name])) { if (isset($this->_references[$name])) {
$this->_references[$name]->setData($value->getData()); $this->_references[$name]->setData($value->getData());
return $this; return;
} }
} else { } else {
$relatedTable = $value->getTable(); $relatedTable = $value->getTable();
...@@ -819,12 +712,12 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -819,12 +712,12 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
if ($rel instanceof Doctrine_Relation_LocalKey) { if ($rel instanceof Doctrine_Relation_LocalKey) {
$idFieldNames = $value->getTable()->getIdentifier(); $idFieldNames = $value->getTable()->getIdentifier();
if ( ! empty($foreignFieldName) && $foreignFieldName != $idFieldNames[0]) { if ( ! empty($foreignFieldName) && $foreignFieldName != $idFieldNames[0]) {
$this->set($localFieldName, $value->_rawGet($foreignFieldName), false); $this->set($localFieldName, $value->_rawGet($foreignFieldName));
} else { } else {
$this->set($localFieldName, $value, false); $this->set($localFieldName, $value);
} }
} else { } else {
$value->set($foreignFieldName, $this, false); $value->set($foreignFieldName, $this);
} }
} }
} else if ($rel instanceof Doctrine_Relation_Association) { } else if ($rel instanceof Doctrine_Relation_Association) {
...@@ -894,6 +787,13 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -894,6 +787,13 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
} }
} }
/**
* Gets the custom mutator method for a field, if it exists.
*
* @param string $fieldName The field name.
* @return mixed The name of the custom mutator or FALSE, if the field does
* not have a custom mutator.
*/
private function _getCustomMutator($fieldName) private function _getCustomMutator($fieldName)
{ {
if ( ! isset(self::$_mutatorCache[$this->_entityName][$fieldName])) { if ( ! isset(self::$_mutatorCache[$this->_entityName][$fieldName])) {
...@@ -916,6 +816,13 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -916,6 +816,13 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
return self::$_mutatorCache[$this->_entityName][$fieldName]; return self::$_mutatorCache[$this->_entityName][$fieldName];
} }
/**
* Gets the custom accessor method of a field, if it exists.
*
* @param string $fieldName The field name.
* @return mixed The name of the custom accessor method, or FALSE if the
* field does not have a custom accessor.
*/
private function _getCustomAccessor($fieldName) private function _getCustomAccessor($fieldName)
{ {
if ( ! isset(self::$_accessorCache[$this->_entityName][$fieldName])) { if ( ! isset(self::$_accessorCache[$this->_entityName][$fieldName])) {
...@@ -952,10 +859,6 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -952,10 +859,6 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
* *
* @param mixed $name name of the property or reference * @param mixed $name name of the property or reference
* @param mixed $value value of the property or reference * @param mixed $value value of the property or reference
* @param boolean $load whether or not to refresh / load the uninitialized record data
*
* @throws Doctrine_Record_Exception if trying to set a value for unknown property / related component
* @throws Doctrine_Record_Exception if trying to set a value of wrong type for related component
*/ */
final public function set($fieldName, $value) final public function set($fieldName, $value)
{ {
...@@ -978,9 +881,9 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -978,9 +881,9 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
if ($old != $value) { if ($old != $value) {
$this->_data[$fieldName] = $value; $this->_data[$fieldName] = $value;
$this->_modified[] = $fieldName; $this->_modified[$fieldName] = array($old => $value);
if ($this->isTransient() && $this->_class->isIdentifier($fieldName)) { if ($this->isNew() && $this->_class->isIdentifier($fieldName)) {
$this->_id[$fieldName] = $value; $this->_id[$fieldName] = $value;
} }
...@@ -1001,7 +904,9 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -1001,7 +904,9 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
} }
/** /**
* contains * Checks whether a field is set (not null).
*
* NOTE: Invoked by Doctrine::ORM::Access#__isset().
* *
* @param string $name * @param string $name
* @return boolean * @return boolean
...@@ -1025,6 +930,10 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -1025,6 +930,10 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
} }
/** /**
* Clears the value of a field.
*
* NOTE: Invoked by Doctrine::ORM::Access#__unset().
*
* @param string $name * @param string $name
* @return void * @return void
*/ */
...@@ -1220,8 +1129,8 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -1220,8 +1129,8 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
} }
/** /**
* Merges this record with an array of values * Merges this Entity with an array of values
* or with another existing instance of this object * or with another existing instance of.
* *
* @param mixed $data Data to merge. Either another instance of this model or an array * @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 * @param bool $deep Bool value for whether or not to merge the data deep
...@@ -1341,42 +1250,18 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -1341,42 +1250,18 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
* Checks whether the entity already has a persistent state. * Checks whether the entity already has a persistent state.
* *
* @return boolean TRUE if the object is new, FALSE otherwise. * @return boolean TRUE if the object is new, FALSE otherwise.
* @deprecated Use isTransient()
*/ */
final public function isNew() final public function isNew()
{ {
return $this->_state == self::STATE_TCLEAN || $this->_state == self::STATE_TDIRTY; return $this->_state == self::STATE_TCLEAN || $this->_state == self::STATE_TDIRTY;
} }
/**
* Checks whether the entity already has a persistent state.
*
* @return boolean TRUE if the object is new, FALSE otherwise.
*/
final public function isTransient()
{
return $this->_state == self::STATE_TCLEAN || $this->_state == self::STATE_TDIRTY;
}
/** /**
* Checks whether the entity has been modified since it was last synchronized * Checks whether the entity has been modified since it was last synchronized
* with the database. * with the database.
* *
* @return boolean TRUE if the object has been modified, FALSE otherwise. * @return boolean TRUE if the object has been modified, FALSE otherwise.
*/ */
final public function isDirty()
{
return ($this->_state === Doctrine_Entity::STATE_DIRTY ||
$this->_state === Doctrine_Entity::STATE_TDIRTY);
}
/**
* Checks whether the entity has been modified since it was last synchronized
* with the database.
*
* @return boolean TRUE if the object has been modified, FALSE otherwise.
* @deprecated Use isDirty()
*/
final public function isModified() final public function isModified()
{ {
return ($this->_state === Doctrine_Entity::STATE_DIRTY || return ($this->_state === Doctrine_Entity::STATE_DIRTY ||
...@@ -1512,7 +1397,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -1512,7 +1397,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
* @return boolean * @return boolean
* @todo Better name? hasAssociation() ? * @todo Better name? hasAssociation() ?
*/ */
public function hasReference($name) final public function hasReference($name)
{ {
return isset($this->_references[$name]); return isset($this->_references[$name]);
} }
...@@ -1523,7 +1408,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -1523,7 +1408,7 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
* @param string $name * @param string $name
* @throws Doctrine_Record_Exception if trying to get an unknown related component * @throws Doctrine_Record_Exception if trying to get an unknown related component
*/ */
public function obtainReference($name) final public function obtainReference($name)
{ {
if (isset($this->_references[$name])) { if (isset($this->_references[$name])) {
return $this->_references[$name]; return $this->_references[$name];
...@@ -1774,6 +1659,8 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -1774,6 +1659,8 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
/** /**
* Gets the ClassMetadata object that describes the entity class. * Gets the ClassMetadata object that describes the entity class.
*
* @return Doctrine::ORM::Mapping::ClassMetadata
*/ */
final public function getClassMetadata() final public function getClassMetadata()
{ {
...@@ -1781,9 +1668,10 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -1781,9 +1668,10 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
} }
/** /**
* Enter description here... * Gets the EntityManager that is responsible for the persistence of
* the Entity.
* *
* @return unknown * @return Doctrine::ORM::EntityManager
*/ */
final public function getEntityManager() final public function getEntityManager()
{ {
...@@ -1791,9 +1679,9 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable ...@@ -1791,9 +1679,9 @@ abstract class Doctrine_Entity extends Doctrine_Access implements Serializable
} }
/** /**
* Enter description here... * Gets the EntityRepository of the Entity.
* *
* @return unknown * @return Doctrine::ORM::EntityRepository
*/ */
final public function getRepository() final public function getRepository()
{ {
......
...@@ -31,10 +31,8 @@ ...@@ -31,10 +31,8 @@
/** /**
* The EntityManager is a central access point to ORM functionality. * The EntityManager is the central access point to ORM functionality.
* *
* @package Doctrine
* @subpackage EntityManager
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org * @link www.phpdoctrine.org
* @since 2.0 * @since 2.0
...@@ -88,7 +86,6 @@ class Doctrine_EntityManager ...@@ -88,7 +86,6 @@ class Doctrine_EntityManager
/** /**
* The EntityPersister instances. * The EntityPersister instances.
* @todo Implementation.
* *
* @var array * @var array
*/ */
...@@ -109,7 +106,7 @@ class Doctrine_EntityManager ...@@ -109,7 +106,7 @@ class Doctrine_EntityManager
private $_flushMode = 'commit'; private $_flushMode = 'commit';
/** /**
* The unit of work. * The unit of work used to coordinate object-level transactions.
* *
* @var UnitOfWork * @var UnitOfWork
*/ */
...@@ -122,13 +119,6 @@ class Doctrine_EntityManager ...@@ -122,13 +119,6 @@ class Doctrine_EntityManager
*/ */
private $_eventManager; private $_eventManager;
/**
* Enter description here...
*
* @var unknown_type
*/
//private $_dataTemplates = array();
/** /**
* Container that is used temporarily during hydration. * Container that is used temporarily during hydration.
* *
...@@ -163,7 +153,7 @@ class Doctrine_EntityManager ...@@ -163,7 +153,7 @@ class Doctrine_EntityManager
} }
/** /**
* Returns the metadata for a class. Alias for getClassMetadata(). * Gets the metadata for a class. Alias for getClassMetadata().
* *
* @return Doctrine_Metadata * @return Doctrine_Metadata
* @todo package:orm * @todo package:orm
...@@ -173,6 +163,17 @@ class Doctrine_EntityManager ...@@ -173,6 +163,17 @@ class Doctrine_EntityManager
return $this->getClassMetadata($className); return $this->getClassMetadata($className);
} }
/**
* Gets the transaction object used by the EntityManager to manage
* database transactions.
*
* @return Doctrine::DBAL::Transaction
*/
public function getTransaction()
{
return $this->_conn->getTransaction();
}
/** /**
* Returns the metadata for a class. * Returns the metadata for a class.
* *
...@@ -184,8 +185,8 @@ class Doctrine_EntityManager ...@@ -184,8 +185,8 @@ class Doctrine_EntityManager
} }
/** /**
* Sets the driver that is used to obtain metadata informations about entity * Sets the driver that is used to obtain metadata mapping information
* classes. * about Entities.
* *
* @param $driver The driver to use. * @param $driver The driver to use.
*/ */
...@@ -197,7 +198,8 @@ class Doctrine_EntityManager ...@@ -197,7 +198,8 @@ class Doctrine_EntityManager
/** /**
* Creates a new Doctrine_Query object that operates on this connection. * Creates a new Doctrine_Query object that operates on this connection.
* *
* @return Doctrine_Query * @param string The DQL string.
* @return Doctrine::ORM::Query
* @todo package:orm * @todo package:orm
*/ */
public function createQuery($dql = "") public function createQuery($dql = "")
...@@ -211,10 +213,12 @@ class Doctrine_EntityManager ...@@ -211,10 +213,12 @@ class Doctrine_EntityManager
} }
/** /**
* Enter description here... * Gets the EntityPersister for an Entity.
* *
* @param unknown_type $entityName * This is usually not of interest for users, mainly for internal use.
* @return unknown *
* @param string $entityName The name of the Entity.
* @return Doctrine::ORM::Internal::EntityPersister
*/ */
public function getEntityPersister($entityName) public function getEntityPersister($entityName)
{ {
...@@ -241,30 +245,6 @@ class Doctrine_EntityManager ...@@ -241,30 +245,6 @@ class Doctrine_EntityManager
return $this->_unitOfWork->unregisterIdentity($entity); return $this->_unitOfWork->unregisterIdentity($entity);
} }
/**
* Returns the current internal transaction nesting level.
*
* @return integer The nesting level. A value of 0 means theres no active transaction.
* @todo package:orm???
*/
public function getInternalTransactionLevel()
{
return $this->transaction->getInternalTransactionLevel();
}
/**
* Initiates a transaction.
*
* This method must only be used by Doctrine itself to initiate transactions.
* Userland-code must use {@link beginTransaction()}.
*
* @todo package:orm???
*/
public function beginInternalTransaction($savepoint = null)
{
return $this->transaction->beginInternalTransaction($savepoint);
}
/** /**
* Creates a query with the specified name. * Creates a query with the specified name.
* *
...@@ -307,16 +287,16 @@ class Doctrine_EntityManager ...@@ -307,16 +287,16 @@ class Doctrine_EntityManager
*/ */
public function flush() public function flush()
{ {
$this->beginInternalTransaction();
$this->_unitOfWork->flush(); $this->_unitOfWork->flush();
$this->commit();
} }
/** /**
* Enter description here... * Finds an Entity by its identifier.
* This is just a convenient shortcut for getRepository()->find().
* *
* @param unknown_type $entityName * @param string $entityName
* @param unknown_type $identifier * @param mixed $identifier
* @return Doctrine::ORM::Entity
*/ */
public function find($entityName, $identifier) public function find($entityName, $identifier)
{ {
...@@ -356,11 +336,8 @@ class Doctrine_EntityManager ...@@ -356,11 +336,8 @@ class Doctrine_EntityManager
{ {
if ($entityName === null) { if ($entityName === null) {
$this->_unitOfWork->detachAll(); $this->_unitOfWork->detachAll();
foreach ($this->_mappers as $mapper) {
$mapper->clear(); // clear identity map of each mapper
}
} else { } else {
$this->getMapper($entityName)->clear(); //...
} }
} }
...@@ -370,7 +347,7 @@ class Doctrine_EntityManager ...@@ -370,7 +347,7 @@ class Doctrine_EntityManager
*/ */
public function close() public function close()
{ {
//Doctrine_EntityManagerFactory::releaseManager($this);
} }
/** /**
...@@ -408,24 +385,7 @@ class Doctrine_EntityManager ...@@ -408,24 +385,7 @@ class Doctrine_EntityManager
*/ */
public function save(Doctrine_Entity $entity) public function save(Doctrine_Entity $entity)
{ {
$state = $entity->_state(); $this->_unitOfWork->save($entity);
if ($state == Doctrine_Entity::STATE_CLEAN || $state == Doctrine_Entity::STATE_LOCKED) {
return;
}
//...
//$this->_unitOfWork->
switch ($entity->_state()) {
case Doctrine_Entity::STATE_CLEAN:
//nothing to do
break;
case Doctrine_Entity::STATE_DIRTY:
$this->_unitOfWork->registerDirty($entity);
break;
case Doctrine_Entity::STATE_TCLEAN:
case Doctrine_Entity::STATE_TDIRTY:
//...
}
} }
/** /**
...@@ -433,14 +393,14 @@ class Doctrine_EntityManager ...@@ -433,14 +393,14 @@ class Doctrine_EntityManager
*/ */
public function delete(Doctrine_Entity $entity) public function delete(Doctrine_Entity $entity)
{ {
//... $this->_unitOfWork->delete($entity);
} }
/** /**
* Gets the repository for the given entity name. * Gets the repository for an Entity.
* *
* @return Doctrine_EntityRepository The repository. * @param string $entityName The name of the Entity.
* @todo Implementation. * @return Doctrine::ORM::EntityRepository The repository.
*/ */
public function getRepository($entityName) public function getRepository($entityName)
{ {
......
...@@ -62,21 +62,11 @@ abstract class Doctrine_EntityPersister_Abstract ...@@ -62,21 +62,11 @@ abstract class Doctrine_EntityPersister_Abstract
*/ */
protected $_em; protected $_em;
/**
* The concrete mapping strategy that is used.
*/
protected $_mappingStrategy;
/** /**
* Null object. * Null object.
*/ */
private $_nullObject; private $_nullObject;
/**
* A list of registered entity listeners.
*/
private $_entityListeners = array();
/** /**
* Enter description here... * Enter description here...
* *
...@@ -318,8 +308,8 @@ abstract class Doctrine_EntityPersister_Abstract ...@@ -318,8 +308,8 @@ abstract class Doctrine_EntityPersister_Abstract
*/ */
protected function _insertOrUpdate(Doctrine_Entity $record) protected function _insertOrUpdate(Doctrine_Entity $record)
{ {
$record->preSave(); //$record->preSave();
$this->notifyEntityListeners($record, 'preSave', Doctrine_Event::RECORD_SAVE); //$this->notifyEntityListeners($record, 'preSave', Doctrine_Event::RECORD_SAVE);
switch ($record->_state()) { switch ($record->_state()) {
case Doctrine_Entity::STATE_TDIRTY: case Doctrine_Entity::STATE_TDIRTY:
...@@ -335,8 +325,8 @@ abstract class Doctrine_EntityPersister_Abstract ...@@ -335,8 +325,8 @@ abstract class Doctrine_EntityPersister_Abstract
break; break;
} }
$record->postSave(); //$record->postSave();
$this->notifyEntityListeners($record, 'postSave', Doctrine_Event::RECORD_SAVE); //$this->notifyEntityListeners($record, 'postSave', Doctrine_Event::RECORD_SAVE);
} }
/** /**
...@@ -351,7 +341,6 @@ abstract class Doctrine_EntityPersister_Abstract ...@@ -351,7 +341,6 @@ abstract class Doctrine_EntityPersister_Abstract
} }
/** /**
* _saveRelated
* saves all related records to $record * saves all related records to $record
* *
* @throws PDOException if something went wrong at database level * @throws PDOException if something went wrong at database level
......
...@@ -20,12 +20,10 @@ ...@@ -20,12 +20,10 @@
*/ */
/** /**
* The joined mapping strategy maps a single entity instance to several tables in the * The joined subclass persister maps a single entity instance to several tables in the
* database as it is defined by <tt>Class Table Inheritance</tt>. * database as it is defined by <tt>Class Table Inheritance</tt>.
* *
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @package Doctrine
* @subpackage JoinedSubclass
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version $Revision$ * @version $Revision$
* @link www.phpdoctrine.org * @link www.phpdoctrine.org
...@@ -33,7 +31,7 @@ ...@@ -33,7 +31,7 @@
*/ */
class Doctrine_EntityPersister_JoinedSubclass extends Doctrine_EntityPersister_Abstract class Doctrine_EntityPersister_JoinedSubclass extends Doctrine_EntityPersister_Abstract
{ {
protected $_columnNameFieldNameMap = array(); //protected $_columnNameFieldNameMap = array();
/** /**
* Inserts an entity that is part of a Class Table Inheritance hierarchy. * Inserts an entity that is part of a Class Table Inheritance hierarchy.
...@@ -94,7 +92,6 @@ class Doctrine_EntityPersister_JoinedSubclass extends Doctrine_EntityPersister_A ...@@ -94,7 +92,6 @@ class Doctrine_EntityPersister_JoinedSubclass extends Doctrine_EntityPersister_A
* *
* @param Doctrine_Entity $record record to be updated * @param Doctrine_Entity $record record to be updated
* @return boolean whether or not the update was successful * @return boolean whether or not the update was successful
* @todo Move to Doctrine_Table (which will become Doctrine_Mapper).
*/ */
protected function _doUpdate(Doctrine_Entity $record) protected function _doUpdate(Doctrine_Entity $record)
{ {
...@@ -223,34 +220,6 @@ class Doctrine_EntityPersister_JoinedSubclass extends Doctrine_EntityPersister_A ...@@ -223,34 +220,6 @@ class Doctrine_EntityPersister_JoinedSubclass extends Doctrine_EntityPersister_A
return $fieldNames; return $fieldNames;
} }
/**
*
*/
/*public function getFieldName($columnName)
{
if (isset($this->_columnNameFieldNameMap[$columnName])) {
return $this->_columnNameFieldNameMap[$columnName];
}
$classMetadata = $this->_classMetadata;
$conn = $this->_conn;
if ($classMetadata->hasColumn($columnName)) {
$this->_columnNameFieldNameMap[$columnName] = $classMetadata->getFieldName($columnName);
return $this->_columnNameFieldNameMap[$columnName];
}
foreach ($classMetadata->getSubclasses() as $subClass) {
$subTable = $conn->getClassMetadata($subClass);
if ($subTable->hasColumn($columnName)) {
$this->_columnNameFieldNameMap[$columnName] = $subTable->getFieldName($columnName);
return $this->_columnNameFieldNameMap[$columnName];
}
}
throw new Doctrine_Mapper_Exception("No field name found for column name '$columnName'.");
}*/
/** /**
* *
* @todo Looks like this better belongs into the ClassMetadata class. * @todo Looks like this better belongs into the ClassMetadata class.
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#namespace Doctrine::ORM; #namespace Doctrine::ORM;
/** /**
* A repository provides the illusion of an in-memory Entity store.
* Base class for all custom user-defined repositories. * Base class for all custom user-defined repositories.
* Provides basic finder methods, common to all repositories. * Provides basic finder methods, common to all repositories.
* *
...@@ -48,7 +49,6 @@ class Doctrine_EntityRepository ...@@ -48,7 +49,6 @@ class Doctrine_EntityRepository
} }
/** /**
* createQuery
* creates a new Doctrine_Query object and adds the component name * creates a new Doctrine_Query object and adds the component name
* of this table as the query 'from' part * of this table as the query 'from' part
* *
......
...@@ -29,93 +29,11 @@ ...@@ -29,93 +29,11 @@
* @subpackage EventListener * @subpackage EventListener
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org * @link www.phpdoctrine.org
* @since 1.0 * @since 2.0
* @version $Revision$ * @version $Revision$
* @todo Remove. The 2.0 event system has no listener interfaces. * @todo Remove. The 2.0 event system has no listener interfaces.
*/ */
class Doctrine_EventListener implements Doctrine_EventListener_Interface interface Doctrine_EventSubscriber
{ {
public function preClose(Doctrine_Event $event) public function getSubscribedEvents();
{ }
public function postClose(Doctrine_Event $event)
{ }
public function onCollectionDelete(Doctrine_Collection $collection)
{ }
public function onPreCollectionDelete(Doctrine_Collection $collection)
{ }
public function onOpen(Doctrine_Connection $connection)
{ }
public function preTransactionCommit(Doctrine_Event $event)
{ }
public function postTransactionCommit(Doctrine_Event $event)
{ }
public function preTransactionRollback(Doctrine_Event $event)
{ }
public function postTransactionRollback(Doctrine_Event $event)
{ }
public function preTransactionBegin(Doctrine_Event $event)
{ }
public function postTransactionBegin(Doctrine_Event $event)
{ }
public function preSavepointCommit(Doctrine_Event $event)
{ }
public function postSavepointCommit(Doctrine_Event $event)
{ }
public function preSavepointRollback(Doctrine_Event $event)
{ }
public function postSavepointRollback(Doctrine_Event $event)
{ }
public function preSavepointCreate(Doctrine_Event $event)
{ }
public function postSavepointCreate(Doctrine_Event $event)
{ }
public function postConnect(Doctrine_Event $event)
{ }
public function preConnect(Doctrine_Event $event)
{ }
public function preQuery(Doctrine_Event $event)
{ }
public function postQuery(Doctrine_Event $event)
{ }
public function prePrepare(Doctrine_Event $event)
{ }
public function postPrepare(Doctrine_Event $event)
{ }
public function preExec(Doctrine_Event $event)
{ }
public function postExec(Doctrine_Event $event)
{ }
public function preError(Doctrine_Event $event)
{ }
public function postError(Doctrine_Event $event)
{ }
public function preFetch(Doctrine_Event $event)
{ }
public function postFetch(Doctrine_Event $event)
{ }
public function preFetchAll(Doctrine_Event $event)
{ }
public function postFetchAll(Doctrine_Event $event)
{ }
public function preStmtExecute(Doctrine_Event $event)
{ }
public function postStmtExecute(Doctrine_Event $event)
{ }
} }
...@@ -56,10 +56,10 @@ class Doctrine_EventManager ...@@ -56,10 +56,10 @@ class Doctrine_EventManager
foreach ($this->_listeners[$callback] as $listener) { foreach ($this->_listeners[$callback] as $listener) {
$listener->$callback($event); $listener->$callback($event);
} }
}
return ! $event->getDefaultPrevented(); return ! $event->getDefaultPrevented();
} }
return true;
}
/** /**
* Gets the listeners of a specific event or all listeners. * Gets the listeners of a specific event or all listeners.
......
...@@ -227,6 +227,7 @@ class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract ...@@ -227,6 +227,7 @@ class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract
} else if (isset($resultPointers[$parent])) { } else if (isset($resultPointers[$parent])) {
$baseElement =& $resultPointers[$parent]; $baseElement =& $resultPointers[$parent];
} else { } else {
unset($prev[$dqlAlias]); // Ticket #1228
continue; continue;
} }
...@@ -256,7 +257,8 @@ class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract ...@@ -256,7 +257,8 @@ class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract
} else { } else {
// x-1 relation // x-1 relation
$oneToOne = true; $oneToOne = true;
if ( ! isset($nonemptyComponents[$dqlAlias])) { if ( ! isset($nonemptyComponents[$dqlAlias]) &&
! $driver->isFieldSet($baseElement, $relationAlias)) {
$driver->setRelatedElement($baseElement, $relationAlias, $driver->setRelatedElement($baseElement, $relationAlias,
$driver->getNullPointer()); $driver->getNullPointer());
} else if ( ! $driver->isFieldSet($baseElement, $relationAlias)) { } else if ( ! $driver->isFieldSet($baseElement, $relationAlias)) {
...@@ -293,8 +295,6 @@ class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract ...@@ -293,8 +295,6 @@ class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract
} }
/** /**
* _setLastElement
*
* sets the last element of given data array / collection * sets the last element of given data array / collection
* as previous element * as previous element
* *
...@@ -308,7 +308,8 @@ class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract ...@@ -308,7 +308,8 @@ class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract
*/ */
protected function _setLastElement(&$resultPointers, &$coll, $index, $dqlAlias, $oneToOne) protected function _setLastElement(&$resultPointers, &$coll, $index, $dqlAlias, $oneToOne)
{ {
if ($coll === $this->_nullObject) { if ($coll === $this->_nullObject || $coll === null) {
unset($resultPointers[$dqlAlias]); // Ticket #1228
return false; return false;
} }
...@@ -330,8 +331,6 @@ class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract ...@@ -330,8 +331,6 @@ class Doctrine_HydratorNew extends Doctrine_Hydrator_Abstract
$resultPointers[$dqlAlias] = $coll; $resultPointers[$dqlAlias] = $coll;
} else if (count($coll) > 0) { } else if (count($coll) > 0) {
$resultPointers[$dqlAlias] = $coll->getLast(); $resultPointers[$dqlAlias] = $coll->getLast();
} else if (isset($resultPointers[$dqlAlias])) {
unset($resultPointers[$dqlAlias]);
} }
} }
......
...@@ -77,7 +77,7 @@ class Doctrine_Query_Production_IndexBy extends Doctrine_Query_Production ...@@ -77,7 +77,7 @@ class Doctrine_Query_Production_IndexBy extends Doctrine_Query_Production
} }
// The INDEXBY field must be either the (primary && not part of composite pk) || (unique && notnull) // The INDEXBY field must be either the (primary && not part of composite pk) || (unique && notnull)
$columnMapping = $classMetadata->getColumnMapping($this->_fieldName); $columnMapping = $classMetadata->getFieldMapping($this->_fieldName);
if ( ! $classMetadata->isIdentifier($this->_fieldName) && ! $classMetadata->isUniqueField($this->_fieldName) && ! $classMetadata->isNotNull($this->_fieldName)) { if ( ! $classMetadata->isIdentifier($this->_fieldName) && ! $classMetadata->isUniqueField($this->_fieldName) && ! $classMetadata->isNotNull($this->_fieldName)) {
$this->_parser->semanticalError( $this->_parser->semanticalError(
......
...@@ -22,6 +22,7 @@ class CustomAccessorMutatorTestEntity extends Doctrine_Entity ...@@ -22,6 +22,7 @@ class CustomAccessorMutatorTestEntity extends Doctrine_Entity
{ {
public static function initMetadata($class) public static function initMetadata($class)
{ {
$class->mapColumn('id', 'integer', 4, array('primary'));
$class->mapColumn('username', 'string', 50, array( $class->mapColumn('username', 'string', 50, array(
'accessor' => 'getUsernameCustom', 'accessor' => 'getUsernameCustom',
'mutator' => 'setUsernameCustom')); 'mutator' => 'setUsernameCustom'));
...@@ -42,6 +43,7 @@ class MagicAccessorMutatorTestEntity extends Doctrine_Entity ...@@ -42,6 +43,7 @@ class MagicAccessorMutatorTestEntity extends Doctrine_Entity
{ {
public static function initMetadata($class) public static function initMetadata($class)
{ {
$class->mapColumn('id', 'integer', 4, array('primary'));
$class->mapColumn('username', 'string', 50, array()); $class->mapColumn('username', 'string', 50, array());
} }
......
...@@ -6,7 +6,7 @@ class Orm_Entity_ConstructorTest extends Doctrine_OrmTestCase ...@@ -6,7 +6,7 @@ class Orm_Entity_ConstructorTest extends Doctrine_OrmTestCase
public function testFieldInitializationInConstructor() public function testFieldInitializationInConstructor()
{ {
$entity = new ConstructorTestEntity1("romanb"); $entity = new ConstructorTestEntity1("romanb");
$this->assertTrue($entity->isTransient()); $this->assertTrue($entity->isNew());
$this->assertEquals("romanb", $entity->username); $this->assertEquals("romanb", $entity->username);
} }
} }
...@@ -16,7 +16,7 @@ class ConstructorTestEntity1 extends Doctrine_Entity ...@@ -16,7 +16,7 @@ class ConstructorTestEntity1 extends Doctrine_Entity
public function __construct($username = null) public function __construct($username = null)
{ {
parent::__construct(); parent::__construct();
if ($this->isTransient()) { if ($this->isNew()) {
$this->username = $username; $this->username = $username;
} }
} }
...@@ -24,6 +24,7 @@ class ConstructorTestEntity1 extends Doctrine_Entity ...@@ -24,6 +24,7 @@ class ConstructorTestEntity1 extends Doctrine_Entity
/* The mapping definition */ /* The mapping definition */
public static function initMetadata($class) public static function initMetadata($class)
{ {
$class->mapColumn('id', 'integer', 4, array('primary'));
$class->mapColumn('username', 'string', 50, array()); $class->mapColumn('username', 'string', 50, array());
} }
} }
......
<?php <?php
class ForumBoard extends Doctrine_Entity { class ForumBoard extends Doctrine_Entity {
public static function initMetadata($class) { public static function initMetadata($metadata) {
$class->mapColumn('position', 'integer'); /*$metadata->mapField(array(
$class->mapColumn('category_id', 'integer'); 'fieldName' => 'id',
$class->hasOne('ForumCategory as category', 'id' => true,
'type' => 'integer',
'length' => 4
));
*/
$metadata->mapColumn('id', 'integer', 4, array('primary'));
$metadata->mapColumn('position', 'integer');
$metadata->mapColumn('category_id', 'integer');
$metadata->hasOne('ForumCategory as category',
array('local' => 'category_id', 'foreign' => 'id')); array('local' => 'category_id', 'foreign' => 'id'));
/*
$metadata->mapOneToOne(array(
'fieldName' => 'category', // optional, defaults to targetEntity
'targetEntity' => 'ForumCategory',
'joinColumns' => array('category_id' => 'id')
));
*/
} }
} }
<?php <?php
class ForumCategory extends Doctrine_Entity { class ForumCategory extends Doctrine_Entity {
public static function initMetadata($class) { public static function initMetadata($class) {
$class->mapColumn('id', 'integer', 4, array('primary'));
$class->mapColumn('position', 'integer'); $class->mapColumn('position', 'integer');
$class->mapColumn('name', 'string', 255); $class->mapColumn('name', 'string', 255);
$class->hasMany('ForumBoard as boards', array( $class->hasMany('ForumBoard as boards', array(
......
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