/**
  * {@inheritdoc}
  */
 public function update(PersistentCollection $collection)
 {
     if ($collection->isDirty() && $collection->getSnapshot()) {
         throw CacheException::updateReadOnlyCollection(ClassUtils::getClass($collection->getOwner()), $this->association['fieldName']);
     }
     parent::update($collection);
 }
 /**
  * {@inheritdoc}
  */
 public function delete(PersistentCollection $collection)
 {
     $ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
     $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId);
     $lock = $this->region->lock($key);
     $this->persister->delete($collection);
     if ($lock === null) {
         return;
     }
     $this->queuedCache['delete'][spl_object_hash($collection)] = array('key' => $key, 'lock' => $lock);
 }
 /**
  * {@inheritdoc}
  */
 public function update(PersistentCollection $collection)
 {
     $isInitialized = $collection->isInitialized();
     $isDirty = $collection->isDirty();
     if (!$isInitialized && !$isDirty) {
         return;
     }
     $ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
     $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId);
     // Invalidate non initialized collections OR ordered collection
     if ($isDirty && !$isInitialized || isset($this->association['orderBy'])) {
         $this->persister->update($collection);
         $this->queuedCache['delete'][spl_object_hash($collection)] = $key;
         return;
     }
     $this->persister->update($collection);
     $this->queuedCache['update'][spl_object_hash($collection)] = ['key' => $key, 'list' => $collection];
 }
 /**
  * {@inheritdoc}
  */
 public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll)
 {
     $persister = $this->uow->getCollectionPersister($assoc);
     $hasCache = $persister instanceof CachedPersister;
     if ($hasCache) {
         $ownerId = $this->uow->getEntityIdentifier($coll->getOwner());
         $key = new CollectionCacheKey($assoc['sourceEntity'], $assoc['fieldName'], $ownerId);
         $list = $persister->loadCollectionCache($coll, $key);
         if ($list !== null) {
             if ($this->cacheLogger) {
                 $this->cacheLogger->collectionCacheHit($persister->getCacheRegion()->getName(), $key);
             }
             return $list;
         }
     }
     $list = $this->persister->loadOneToManyCollection($assoc, $sourceEntity, $coll);
     if ($hasCache) {
         $persister->storeCollectionCache($key, $list);
         if ($this->cacheLogger) {
             $this->cacheLogger->collectionCacheMiss($persister->getCacheRegion()->getName(), $key);
         }
     }
     return $list;
 }
