Commit 99710570 authored by romanb's avatar romanb

moving towards transparent persistence.

parent 2aea62a4
This diff is collapsed.
......@@ -6,9 +6,10 @@
* Usage recommendation:
* 1) Use only 1 class loader instance.
* 2) Prepend the base paths to your class libraries (including Doctrine's) to your include path.
* 3) DO NOT setCheckFileExists(true). Doing so is expensive.
* 3) DO NOT setCheckFileExists(true). Doing so is expensive in terms of performance.
*
* @since 2.0
* @author romanb <roman@code-factory.org>
*/
class Doctrine_Common_ClassLoader
{
......@@ -79,12 +80,13 @@ class Doctrine_Common_ClassLoader
/**
* Registers this class loader using spl_autoload_register().
*
* @return void
*/
public function register()
{
spl_autoload_register(array($this, 'loadClass'));
}
}
......
<?php
#namespace Doctrine\Common;
/**
* The ClassMetadata class represents a generic container for metadata of a class.
*
* @author robo
*/
class Doctrine_Common_ClassMetadata
{
/** The metadata that applies to the class. */
protected $_classMetadata = array();
/** The metadata that applies to properties of the class. */
protected $_fieldMetadata = array();
protected $_entityName;
/**
*
*
* @param <type> $className
*/
public function __construct($className)
{
$this->_entityName = $className;
}
/**
* Adds metadata to a property of the class.
*
* @param string $fieldName
* @param array $fieldMetadata
*/
public function addFieldMetadata($fieldName, array $fieldMetadata)
{
$this->_fieldMetadata[$fieldName] = array_merge(
isset($this->_fieldMetadata[$fieldName]) ? $this->_fieldMetadata[$fieldName] : array(),
$fieldMetadata);
}
/**
*
*
* @param <type> $fieldName
* @param <type> $metadata
*/
public function setFieldMetadata($fieldName, array $metadata)
{
$this->_fieldMetadata[$fieldName] = $metadata;
}
/**
*
* @param <type> $fieldName
* @param <type> $metadataKey
* @param <type> $value
*/
public function setFieldMetadataEntry($fieldName, $metadataKey, $value)
{
$this->_fieldMetadata[$fieldName][$metadataKey] = $value;
}
/**
* Gets metadata of a property of the class.
*
* @param string $fieldName
* @param string $metadataKey
* @return mixed
*/
public function getFieldMetadata($fieldName)
{
return $this->_fieldMetadata[$fieldName];
}
/**
*
* @param <type> $fieldName
* @param <type> $metadataKey
* @return <type>
*/
public function getFieldMetadataEntry($fieldName, $metadataKey)
{
return isset($this->_fieldMetadata[$fieldName][$metadataKey]) ?
$this->_fieldMetadata[$fieldName][$metadataKey] : null;
}
/**
* Gets metadata of the class.
*
* @param string $metadataKey
* @return mixed
*/
public function getClassMetadata()
{
return $this->_classMetadata;
}
/**
*
*
* @param <type> $metadataKey
*/
public function getClassMetadataEntry($metadataKey)
{
return isset($this->_classMetadata[$metadataKey]) ?
$this->_classMetadata[$metadataKey] : null;
}
/**
* Adds metadata to the class.
*
* @param array $classMetadata
*/
public function addClassMetadata(array $classMetadata)
{
$this->_classMetadata = array_merge($this->_classMetadata, $classMetadata);
}
/**
*
*
* @param <type> $metadata
*/
public function setClassMetadata(array $metadata)
{
$this->_classMetadata = $metadata;
}
/**
*
* @param <type> $metadataKey
* @param <type> $value
*/
public function setClassMetadataEntry($metadataKey, $value)
{
$this->_classMetadata[$metadataKey] = $value;
}
}
?>
<?php
#namespace Doctrine\Common;
/**
* Description of ClassMetadataFactory
*
* @author robo
*/
class Doctrine_Common_ClassMetadataFactory {
/** The factory driver. */
protected $_driver;
/** Map of the already loaded ClassMetadata instances, indexed by class name. */
protected $_loadedMetadata = array();
/**
* Creates a new factory instance that uses the given metadata driver implementation.
*
* @param $driver The metadata driver to use.
*/
public function __construct($driver)
{
$this->_driver = $driver;
}
/**
* Returns the metadata object for a class.
*
* @param string $className The name of the class.
* @return Doctrine_Metadata
*/
public function getMetadataFor($className)
{
if ( ! isset($this->_loadedMetadata[$className])) {
$this->_loadMetadata($className);
$this->_validateAndCompleteMetadata($className);
}
return $this->_loadedMetadata[$className];
}
/**
* Loads the metadata for the given class.
*
* @param <type> $className
* @return <type>
*/
protected function _loadMetadata($className)
{
$classMetadata = new Doctrine_Common_ClassMetadata();
$this->_driver->loadMetadataForClass($className, $classMetadata);
return $classMetadata;
}
/** Template method for subclasses */
protected function _validateAndCompleteMetadata($className)
{ /*empty*/ }
}
?>
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
#namespace Doctrine\Common\Collections;
#use \Countable;
#use \IteratorAggregate;
#use \Serializable;
#use \ArrayAccess;
/**
* A Collection is a wrapper around a php array and just like a php array a
* collection instance can be a list, a map or a hashmap, depending on how it
* is used.
*
* @author robo
*/
class Doctrine_Common_Collection implements Countable, IteratorAggregate, Serializable, ArrayAccess {
/**
* An array containing the entries of this collection.
* This is the wrapped php array.
*
* @var array
*/
protected $_data = array();
/**
* Unwraps the array contained in the Collection instance.
*
* @return array The wrapped array.
*/
public function unwrap()
{
return $this->_data;
}
/**
* returns the first record in the collection
*
* @return mixed
*/
public function getFirst()
{
return reset($this->_data);
}
/**
* returns the last record in the collection
*
* @return mixed
*/
public function getLast()
{
return end($this->_data);
}
/**
* returns the last record in the collection
*
* @return mixed
*/
public function end()
{
return end($this->_data);
}
/**
* returns the current key
*
* @return mixed
*/
public function key()
{
return key($this->_data);
}
/**
* Removes an entry from the collection.
*
* @param mixed $key
* @return boolean
*/
public function remove($key)
{
$removed = $this->_data[$key];
unset($this->_data[$key]);
return $removed;
}
/**
* __isset()
*
* @param string $name
* @return boolean whether or not this object contains $name
*/
public function __isset($key)
{
return $this->containsKey($key);
}
/**
* __unset()
*
* @param string $name
* @since 1.0
* @return mixed
*/
public function __unset($key)
{
return $this->remove($key);
}
/**
* Check if an offsetExists.
*
* Part of the ArrayAccess implementation.
*
* @param mixed $offset
* @return boolean whether or not this object contains $offset
*/
public function offsetExists($offset)
{
return $this->containsKey($offset);
}
/**
* offsetGet an alias of get()
*
* Part of the ArrayAccess implementation.
*
* @see get, __get
* @param mixed $offset
* @return mixed
*/
public function offsetGet($offset)
{
return $this->get($offset);
}
/**
* Part of the ArrayAccess implementation.
*
* sets $offset to $value
* @see set, __set
* @param mixed $offset
* @param mixed $value
* @return void
*/
public function offsetSet($offset, $value)
{
if ( ! isset($offset)) {
return $this->add($value);
}
return $this->set($offset, $value);
}
/**
* Part of the ArrayAccess implementation.
*
* unset a given offset
* @see set, offsetSet, __set
* @param mixed $offset
*/
public function offsetUnset($offset)
{
return $this->remove($offset);
}
/**
* Checks whether the collection contains an entity.
*
* @param mixed $key the key of the element
* @return boolean
*/
public function containsKey($key)
{
return isset($this->_data[$key]);
}
/**
* Enter description here...
*
* @param unknown_type $entity
* @return unknown
*/
public function contains($entity)
{
return in_array($entity, $this->_data, true);
}
/**
* Enter description here...
*
* @param unknown_type $otherColl
* @todo Impl
*/
public function containsAll($otherColl)
{
//...
}
/**
*
*/
public function search(Doctrine_ORM_Entity $record)
{
return array_search($record, $this->_data, true);
}
/**
* returns a record for given key
*
* Collection also maps referential information to newly created records
*
* @param mixed $key the key of the element
* @return Doctrine_Entity return a specified record
*/
public function get($key)
{
if (isset($this->_data[$key])) {
return $this->_data[$key];
}
return null;
}
/**
* Gets all keys.
* (Map method)
*
* @return array
*/
public function getKeys()
{
return array_keys($this->_data);
}
/**
* Gets all values.
* (Map method)
*
* @return array
*/
public function getValues()
{
return array_values($this->_data);
}
/**
* Returns the number of records in this collection.
*
* Implementation of the Countable interface.
*
* @return integer The number of records in the collection.
*/
public function count()
{
return count($this->_data);
}
/**
* When the collection is a Map this is like put(key,value)/add(key,value).
* When the collection is a List this is like add(position,value).
*
* @param integer $key
* @param mixed $value
* @return void
*/
public function set($key, $value)
{
if ( ! $value instanceof Doctrine_ORM_Entity) {
throw new Doctrine_Collection_Exception('Value variable in set is not an instance of Doctrine_Entity');
}
$this->_data[$key] = $value;
//TODO: Register collection as dirty with the UoW if necessary
$this->_changed();
}
/**
* Adds an entry to the collection.
*
* @param mixed $value
* @param string $key
* @return boolean
*/
public function add($value, $key = null)
{
//TODO: really only allow entities?
if ( ! $value instanceof Doctrine_ORM_Entity) {
throw new Doctrine_Record_Exception('Value variable in collection is not an instance of Doctrine_Entity.');
}
// TODO: Really prohibit duplicates?
if (in_array($value, $this->_data, true)) {
return false;
}
if (isset($key)) {
if (isset($this->_data[$key])) {
return false;
}
$this->_data[$key] = $value;
} else {
$this->_data[] = $value;
}
if ($this->_hydrationFlag) {
if ($this->_backRefFieldName) {
// set back reference to owner
$value->_internalSetReference($this->_backRefFieldName, $this->_owner);
}
} else {
//TODO: Register collection as dirty with the UoW if necessary
$this->_changed();
}
return true;
}
/**
* Adds all entities of the other collection to this collection.
*
* @param unknown_type $otherCollection
* @todo Impl
*/
public function addAll($otherCollection)
{
}
/**
* Checks whether the collection is empty.
*
* @return boolean TRUE if the collection is empty, FALSE otherwise.
*/
public function isEmpty()
{
// Note: Little "trick". Empty arrays evaluate to FALSE. No need to count().
return ! (bool)$this->_data;
}
/**
* getIterator
*
* @return object ArrayIterator
*/
public function getIterator()
{
$data = $this->_data;
return new ArrayIterator($data);
}
/**
* returns a string representation of this object
*/
public function __toString()
{
return Doctrine_Lib::getCollectionAsString($this);
}
/**
* Clears the collection.
*
* @return void
*/
public function clear()
{
$this->_data = array();
}
}
?>
......@@ -140,7 +140,7 @@ class Doctrine_Common_Configuration
public function setTypeOverrides(array $overrides)
{
foreach ($override as $name => $typeClassName) {
Doctrine_DataType::overrideType($name, $typeClassName);
Doctrine_DBAL_Types_Type::overrideType($name, $typeClassName);
}
}
}
\ No newline at end of file
......@@ -92,11 +92,7 @@ class Doctrine_Common_EventManager
public function addEventListener($events, $listener)
{
// TODO: maybe check for duplicate registrations?
if ( ! is_array($events)) {
$events = array($events);
}
foreach ($events as $event) {
foreach ((array)$events as $event) {
$this->_listeners[$event] = $listener;
}
}
......
......@@ -18,13 +18,13 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
#namespace Doctrine::Common;
#namespace Doctrine::Common;
/**
* An EventSubscriber knows itself what events it is interested in.
* If an EventSubscriber is added to an EventManager, the manager invokes
* getSubscribedEvents() and registers the subscriber as a listener for all
* An EventSubscriber knows himself what events he is interested in.
* If an EventSubscriber is added to an EventManager, the manager invokes
* getSubscribedEvents() and registers the subscriber as a listener for all
* returned events.
*
* @author Roman Borschel <roman@code-factory.org>
......
......@@ -18,8 +18,8 @@
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.org>.
*/
#namespace Doctrine::Common::Events;
#namespace Doctrine::Common::Events;
/**
* Doctrine_Event
......@@ -32,47 +32,46 @@
* @since 2.0
* @version $Revision$
*/
class Doctrine_Common_Events_Event
{
/* Event callback constants */
const preDelete = 'preDelete';
const postDelete = 'postDelete';
//...more
protected $_type;
protected $_target;
protected $_defaultPrevented;
public function __construct($type, $target = null)
{
$this->_type = $type;
$this->_target = $target;
$this->_defaultPrevented = false;
}
public function getType()
{
return $this->_type;
}
public function preventDefault()
{
$this->_defaultPrevented = true;
}
public function getDefaultPrevented()
{
return $this->_defaultPrevented;
}
public function getTarget()
{
return $this->_target;
}
class Doctrine_Common_Events_Event
{
/* Event callback constants */
const preDelete = 'preDelete';
const postDelete = 'postDelete';
//...more
protected $_type;
protected $_target;
protected $_defaultPrevented;
public function __construct($type, $target = null)
{
$this->_type = $type;
$this->_target = $target;
$this->_defaultPrevented = false;
}
public function getType()
{
return $this->_type;
}
public function preventDefault()
{
$this->_defaultPrevented = true;
}
public function getDefaultPrevented()
{
return $this->_defaultPrevented;
}
public function getTarget()
{
return $this->_target;
}
}
......@@ -17,7 +17,7 @@ class Doctrine_Common_Exceptions_DoctrineException extends Exception
public static function notImplemented($method, $class)
{
return new self("The method '$method' is not implemented in the class '$class'.");
return new self("The method '$method' is not implemented in class '$class'.");
}
}
......
<?php
#namespace Doctrine\Common;
#use \ArrayAccess;
/**
* Base class for classes that use the virtual property system.
*
* @author robo
*/
class Doctrine_Common_VirtualPropertyObject implements ArrayAccess
{
protected $_data = array();
protected $_entityName;
/**
* Initializes a new instance of a class derived from VirtualPropertyObject.
*/
public function __construct()
{
$this->_entityName = get_class($this);
if ( ! Doctrine_Common_VirtualPropertySystem::isInitialized($this->_entityName)) {
Doctrine_Common_VirtualPropertySystem::initialize($this->_entityName);
}
}
/**
* Generic getter for virtual properties.
*
* @param string $fieldName Name of the field.
* @return mixed
*/
final public function get($fieldName)
{
if ( ! Doctrine_Common_VirtualPropertySystem::hasProperty($this->_entityName, $fieldName)) {
throw new Doctrine_Exception("Access of undefined property '$fieldName'.");
}
$getter = $this->_getCustomAccessor($fieldName);
if ($getter) {
return $this->$getter();
}
return $this->_get($fieldName);
}
/**
* Generic setter for virtual properties.
*
* @param string $name The name of the field to set.
* @param mixed $value The value of the field.
*/
final public function set($fieldName, $value)
{
if ( ! Doctrine_Common_VirtualPropertySystem::hasProperty($this->_entityName, $fieldName)) {
throw new Doctrine_Exception("Access of undefined property '$fieldName'.");
}
if (Doctrine_Common_VirtualPropertySystem::isTypeCheckEnabled()) {
$this->_checkType($fieldName, $value);
}
$setter = $this->_getCustomMutator($fieldName);
if ($setter) {
return $this->$setter($value);
}
$this->_set($fieldName, $value);
}
/**
* Checks the type of a virtual property.
*
* @param <type> $fieldName
* @param <type> $value
*/
protected function _checkType($fieldName, $value)
{
$type = Doctrine_Common_VirtualPropertySystem::getType($this->_entityName, $fieldName);
if (Doctrine_Common_VirtualPropertySystem::isSimplePHPType($type)) {
$is_type = "is_$type";
if ( ! $is_type($value)) {
throw new Doctrine_Exception("'$value' is of an invalid type. Expected: $type.");
}
} else if ($type == 'array') {
if ( ! is_array($value)) {
throw new Doctrine_Exception("'$value' is of an invalid type. Expected: array.");
}
} else {
if ( ! $value instanceof $type) {
throw new Doctrine_Exception("'$value' is of an invalid type. Expected: $type.");
}
}
}
protected function _get($fieldName)
{
return isset($this->_data[$fieldName]) ? $this->_data[$fieldName] : null;
}
protected function _set($fieldName, $value)
{
$this->_data[$fieldName] = $value;
}
/**
* Gets the custom mutator method for a virtual property, 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)
{
if (Doctrine_Common_VirtualPropertySystem::getMutator($this->_entityName, $fieldName) === null) {
if (Doctrine_Common_VirtualPropertySystem::isAutoAccessorOverride()) {
$setterMethod = 'set' . Doctrine::classify($fieldName);
if ( ! method_exists($this, $setterMethod)) {
$setterMethod = false;
}
Doctrine_Common_VirtualPropertySystem::setMutator(
$this->_entityName, $fieldName, $setterMethod);
} else {
Doctrine_Common_VirtualPropertySystem::setMutator(
$this->_entityName, $fieldName, false);
}
}
return Doctrine_Common_VirtualPropertySystem::getMutator($this->_entityName, $fieldName);
}
/**
* Gets the custom accessor method of a virtual property, 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)
{
if (Doctrine_Common_VirtualPropertySystem::getAccessor($this->_entityName, $fieldName) === null) {
if (Doctrine_Common_VirtualPropertySystem::isAutoAccessorOverride()) {
$getterMethod = 'get' . Doctrine::classify($fieldName);
if ( ! method_exists($this, $getterMethod)) {
$getterMethod = false;
}
Doctrine_Common_VirtualPropertySystem::setAccessor(
$this->_entityName, $fieldName, $getterMethod);
} else {
Doctrine_Common_VirtualPropertySystem::setAccessor(
$this->_entityName, $fieldName, false);
}
}
return Doctrine_Common_VirtualPropertySystem::getAccessor($this->_entityName, $fieldName);
}
protected function _contains($fieldName)
{
return isset($this->_data[$fieldName]);
}
protected function _unset($fieldName)
{
unset($this->_data[$fieldName]);
}
/**
* Intercepts mutating calls for virtual properties.
*
* @see set, offsetSet
* @param $name
* @param $value
* @since 1.0
* @return void
*/
public function __set($name, $value)
{
$this->set($name, $value);
}
/**
* Intercepts accessing calls for virtual properties.
*
* @see get, offsetGet
* @param mixed $name
* @return mixed
*/
public function __get($name)
{
return $this->get($name);
}
/**
* Intercepts isset() calls for virtual properties.
*
* @param string $name
* @return boolean whether or not this object contains $name
*/
public function __isset($name)
{
return $this->_contains($name);
}
/**
* Intercepts unset() calls for virtual properties.
*
* @param string $name
* @return void
*/
public function __unset($name)
{
return $this->_unset($name);
}
/* ArrayAccess implementation */
/**
* Check if an offsetExists.
*
* @param mixed $offset
* @return boolean whether or not this object contains $offset
*/
public function offsetExists($offset)
{
return $this->_contains($offset);
}
/**
* offsetGet an alias of get()
*
* @see get, __get
* @param mixed $offset
* @return mixed
*/
public function offsetGet($offset)
{
return $this->get($offset);
}
/**
* sets $offset to $value
* @see set, __set
* @param mixed $offset
* @param mixed $value
* @return void
*/
public function offsetSet($offset, $value)
{
return $this->set($offset, $value);
}
/**
* unset a given offset
* @see set, offsetSet, __set
* @param mixed $offset
*/
public function offsetUnset($offset)
{
return $this->_unset($offset);
}
/* END of ArrayAccess implementation */
}
?>
<?php
/**
* The VirtualPropertySystem class is a class consisting solely of static methods and
* serves as a generic virtual property registry system.
* Classes register their (virtual) properties with the property system, optionally specifying
* property features/options. These can then be evaluated by other code.
*
* @author robo
* @since 2.0
*/
class Doctrine_Common_VirtualPropertySystem {
private static $_properties = array();
private static $_callback = 'construct';
private static $_checkTypes = false;
private static $_useAutoAccessorOverride = true;
private static $_simplePHPTypes = array(
'int' => true,
'string' => true,
'bool' => true,
'double' => true
);
/** Private constructor. This class cannot be instantiated. */
private function __construct() {}
/**
* Gets all properties of a class that are registered with the VirtualPropertySystem.
*
* @param string $class
* @return array
*/
public static function getProperties($class)
{
if ( ! self::isInitialized($class)) {
self::initialize($class);
}
return self::$_properties[$class];
}
/**
* Gets whether automatic accessor overrides are enabled.
*
* @return boolean
*/
public static function isAutoAccessorOverride()
{
return self::$_useAutoAccessorOverride;
}
/**
* Sets whether automatic accessor overrides are enabled.
*
* @param boolean $bool
*/
public static function setAutoAccessorOverride($bool)
{
self::$_useAutoAccessorOverride = (bool)$bool;
}
/**
* Prepopulates the property system.
*
* @param array $properties
*/
public static function populate(array $properties)
{
self::$_properties = $properties;
}
/**
* Checks whether the given type is a simple PHP type.
* Simple php types are: int, string, bool, double.
*
* @param string $type The type to check.
* @return boolean
*/
public static function isSimplePHPType($type)
{
return isset(self::$_simplePHPTypes[$type]);
}
/**
* Gets whether type checks are enabled.
*
* @return boolean
*/
public static function isTypeCheckEnabled()
{
return self::$_checkTypes;
}
/**
* Sets whether type checks are enabled.
*
* @param boolean $bool
*/
public static function setTypeCheckEnabled($bool)
{
self::$_checkTypes = (bool)$bool;
}
/**
* Sets the name of the callback method to use for initializing the virtual
* properties of a class. The callback must be static and public.
*
* @param string $callback
*/
public static function setCallback($callback)
{
self::$_callback = $callback;
}
/**
* Registers a virtual property for a class.
*
* @param string $class
* @param string $propName
* @param string $type
* @param string $accessor
* @param string $mutator
*/
public static function register($class, $propName, $type, $accessor = null, $mutator = null)
{
self::$_properties[$class][$propName] = array(
'type' => $type, 'accessor' => $accessor, 'mutator' => $mutator
);
}
/**
* Gets whether a class has already been initialized by the virtual property system.
*
* @param string $class
* @return boolean
*/
public static function isInitialized($class)
{
return isset(self::$_properties[$class]);
}
/**
* Initializes a class with the virtual property system.
*
* @param <type> $class
*/
public static function initialize($class)
{
if (method_exists($class, self::$_callback)) {
call_user_func(array($class, self::$_callback));
} else {
self::$_properties[$class] = false;
}
}
/**
* Gets whether a class has a virtual property with a certain name.
*
* @param string $class
* @param string $propName
* @return boolean
*/
public static function hasProperty($class, $propName)
{
return isset(self::$_properties[$class][$propName]);
}
/**
* Gets the accessor for a virtual property.
*
* @param string $class
* @param string $propName
* @return string|null
*/
public static function getAccessor($class, $propName)
{
return isset(self::$_properties[$class][$propName]['accessor']) ?
self::$_properties[$class][$propName]['accessor'] : null;
}
/**
* Sets the accessor method for a virtual property.
*
* @param <type> $class
* @param <type> $propName
* @param <type> $accessor
*/
public static function setAccessor($class, $propName, $accessor)
{
self::$_properties[$class][$propName]['accessor'] = $accessor;
}
/**
* Gets the mutator method for a virtual property.
*
* @param <type> $class
* @param <type> $propName
* @return <type>
*/
public static function getMutator($class, $propName)
{
return isset(self::$_properties[$class][$propName]['mutator']) ?
self::$_properties[$class][$propName]['mutator'] : null;
}
/**
* Sets the mutator method for a virtual property.
*
* @param <type> $class
* @param <type> $propName
* @param <type> $mutator
*/
public static function setMutator($class, $propName, $mutator)
{
self::$_properties[$class][$propName]['mutator'] = $mutator;
}
/**
* Gets the type of a virtual property.
*
* @param <type> $class
* @param <type> $propName
* @return <type>
*/
public static function getType($class, $propName)
{
return isset(self::$_properties[$class][$propName]['type']) ?
self::$_properties[$class][$propName]['type'] : null;
}
/**
* Sets the type of a virtual property.
*
* @param <type> $class
* @param <type> $propName
* @param <type> $type
*/
public static function setType($class, $propName, $type)
{
self::$_properties[$class][$propName]['type'] = $type;
}
}
?>
......@@ -19,14 +19,14 @@
* <http://www.phpdoctrine.org>.
*/
#namespace Doctrine::DBAL;
#namespace Doctrine\DBAL;
#use Doctrine::Common::Configuration;
#use Doctrine::Common::EventManager;
#use Doctrine::DBAL::Exceptions::ConnectionException;
#use Doctrine\Common\Configuration;
#use Doctrine\Common\EventManager;
#use Doctrine\DBAL\Exceptions\ConnectionException;
/**
* A wrapper around a Doctrine::DBAL::Driver::Connection that adds features like
* A wrapper around a Doctrine\DBAL\Driver\Connection that adds features like
* events, transaction isolation levels, configuration, emulated transaction nesting,
* lazy connecting and more.
*
......@@ -51,7 +51,7 @@
* 'masters' => array(...),
* 'masterConnectionResolver' => new MyMasterConnectionResolver()
*
* Doctrine::DBAL could ship with a simple standard broker that uses a primitive
* Doctrine\DBAL could ship with a simple standard broker that uses a primitive
* round-robin approach to distribution. User can provide its own brokers.
*/
class Doctrine_DBAL_Connection
......@@ -76,21 +76,21 @@ class Doctrine_DBAL_Connection
/**
* The wrapped driver connection.
*
* @var Doctrine::DBAL::Driver::Connection
* @var Doctrine\DBAL\Driver\Connection
*/
protected $_conn;
/**
* The Configuration.
*
* @var Doctrine::Common::Configuration
* @var Doctrine\Common\Configuration
*/
protected $_config;
/**
* The EventManager.
*
* @var Doctrine::Commom::EventManager
* @var Doctrine\Common\EventManager
*/
protected $_eventManager;
......@@ -116,7 +116,7 @@ class Doctrine_DBAL_Connection
protected $_transactionIsolationLevel;
/**
* The parameters used during creation of the Connection.
* The parameters used during creation of the Connection instance.
*
* @var array
*/
......@@ -133,32 +133,32 @@ class Doctrine_DBAL_Connection
* The DatabasePlatform object that provides information about the
* database platform used by the connection.
*
* @var Doctrine::DBAL::Platforms::DatabasePlatform
* @var Doctrine\DBAL\Platforms\AbstractPlatform
*/
protected $_platform;
/**
* The schema manager.
*
* @var Doctrine::DBAL::Schema::SchemaManager
* @var Doctrine\DBAL\Schema\SchemaManager
*/
protected $_schemaManager;
/**
* The used DBAL driver.
*
* @var Doctrine::DBAL::Driver
* @var Doctrine\DBAL\Driver
*/
protected $_driver;
/**
* Constructor.
* Creates a new Connection.
* Initializes a new instance of the Connection class.
*
* @param array $params The connection parameters.
*/
public function __construct(array $params, Doctrine_DBAL_Driver $driver,
Doctrine_Common_Configuration $config = null, Doctrine_Common_EventManager $eventManager = null)
Doctrine_Common_Configuration $config = null,
Doctrine_Common_EventManager $eventManager = null)
{
$this->_driver = $driver;
$this->_params = $params;
......@@ -193,7 +193,7 @@ class Doctrine_DBAL_Connection
/**
* Gets the EventManager used by the Connection.
*
* @return Doctrine::Common::EventManager
* @return Doctrine\Common\EventManager
*/
public function getEventManager()
{
......@@ -203,7 +203,7 @@ class Doctrine_DBAL_Connection
/**
* Gets the DatabasePlatform for the connection.
*
* @return Doctrine::DBAL::Platforms::DatabasePlatform
* @return Doctrine\DBAL\Platforms\AbstractPlatform
*/
public function getDatabasePlatform()
{
......@@ -842,7 +842,7 @@ class Doctrine_DBAL_Connection
/**
* Gets the wrapped driver connection.
*
* @return Doctrine::DBAL::Driver::Connection
* @return Doctrine\DBAL\Driver\Connection
*/
public function getWrappedConnection()
{
......@@ -853,7 +853,7 @@ class Doctrine_DBAL_Connection
* Gets the SchemaManager that can be used to inspect or change the
* database schema through the connection.
*
* @return Doctrine::DBAL::Schema::SchemaManager
* @return Doctrine\DBAL\Schema\SchemaManager
*/
public function getSchemaManager()
{
......
......@@ -90,7 +90,8 @@ final class Doctrine_DBAL_DriverManager
* @param Doctrine::Common::EventManager The event manager to use.
* @return Doctrine::DBAL::Connection
*/
public static function getConnection(array $params, Doctrine_Common_Configuration $config = null,
public static function getConnection(array $params,
Doctrine_Common_Configuration $config = null,
Doctrine_Common_EventManager $eventManager = null)
{
// create default config and event manager, if not set
......
<?php
#namespace Doctrine::DBAL::Types;
#namespace Doctrine\DBAL\Types;
#use Doctrine\DBAL\Platforms\AbstractDatabasePlatform;
abstract class Doctrine_DBAL_Types_Type
{
......@@ -14,7 +16,7 @@ abstract class Doctrine_DBAL_Types_Type
'double' => 'Doctrine_DataType_DoubleType'
);
public function convertToDatabaseValue($value, Doctrine_DatabasePlatform $platform)
public function convertToDatabaseValue($value, Doctrine_DBAL_Platforms_AbstractDatabasePlatform $platform)
{
return $value;
}
......@@ -24,8 +26,8 @@ abstract class Doctrine_DBAL_Types_Type
return $value;
}
abstract public function getDefaultLength(Doctrine_DatabasePlatform $platform);
abstract public function getSqlDeclaration(array $fieldDeclaration, Doctrine_DatabasePlatform $platform);
abstract public function getDefaultLength(Doctrine_DBAL_Platforms_AbstractDatabasePlatform $platform);
abstract public function getSqlDeclaration(array $fieldDeclaration, Doctrine_DBAL_Platforms_AbstractDatabasePlatform $platform);
abstract public function getName();
/**
......
......@@ -10,8 +10,45 @@
*
* @since 2.0
*/
class Doctrine_ORM_ActiveEntity extends Doctrine_ORM_Entity
class Doctrine_ORM_ActiveEntity extends Doctrine_Common_VirtualPropertyObject implements Doctrine_ORM_Entity
{
/**
* The class descriptor.
*
* @var Doctrine::ORM::ClassMetadata
*/
private $_class;
/**
* The changes that happened to fields of a managed entity.
* Keys are field names, values oldValue => newValue tuples.
*
* @var array
*/
private $_dataChangeSet = array();
/**
* The EntityManager that is responsible for the persistent state of the entity.
* Only managed entities have an associated EntityManager.
*
* @var Doctrine\ORM\EntityManager
*/
private $_em;
/**
* Initializes a new instance of a class derived from ActiveEntity.
*/
public function __construct() {
parent::__construct();
$this->_oid = self::$_index++;
$this->_em = Doctrine_ORM_EntityManager::getActiveEntityManager();
if (is_null($this->_em)) {
throw new Doctrine_Exception("No EntityManager found. ActiveEntity instances "
. "can only be instantiated within the context of an active EntityManager.");
}
$this->_class = $this->_em->getClassMetadata($this->_entityName);
}
/**
* Saves the current state of the entity into the database.
*
......@@ -419,6 +456,270 @@ class Doctrine_ORM_ActiveEntity extends Doctrine_ORM_Entity
$this->_data = array_merge($this->_data, $data);
$this->_extractIdentifier();
}
/**
* Helps freeing the memory occupied by the entity.
* Cuts all references the entity has to other entities and removes the entity
* from the instance pool.
* Note: The entity is no longer useable after free() has been called. Any operations
* done with the entity afterwards can lead to unpredictable results.
*
* @param boolean $deep Whether to cascade the free() call to (loaded) associated entities.
*/
public function free($deep = false)
{
if ($this->_state != self::STATE_LOCKED) {
if ($this->_state == self::STATE_MANAGED) {
$this->_em->detach($this);
}
if ($deep) {
foreach ($this->_data as $name => $value) {
if ($value instanceof Doctrine_ORM_Entity || $value instanceof Doctrine_ORM_Collection) {
$value->free($deep);
}
}
}
$this->_data = array();
}
}
/**
* Returns a string representation of this object.
*/
public function __toString()
{
return (string)$this->_oid;
}
/**
* Checks whether the entity is new.
*
* @return boolean TRUE if the entity is new, FALSE otherwise.
*/
final public function isNew()
{
return $this->_state == self::STATE_NEW;
}
/**
* 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.
*/
final public function isModified()
{
return count($this->_dataChangeSet) > 0;
}
/**
* Gets the ClassMetadata object that describes the entity class.
*
* @return Doctrine::ORM::Mapping::ClassMetadata
*/
final public function getClass()
{
return $this->_class;
}
/**
* Gets the EntityManager that is responsible for the persistence of
* this entity.
*
* @return Doctrine::ORM::EntityManager
*/
final public function getEntityManager()
{
return $this->_em;
}
/**
* Gets the EntityRepository of the Entity.
*
* @return Doctrine::ORM::EntityRepository
*/
final public function getRepository()
{
return $this->_em->getRepository($this->_entityName);
}
/**
* Checks whether a field is set (not null).
*
* @param string $name
* @return boolean
* @override
*/
final protected function _contains($fieldName)
{
if (isset($this->_data[$fieldName])) {
if ($this->_data[$fieldName] === Doctrine_ORM_Internal_Null::$INSTANCE) {
return false;
}
return true;
}
return false;
}
/**
* Clears the value of a field.
*
* @param string $name
* @return void
* @override
*/
final protected function _unset($fieldName)
{
if (isset($this->_data[$fieldName])) {
if ($this->_state == self::STATE_MANAGED && $this->_class->hasAssociation($fieldName)) {
$assoc = $this->_class->getAssociationMapping($fieldName);
if ($assoc->isOneToOne() && $assoc->shouldDeleteOrphans()) {
$this->_em->delete($this->_references[$fieldName]);
} else if ($assoc->isOneToMany() && $assoc->shouldDeleteOrphans()) {
foreach ($this->_references[$fieldName] as $entity) {
$this->_em->delete($entity);
}
}
}
$this->_data[$fieldName] = null;
}
}
/**
* Registers the entity as dirty with the UnitOfWork.
* Note: The Entity is only registered dirty if it is MANAGED and not yet
* registered as dirty.
*/
private function _registerDirty()
{
if ($this->_state == self::STATE_MANAGED &&
! $this->_em->getUnitOfWork()->isRegisteredDirty($this)) {
$this->_em->getUnitOfWork()->registerDirty($this);
}
}
/**
* Gets the entity class name.
*
* @return string
*/
final public function getClassName()
{
return $this->_entityName;
}
/**
* Gets the data of the Entity.
*
* @return array The fields and their values.
*/
final public function getData()
{
return $this->_data;
}
/**
* Gets the value of a field (regular field or reference).
*
* @param $name Name of the field.
* @return mixed Value of the field.
* @throws Doctrine::ORM::Exceptions::EntityException If trying to get an unknown field.
* @override
*/
final protected function _get($fieldName)
{
$nullObj = Doctrine_ORM_Internal_Null::$INSTANCE;
if (isset($this->_data[$fieldName])) {
return $this->_data[$fieldName] !== $nullObj ?
$this->_data[$fieldName] : null;
} else {
if ($this->_state == self::STATE_MANAGED && $this->_class->hasAssociation($fieldName)) {
$rel = $this->_class->getAssociationMapping($fieldName);
if ($rel->isLazilyFetched()) {
$this->_data[$fieldName] = $rel->lazyLoadFor($this);
return $this->_data[$fieldName] !== $nullObj ?
$this->_data[$fieldName] : null;
} else {
return null;
}
} else {
return null;
}
}
}
/**
* Sets the value of a field (regular field or reference).
*
* @param $fieldName The name of the field.
* @param $value The value of the field.
* @return void
* @throws Doctrine::ORM::Exceptions::EntityException
* @override
*/
final protected function _set($fieldName, $value)
{
$old = isset($this->_data[$fieldName]) ? $this->_data[$fieldName] : null;
if ( ! is_object($value)) {
// NOTE: Common case: $old != $value. Special case: null == 0 (TRUE), which
// is addressed by xor.
if ($old != $value || (is_null($old) xor is_null($value))) {
$this->_data[$fieldName] = $value;
$this->_dataChangeSet[$fieldName] = array($old => $value);
$this->_registerDirty();
}
} else {
if ($old !== $value) {
$this->_internalSetReference($fieldName, $value);
$this->_dataChangeSet[$fieldName] = array($old => $value);
$this->_registerDirty();
if ($this->_state == self::STATE_MANAGED) {
//TODO: Allow arrays in $value. Wrap them in a Collection transparently.
if ($old instanceof Doctrine_ORM_Collection) {
$this->_em->getUnitOfWork()->scheduleCollectionDeletion($old);
}
if ($value instanceof Doctrine_ORM_Collection) {
$this->_em->getUnitOfWork()->scheduleCollectionRecreation($value);
}
}
}
}
}
/* Serializable implementation */
/**
* Serializes the entity.
* This method is automatically called when the entity is serialized.
*
* Part of the implementation of the Serializable interface.
*
* @return string
* @todo Reimplement
*/
public function serialize()
{
return "";
}
/**
* Reconstructs the entity from it's serialized form.
* This method is automatically called everytime the entity is unserialized.
*
* @param string $serialized Doctrine_Entity as serialized string
* @throws Doctrine_Record_Exception if the cleanData operation fails somehow
* @return void
* @todo Reimplement.
*/
public function unserialize($serialized)
{
;
}
/* END of Serializable implementation */
}
?>
\ No newline at end of file
......@@ -45,6 +45,7 @@
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Roman Borschel <roman@code-factory.org>
* @todo Add more typical Collection methods.
* @todo Rename to PersistentCollection
*/
class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializable, ArrayAccess
{
......@@ -74,7 +75,7 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
/**
* This entity that owns this collection.
*
* @var Doctrine::ORM::Entity
* @var Doctrine\ORM\Entity
*/
protected $_owner;
......@@ -82,7 +83,7 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
* The association mapping the collection belongs to.
* This is currently either a OneToManyMapping or a ManyToManyMapping.
*
* @var Doctrine::ORM::Mapping::AssociationMapping
* @var Doctrine\ORM\Mapping\AssociationMapping
*/
protected $_association;
......@@ -92,18 +93,11 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
* @var string
*/
protected $_keyField;
/**
* Helper variable. Used for fast null value testing.
*
* @var Doctrine_Null
*/
//protected static $null;
/**
* The EntityManager that manages the persistence of the collection.
*
* @var Doctrine::ORM::EntityManager
* @var Doctrine\ORM\EntityManager
*/
protected $_em;
......@@ -124,7 +118,6 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
protected $_hydrationFlag;
/**
* Constructor.
* Creates a new persistent collection.
*/
public function __construct($entityBaseType, $keyField = null)
......@@ -174,9 +167,9 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
}
/**
* returns all the records as an array
* Unwraps the array contained in the Collection instance.
*
* @return array
* @return array The wrapped array.
*/
public function unwrap()
{
......@@ -229,7 +222,7 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
*
* @return void
*/
public function _setOwner(Doctrine_ORM_Entity $entity, Doctrine_ORM_Mapping_AssociationMapping $relation)
public function _setOwner($entity, Doctrine_ORM_Mapping_AssociationMapping $relation)
{
$this->_owner = $entity;
$this->_association = $relation;
......@@ -248,9 +241,9 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
/**
* INTERNAL:
* getReference
* Gets the collection owner.
*
* @return mixed
* @return Doctrine\ORM\Entity
*/
public function _getOwner()
{
......@@ -474,8 +467,7 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
*/
public function add($value, $key = null)
{
//TODO: really only allow entities?
if ( ! $value instanceof Doctrine_ORM_Entity) {
if ( ! $value instanceof $this->_entityBaseType) {
throw new Doctrine_Record_Exception('Value variable in collection is not an instance of Doctrine_Entity.');
}
......@@ -496,7 +488,8 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
if ($this->_hydrationFlag) {
if ($this->_backRefFieldName) {
// set back reference to owner
$value->_internalSetReference($this->_backRefFieldName, $this->_owner);
$this->_em->getClassMetadata($this->_entityBaseType)->getReflectionProperty(
$this->_backRefFieldName)->setValue($value, $this->_owner);
}
} else {
//TODO: Register collection as dirty with the UoW if necessary
......@@ -721,7 +714,8 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
*/
public function isEmpty()
{
return $this->count() == 0;
// Note: Little "trick". Empty arrays evaluate to FALSE. No need to count().
return ! (bool)$this->_data;
}
/**
......@@ -765,40 +759,6 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
}
}
/**
* Export a Doctrine_Collection to one of the supported Doctrine_Parser formats
*
* @param string $type
* @param string $deep
* @return void
* @todo Move elsewhere.
*/
/*public function exportTo($type, $deep = false)
{
if ($type == 'array') {
return $this->toArray($deep);
} else {
return Doctrine_Parser::dump($this->toArray($deep, true), $type);
}
}*/
/**
* Import data to a Doctrine_Collection from one of the supported Doctrine_Parser formats
*
* @param string $type
* @param string $data
* @return void
* @todo Move elsewhere.
*/
/*public function importFrom($type, $data)
{
if ($type == 'array') {
return $this->fromArray($data);
} else {
return $this->fromArray(Doctrine_Parser::load($data, $type));
}
}*/
/**
* INTERNAL: getDeleteDiff
*
......@@ -833,62 +793,9 @@ class Doctrine_ORM_Collection implements Countable, IteratorAggregate, Serializa
}
/**
* Saves all records of this collection and processes the
* difference of the last snapshot and the current data.
*
* @param Doctrine_Connection $conn optional connection parameter
* @return Doctrine_Collection
* @param <type> $deep
*/
/*public function save()
{
$conn = $this->_mapper->getConnection();
try {
$conn->beginInternalTransaction();
$conn->transaction->addCollection($this);
$this->processDiff();
foreach ($this->getData() as $key => $record) {
$record->save($conn);
}
$conn->commit();
} catch (Exception $e) {
$conn->rollback();
throw $e;
}
return $this;
}*/
/**
* Deletes all records from the collection.
* Shorthand for calling delete() for all entities in the collection.
*
* @return void
*/
/*public function delete()
{
$conn = $this->_mapper->getConnection();
try {
$conn->beginInternalTransaction();
$conn->transaction->addCollection($this);
foreach ($this as $key => $record) {
$record->delete($conn);
}
$conn->commit();
} catch (Exception $e) {
$conn->rollback();
throw $e;
}
$this->clear();
}*/
public function free($deep = false)
{
foreach ($this->getData() as $key => $record) {
......
This diff is collapsed.
......@@ -19,14 +19,14 @@
* <http://www.phpdoctrine.org>.
*/
#namespace Doctrine::ORM;
#namespace Doctrine\ORM;
#use Doctrine::Common::Configuration;
#use Doctrine::Common::EventManager;
#use Doctrine::DBAL::Connection;
#use Doctrine::ORM::Exceptions::EntityManagerException;
#use Doctrine::ORM::Internal::UnitOfWork;
#use Doctrine::ORM::Mapping::ClassMetadata;
#use Doctrine\Common\Configuration;
#use Doctrine\Common\EventManager;
#use Doctrine\DBAL\Connection;
#use Doctrine\ORM\Exceptions\EntityManagerException;
#use Doctrine\ORM\Internal\UnitOfWork;
#use Doctrine\ORM\Mapping\ClassMetadata;
/**
* The EntityManager is the central access point to ORM functionality.
......@@ -138,8 +138,12 @@ class Doctrine_ORM_EntityManager
* @var array
*/
private $_tmpEntityData = array();
private $_idGenerators = array();
private $_closed = false;
private $_originalEntityData = array();
/**
* Creates a new EntityManager that operates on the given database connection.
......@@ -155,7 +159,8 @@ class Doctrine_ORM_EntityManager
$this->_config = $config;
$this->_eventManager = $eventManager;
$this->_metadataFactory = new Doctrine_ORM_Mapping_ClassMetadataFactory(
$this, new Doctrine_ORM_Mapping_Driver_CodeDriver());
new Doctrine_ORM_Mapping_Driver_CodeDriver(),
$this->_conn->getDatabasePlatform());
$this->_unitOfWork = new Doctrine_ORM_UnitOfWork($this);
$this->_nullObject = Doctrine_ORM_Internal_Null::$INSTANCE;
}
......@@ -169,25 +174,23 @@ class Doctrine_ORM_EntityManager
{
return $this->_conn;
}
/**
* Gets the name of the EntityManager.
*
* @return string The name of the EntityManager.
* Gets the metadata factory used to gather the metadata of classes.
*/
public function getName()
public function getMetadataFactory()
{
return $this->_name;
return $this->_metadataFactory;
}
/**
* Gets the metadata for a class. Alias for getClassMetadata().
* Gets the name of the EntityManager.
*
* @return Doctrine_Metadata
* @return string The name of the EntityManager.
*/
public function getMetadata($className)
public function getName()
{
return $this->getClassMetadata($className);
return $this->_name;
}
/**
......@@ -222,20 +225,41 @@ class Doctrine_ORM_EntityManager
{
return $this->_metadataFactory->getMetadataFor($className);
}
/**
* Sets the driver that is used to obtain metadata mapping information
* about Entities.
* Gets an IdGenerator that can be used to generate identifiers for the specified
* class.
*/
public function getIdGenerator($className)
{
if (!isset($this->_idGenerators[$className])) {
$this->_idGenerators[$className] = $this->_createIdGenerator(
$this->getClassMetadata($className)->getIdGeneratorType());
}
return $this->_idGenerators[$className];
}
/**
* Used to lazily create the id generator.
*
* @param $driver The driver to use.
* @param string $generatorType
* @return void
*/
public function setClassMetadataDriver($driver)
protected function _createIdGenerator($generatorType)
{
$this->_metadataFactory->setDriver($driver);
if ($generatorType == Doctrine_ORM_Mapping_ClassMetadata::GENERATOR_TYPE_IDENTITY) {
return new Doctrine_ORM_Id_IdentityGenerator($this);
} else if ($generatorType == Doctrine_ORM_Mapping_ClassMetadata::GENERATOR_TYPE_SEQUENCE) {
return new Doctrine_ORM_Id_SequenceGenerator($this);
} else if ($generatorType == Doctrine_ORM_Mapping_ClassMetadata::GENERATOR_TYPE_TABLE) {
return new Doctrine_ORM_Id_TableGenerator($this);
} else {
return new Doctrine_ORM_Id_Assigned($this);
}
}
/**
* Creates a new Doctrine_Query object that operates on this connection.
* Creates a new Query object.
*
* @param string The DQL string.
* @return Doctrine::ORM::Query
......@@ -405,7 +429,7 @@ class Doctrine_ORM_EntityManager
/**
* Saves the given entity, persisting it's state.
*
* @param Doctrine::ORM::Entity $entity
* @param Doctrine\ORM\Entity $entity
* @return void
*/
public function save(Doctrine_ORM_Entity $entity)
......@@ -487,12 +511,12 @@ class Doctrine_ORM_EntityManager
*
* @param string $className The name of the entity class.
* @param array $data The data for the entity.
* @return Doctrine::ORM::Entity
* @return Doctrine\ORM\Entity
*/
public function createEntity($className, array $data)
public function createEntity($className, array $data, Doctrine_Query $query = null)
{
$this->_errorIfNotActiveOrClosed();
$this->_tmpEntityData = $data;
$className = $this->_inferCorrectClassName($data, $className);
$classMetadata = $this->getClassMetadata($className);
......@@ -512,9 +536,9 @@ class Doctrine_ORM_EntityManager
$entity = new $className;
} else {
$idHash = $this->_unitOfWork->getIdentifierHash($id);
if ($entity = $this->_unitOfWork->tryGetByIdHash($idHash,
$classMetadata->getRootClassName())) {
$this->_mergeData($entity, $data);
$entity = $this->_unitOfWork->tryGetByIdHash($idHash, $classMetadata->getRootClassName());
if ($entity) {
$this->_mergeData($entity, $data/*, $classMetadata, $query->getHint('doctrine.refresh')*/);
return $entity;
} else {
$entity = new $className;
......@@ -525,6 +549,8 @@ class Doctrine_ORM_EntityManager
$entity = new $className;
}
//$this->_originalEntityData[$entity->getOid()] = $data;
return $entity;
}
......@@ -532,12 +558,12 @@ class Doctrine_ORM_EntityManager
* Merges the given data into the given entity, optionally overriding
* local changes.
*
* @param Doctrine::ORM::Entity $entity
* @param Doctrine\ORM\Entity $entity
* @param array $data
* @param boolean $overrideLocalChanges
* @return void
*/
private function _mergeData(Doctrine_ORM_Entity $entity, array $data, $overrideLocalChanges = false) {
private function _mergeData(Doctrine_ORM_Entity $entity, /*$class,*/ array $data, $overrideLocalChanges = false) {
if ($overrideLocalChanges) {
foreach ($data as $field => $value) {
$entity->_internalSetField($field, $value);
......@@ -550,6 +576,21 @@ class Doctrine_ORM_EntityManager
}
}
}
// NEW
/*if ($overrideLocalChanges) {
foreach ($data as $field => $value) {
$class->getReflectionProperty($field)->setValue($entity, $value);
}
} else {
foreach ($data as $field => $value) {
$currentValue = $class->getReflectionProperty($field)->getValue($entity);
if ( ! isset($this->_originalEntityData[$entity->getOid()]) ||
$currentValue == $this->_originalEntityData[$entity->getOid()]) {
$class->getReflectionProperty($field)->setValue($entity, $value);
}
}
}*/
}
/**
......@@ -628,6 +669,8 @@ class Doctrine_ORM_EntityManager
/**
* Throws an exception if the EntityManager is closed or currently not active.
*
* @throws EntityManagerException If the EntityManager is closed or not active.
*/
private function _errorIfNotActiveOrClosed()
{
......@@ -668,15 +711,16 @@ class Doctrine_ORM_EntityManager
/**
* Factory method to create EntityManager instances.
*
* A newly created EntityManager is immediately activated, making it the
* currently active EntityManager.
*
* @param mixed $conn An array with the connection parameters or an existing
* Doctrine::DBAL::Connection instance.
* @param string $name
* @param Doctrine::Common::Configuration $config The Configuration instance to use.
* @param Doctrine::Common::EventManager $eventManager The EventManager instance to use.
* @return Doctrine::ORM::EntityManager The created EntityManager.
* Connection instance.
* @param string $name The name of the EntityManager.
* @param Configuration $config The Configuration instance to use.
* @param EventManager $eventManager The EventManager instance to use.
* @return EntityManager The created EntityManager.
*/
public static function create($conn, $name, Doctrine_Common_Configuration $config = null,
Doctrine_Common_EventManager $eventManager = null)
......@@ -702,8 +746,6 @@ class Doctrine_ORM_EntityManager
/**
* Static lookup to get the currently active EntityManager.
* This is used in the Entity constructor as well as unserialize() to connect
* the Entity with an EntityManager.
*
* @return Doctrine::ORM::EntityManager
*/
......
......@@ -18,7 +18,7 @@ abstract class Doctrine_ORM_Id_AbstractIdGenerator
$this->_em = $em;
}
abstract public function generate(Doctrine_ORM_Entity $entity);
abstract public function generate($entity);
}
?>
\ No newline at end of file
......@@ -14,11 +14,12 @@ class Doctrine_ORM_Id_Assigned extends Doctrine_ORM_Id_AbstractIdGenerator
* @return unknown
* @override
*/
public function generate(Doctrine_ORM_Entity $entity)
public function generate($entity)
{
if ( ! $entity->_identifier()) {
throw Doctrine_IdException::missingAssignedId($entity);
throw new Doctrine_Exception("Entity '$entity' is missing an assigned Id");
}
return $entity->_identifier();
}
}
......
......@@ -9,7 +9,7 @@ class Doctrine_ORM_Id_IdentityGenerator extends Doctrine_ORM_Id_AbstractIdGenera
* @return unknown
* @override
*/
public function generate(Doctrine_ORM_Entity $entity)
public function generate($entity)
{
return self::POST_INSERT_INDICATOR;
}
......
......@@ -15,7 +15,7 @@ class Doctrine_ORM_Id_SequenceGenerator extends Doctrine_ORM_Id_AbstractIdGenera
* @param Doctrine_ORM_Entity $entity
* @override
*/
public function generate(Doctrine_ORM_Entity $entity)
public function generate($entity)
{
$conn = $this->_em->getConnection();
$sql = $conn->getDatabasePlatform()->getSequenceNextValSql($this->_sequenceName);
......
......@@ -8,7 +8,7 @@
class Doctrine_ORM_Id_TableGenerator extends Doctrine_ORM_Id_AbstractIdGenerator
{
public function generate(Doctrine_ORM_Entity $entity)
public function generate($entity)
{
throw new Exception("Not implemented");
}
......
......@@ -129,6 +129,38 @@ class Doctrine_ORM_Internal_Hydration_ArrayDriver
return key($data);
}
/**
* Updates the result pointer for an Entity. The result pointers point to the
* last seen instance of each Entity type. This is used for graph construction.
*
* @param array $resultPointers The result pointers.
* @param array|Collection $coll The element.
* @param boolean|integer $index Index of the element in the collection.
* @param string $dqlAlias
* @param boolean $oneToOne Whether it is a single-valued association or not.
*/
public function updateResultPointer(&$resultPointers, &$coll, $index, $dqlAlias, $oneToOne)
{
if ($coll === null) {
unset($resultPointers[$dqlAlias]); // Ticket #1228
return;
}
if ($index !== false) {
$resultPointers[$dqlAlias] =& $coll[$index];
return;
}
if ($coll) {
if ($oneToOne) {
$resultPointers[$dqlAlias] =& $coll;
} else {
end($coll);
$resultPointers[$dqlAlias] =& $coll[key($coll)];
}
}
}
/**
*
*/
......
......@@ -19,7 +19,7 @@
* <http://www.phpdoctrine.org>.
*/
#namespace Doctrine::ORM::Internal::Hydration;
#namespace Doctrine\ORM\Internal\Hydration;
/**
* Hydration strategy used for creating graphs of entities.
......@@ -41,6 +41,7 @@ class Doctrine_ORM_Internal_Hydration_ObjectDriver
private $_nullObject;
/** The EntityManager */
private $_em;
private $_metadataMap = array();
public function __construct(Doctrine_ORM_EntityManager $em)
{
......@@ -52,32 +53,36 @@ class Doctrine_ORM_Internal_Hydration_ObjectDriver
{
$coll = new Doctrine_ORM_Collection($component);
$this->_collections[] = $coll;
return $coll;
}
public function getLastKey($coll)
{
// check needed because of mixed results
if (is_array($coll)) {
// check needed because of mixed results.
// is_object instead of is_array because is_array is slow.
if (is_object($coll)) {
$coll->end();
return $coll->key();
} else {
end($coll);
return key($coll);
} else {
$coll->end();
return $coll->key();
}
}
public function initRelatedCollection(Doctrine_ORM_Entity $entity, $name)
public function initRelatedCollection($entity, $name)
{
if ( ! isset($this->_initializedRelations[$entity->getOid()][$name])) {
$relation = $entity->getClass()->getAssociationMapping($name);
//$class = get_class($entity);
$oid = spl_object_id($entity);
$classMetadata = $this->_metadataMap[$oid];
//$classMetadata = $this->_em->getClassMetadata(get_class($entity));
if ( ! isset($this->_initializedRelations[$oid][$name])) {
$relation = $classMetadata->getAssociationMapping($name);
$relatedClass = $this->_em->getClassMetadata($relation->getTargetEntityName());
$coll = $this->getElementCollection($relatedClass->getClassName());
$coll->_setOwner($entity, $relation);
$coll->_setHydrationFlag(true);
$entity->_internalSetReference($name, $coll, true);
$this->_initializedRelations[$entity->getOid()][$name] = true;
$classMetadata->getReflectionProperty($name)->setValue($entity, $coll);
$this->_initializedRelations[$oid][$name] = true;
}
}
......@@ -93,49 +98,91 @@ class Doctrine_ORM_Internal_Hydration_ObjectDriver
public function getElement(array $data, $className)
{
return $this->_em->createEntity($className, $data);
}
public function addRelatedIndexedElement(Doctrine_ORM_Entity $entity1, $property,
Doctrine_ORM_Entity $entity2, $indexField)
{
$entity1->_internalGetReference($property)->add($entity2, $entity2->_internalGetField($indexField));
}
public function addRelatedElement(Doctrine_ORM_Entity $entity1, $property,
Doctrine_ORM_Entity $entity2)
{
$entity1->_internalGetReference($property)->add($entity2);
}
public function setRelatedElement(Doctrine_ORM_Entity $entity1, $property, $entity2)
{
$entity1->_internalSetReference($property, $entity2, true);
$entity = $this->_em->getUnitOfWork()->createEntity($className, $data);
$this->_metadataMap[spl_object_id($entity)] = $this->_em->getClassMetadata($className);
return $entity;
}
public function addRelatedIndexedElement($entity1, $property, $entity2, $indexField)
{
$classMetadata1 = $this->_metadataMap[spl_object_id($entity1)];
$classMetadata2 = $this->_metadataMap[spl_object_id($entity2)];
//$classMetadata1 = $this->_em->getClassMetadata(get_class($entity1));
//$classMetadata2 = $this->_em->getClassMetadata(get_class($entity2));
$indexValue = $classMetadata2->getReflectionProperty($indexField)->getValue($entity2);
$classMetadata1->getReflectionProperty($property)->getValue($entity1)->add($entity2, $indexValue);
}
public function addRelatedElement($entity1, $property, $entity2)
{
$classMetadata1 = $this->_metadataMap[spl_object_id($entity1)];
//$classMetadata1 = $this->_em->getClassMetadata(get_class($entity1));
$classMetadata1->getReflectionProperty($property)
->getValue($entity1)->add($entity2);
}
public function setRelatedElement($entity1, $property, $entity2)
{
$classMetadata1 = $this->_metadataMap[spl_object_id($entity1)];
//$classMetadata1 = $this->_em->getClassMetadata(get_class($entity1));
$classMetadata1->getReflectionProperty($property)
->setValue($entity1, $entity2);
$relation = $classMetadata1->getAssociationMapping($property);
if ($relation->isOneToOne()) {
$targetClass = $this->_em->getClassMetadata($relation->getTargetEntityName());
if ($relation->isOwningSide()) {
// If there is an inverse mapping on the target class its bidirectional
if ($targetClass->hasInverseAssociationMapping($property)) {
$refProp = $targetClass->getReflectionProperty(
$targetClass->getInverseAssociationMapping($fieldName)
->getSourceFieldName());
$refProp->setValue($entity2, $entity1);
}
} else {
// for sure bidirectional, as there is no inverse side in unidirectional
$targetClass->getReflectionProperty($relation->getMappedByFieldName())
->setValue($entity2, $entity1);
}
}
}
public function isIndexKeyInUse(Doctrine_ORM_Entity $entity, $assocField, $indexField)
public function isIndexKeyInUse($entity, $assocField, $indexField)
{
return $entity->_internalGetReference($assocField)->contains($indexField);
return $this->_metadataMap[spl_object_id($entity)]->getReflectionProperty($assocField)
->getValue($entity)->containsKey($indexField);
/*return $this->_em->getClassMetadata(get_class($entity))->getReflectionProperty($assocField)
->getValue($entity)->containsKey($indexField);*/
}
public function isFieldSet(Doctrine_ORM_Entity $entity, $field)
public function isFieldSet($entity, $field)
{
return $entity->contains($field);
return $this->_metadataMap[spl_object_id($entity)]->getReflectionProperty($field)
->getValue($entity) !== null;
/*return $this->_em->getClassMetadata(get_class($entity))->getReflectionProperty($field)
->getValue($entity) !== null;*/
}
public function getFieldValue(Doctrine_ORM_Entity $entity, $field)
public function getFieldValue($entity, $field)
{
return $entity->_internalGetField($field);
return $this->_metadataMap[spl_object_id($entity)]->getReflectionProperty($field)
->getValue($entity);
/*return $this->_em->getClassMetadata(get_class($entity))->getReflectionProperty($field)
->getValue($entity);*/
}
public function getReferenceValue(Doctrine_ORM_Entity $entity, $field)
public function getReferenceValue($entity, $field)
{
return $entity->_internalGetReference($field);
return $this->_metadataMap[spl_object_id($entity)]->getReflectionProperty($field)
->getValue($entity);
/*return $this->_em->getClassMetadata(get_class($entity))->getReflectionProperty($field)
->getValue($entity);*/
}
public function addElementToIndexedCollection($coll, $entity, $keyField)
{
$coll->add($entity, $entity->_internalGetField($keyField));
$coll->add($entity, $this->getFieldValue($entity, $keyField));
}
public function addElementToCollection($coll, $entity)
......@@ -143,6 +190,40 @@ class Doctrine_ORM_Internal_Hydration_ObjectDriver
$coll->add($entity);
}
/**
* Updates the result pointer for an Entity. The result pointers point to the
* last seen instance of each Entity type. This is used for graph construction.
*
* @param array $resultPointers The result pointers.
* @param array|Collection $coll The element.
* @param boolean|integer $index Index of the element in the collection.
* @param string $dqlAlias
* @param boolean $oneToOne Whether it is a single-valued association or not.
*/
public function updateResultPointer(&$resultPointers, &$coll, $index, $dqlAlias, $oneToOne)
{
if ($coll === $this->_nullObject) {
unset($resultPointers[$dqlAlias]); // Ticket #1228
return;
}
if ($index !== false) {
$resultPointers[$dqlAlias] = $coll[$index];
return;
}
if ( ! is_object($coll)) {
end($coll);
$resultPointers[$dqlAlias] =& $coll[key($coll)];
} else if ($coll instanceof Doctrine_ORM_Collection) {
if (count($coll) > 0) {
$resultPointers[$dqlAlias] = $coll->getLast();
}
} else {
$resultPointers[$dqlAlias] = $coll;
}
}
public function flush()
{
// take snapshots from all initialized collections
......@@ -152,6 +233,7 @@ class Doctrine_ORM_Internal_Hydration_ObjectDriver
}
$this->_collections = array();
$this->_initializedRelations = array();
$this->_metadataMap = array();
}
}
......@@ -19,7 +19,7 @@
* <http://www.phpdoctrine.org>.
*/
#namespace Doctrine::ORM::Mapping;
#namespace Doctrine\ORM\Mapping;
/**
* Base class for association mappings.
......
This diff is collapsed.
......@@ -219,7 +219,7 @@ class Doctrine_ORM_Persisters_JoinedSubclassPersister extends Doctrine_ORM_Persi
*
* @todo Looks like this better belongs into the ClassMetadata class.
*/
public function getOwningClass($fieldName)
/*public function getOwningClass($fieldName)
{
$conn = $this->_conn;
$classMetadata = $this->_classMetadata;
......@@ -242,7 +242,7 @@ class Doctrine_ORM_Persisters_JoinedSubclassPersister extends Doctrine_ORM_Persi
}
throw new Doctrine_Mapper_Exception("Unable to find defining class of field '$fieldName'.");
}
}*/
/**
* Analyzes the fields of the entity and creates a map in which the field names
......
......@@ -19,6 +19,10 @@
* <http://www.phpdoctrine.org>.
*/
#namespace Doctrine\ORM\Persisters;
#use Doctrine\ORM\Entity;
/**
* The default persister strategy maps a single entity instance to a single database table,
* as is the case in Single Table Inheritance & Concrete Table Inheritance.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -20,7 +20,7 @@ class Orm_Entity_AllTests
{
$suite = new Doctrine_TestSuite('Doctrine Orm Entity Tests');
$suite->addTestSuite('Orm_Entity_AccessorTest');
//$suite->addTestSuite('Orm_Entity_AccessorTest');
$suite->addTestSuite('Orm_Entity_ConstructorTest');
return $suite;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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