Commit 2ec4cc5c authored by romanb's avatar romanb

[2.0] More cleanups for recent lazy-loading implementation and minor object...

[2.0] More cleanups for recent lazy-loading implementation and minor object hydration improvements and cleanups. Collection refactoring part I for ticket #2352.
parent 62446f0f
...@@ -21,11 +21,7 @@ ...@@ -21,11 +21,7 @@
namespace Doctrine\Common\Collections; namespace Doctrine\Common\Collections;
use \Closure; use \Closure, \ArrayIterator;
use \Countable;
use \IteratorAggregate;
use \ArrayAccess;
use \ArrayIterator;
/** /**
* A Collection is a thin wrapper around a php array. Like a php array it is essentially * A Collection is a thin wrapper around a php array. Like a php array it is essentially
...@@ -34,7 +30,7 @@ use \ArrayIterator; ...@@ -34,7 +30,7 @@ use \ArrayIterator;
* @author Roman S. Borschel <roman@code-factory.org> * @author Roman S. Borschel <roman@code-factory.org>
* @since 2.0 * @since 2.0
*/ */
class Collection implements Countable, IteratorAggregate, ArrayAccess class ArrayCollection implements ICollection
{ {
/** /**
* An array containing the entries of this collection. * An array containing the entries of this collection.
...@@ -42,10 +38,10 @@ class Collection implements Countable, IteratorAggregate, ArrayAccess ...@@ -42,10 +38,10 @@ class Collection implements Countable, IteratorAggregate, ArrayAccess
* *
* @var array * @var array
*/ */
protected $_elements; private $_elements;
/** /**
* Initializes a new Collection. * Initializes a new ArrayCollection.
* *
* @param array $elements * @param array $elements
*/ */
...@@ -64,6 +60,11 @@ class Collection implements Countable, IteratorAggregate, ArrayAccess ...@@ -64,6 +60,11 @@ class Collection implements Countable, IteratorAggregate, ArrayAccess
return $this->_elements; return $this->_elements;
} }
public function toArray()
{
return $this->_elements;
}
/** /**
* Gets the first element in the collection. * Gets the first element in the collection.
* *
...@@ -249,7 +250,7 @@ class Collection implements Countable, IteratorAggregate, ArrayAccess ...@@ -249,7 +250,7 @@ class Collection implements Countable, IteratorAggregate, ArrayAccess
* *
* @return array * @return array
*/ */
public function getElements() public function getValues()
{ {
return array_values($this->_elements); return array_values($this->_elements);
} }
...@@ -323,7 +324,7 @@ class Collection implements Countable, IteratorAggregate, ArrayAccess ...@@ -323,7 +324,7 @@ class Collection implements Countable, IteratorAggregate, ArrayAccess
*/ */
public function map(Closure $func) public function map(Closure $func)
{ {
return new Collection(array_map($func, $this->_elements)); return new ArrayCollection(array_map($func, $this->_elements));
} }
/** /**
...@@ -335,7 +336,7 @@ class Collection implements Countable, IteratorAggregate, ArrayAccess ...@@ -335,7 +336,7 @@ class Collection implements Countable, IteratorAggregate, ArrayAccess
*/ */
public function filter(Closure $p) public function filter(Closure $p)
{ {
return new Collection(array_filter($this->_elements, $p)); return new ArrayCollection(array_filter($this->_elements, $p));
} }
/** /**
...@@ -374,7 +375,7 @@ class Collection implements Countable, IteratorAggregate, ArrayAccess ...@@ -374,7 +375,7 @@ class Collection implements Countable, IteratorAggregate, ArrayAccess
$coll2[$key] = $element; $coll2[$key] = $element;
} }
} }
return array(new Collection($coll1), new Collection($coll2)); return array(new ArrayCollection($coll1), new ArrayCollection($coll2));
} }
/** /**
......
...@@ -21,9 +21,9 @@ ...@@ -21,9 +21,9 @@
namespace Doctrine\ORM\Internal\Hydration; namespace Doctrine\ORM\Internal\Hydration;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection,
use Doctrine\DBAL\Types\Type; Doctrine\DBAL\Types\Type,
use Doctrine\Common\DoctrineException; Doctrine\Common\DoctrineException;
/** /**
* Base class for all hydrators. A hydrator is a class that provides some form * Base class for all hydrators. A hydrator is a class that provides some form
...@@ -151,7 +151,7 @@ abstract class AbstractHydrator ...@@ -151,7 +151,7 @@ abstract class AbstractHydrator
*/ */
protected function _hydrateRow(array &$data, array &$cache, &$result) protected function _hydrateRow(array &$data, array &$cache, &$result)
{ {
throw new DoctrineException("_hydrateRow() not implemented for this hydrator."); throw new DoctrineException("_hydrateRow() not implemented by this hydrator.");
} }
/** /**
......
...@@ -21,10 +21,11 @@ ...@@ -21,10 +21,11 @@
namespace Doctrine\ORM\Internal\Hydration; namespace Doctrine\ORM\Internal\Hydration;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection,
use Doctrine\ORM\PersistentCollection; Doctrine\ORM\PersistentCollection,
use Doctrine\ORM\Query; Doctrine\ORM\Query,
use Doctrine\Common\Collections\Collection; Doctrine\Common\Collections\ArrayCollection,
Doctrine\Common\Collections\ICollection;
/** /**
* The ObjectHydrator constructs an object graph out of an SQL result set. * The ObjectHydrator constructs an object graph out of an SQL result set.
...@@ -51,11 +52,8 @@ class ObjectHydrator extends AbstractHydrator ...@@ -51,11 +52,8 @@ class ObjectHydrator extends AbstractHydrator
private $_resultCounter; private $_resultCounter;
private $_rootAliases = array(); private $_rootAliases = array();
private $_fetchedAssociations; private $_fetchedAssociations;
/* TODO: Consider unifying _collections and _initializedRelations */ /** Memory for initialized collections. */
/** Collections initialized by the hydrator */ private $_initializedCollections = array();
private $_collections = array();
/** Memory for initialized relations */
private $_initializedRelations = array();
/** @override */ /** @override */
protected function _prepare() protected function _prepare()
...@@ -76,11 +74,11 @@ class ObjectHydrator extends AbstractHydrator ...@@ -76,11 +74,11 @@ class ObjectHydrator extends AbstractHydrator
$this->_idTemplate[$dqlAlias] = ''; $this->_idTemplate[$dqlAlias] = '';
$class = $this->_em->getClassMetadata($className); $class = $this->_em->getClassMetadata($className);
if ( ! isset($this->_ce[$class->name])) { if ( ! isset($this->_ce[$className])) {
$this->_ce[$class->name] = $class; $this->_ce[$className] = $class;
// Gather class descriptors and discriminator values of subclasses, if necessary // Gather class descriptors and discriminator values of subclasses, if necessary
if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined()) { if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined()) {
$this->_discriminatorMap[$class->name][$class->discriminatorValue] = $class->name; $this->_discriminatorMap[$className][$class->discriminatorValue] = $className;
foreach (array_merge($class->parentClasses, $class->subClasses) as $className) { foreach (array_merge($class->parentClasses, $class->subClasses) as $className) {
$otherClass = $this->_em->getClassMetadata($className); $otherClass = $this->_em->getClassMetadata($className);
$value = $otherClass->discriminatorValue; $value = $otherClass->discriminatorValue;
...@@ -115,7 +113,7 @@ class ObjectHydrator extends AbstractHydrator ...@@ -115,7 +113,7 @@ class ObjectHydrator extends AbstractHydrator
*/ */
protected function _hydrateAll() protected function _hydrateAll()
{ {
$result = $this->_rsm->isMixed ? array() : new Collection; $result = $this->_rsm->isMixed ? array() : new ArrayCollection;
$cache = array(); $cache = array();
while ($data = $this->_stmt->fetch(Connection::FETCH_ASSOC)) { while ($data = $this->_stmt->fetch(Connection::FETCH_ASSOC)) {
...@@ -123,13 +121,10 @@ class ObjectHydrator extends AbstractHydrator ...@@ -123,13 +121,10 @@ class ObjectHydrator extends AbstractHydrator
} }
// Take snapshots from all initialized collections // Take snapshots from all initialized collections
foreach ($this->_collections as $coll) { foreach ($this->_initializedCollections as $coll) {
$coll->takeSnapshot(); $coll->takeSnapshot();
} }
$this->_initializedCollections = array();
// Clean up
$this->_collections = array();
$this->_initializedRelations = array();
return $result; return $result;
} }
...@@ -141,16 +136,9 @@ class ObjectHydrator extends AbstractHydrator ...@@ -141,16 +136,9 @@ class ObjectHydrator extends AbstractHydrator
* @param Collection $coll The element. * @param Collection $coll The element.
* @param boolean|integer $index Index of the element in the collection. * @param boolean|integer $index Index of the element in the collection.
* @param string $dqlAlias * @param string $dqlAlias
* @todo May be worth to try to inline this method (through first reducing the
* calls of this method to 1).
*/ */
private function updateResultPointer(&$coll, $index, $dqlAlias) private function updateResultPointer(&$coll, $index, $dqlAlias)
{ {
if ($coll === null) {
unset($this->_resultPointers[$dqlAlias]); // Ticket #1228
return;
}
if ($index !== false) { if ($index !== false) {
$this->_resultPointers[$dqlAlias] = $coll[$index]; $this->_resultPointers[$dqlAlias] = $coll[$index];
return; return;
...@@ -159,7 +147,7 @@ class ObjectHydrator extends AbstractHydrator ...@@ -159,7 +147,7 @@ class ObjectHydrator extends AbstractHydrator
if ( ! is_object($coll)) { if ( ! is_object($coll)) {
end($coll); end($coll);
$this->_resultPointers[$dqlAlias] =& $coll[key($coll)]; $this->_resultPointers[$dqlAlias] =& $coll[key($coll)];
} else if ($coll instanceof Collection) { } else if ($coll instanceof ICollection) {
if (count($coll) > 0) { if (count($coll) > 0) {
$this->_resultPointers[$dqlAlias] = $coll->last(); $this->_resultPointers[$dqlAlias] = $coll->last();
} }
...@@ -178,37 +166,17 @@ class ObjectHydrator extends AbstractHydrator ...@@ -178,37 +166,17 @@ class ObjectHydrator extends AbstractHydrator
{ {
$oid = spl_object_hash($entity); $oid = spl_object_hash($entity);
$class = $this->_ce[get_class($entity)]; $class = $this->_ce[get_class($entity)];
$relation = $class->associationMappings[$name]; $relation = $class->associationMappings[$name];
//$coll = $class->reflFields[$name]->getValue($entity); $pColl = new PersistentCollection($this->_em, $this->_getClassMetadata($relation->targetEntityName),
//if ( ! $coll) { $class->reflFields[$name]->getValue($entity) ?: new ArrayCollection);
// $coll = new Collection;
//}
$pColl = new PersistentCollection($this->_em, $this->_getClassMetadata($relation->targetEntityName));
$this->_collections[] = $pColl;
$pColl->setOwner($entity, $relation); $pColl->setOwner($entity, $relation);
$class->reflFields[$name]->setValue($entity, $pColl); $class->reflFields[$name]->setValue($entity, $pColl);
$this->_uow->setOriginalEntityProperty($oid, $name, $pColl); $this->_uow->setOriginalEntityProperty($oid, $name, $pColl);
$this->_initializedRelations[$oid][$name] = true; $this->_initializedCollections[$oid . $name] = $pColl;
}
/** return $pColl;
*
* @param <type> $entity
* @param <type> $assocField
* @param <type> $indexField
* @return <type>
* @todo Inline this method.
*/
private function isIndexKeyInUse($entity, $assocField, $indexField)
{
return $this->_ce[get_class($entity)]
->reflFields[$assocField]
->getValue($entity)
->containsKey($indexField);
} }
/** /**
...@@ -245,6 +213,7 @@ class ObjectHydrator extends AbstractHydrator ...@@ -245,6 +213,7 @@ class ObjectHydrator extends AbstractHydrator
$className = $this->_discriminatorMap[$className][$data[$discrColumn]]; $className = $this->_discriminatorMap[$className][$data[$discrColumn]];
unset($data[$discrColumn]); unset($data[$discrColumn]);
} }
$entity = $this->_uow->createEntity($className, $data, $this->_hints); $entity = $this->_uow->createEntity($className, $data, $this->_hints);
// Properly initialize any unfetched associations, if partial objects are not allowed. // Properly initialize any unfetched associations, if partial objects are not allowed.
...@@ -269,9 +238,12 @@ class ObjectHydrator extends AbstractHydrator ...@@ -269,9 +238,12 @@ class ObjectHydrator extends AbstractHydrator
} }
} else { } else {
// Inject collection // Inject collection
$pColl = new PersistentCollection($this->_em, $this->_getClassMetadata($assoc->targetEntityName)); $reflField = $this->_ce[$className]->reflFields[$field];
$pColl = new PersistentCollection($this->_em, $this->_getClassMetadata(
$assoc->targetEntityName), $reflField->getValue($entity) ?: new ArrayCollection
);
$pColl->setOwner($entity, $assoc); $pColl->setOwner($entity, $assoc);
$this->_ce[$className]->reflFields[$field]->setValue($entity, $pColl); $reflField->setValue($entity, $pColl);
if ( ! $assoc->isLazilyFetched()) { if ( ! $assoc->isLazilyFetched()) {
//TODO: Allow more efficient and configurable batching of these loads //TODO: Allow more efficient and configurable batching of these loads
$assoc->load($entity, $pColl, $this->_em); $assoc->load($entity, $pColl, $this->_em);
...@@ -302,38 +274,6 @@ class ObjectHydrator extends AbstractHydrator ...@@ -302,38 +274,6 @@ class ObjectHydrator extends AbstractHydrator
return $this->_ce[$className]; return $this->_ce[$className];
} }
/**
* Sets a related element.
*
* @param object $entity1
* @param string $property
* @param object $entity2
*/
private function setRelatedElement($entity1, $property, $entity2)
{
$class = $this->_ce[get_class($entity1)];
$class->reflFields[$property]->setValue($entity1, $entity2);
$this->_uow->setOriginalEntityProperty(spl_object_hash($entity1), $property, $entity2);
$relation = $class->associationMappings[$property];
if ($relation->isOneToOne()) {
$targetClass = $this->_ce[$relation->targetEntityName];
if ($relation->isOwningSide) {
// If there is an inverse mapping on the target class its bidirectional
if (isset($targetClass->inverseMappings[$property])) {
$sourceProp = $targetClass->inverseMappings[$property]->sourceFieldName;
$targetClass->reflFields[$sourceProp]->setValue($entity2, $entity1);
} else if ($class === $targetClass && $relation->mappedByFieldName) {
// Special case: bi-directional self-referencing one-one on the same class
$targetClass->reflFields[$property]->setValue($entity2, $entity1);
}
} else {
// For sure bidirectional, as there is no inverse side in unidirectional mappings
$targetClass->reflFields[$relation->mappedByFieldName]->setValue($entity2, $entity1);
}
}
}
/** /**
* {@inheritdoc} * {@inheritdoc}
* *
...@@ -362,7 +302,7 @@ class ObjectHydrator extends AbstractHydrator ...@@ -362,7 +302,7 @@ class ObjectHydrator extends AbstractHydrator
$parent = $this->_rsm->parentAliasMap[$dqlAlias]; $parent = $this->_rsm->parentAliasMap[$dqlAlias];
$relation = $this->_rsm->relationMap[$dqlAlias]; $relation = $this->_rsm->relationMap[$dqlAlias];
$relationAlias = $relation->sourceFieldName; $relationField = $relation->sourceFieldName;
// Get a reference to the right element in the result tree. // Get a reference to the right element in the result tree.
// This element will get the associated element attached. // This element will get the associated element attached.
...@@ -378,34 +318,38 @@ class ObjectHydrator extends AbstractHydrator ...@@ -378,34 +318,38 @@ class ObjectHydrator extends AbstractHydrator
} }
$parentClass = get_class($baseElement); $parentClass = get_class($baseElement);
$oid = spl_object_hash($baseElement);
$reflField = $this->_ce[$parentClass]->reflFields[$relationField];
$reflFieldValue = $reflField->getValue($baseElement);
// Check the type of the relation (many or single-valued) // Check the type of the relation (many or single-valued)
if ( ! $relation->isOneToOne()) { if ( ! $relation->isOneToOne()) {
// Collection-valued association
if (isset($nonemptyComponents[$dqlAlias])) { if (isset($nonemptyComponents[$dqlAlias])) {
if ( ! isset($this->_initializedRelations[spl_object_hash($baseElement)][$relationAlias])) { if ( ! isset($this->_initializedCollections[$oid . $relationField])) {
$this->initRelatedCollection($baseElement, $relationAlias); $reflFieldValue = $this->initRelatedCollection($baseElement, $relationField);
} }
$path = $parent . '.' . $dqlAlias; $path = $parent . '.' . $dqlAlias;
$indexExists = isset($this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]]); $indexExists = isset($this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]]);
$index = $indexExists ? $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false; $index = $indexExists ? $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false;
$indexIsValid = $index !== false ? $this->isIndexKeyInUse($baseElement, $relationAlias, $index) : false; $indexIsValid = $index !== false ? $reflFieldValue->containsKey($index) : false;
if ( ! $indexExists || ! $indexIsValid) { if ( ! $indexExists || ! $indexIsValid) {
$element = $this->getEntity($data, $dqlAlias); $element = $this->getEntity($data, $dqlAlias);
// If it's a bi-directional many-to-many, also initialize the reverse collection. // If it's a bi-directional many-to-many, also initialize the reverse collection.
if ($relation->isManyToMany()) { if ($relation->isManyToMany()) {
if ($relation->isOwningSide && isset($this->_ce[$entityName]->inverseMappings[$relationAlias])) { if ($relation->isOwningSide && isset($this->_ce[$entityName]->inverseMappings[$relationField])) {
$inverseFieldName = $this->_ce[$entityName]->inverseMappings[$relationAlias]->sourceFieldName; $inverseFieldName = $this->_ce[$entityName]->inverseMappings[$relationField]->sourceFieldName;
// Only initialize reverse collection if it is not yet initialized. // Only initialize reverse collection if it is not yet initialized.
if ( ! isset($this->_initializedRelations[spl_object_hash($element)][$inverseFieldName])) { if ( ! isset($this->_initializedCollections[spl_object_hash($element) . $inverseFieldName])) {
$this->initRelatedCollection($element, $this->_ce[$entityName] $this->initRelatedCollection($element, $this->_ce[$entityName]
->inverseMappings[$relationAlias]->sourceFieldName); ->inverseMappings[$relationField]->sourceFieldName);
} }
} else if ($relation->mappedByFieldName) { } else if ($relation->mappedByFieldName) {
// Only initialize reverse collection if it is not yet initialized. // Only initialize reverse collection if it is not yet initialized.
if ( ! isset($this->_initializedRelations[spl_object_hash($element)][$relation->mappedByFieldName])) { if ( ! isset($this->_initializedCollections[spl_object_hash($element) . $relation->mappedByFieldName])) {
$this->initRelatedCollection($element, $relation->mappedByFieldName); $this->initRelatedCollection($element, $relation->mappedByFieldName);
} }
} }
...@@ -416,40 +360,49 @@ class ObjectHydrator extends AbstractHydrator ...@@ -416,40 +360,49 @@ class ObjectHydrator extends AbstractHydrator
$indexValue = $this->_ce[$entityName] $indexValue = $this->_ce[$entityName]
->reflFields[$field] ->reflFields[$field]
->getValue($element); ->getValue($element);
$this->_ce[$parentClass] $reflFieldValue->hydrateSet($indexValue, $element);
->reflFields[$relationAlias]
->getValue($baseElement)
->hydrateSet($indexValue, $element);
} else { } else {
$this->_ce[$parentClass] $reflFieldValue->hydrateAdd($element);
->reflFields[$relationAlias]
->getValue($baseElement)
->hydrateAdd($element);
} }
$this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] = $this->getLastKey( $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] = $this->getLastKey($reflFieldValue);
$this->_ce[$parentClass]
->reflFields[$relationAlias]
->getValue($baseElement)
);
} }
} else if ( ! $this->_ce[$parentClass]->reflFields[$relationAlias]->getValue($baseElement)) { } else if ( ! $reflFieldValue) {
$coll = new PersistentCollection($this->_em, $this->_ce[$entityName]); $coll = new PersistentCollection($this->_em, $this->_ce[$entityName], new ArrayCollection);
$this->_collections[] = $coll; $reflField->setValue($baseElement, $coll);
$this->setRelatedElement($baseElement, $relationAlias, $coll); $reflFieldValue = $coll;
$this->_uow->setOriginalEntityProperty($oid, $relationField, $coll);
} }
$this->updateResultPointer($reflFieldValue, $index, $dqlAlias);
} else { } else {
if ( ! $this->_ce[$parentClass]->reflFields[$relationAlias]->getValue($baseElement)) { // Single-valued association
$reflFieldValue = $reflField->getValue($baseElement);
if ( ! $reflFieldValue) {
if (isset($nonemptyComponents[$dqlAlias])) { if (isset($nonemptyComponents[$dqlAlias])) {
$this->setRelatedElement($baseElement, $relationAlias, $this->getEntity($data, $dqlAlias)); $element = $this->getEntity($data, $dqlAlias);
$reflField->setValue($baseElement, $element);
$this->_uow->setOriginalEntityProperty($oid, $relationField, $element);
$targetClass = $this->_ce[$relation->targetEntityName];
if ($relation->isOwningSide) {
// If there is an inverse mapping on the target class its bidirectional
if (isset($targetClass->inverseMappings[$relationField])) {
$sourceProp = $targetClass->inverseMappings[$relationField]->sourceFieldName;
$targetClass->reflFields[$sourceProp]->setValue($element, $base);
} else if ($this->_ce[$parentClass] === $targetClass && $relation->mappedByFieldName) {
// Special case: bi-directional self-referencing one-one on the same class
$targetClass->reflFields[$relationField]->setValue($element, $baseElement);
}
} else {
// For sure bidirectional, as there is no inverse side in unidirectional mappings
$targetClass->reflFields[$relation->mappedByFieldName]->setValue($element, $baseElement);
} }
} }
} }
$coll = $this->_ce[$parentClass]->reflFields[$relationAlias]->getValue($baseElement); if ($reflFieldValue !== null) {
$this->updateResultPointer($reflFieldValue, $index, $dqlAlias);
if ($coll !== null) { }
$this->updateResultPointer($coll, $index, $dqlAlias);
} }
} else { } else {
// Its a root result element // Its a root result element
...@@ -499,6 +452,6 @@ class ObjectHydrator extends AbstractHydrator ...@@ -499,6 +452,6 @@ class ObjectHydrator extends AbstractHydrator
/** {@inheritdoc} */ /** {@inheritdoc} */
protected function _getRowContainer() protected function _getRowContainer()
{ {
return new \Doctrine\Common\Collections\Collection; return new \Doctrine\Common\Collections\ArrayCollection;
} }
} }
...@@ -112,6 +112,11 @@ class ClassMetadataFactory ...@@ -112,6 +112,11 @@ class ClassMetadataFactory
return $this->_loadedMetadata[$className]; return $this->_loadedMetadata[$className];
} }
public function hasMetadataFor($className)
{
return isset($this->_loadedMetadata[$className]);
}
/** /**
* Sets the metadata descriptor for a specific class. * Sets the metadata descriptor for a specific class.
* *
......
...@@ -21,9 +21,9 @@ ...@@ -21,9 +21,9 @@
namespace Doctrine\ORM; namespace Doctrine\ORM;
use Doctrine\Common\DoctrineException; use Doctrine\Common\DoctrineException,
use Doctrine\ORM\Mapping\AssociationMapping; Doctrine\ORM\Mapping\AssociationMapping,
use \Closure; \Closure;
/** /**
* A PersistentCollection represents a collection of elements that have persistent state. * A PersistentCollection represents a collection of elements that have persistent state.
...@@ -44,7 +44,7 @@ use \Closure; ...@@ -44,7 +44,7 @@ use \Closure;
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com> * @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
*/ */
final class PersistentCollection extends \Doctrine\Common\Collections\Collection final class PersistentCollection implements \Doctrine\Common\Collections\ICollection
{ {
/** /**
* A snapshot of the collection at the moment it was fetched from the database. * A snapshot of the collection at the moment it was fetched from the database.
...@@ -97,15 +97,30 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -97,15 +97,30 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
*/ */
private $_isDirty = false; private $_isDirty = false;
/** Whether the collection has already been initialized. */ /**
* Whether the collection has already been initialized.
*
* @var boolean
*/
private $_initialized = true; private $_initialized = true;
/**
* The wrapped Collection instance.
*
* @var Collection
*/
private $_coll;
/** /**
* Creates a new persistent collection. * Creates a new persistent collection.
*
* @param EntityManager $em The EntityManager the collection will be associated with.
* @param ClassMetadata $class The class descriptor of the entity type of this collection.
* @param array The collection elements.
*/ */
public function __construct(EntityManager $em, $class, array $data = array()) public function __construct(EntityManager $em, $class, $coll)
{ {
parent::__construct($data); $this->_coll = $coll;
$this->_em = $em; $this->_em = $em;
$this->_typeClass = $class; $this->_typeClass = $class;
} }
...@@ -122,14 +137,13 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -122,14 +137,13 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
$this->_owner = $entity; $this->_owner = $entity;
$this->_association = $assoc; $this->_association = $assoc;
// Check for bidirectionality // Check for bidirectionality
if ($assoc->isInverseSide()) { if ( ! $assoc->isOwningSide) {
// For sure bi-directional // For sure bi-directional
$this->_backRefFieldName = $assoc->mappedByFieldName; $this->_backRefFieldName = $assoc->mappedByFieldName;
} else { } else {
$targetClass = $this->_em->getClassMetadata($assoc->targetEntityName); if (isset($this->_typeClass->inverseMappings[$assoc->sourceFieldName])) {
if (isset($targetClass->inverseMappings[$assoc->sourceFieldName])) {
// Bi-directional // Bi-directional
$this->_backRefFieldName = $targetClass->inverseMappings[$assoc->sourceFieldName]->sourceFieldName; $this->_backRefFieldName = $this->_typeClass->inverseMappings[$assoc->sourceFieldName]->sourceFieldName;
} }
} }
} }
...@@ -163,7 +177,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -163,7 +177,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
*/ */
public function hydrateAdd($element) public function hydrateAdd($element)
{ {
parent::add($element); $this->_coll->add($element);
// If _backRefFieldName is set, then the association is bidirectional // If _backRefFieldName is set, then the association is bidirectional
// and we need to set the back reference. // and we need to set the back reference.
if ($this->_backRefFieldName) { if ($this->_backRefFieldName) {
...@@ -189,7 +203,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -189,7 +203,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
*/ */
public function hydrateSet($key, $value) public function hydrateSet($key, $value)
{ {
parent::set($key, $value); $this->_coll->set($key, $value);
} }
/** /**
...@@ -210,7 +224,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -210,7 +224,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
*/ */
public function takeSnapshot() public function takeSnapshot()
{ {
$this->_snapshot = $this->_elements; $this->_snapshot = $this->_coll->unwrap();
} }
/** /**
...@@ -232,7 +246,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -232,7 +246,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
*/ */
public function getDeleteDiff() public function getDeleteDiff()
{ {
return array_udiff($this->_snapshot, $this->_elements, array($this, '_compareRecords')); return array_udiff($this->_snapshot, $this->_coll->unwrap(), array($this, '_compareRecords'));
} }
/** /**
...@@ -242,7 +256,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -242,7 +256,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
*/ */
public function getInsertDiff() public function getInsertDiff()
{ {
return array_udiff($this->_elements, $this->_snapshot, array($this, '_compareRecords')); return array_udiff($this->_coll->unwrap(), $this->_snapshot, array($this, '_compareRecords'));
} }
/** /**
...@@ -319,14 +333,14 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -319,14 +333,14 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function first() public function first()
{ {
$this->_initialize(); $this->_initialize();
return parent::first(); return $this->_coll->first();
} }
/** {@inheritdoc} */ /** {@inheritdoc} */
public function last() public function last()
{ {
$this->_initialize(); $this->_initialize();
return parent::last(); return $this->_coll->last();
} }
/** /**
...@@ -335,7 +349,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -335,7 +349,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function remove($key) public function remove($key)
{ {
$this->_initialize(); $this->_initialize();
$removed = parent::remove($key); $removed = $this->_coll->remove($key);
if ($removed) { if ($removed) {
$this->_changed(); $this->_changed();
if ($this->_association->isOneToMany() && $this->_association->orphanRemoval) { if ($this->_association->isOneToMany() && $this->_association->orphanRemoval) {
...@@ -352,7 +366,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -352,7 +366,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function removeElement($element) public function removeElement($element)
{ {
$this->_initialize(); $this->_initialize();
$result = parent::removeElement($element); $result = $this->_coll->removeElement($element);
$this->_changed(); $this->_changed();
return $result; return $result;
} }
...@@ -363,7 +377,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -363,7 +377,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function containsKey($key) public function containsKey($key)
{ {
$this->_initialize(); $this->_initialize();
return parent::containsKey($key); return $this->_coll->containsKey($key);
} }
/** /**
...@@ -372,7 +386,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -372,7 +386,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function contains($element) public function contains($element)
{ {
$this->_initialize(); $this->_initialize();
return parent::contains($element); return $this->_coll->contains($element);
} }
/** /**
...@@ -381,7 +395,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -381,7 +395,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function exists(Closure $p) public function exists(Closure $p)
{ {
$this->_initialize(); $this->_initialize();
return parent::exists($p); return $this->_coll->exists($p);
} }
/** /**
...@@ -390,7 +404,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -390,7 +404,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function search($element) public function search($element)
{ {
$this->_initialize(); $this->_initialize();
return parent::search($element); return $this->_coll->search($element);
} }
/** /**
...@@ -399,7 +413,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -399,7 +413,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function get($key) public function get($key)
{ {
$this->_initialize(); $this->_initialize();
return parent::get($key); return $this->_coll->get($key);
} }
/** /**
...@@ -408,16 +422,16 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -408,16 +422,16 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function getKeys() public function getKeys()
{ {
$this->_initialize(); $this->_initialize();
return parent::getKeys(); return $this->_coll->getKeys();
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getElements() public function getValues()
{ {
$this->_initialize(); $this->_initialize();
return parent::getElements(); return $this->_coll->getValues();
} }
/** /**
...@@ -426,7 +440,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -426,7 +440,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function count() public function count()
{ {
$this->_initialize(); $this->_initialize();
return parent::count(); return $this->_coll->count();
} }
/** /**
...@@ -434,7 +448,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -434,7 +448,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
*/ */
public function set($key, $value) public function set($key, $value)
{ {
parent::set($key, $value); $this->_coll->set($key, $value);
$this->_changed(); $this->_changed();
} }
...@@ -443,7 +457,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -443,7 +457,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
*/ */
public function add($value) public function add($value)
{ {
parent::add($value); $this->_coll->add($value);
$this->_changed(); $this->_changed();
return true; return true;
} }
...@@ -454,7 +468,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -454,7 +468,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function isEmpty() public function isEmpty()
{ {
$this->_initialize(); $this->_initialize();
return parent::isEmpty(); return $this->_coll->isEmpty();
} }
/** /**
...@@ -463,7 +477,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -463,7 +477,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function getIterator() public function getIterator()
{ {
$this->_initialize(); $this->_initialize();
return parent::getIterator(); return $this->_coll->getIterator();
} }
/** /**
...@@ -472,7 +486,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -472,7 +486,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function map(Closure $func) public function map(Closure $func)
{ {
$this->_initialize(); $this->_initialize();
$result = parent::map($func); $result = $this->_coll->map($func);
$this->_changed(); $this->_changed();
return $result; return $result;
} }
...@@ -483,7 +497,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -483,7 +497,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function filter(Closure $p) public function filter(Closure $p)
{ {
$this->_initialize(); $this->_initialize();
return parent::filter($p); return $this->_coll->filter($p);
} }
/** /**
...@@ -492,7 +506,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -492,7 +506,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function forAll(Closure $p) public function forAll(Closure $p)
{ {
$this->_initialize(); $this->_initialize();
return parent::forAll($p); return $this->_coll->forAll($p);
} }
/** /**
...@@ -501,7 +515,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -501,7 +515,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function partition(Closure $p) public function partition(Closure $p)
{ {
$this->_initialize(); $this->_initialize();
return parent::partition($p); return $this->_coll->partition($p);
} }
/** /**
...@@ -510,7 +524,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -510,7 +524,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public function clear() public function clear()
{ {
$this->_initialize(); $this->_initialize();
$result = parent::clear(); $result = $this->_coll->clear();
if ($this->_association->isOwningSide) { if ($this->_association->isOwningSide) {
$this->_changed(); $this->_changed();
$this->_em->getUnitOfWork()->scheduleCollectionDeletion($this); $this->_em->getUnitOfWork()->scheduleCollectionDeletion($this);
...@@ -528,6 +542,59 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection ...@@ -528,6 +542,59 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
*/ */
public function __sleep() public function __sleep()
{ {
return array('_elements'); return array('_coll');
}
/* ArrayAccess implementation */
/**
* @see containsKey()
*/
public function offsetExists($offset)
{
return $this->containsKey($offset);
}
/**
* @see get()
*/
public function offsetGet($offset)
{
return $this->get($offset);
}
/**
* @see add()
* @see set()
*/
public function offsetSet($offset, $value)
{
if ( ! isset($offset)) {
return $this->add($value);
}
return $this->set($offset, $value);
}
/**
* @see remove()
*/
public function offsetUnset($offset)
{
return $this->remove($offset);
}
public function toArray()
{
return $this->_coll->toArray();
}
public function key()
{
return $this->_coll->key();
}
public function unwrap()
{
return $this->_coll;
} }
} }
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
namespace Doctrine\ORM\Persisters; namespace Doctrine\ORM\Persisters;
use Doctrine\Common\DoctrineException; use Doctrine\Common\DoctrineException;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
...@@ -490,7 +491,8 @@ class StandardEntityPersister ...@@ -490,7 +491,8 @@ class StandardEntityPersister
} }
} else { } else {
// Inject collection // Inject collection
$coll = new PersistentCollection($this->_em, $this->_em->getClassMetadata($assoc->targetEntityName)); $coll = new PersistentCollection($this->_em, $this->_em->getClassMetadata($assoc->targetEntityName),
new ArrayCollection);
$coll->setOwner($entity, $assoc); $coll->setOwner($entity, $assoc);
$this->_class->reflFields[$field]->setValue($entity, $coll); $this->_class->reflFields[$field]->setValue($entity, $coll);
if ($assoc->isLazilyFetched()) { if ($assoc->isLazilyFetched()) {
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
*/ */
namespace Doctrine\ORM\Proxy; namespace Doctrine\ORM\Proxy;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadata;
...@@ -85,9 +86,12 @@ class ProxyClassGenerator ...@@ -85,9 +86,12 @@ class ProxyClassGenerator
protected function _generateClass($originalClassName, $proxyClassName, $file) protected function _generateClass($originalClassName, $proxyClassName, $file)
{ {
$class = $this->_em->getClassMetadata($originalClassName);
$proxyFullyQualifiedClassName = self::$_ns . $proxyClassName; $proxyFullyQualifiedClassName = self::$_ns . $proxyClassName;
if ($this->_em->getMetadataFactory()->hasMetadataFor($proxyFullyQualifiedClassName)) {
return $proxyFullyQualifiedClassName;
}
$class = $this->_em->getClassMetadata($originalClassName); $class = $this->_em->getClassMetadata($originalClassName);
$this->_em->getMetadataFactory()->setMetadataFor($proxyFullyQualifiedClassName, $class); $this->_em->getMetadataFactory()->setMetadataFor($proxyFullyQualifiedClassName, $class);
...@@ -214,7 +218,7 @@ namespace Doctrine\Generated\Proxies { ...@@ -214,7 +218,7 @@ namespace Doctrine\Generated\Proxies {
public function __sleep() { public function __sleep() {
if (!$this->_loaded) { if (!$this->_loaded) {
throw new RuntimeException("Not fully loaded proxy can not be serialized."); throw new \RuntimeException("Not fully loaded proxy can not be serialized.");
} }
<sleepImpl> <sleepImpl>
} }
...@@ -252,7 +256,7 @@ namespace Doctrine\Generated\Proxies { ...@@ -252,7 +256,7 @@ namespace Doctrine\Generated\Proxies {
public function __sleep() { public function __sleep() {
if (!$this->_loaded) { if (!$this->_loaded) {
throw new RuntimeException("Not fully loaded proxy can not be serialized."); throw new \RuntimeException("Not fully loaded proxy can not be serialized.");
} }
<sleepImpl> <sleepImpl>
} }
......
...@@ -75,6 +75,8 @@ final class Query extends AbstractQuery ...@@ -75,6 +75,8 @@ final class Query extends AbstractQuery
*/ */
const HINT_INCLUDE_META_COLUMNS = 'doctrine.includeMetaColumns'; const HINT_INCLUDE_META_COLUMNS = 'doctrine.includeMetaColumns';
//const HINT_READ_ONLY = 'doctrine.readOnly';
/** /**
* @var integer $_state The current state of this query. * @var integer $_state The current state of this query.
*/ */
......
...@@ -21,17 +21,13 @@ ...@@ -21,17 +21,13 @@
namespace Doctrine\ORM; namespace Doctrine\ORM;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\ArrayCollection,
use Doctrine\Common\DoctrineException; Doctrine\Common\Collections\ICollection,
use Doctrine\Common\PropertyChangedListener; Doctrine\Common\DoctrineException,
use Doctrine\ORM\Events; Doctrine\Common\PropertyChangedListener,
use Doctrine\ORM\Event\LifecycleEventArgs; Doctrine\ORM\Event\LifecycleEventArgs,
use Doctrine\ORM\Internal\CommitOrderCalculator; Doctrine\ORM\Internal\CommitOrderCalculator,
use Doctrine\ORM\Internal\CommitOrderNode; Doctrine\ORM\Internal\CommitOrderNode;
use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\Mapping;
use Doctrine\ORM\Persisters;
use Doctrine\ORM\EntityManager;
/** /**
* The UnitOfWork is responsible for tracking changes to objects during an * The UnitOfWork is responsible for tracking changes to objects during an
...@@ -468,13 +464,13 @@ class UnitOfWork implements PropertyChangedListener ...@@ -468,13 +464,13 @@ class UnitOfWork implements PropertyChangedListener
if ($class->isCollectionValuedAssociation($name) && $actualData[$name] !== null if ($class->isCollectionValuedAssociation($name) && $actualData[$name] !== null
&& ! ($actualData[$name] instanceof PersistentCollection)) { && ! ($actualData[$name] instanceof PersistentCollection)) {
// If $actualData[$name] is Collection then unwrap the array // If $actualData[$name] is Collection then unwrap the array
if ($actualData[$name] instanceof Collection) { if ( ! $actualData[$name] instanceof ArrayCollection) {
$actualData[$name] = $actualData[$name]->unwrap(); $actualData[$name] = new ArrayCollection($actualData[$name]);
} }
$assoc = $class->associationMappings[$name]; $assoc = $class->associationMappings[$name];
// Inject PersistentCollection // Inject PersistentCollection
$coll = new PersistentCollection($this->_em, $this->_em->getClassMetadata($assoc->targetEntityName), $coll = new PersistentCollection($this->_em, $this->_em->getClassMetadata(
$actualData[$name] ? $actualData[$name] : array()); $assoc->targetEntityName), $actualData[$name]);
$coll->setOwner($entity, $assoc); $coll->setOwner($entity, $assoc);
$coll->setDirty( ! $coll->isEmpty()); $coll->setDirty( ! $coll->isEmpty());
$class->reflFields[$name]->setValue($entity, $coll); $class->reflFields[$name]->setValue($entity, $coll);
...@@ -1326,7 +1322,8 @@ class UnitOfWork implements PropertyChangedListener ...@@ -1326,7 +1322,8 @@ class UnitOfWork implements PropertyChangedListener
} else { } else {
//TODO: Only do this when allowPartialObjects == false? //TODO: Only do this when allowPartialObjects == false?
$coll = new PersistentCollection($this->_em, $coll = new PersistentCollection($this->_em,
$this->_em->getClassMetadata($assoc2->targetEntityName) $this->_em->getClassMetadata($assoc2->targetEntityName),
new ArrayCollection
); );
$coll->setOwner($managedCopy, $assoc2); $coll->setOwner($managedCopy, $assoc2);
$coll->setInitialized($assoc2->isCascadeMerge); $coll->setInitialized($assoc2->isCascadeMerge);
...@@ -1458,7 +1455,7 @@ class UnitOfWork implements PropertyChangedListener ...@@ -1458,7 +1455,7 @@ class UnitOfWork implements PropertyChangedListener
continue; continue;
} }
$relatedEntities = $class->reflFields[$assocMapping->sourceFieldName]->getValue($entity); $relatedEntities = $class->reflFields[$assocMapping->sourceFieldName]->getValue($entity);
if ($relatedEntities instanceof Collection) { if ($relatedEntities instanceof ICollection) {
foreach ($relatedEntities as $relatedEntity) { foreach ($relatedEntities as $relatedEntity) {
$this->_doRefresh($relatedEntity, $visited); $this->_doRefresh($relatedEntity, $visited);
} }
...@@ -1482,7 +1479,7 @@ class UnitOfWork implements PropertyChangedListener ...@@ -1482,7 +1479,7 @@ class UnitOfWork implements PropertyChangedListener
continue; continue;
} }
$relatedEntities = $class->reflFields[$assocMapping->sourceFieldName]->getValue($entity); $relatedEntities = $class->reflFields[$assocMapping->sourceFieldName]->getValue($entity);
if ($relatedEntities instanceof Collection) { if ($relatedEntities instanceof ICollection) {
foreach ($relatedEntities as $relatedEntity) { foreach ($relatedEntities as $relatedEntity) {
$this->_doDetach($relatedEntity, $visited); $this->_doDetach($relatedEntity, $visited);
} }
...@@ -1507,7 +1504,7 @@ class UnitOfWork implements PropertyChangedListener ...@@ -1507,7 +1504,7 @@ class UnitOfWork implements PropertyChangedListener
continue; continue;
} }
$relatedEntities = $class->reflFields[$assocMapping->sourceFieldName]->getValue($entity); $relatedEntities = $class->reflFields[$assocMapping->sourceFieldName]->getValue($entity);
if ($relatedEntities instanceof Collection) { if ($relatedEntities instanceof ICollection) {
foreach ($relatedEntities as $relatedEntity) { foreach ($relatedEntities as $relatedEntity) {
$this->_doMerge($relatedEntity, $visited, $managedCopy, $assocMapping); $this->_doMerge($relatedEntity, $visited, $managedCopy, $assocMapping);
} }
...@@ -1532,7 +1529,7 @@ class UnitOfWork implements PropertyChangedListener ...@@ -1532,7 +1529,7 @@ class UnitOfWork implements PropertyChangedListener
continue; continue;
} }
$relatedEntities = $class->reflFields[$assocMapping->sourceFieldName]->getValue($entity); $relatedEntities = $class->reflFields[$assocMapping->sourceFieldName]->getValue($entity);
if (($relatedEntities instanceof Collection || is_array($relatedEntities))) { if (($relatedEntities instanceof ICollection || is_array($relatedEntities))) {
foreach ($relatedEntities as $relatedEntity) { foreach ($relatedEntities as $relatedEntity) {
$this->_doPersist($relatedEntity, $visited); $this->_doPersist($relatedEntity, $visited);
} }
...@@ -1557,7 +1554,7 @@ class UnitOfWork implements PropertyChangedListener ...@@ -1557,7 +1554,7 @@ class UnitOfWork implements PropertyChangedListener
} }
$relatedEntities = $class->reflFields[$assocMapping->sourceFieldName] $relatedEntities = $class->reflFields[$assocMapping->sourceFieldName]
->getValue($entity); ->getValue($entity);
if ($relatedEntities instanceof Collection || is_array($relatedEntities)) { if ($relatedEntities instanceof ICollection || is_array($relatedEntities)) {
foreach ($relatedEntities as $relatedEntity) { foreach ($relatedEntities as $relatedEntity) {
$this->_doRemove($relatedEntity, $visited); $this->_doRemove($relatedEntity, $visited);
} }
......
...@@ -12,7 +12,7 @@ class CollectionTest extends \Doctrine\Tests\DoctrineTestCase ...@@ -12,7 +12,7 @@ class CollectionTest extends \Doctrine\Tests\DoctrineTestCase
protected function setUp() protected function setUp()
{ {
$this->_coll = new \Doctrine\Common\Collections\Collection; $this->_coll = new \Doctrine\Common\Collections\ArrayCollection;
} }
public function testIssetAndUnset() public function testIssetAndUnset()
...@@ -114,11 +114,11 @@ class CollectionTest extends \Doctrine\Tests\DoctrineTestCase ...@@ -114,11 +114,11 @@ class CollectionTest extends \Doctrine\Tests\DoctrineTestCase
$this->assertEquals(array(0, 1), $this->_coll->getKeys()); $this->assertEquals(array(0, 1), $this->_coll->getKeys());
} }
public function testGetElements() public function testGetValues()
{ {
$this->_coll[] = 'one'; $this->_coll[] = 'one';
$this->_coll[] = 'two'; $this->_coll[] = 'two';
$this->assertEquals(array('one', 'two'), $this->_coll->getElements()); $this->assertEquals(array('one', 'two'), $this->_coll->getValues());
} }
public function testCount() public function testCount()
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
namespace Doctrine\Tests\Models\CMS; namespace Doctrine\Tests\Models\CMS;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\ArrayCollection;
/** /**
* @Entity * @Entity
...@@ -49,9 +49,9 @@ class CmsUser ...@@ -49,9 +49,9 @@ class CmsUser
public $groups; public $groups;
public function __construct() { public function __construct() {
$this->phonenumbers = new Collection; $this->phonenumbers = new ArrayCollection;
$this->articles = new Collection; $this->articles = new ArrayCollection;
$this->groups = new Collection; $this->groups = new ArrayCollection;
} }
public function getId() { public function getId() {
......
...@@ -62,7 +62,7 @@ class CompanyPerson ...@@ -62,7 +62,7 @@ class CompanyPerson
public function addFriend(CompanyPerson $friend) { public function addFriend(CompanyPerson $friend) {
if ( ! $this->friends) { if ( ! $this->friends) {
$this->friends = new \Doctrine\Common\Collections\Collection; $this->friends = new \Doctrine\Common\Collections\ArrayCollection;
} }
if ( ! $this->friends->contains($friend)) { if ( ! $this->friends->contains($friend)) {
$this->friends->add($friend); $this->friends->add($friend);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
namespace Doctrine\Tests\Models\ECommerce; namespace Doctrine\Tests\Models\ECommerce;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\ArrayCollection;
/** /**
* ECommerceCart * ECommerceCart
...@@ -42,7 +42,7 @@ class ECommerceCart ...@@ -42,7 +42,7 @@ class ECommerceCart
public function __construct() public function __construct()
{ {
$this->products = new Collection; $this->products = new ArrayCollection;
} }
public function getId() { public function getId() {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
namespace Doctrine\Tests\Models\ECommerce; namespace Doctrine\Tests\Models\ECommerce;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\ArrayCollection;
/** /**
* ECommerceCategory * ECommerceCategory
...@@ -44,8 +44,8 @@ class ECommerceCategory ...@@ -44,8 +44,8 @@ class ECommerceCategory
public function __construct() public function __construct()
{ {
$this->products = new Collection(); $this->products = new ArrayCollection();
$this->children = new Collection(); $this->children = new ArrayCollection();
} }
public function getId() public function getId()
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
namespace Doctrine\Tests\Models\ECommerce; namespace Doctrine\Tests\Models\ECommerce;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\ArrayCollection;
/** /**
* ECommerceProduct * ECommerceProduct
...@@ -57,9 +57,9 @@ class ECommerceProduct ...@@ -57,9 +57,9 @@ class ECommerceProduct
public function __construct() public function __construct()
{ {
$this->features = new Collection; $this->features = new ArrayCollection;
$this->categories = new Collection; $this->categories = new ArrayCollection;
$this->related = new Collection; $this->related = new ArrayCollection;
} }
public function getId() public function getId()
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
namespace Doctrine\Tests\ORM\Functional; namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\ICollection;
require_once __DIR__ . '/../../TestInit.php'; require_once __DIR__ . '/../../TestInit.php';
...@@ -36,18 +36,8 @@ class AbstractManyToManyAssociationTestCase extends \Doctrine\Tests\OrmFunctiona ...@@ -36,18 +36,8 @@ class AbstractManyToManyAssociationTestCase extends \Doctrine\Tests\OrmFunctiona
->fetchAll()); ->fetchAll());
} }
public function assertCollectionEquals(Collection $first, Collection $second) public function assertCollectionEquals(ICollection $first, ICollection $second)
{ {
return $first->forAll(function($k, $e) use($second) { return $second->contains($e); }); return $first->forAll(function($k, $e) use($second) { return $second->contains($e); });
/*if (count($first) != count($second)) {
return false;
}
foreach ($first as $element) {
if (!$second->contains($element)) {
return false;
}
}
return true;*/
} }
} }
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
namespace Doctrine\Tests\ORM\Functional; namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Common\Collections\Collection;
use Doctrine\Tests\Models\ECommerce\ECommerceProduct; use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
use Doctrine\Tests\Models\ECommerce\ECommerceCategory; use Doctrine\Tests\Models\ECommerce\ECommerceCategory;
use Doctrine\ORM\Mapping\AssociationMapping; use Doctrine\ORM\Mapping\AssociationMapping;
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
namespace Doctrine\Tests\ORM\Functional; namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Common\Collections\Collection;
use Doctrine\Tests\Models\ECommerce\ECommerceProduct; use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
use Doctrine\ORM\Mapping\AssociationMapping; use Doctrine\ORM\Mapping\AssociationMapping;
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
namespace Doctrine\Tests\ORM\Functional; namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Common\Collections\Collection;
use Doctrine\Tests\Models\ECommerce\ECommerceCart; use Doctrine\Tests\Models\ECommerce\ECommerceCart;
use Doctrine\Tests\Models\ECommerce\ECommerceProduct; use Doctrine\Tests\Models\ECommerce\ECommerceProduct;
use Doctrine\ORM\Mapping\AssociationMapping; use Doctrine\ORM\Mapping\AssociationMapping;
......
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