Beispiel #5
0
 /**
  * @param PersistentCollection $collection
  */
 protected function calculateCollectionData(PersistentCollection $collection)
 {
     $ownerEntity = $collection->getOwner();
     $ownerEntityClassName = $this->getEntityClassName($ownerEntity);
     if ($this->checkAuditable($ownerEntityClassName)) {
         $meta = $this->getConfig($ownerEntityClassName);
         $collectionMapping = $collection->getMapping();
         if (isset($meta->propertyMetadata[$collectionMapping['fieldName']])) {
             $method = $meta->propertyMetadata[$collectionMapping['fieldName']]->method;
             // calculate collection changes
             $newCollection = $collection->toArray();
             $oldCollection = $collection->getSnapshot();
             $oldData = array_reduce($oldCollection, function ($result, $item) use($method) {
                 return $result . ($result ? ', ' : '') . $item->{$method}();
             });
             $newData = array_reduce($newCollection, function ($result, $item) use($method) {
                 return $result . ($result ? ', ' : '') . $item->{$method}();
             });
             $entityIdentifier = $this->getEntityIdentifierString($ownerEntity);
             $fieldName = $collectionMapping['fieldName'];
             $this->collectionLogData[$ownerEntityClassName][$entityIdentifier][$fieldName] = array('old' => $oldData, 'new' => $newData);
         }
     }
 }
 /**
  * {@inheritdoc}
  *
  * @override
  */
 protected function _getDeleteSqlParameters(PersistentCollection $coll)
 {
     //FIXME: This is still problematic for composite keys because we silently
     // rely on a specific ordering of the columns.
     return $this->_uow->getEntityIdentifier($coll->getOwner());
 }
 /**
  * {@inheritDoc}
  */
 public function loadCriteria(PersistentCollection $coll, Criteria $criteria)
 {
     $mapping = $coll->getMapping();
     $owner = $coll->getOwner();
     $ownerMetadata = $this->em->getClassMetadata(get_class($owner));
     $whereClauses = $params = array();
     foreach ($mapping['relationToSourceKeyColumns'] as $key => $value) {
         $whereClauses[] = sprintf('t.%s = ?', $key);
         $params[] = $ownerMetadata->getFieldValue($owner, $value);
     }
     $parameters = $this->expandCriteriaParameters($criteria);
     foreach ($parameters as $parameter) {
         list($name, $value) = $parameter;
         $whereClauses[] = sprintf('te.%s = ?', $name);
         $params[] = $value;
     }
     $mapping = $coll->getMapping();
     $targetClass = $this->em->getClassMetadata($mapping['targetEntity']);
     $tableName = $this->quoteStrategy->getTableName($targetClass, $this->platform);
     $joinTable = $this->quoteStrategy->getJoinTableName($mapping, $ownerMetadata, $this->platform);
     $onConditions = $this->getOnConditionSQL($mapping);
     $rsm = new Query\ResultSetMappingBuilder($this->em);
     $rsm->addRootEntityFromClassMetadata($mapping['targetEntity'], 'te');
     $sql = 'SELECT ' . $rsm->generateSelectClause() . ' FROM ' . $tableName . ' te' . ' JOIN ' . $joinTable . ' t ON' . implode(' AND ', $onConditions) . ' WHERE ' . implode(' AND ', $whereClauses);
     $stmt = $this->conn->executeQuery($sql, $params);
     $hydrator = $this->em->newHydrator(Query::HYDRATE_OBJECT);
     return $hydrator->hydrateAll($stmt, $rsm);
 }
