. */ namespace Doctrine\ORM\Persisters; use Doctrine\Common\Collections\Criteria; use Doctrine\ORM\PersistentCollection; use Doctrine\ORM\UnitOfWork; /** * Persister for one-to-many collections. * * @author Roman Borschel * @author Guilherme Blanco * @author Alexander * @since 2.0 */ class OneToManyPersister extends AbstractCollectionPersister { /** * {@inheritdoc} */ public function delete(PersistentCollection $coll) { // This can never happen. One to many can only be inverse side. // For owning side one to many, it is required to have a join table, // then classifying it as a ManyToManyPersister. return; } /** * {@inheritdoc} */ public function update(PersistentCollection $coll) { // This can never happen. One to many can only be inverse side. // For owning side one to many, it is required to have a join table, // then classifying it as a ManyToManyPersister. return; } /** * {@inheritdoc} */ public function get(PersistentCollection $coll, $index) { $mapping = $coll->getMapping(); $persister = $this->uow->getEntityPersister($mapping['targetEntity']); if (!isset($mapping['indexBy'])) { throw new \BadMethodCallException("Selecting a collection by index is only supported on indexed collections."); } return $persister->load( array( $mapping['mappedBy'] => $coll->getOwner(), $mapping['indexBy'] => $index ), null, null, array(), null, 1 ); } /** * {@inheritdoc} */ public function count(PersistentCollection $coll) { $mapping = $coll->getMapping(); $persister = $this->uow->getEntityPersister($mapping['targetEntity']); // only works with single id identifier entities. Will throw an // exception in Entity Persisters if that is not the case for the // 'mappedBy' field. $criteria = new Criteria(Criteria::expr()->eq($mapping['mappedBy'], $coll->getOwner())); return $persister->count($criteria); } /** * {@inheritdoc} */ public function slice(PersistentCollection $coll, $offset, $length = null) { $mapping = $coll->getMapping(); $persister = $this->uow->getEntityPersister($mapping['targetEntity']); return $persister->getOneToManyCollection($mapping, $coll->getOwner(), $offset, $length); } /** * {@inheritdoc} */ public function containsKey(PersistentCollection $coll, $key) { $mapping = $coll->getMapping(); $persister = $this->uow->getEntityPersister($mapping['targetEntity']); // only works with single id identifier entities. Will throw an // exception in Entity Persisters if that is not the case for the // 'mappedBy' field. $criteria = new Criteria(); $criteria->andWhere(Criteria::expr()->eq($mapping['mappedBy'], $coll->getOwner())); $criteria->andWhere(Criteria::expr()->eq($mapping['indexBy'], $key)); return (bool) $persister->count($criteria); } /** * {@inheritdoc} */ public function contains(PersistentCollection $coll, $element) { if ( ! $this->isValidEntityState($element)) { return false; } $mapping = $coll->getMapping(); $persister = $this->uow->getEntityPersister($mapping['targetEntity']); // only works with single id identifier entities. Will throw an // exception in Entity Persisters if that is not the case for the // 'mappedBy' field. $criteria = new Criteria(Criteria::expr()->eq($mapping['mappedBy'], $coll->getOwner())); return $persister->exists($element, $criteria); } /** * {@inheritdoc} */ public function removeElement(PersistentCollection $coll, $element) { if ( ! $this->isValidEntityState($element)) { return false; } $mapping = $coll->getMapping(); $persister = $this->uow->getEntityPersister($mapping['targetEntity']); return $persister->delete($element); } /** * {@inheritdoc} */ public function loadCriteria(PersistentCollection $collection, Criteria $criteria) { throw new \BadMethodCallException("Filtering a collection by Criteria is not supported by this CollectionPersister."); } /** * Check if entity is in a valid state for operations. * * @param $entity * * @return bool */ private function isValidEntityState($entity) { $entityState = $this->uow->getEntityState($entity, UnitOfWork::STATE_NEW); if ($entityState === UnitOfWork::STATE_NEW) { return false; } // If Entity is scheduled for inclusion, it is not in this collection. // We can assure that because it would have return true before on array check if ($entityState === UnitOfWork::STATE_MANAGED && $this->uow->isScheduledForInsert($entity)) { return false; } return true; } }