Beispiel #8
0
 /**
  * @param \Doctrine\ORM\PersistentCollection $coll
  * @param object $element
  * @param boolean $addFilters Whether the filter SQL should be included or not.
  * @return array
  */
 private function getJoinTableRestrictions(PersistentCollection $coll, $element, $addFilters)
 {
     $uow = $this->_em->getUnitOfWork();
     $mapping = $filterMapping = $coll->getMapping();
     if (!$mapping['isOwningSide']) {
         $sourceClass = $this->_em->getClassMetadata($mapping['targetEntity']);
         $targetClass = $this->_em->getClassMetadata($mapping['sourceEntity']);
         $sourceId = $uow->getEntityIdentifier($element);
         $targetId = $uow->getEntityIdentifier($coll->getOwner());
         $mapping = $sourceClass->associationMappings[$mapping['mappedBy']];
     } else {
         $sourceClass = $this->_em->getClassMetadata($mapping['sourceEntity']);
         $targetClass = $this->_em->getClassMetadata($mapping['targetEntity']);
         $sourceId = $uow->getEntityIdentifier($coll->getOwner());
         $targetId = $uow->getEntityIdentifier($element);
     }
     $quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $sourceClass, $this->platform);
     $whereClauses = array();
     $params = array();
     foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
         $whereClauses[] = $joinTableColumn . ' = ?';
         if (isset($mapping['relationToTargetKeyColumns'][$joinTableColumn])) {
             $params[] = $targetClass->containsForeignIdentifier ? $targetId[$targetClass->getFieldForColumn($mapping['relationToTargetKeyColumns'][$joinTableColumn])] : $targetId[$targetClass->fieldNames[$mapping['relationToTargetKeyColumns'][$joinTableColumn]]];
             continue;
         }
         // relationToSourceKeyColumns
         $params[] = $sourceClass->containsForeignIdentifier ? $sourceId[$sourceClass->getFieldForColumn($mapping['relationToSourceKeyColumns'][$joinTableColumn])] : $sourceId[$sourceClass->fieldNames[$mapping['relationToSourceKeyColumns'][$joinTableColumn]]];
     }
     if ($addFilters) {
         list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($filterMapping);
         if ($filterSql) {
             $quotedJoinTable .= ' t ' . $joinTargetEntitySQL;
             $whereClauses[] = $filterSql;
         }
     }
     return array($quotedJoinTable, $whereClauses, $params);
 }
 /**
  * @param PersistentCollection $coll
  * @param object $element
  */
 public function contains(PersistentCollection $coll, $element)
 {
     $uow = $this->_em->getUnitOfWork();
     // shortcut for new entities
     if ($uow->getEntityState($element, UnitOfWork::STATE_NEW) == UnitOfWork::STATE_NEW) {
         return false;
     }
     $params = array();
     $mapping = $coll->getMapping();
     if (!$mapping['isOwningSide']) {
         $sourceClass = $this->_em->getClassMetadata($mapping['targetEntity']);
         $targetClass = $this->_em->getClassMetadata($mapping['sourceEntity']);
         $sourceId = $uow->getEntityIdentifier($element);
         $targetId = $uow->getEntityIdentifier($coll->getOwner());
         $mapping = $sourceClass->associationMappings[$mapping['mappedBy']];
     } else {
         $sourceClass = $this->_em->getClassMetadata($mapping['sourceEntity']);
         $targetClass = $this->_em->getClassMetadata($mapping['targetEntity']);
         $sourceId = $uow->getEntityIdentifier($coll->getOwner());
         $targetId = $uow->getEntityIdentifier($element);
     }
     $joinTable = $mapping['joinTable'];
     $whereClause = '';
     foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
         if (isset($mapping['relationToTargetKeyColumns'][$joinTableColumn])) {
             if ($whereClause !== '') {
                 $whereClause .= ' AND ';
             }
             $whereClause .= "{$joinTableColumn} = ?";
             if ($targetClass->containsForeignIdentifier) {
                 $params[] = $targetId[$targetClass->getFieldForColumn($mapping['relationToTargetKeyColumns'][$joinTableColumn])];
             } else {
                 $params[] = $targetId[$targetClass->fieldNames[$mapping['relationToTargetKeyColumns'][$joinTableColumn]]];
             }
         } else {
             if (isset($mapping['relationToSourceKeyColumns'][$joinTableColumn])) {
                 if ($whereClause !== '') {
                     $whereClause .= ' AND ';
                 }
                 $whereClause .= "{$joinTableColumn} = ?";
                 if ($sourceClass->containsForeignIdentifier) {
                     $params[] = $sourceId[$sourceClass->getFieldForColumn($mapping['relationToSourceKeyColumns'][$joinTableColumn])];
                 } else {
                     $params[] = $sourceId[$sourceClass->fieldNames[$mapping['relationToSourceKeyColumns'][$joinTableColumn]]];
                 }
             }
         }
     }
     $sql = 'SELECT 1 FROM ' . $joinTable['name'] . ' WHERE ' . $whereClause;
     return (bool) $this->_conn->fetchColumn($sql, $params);
 }
 /**
  * Delete Class Table Inheritance entities.
  * A temporary table is needed to keep IDs to be deleted in both parent and child class' tables.
  *
  * Thanks Steve Ebersole (Hibernate) for idea on how to tackle reliably this scenario, we owe him a beer! =)
  *
  * @param PersistentCollection $collection
  *
  * @return int
  *
  * @throws \Doctrine\DBAL\DBALException
  */
 private function deleteJoinedEntityCollection(PersistentCollection $collection)
 {
     $mapping = $collection->getMapping();
     $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']);
     $targetClass = $this->em->getClassMetadata($mapping['targetEntity']);
     $rootClass = $this->em->getClassMetadata($targetClass->rootEntityName);
     // 1) Build temporary table DDL
     $tempTable = $this->platform->getTemporaryTableName($rootClass->getTemporaryIdTableName());
     $idColumnNames = $rootClass->getIdentifierColumnNames();
     $idColumnList = implode(', ', $idColumnNames);
     $columnDefinitions = [];
     foreach ($idColumnNames as $idColumnName) {
         $columnDefinitions[$idColumnName] = ['notnull' => true, 'type' => Type::getType(PersisterHelper::getTypeOfColumn($idColumnName, $rootClass, $this->em))];
     }
     $statement = $this->platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable . ' (' . $this->platform->getColumnDeclarationListSQL($columnDefinitions) . ')';
     $this->conn->executeUpdate($statement);
     // 2) Build insert table records into temporary table
     $query = $this->em->createQuery(' SELECT t0.' . implode(', t0.', $rootClass->getIdentifierFieldNames()) . ' FROM ' . $targetClass->name . ' t0 WHERE t0.' . $mapping['mappedBy'] . ' = :owner')->setParameter('owner', $collection->getOwner());
     $statement = 'INSERT INTO ' . $tempTable . ' (' . $idColumnList . ') ' . $query->getSQL();
     $parameters = array_values($sourceClass->getIdentifierValues($collection->getOwner()));
     $numDeleted = $this->conn->executeUpdate($statement, $parameters);
     // 3) Delete records on each table in the hierarchy
     $classNames = array_merge($targetClass->parentClasses, [$targetClass->name], $targetClass->subClasses);
     foreach (array_reverse($classNames) as $className) {
         $tableName = $this->quoteStrategy->getTableName($this->em->getClassMetadata($className), $this->platform);
         $statement = 'DELETE FROM ' . $tableName . ' WHERE (' . $idColumnList . ')' . ' IN (SELECT ' . $idColumnList . ' FROM ' . $tempTable . ')';
         $this->conn->executeUpdate($statement);
     }
     // 4) Drop temporary table
     $statement = $this->platform->getDropTemporaryTableSQL($tempTable);
     $this->conn->executeUpdate($statement);
     return $numDeleted;
 }
 /**
  * Clears cache entries related to the current collection
  *
  * @param PersistentCollection $collection
  */
 protected function evictCollectionCache(PersistentCollection $collection)
 {
     $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $this->uow->getEntityIdentifier($collection->getOwner()));
     $this->region->evict($key);
     if ($this->cacheLogger) {
         $this->cacheLogger->collectionCachePut($this->regionName, $key);
     }
 }
 /**
  * @param PersistentCollection $coll
  * @param object $element
  * @return boolean
  */
 public function contains(PersistentCollection $coll, $element)
 {
     $mapping = $coll->getMapping();
     $uow = $this->_em->getUnitOfWork();
     // shortcut for new entities
     $entityState = $uow->getEntityState($element, UnitOfWork::STATE_NEW);
     if ($entityState === UnitOfWork::STATE_NEW) {
         return false;
     }
     // Entity is scheduled for inclusion
     if ($entityState === UnitOfWork::STATE_MANAGED && $uow->isScheduledForInsert($element)) {
         return false;
     }
     $persister = $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.
     $id = current($uow->getEntityIdentifier($coll->getOwner()));
     return $persister->exists($element, array($mapping['mappedBy'] => $id));
 }
 /**
  * {@inheritdoc}
  */
 public function count(PersistentCollection $collection)
 {
     $ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
     $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId);
     $entry = $this->region->get($key);
     if ($entry !== null) {
         return count($entry->identifiers);
     }
     return $this->persister->count($collection);
 }
 /**
  * {@inheritdoc}
  *
  * @override
  * @internal Order of the parameters must be the same as the order of the columns in
  *           _getDeleteSql.
  */
 protected function _getDeleteSqlParameters(PersistentCollection $coll)
 {
     $params = array();
     $mapping = $coll->getMapping();
     $identifier = $this->_uow->getEntityIdentifier($coll->getOwner());
     if (count($mapping->relationToSourceKeyColumns) > 1) {
         $sourceClass = $this->_em->getClassMetadata(get_class($mapping->getOwner()));
         foreach ($mapping->relationToSourceKeyColumns as $relColumn => $srcColumn) {
             $params[] = $identifier[$sourceClass->fieldNames[$srcColumn]];
         }
     } else {
         $params[] = array_pop($identifier);
     }
     return $params;
 }
 /**
  * @param PersistentCollection $collection
  */
 protected function calculateCollectionData(PersistentCollection $collection)
 {
     $ownerEntity = $collection->getOwner();
     if ($this->hasConfig(get_class($ownerEntity))) {
         $meta = $this->getConfig(get_class($ownerEntity));
         $collectionMapping = $collection->getMapping();
         if (isset($meta->propertyMetadata[$collectionMapping['fieldName']])) {
             $method = $meta->propertyMetadata[$collectionMapping['fieldName']]->method;
             $newCollection = $collection->toArray();
             $oldCollection = $collection->getSnapshot();
             $oldData = array_reduce($oldCollection, function ($result, $item) use($method) {
                 return $result . ($result ? ', ' : '') . $item->{$method}();
             });
             $newData = array_reduce($newCollection, function ($result, $item) use($method) {
                 return $result . ($result ? ', ' : '') . $item->{$method}();
             });
             $this->collectionLogData[$collectionMapping['fieldName']] = array('old' => $oldData, 'new' => $newData);
         }
     }
 }
Beispiel #16
0
 /**
  * @param \Doctrine\ORM\PersistentCollection $collection
  * @param object                             $element
  * @param boolean                            $addFilters Whether the filter SQL should be included or not.
  *
  * @return array ordered vector:
  *                - quoted join table name
  *                - where clauses to be added for filtering
  *                - parameters to be bound for filtering
  *                - types of the parameters to be bound for filtering
  */
 private function getJoinTableRestrictions(PersistentCollection $collection, $element, $addFilters)
 {
     $filterMapping = $collection->getMapping();
     $mapping = $filterMapping;
     if (!$mapping['isOwningSide']) {
         $sourceClass = $this->em->getClassMetadata($mapping['targetEntity']);
         $targetClass = $this->em->getClassMetadata($mapping['sourceEntity']);
         $sourceId = $this->uow->getEntityIdentifier($element);
         $targetId = $this->uow->getEntityIdentifier($collection->getOwner());
         $mapping = $sourceClass->associationMappings[$mapping['mappedBy']];
     } else {
         $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']);
         $targetClass = $this->em->getClassMetadata($mapping['targetEntity']);
         $sourceId = $this->uow->getEntityIdentifier($collection->getOwner());
         $targetId = $this->uow->getEntityIdentifier($element);
     }
     $quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $sourceClass, $this->platform);
     $whereClauses = array();
     $params = array();
     $types = array();
     foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
         $whereClauses[] = ($addFilters ? 't.' : '') . $joinTableColumn . ' = ?';
         if (isset($mapping['relationToTargetKeyColumns'][$joinTableColumn])) {
             $targetColumn = $mapping['relationToTargetKeyColumns'][$joinTableColumn];
             $params[] = $targetId[$targetClass->getFieldForColumn($targetColumn)];
             $types[] = PersisterHelper::getTypeOfColumn($targetColumn, $targetClass, $this->em);
             continue;
         }
         // relationToSourceKeyColumns
         $targetColumn = $mapping['relationToSourceKeyColumns'][$joinTableColumn];
         $params[] = $sourceId[$sourceClass->getFieldForColumn($targetColumn)];
         $types[] = PersisterHelper::getTypeOfColumn($targetColumn, $sourceClass, $this->em);
     }
     if ($addFilters) {
         $quotedJoinTable .= ' t';
         list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($filterMapping);
         if ($filterSql) {
             $quotedJoinTable .= ' ' . $joinTargetEntitySQL;
             $whereClauses[] = $filterSql;
         }
     }
     return array($quotedJoinTable, $whereClauses, $params, $types);
 }
Beispiel #17
0
 /**
  * {@inheritdoc}
  */
 public function contains(PersistentCollection $collection, $element)
 {
     if (!$this->isValidEntityState($element)) {
         return false;
     }
     $mapping = $collection->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'], $collection->getOwner()));
     return $persister->exists($element, $criteria);
 }
 /**
  * @param PersistentCollection $coll
  * @param object $element
  */
 public function contains(PersistentCollection $coll, $element)
 {
     $mapping = $coll->getMapping();
     $uow = $this->_em->getUnitOfWork();
     // shortcut for new entities
     if ($uow->getEntityState($element, UnitOfWork::STATE_NEW) == UnitOfWork::STATE_NEW) {
         return false;
     }
     // only works with single id identifier entities. Will throw an exception in Entity Persisters
     // if that is not the case for the 'mappedBy' field.
     $id = current($uow->getEntityIdentifier($coll->getOwner()));
     return $uow->getEntityPersister($mapping['targetEntity'])->exists($element, array($mapping['mappedBy'] => $id));
 }