Beispiel #1
0
 /**
  * @param PersistentCollection $coll
  *
  * @return string|null
  */
 protected function buildSnapshotValue(PersistentCollection $coll)
 {
     if ($coll->isEmpty()) {
         return null;
     }
     $ids = [];
     /** @var AbstractEnumValue $item */
     foreach ($coll as $item) {
         $ids[] = $item->getId();
     }
     sort($ids);
     $snapshot = implode(',', $ids);
     if (strlen($snapshot) > ExtendHelper::MAX_ENUM_SNAPSHOT_LENGTH) {
         $snapshot = substr($snapshot, 0, ExtendHelper::MAX_ENUM_SNAPSHOT_LENGTH);
         $lastDelim = strrpos($snapshot, ',');
         if (ExtendHelper::MAX_ENUM_SNAPSHOT_LENGTH - $lastDelim - 1 < 3) {
             $lastDelim = strrpos($snapshot, ',', -(strlen($snapshot) - $lastDelim + 1));
         }
         $snapshot = substr($snapshot, 0, $lastDelim + 1) . '...';
     }
     return $snapshot;
 }
Beispiel #2
0
 /**
  * Computes the changes that happened to a single entity.
  *
  * Modifies/populates the following properties:
  *
  * {@link _originalEntityData}
  * If the entity is NEW or MANAGED but not yet fully persisted (only has an id)
  * then it was not fetched from the database and therefore we have no original
  * entity data yet. All of the current entity data is stored as the original entity data.
  *
  * {@link _entityChangeSets}
  * The changes detected on all properties of the entity are stored there.
  * A change is a tuple array where the first entry is the old value and the second
  * entry is the new value of the property. Changesets are used by persisters
  * to INSERT/UPDATE the persistent entity state.
  *
  * {@link _entityUpdates}
  * If the entity is already fully MANAGED (has been fetched from the database before)
  * and any changes to its properties are detected, then a reference to the entity is stored
  * there to mark it for an update.
  *
  * {@link _collectionDeletions}
  * If a PersistentCollection has been de-referenced in a fully MANAGED entity,
  * then this collection is marked for deletion.
  *
  * @ignore
  *
  * @internal Don't call from the outside.
  *
  * @param ClassMetadata $class The class descriptor of the entity.
  * @param object $entity The entity for which to compute the changes.
  *
  * @return void
  */
 public function computeChangeSet(ClassMetadata $class, $entity)
 {
     $oid = spl_object_hash($entity);
     if (isset($this->readOnlyObjects[$oid])) {
         return;
     }
     if (!$class->isInheritanceTypeNone()) {
         $class = $this->em->getClassMetadata(get_class($entity));
     }
     $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preFlush) & ~ListenersInvoker::INVOKE_MANAGER;
     if ($invoke !== ListenersInvoker::INVOKE_NONE) {
         $this->listenersInvoker->invoke($class, Events::preFlush, $entity, new PreFlushEventArgs($this->em), $invoke);
     }
     $actualData = array();
     foreach ($class->reflFields as $name => $refProp) {
         $value = $refProp->getValue($entity);
         if ($class->isCollectionValuedAssociation($name) && $value !== null) {
             if ($value instanceof PersistentCollection) {
                 if ($value->getOwner() === $entity) {
                     continue;
                 }
                 $value = new ArrayCollection($value->getValues());
             }
             // If $value is not a Collection then use an ArrayCollection.
             if (!$value instanceof Collection) {
                 $value = new ArrayCollection($value);
             }
             $assoc = $class->associationMappings[$name];
             // Inject PersistentCollection
             $value = new PersistentCollection($this->em, $this->em->getClassMetadata($assoc['targetEntity']), $value);
             $value->setOwner($entity, $assoc);
             $value->setDirty(!$value->isEmpty());
             $class->reflFields[$name]->setValue($entity, $value);
             $actualData[$name] = $value;
             continue;
         }
         if ((!$class->isIdentifier($name) || !$class->isIdGeneratorIdentity()) && $name !== $class->versionField) {
             $actualData[$name] = $value;
         }
     }
     if (!isset($this->originalEntityData[$oid])) {
         // Entity is either NEW or MANAGED but not yet fully persisted (only has an id).
         // These result in an INSERT.
         $this->originalEntityData[$oid] = $actualData;
         $changeSet = array();
         foreach ($actualData as $propName => $actualValue) {
             if (!isset($class->associationMappings[$propName])) {
                 $changeSet[$propName] = array(null, $actualValue);
                 continue;
             }
             $assoc = $class->associationMappings[$propName];
             if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
                 $changeSet[$propName] = array(null, $actualValue);
             }
         }
         $this->entityChangeSets[$oid] = $changeSet;
     } else {
         // Entity is "fully" MANAGED: it was already fully persisted before
         // and we have a copy of the original data
         $originalData = $this->originalEntityData[$oid];
         $isChangeTrackingNotify = $class->isChangeTrackingNotify();
         $changeSet = $isChangeTrackingNotify && isset($this->entityChangeSets[$oid]) ? $this->entityChangeSets[$oid] : array();
         foreach ($actualData as $propName => $actualValue) {
             // skip field, its a partially omitted one!
             if (!(isset($originalData[$propName]) || array_key_exists($propName, $originalData))) {
                 continue;
             }
             $orgValue = $originalData[$propName];
             // skip if value haven't changed
             if ($orgValue === $actualValue) {
                 continue;
             }
             // if regular field
             if (!isset($class->associationMappings[$propName])) {
                 if ($isChangeTrackingNotify) {
                     continue;
                 }
                 $changeSet[$propName] = array($orgValue, $actualValue);
                 continue;
             }
             $assoc = $class->associationMappings[$propName];
             // Persistent collection was exchanged with the "originally"
             // created one. This can only mean it was cloned and replaced
             // on another entity.
             if ($actualValue instanceof PersistentCollection) {
                 $owner = $actualValue->getOwner();
                 if ($owner === null) {
                     // cloned
                     $actualValue->setOwner($entity, $assoc);
                 } else {
                     if ($owner !== $entity) {
                         // no clone, we have to fix
                         if (!$actualValue->isInitialized()) {
                             $actualValue->initialize();
                             // we have to do this otherwise the cols share state
                         }
                         $newValue = clone $actualValue;
                         $newValue->setOwner($entity, $assoc);
                         $class->reflFields[$propName]->setValue($entity, $newValue);
                     }
                 }
             }
             if ($orgValue instanceof PersistentCollection) {
                 // A PersistentCollection was de-referenced, so delete it.
                 $coid = spl_object_hash($orgValue);
                 if (isset($this->collectionDeletions[$coid])) {
                     continue;
                 }
                 $this->collectionDeletions[$coid] = $orgValue;
                 $changeSet[$propName] = $orgValue;
                 // Signal changeset, to-many assocs will be ignored.
                 continue;
             }
             if ($assoc['type'] & ClassMetadata::TO_ONE) {
                 if ($assoc['isOwningSide']) {
                     $changeSet[$propName] = array($orgValue, $actualValue);
                 }
                 if ($orgValue !== null && $assoc['orphanRemoval']) {
                     $this->scheduleOrphanRemoval($orgValue);
                 }
             }
         }
         if ($changeSet) {
             $this->entityChangeSets[$oid] = $changeSet;
             $this->originalEntityData[$oid] = $actualData;
             $this->entityUpdates[$oid] = $entity;
         }
     }
     // Look for changes in associations of the entity
     foreach ($class->associationMappings as $field => $assoc) {
         if (($val = $class->reflFields[$field]->getValue($entity)) === null) {
             continue;
         }
         $this->computeAssociationChanges($assoc, $val);
         if (!isset($this->entityChangeSets[$oid]) && $assoc['isOwningSide'] && $assoc['type'] == ClassMetadata::MANY_TO_MANY && $val instanceof PersistentCollection && $val->isDirty()) {
             $this->entityChangeSets[$oid] = array();
             $this->originalEntityData[$oid] = $actualData;
             $this->entityUpdates[$oid] = $entity;
         }
     }
 }
Beispiel #3
0
 /**
  * Computes the changes that happened to a single entity.
  *
  * Modifies/populates the following properties:
  *
  * {@link _originalEntityData}
  * If the entity is NEW or MANAGED but not yet fully persisted (only has an id)
  * then it was not fetched from the database and therefore we have no original
  * entity data yet. All of the current entity data is stored as the original entity data.
  *
  * {@link _entityChangeSets}
  * The changes detected on all properties of the entity are stored there.
  * A change is a tuple array where the first entry is the old value and the second
  * entry is the new value of the property. Changesets are used by persisters
  * to INSERT/UPDATE the persistent entity state.
  *
  * {@link _entityUpdates}
  * If the entity is already fully MANAGED (has been fetched from the database before)
  * and any changes to its properties are detected, then a reference to the entity is stored
  * there to mark it for an update.
  *
  * {@link _collectionDeletions}
  * If a PersistentCollection has been de-referenced in a fully MANAGED entity,
  * then this collection is marked for deletion.
  *
  * @param ClassMetadata $class The class descriptor of the entity.
  * @param object $entity The entity for which to compute the changes.
  */
 public function computeChangeSet(ClassMetadata $class, $entity)
 {
     if (!$class->isInheritanceTypeNone()) {
         $class = $this->em->getClassMetadata(get_class($entity));
     }
     $oid = spl_object_hash($entity);
     $actualData = array();
     foreach ($class->reflFields as $name => $refProp) {
         $value = $refProp->getValue($entity);
         if ($class->isCollectionValuedAssociation($name) && $value !== null && !$value instanceof PersistentCollection) {
             // If $value is not a Collection then use an ArrayCollection.
             if (!$value instanceof Collection) {
                 $value = new ArrayCollection($value);
             }
             $assoc = $class->associationMappings[$name];
             // Inject PersistentCollection
             $coll = new PersistentCollection($this->em, $this->em->getClassMetadata($assoc['targetEntity']), $value);
             $coll->setOwner($entity, $assoc);
             $coll->setDirty(!$coll->isEmpty());
             $class->reflFields[$name]->setValue($entity, $coll);
             $actualData[$name] = $coll;
         } else {
             if (!$class->isIdentifier($name) || !$class->isIdGeneratorIdentity()) {
                 $actualData[$name] = $value;
             }
         }
     }
     if (!isset($this->originalEntityData[$oid])) {
         // Entity is either NEW or MANAGED but not yet fully persisted (only has an id).
         // These result in an INSERT.
         $this->originalEntityData[$oid] = $actualData;
         $changeSet = array();
         foreach ($actualData as $propName => $actualValue) {
             if (isset($class->associationMappings[$propName])) {
                 $assoc = $class->associationMappings[$propName];
                 if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
                     $changeSet[$propName] = array(null, $actualValue);
                 }
             } else {
                 $changeSet[$propName] = array(null, $actualValue);
             }
         }
         $this->entityChangeSets[$oid] = $changeSet;
     } else {
         // Entity is "fully" MANAGED: it was already fully persisted before
         // and we have a copy of the original data
         $originalData = $this->originalEntityData[$oid];
         $isChangeTrackingNotify = $class->isChangeTrackingNotify();
         $changeSet = $isChangeTrackingNotify ? $this->entityChangeSets[$oid] : array();
         foreach ($actualData as $propName => $actualValue) {
             $orgValue = isset($originalData[$propName]) ? $originalData[$propName] : null;
             if (isset($class->associationMappings[$propName])) {
                 $assoc = $class->associationMappings[$propName];
                 if ($assoc['type'] & ClassMetadata::TO_ONE && $orgValue !== $actualValue) {
                     if ($assoc['isOwningSide']) {
                         $changeSet[$propName] = array($orgValue, $actualValue);
                     }
                     if ($orgValue !== null && $assoc['orphanRemoval']) {
                         $this->scheduleOrphanRemoval($orgValue);
                     }
                 } else {
                     if ($orgValue instanceof PersistentCollection && $orgValue !== $actualValue) {
                         // A PersistentCollection was de-referenced, so delete it.
                         if (!in_array($orgValue, $this->collectionDeletions, true)) {
                             $this->collectionDeletions[] = $orgValue;
                             $changeSet[$propName] = $orgValue;
                             // Signal changeset, to-many assocs will be ignored.
                         }
                     }
                 }
             } else {
                 if ($isChangeTrackingNotify) {
                     continue;
                 } else {
                     if (is_object($orgValue) && $orgValue !== $actualValue) {
                         $changeSet[$propName] = array($orgValue, $actualValue);
                     } else {
                         if ($orgValue != $actualValue || $orgValue === null ^ $actualValue === null) {
                             $changeSet[$propName] = array($orgValue, $actualValue);
                         }
                     }
                 }
             }
         }
         if ($changeSet) {
             $this->entityChangeSets[$oid] = $changeSet;
             $this->originalEntityData[$oid] = $actualData;
             $this->entityUpdates[$oid] = $entity;
         }
     }
     // Look for changes in associations of the entity
     foreach ($class->associationMappings as $field => $assoc) {
         $val = $class->reflFields[$field]->getValue($entity);
         if ($val !== null) {
             $this->computeAssociationChanges($assoc, $val);
         }
     }
 }
Beispiel #4
0
 /**
  * Computes the changes done to a single entity.
  *
  * Modifies/populates the following properties:
  *
  * {@link _originalEntityData}
  * If the entity is NEW or MANAGED but not yet fully persisted (only has an id)
  * then it was not fetched from the database and therefore we have no original
  * entity data yet. All of the current entity data is stored as the original entity data.
  *
  * {@link _entityChangeSets}
  * The changes detected on all properties of the entity are stored there.
  * A change is a tuple array where the first entry is the old value and the second
  * entry is the new value of the property. Changesets are used by persisters
  * to INSERT/UPDATE the persistent entity state.
  *
  * {@link _entityUpdates}
  * If the entity is already fully MANAGED (has been fetched from the database before)
  * and any changes to its properties are detected, then a reference to the entity is stored
  * there to mark it for an update.
  *
  * {@link _collectionDeletions}
  * If a PersistentCollection has been de-referenced in a fully MANAGED entity,
  * then this collection is marked for deletion.
  *
  * @param ClassMetadata $class The class descriptor of the entity.
  * @param object $entity The entity for which to compute the changes.
  */
 private function _computeEntityChanges($class, $entity)
 {
     $oid = spl_object_hash($entity);
     if (!$class->isInheritanceTypeNone()) {
         $class = $this->_em->getClassMetadata(get_class($entity));
     }
     $actualData = array();
     foreach ($class->reflFields as $name => $refProp) {
         if (!$class->isIdentifier($name) || !$class->isIdGeneratorIdentity()) {
             $actualData[$name] = $refProp->getValue($entity);
         }
         if ($class->isCollectionValuedAssociation($name) && $actualData[$name] !== null && !$actualData[$name] instanceof PersistentCollection) {
             //TODO: If $actualData[$name] is Collection then unwrap the array
             $assoc = $class->associationMappings[$name];
             //echo PHP_EOL . "INJECTING PCOLL into $name" . PHP_EOL;
             // Inject PersistentCollection
             $coll = new PersistentCollection($this->_em, $this->_em->getClassMetadata($assoc->targetEntityName), $actualData[$name] ? $actualData[$name] : array());
             $coll->setOwner($entity, $assoc);
             if (!$coll->isEmpty()) {
                 $coll->setDirty(true);
             }
             $class->reflFields[$name]->setValue($entity, $coll);
             $actualData[$name] = $coll;
         }
     }
     if (!isset($this->_originalEntityData[$oid])) {
         // Entity is either NEW or MANAGED but not yet fully persisted
         // (only has an id). These result in an INSERT.
         $this->_originalEntityData[$oid] = $actualData;
         $this->_entityChangeSets[$oid] = array_map(function ($e) {
             return array(null, $e);
         }, $actualData);
     } else {
         // Entity is "fully" MANAGED: it was already fully persisted before
         // and we have a copy of the original data
         $originalData = $this->_originalEntityData[$oid];
         $changeSet = array();
         $entityIsDirty = false;
         foreach ($actualData as $propName => $actualValue) {
             $orgValue = isset($originalData[$propName]) ? $originalData[$propName] : null;
             if (is_object($orgValue) && $orgValue !== $actualValue) {
                 $changeSet[$propName] = array($orgValue, $actualValue);
             } else {
                 if ($orgValue != $actualValue || $orgValue === null ^ $actualValue === null) {
                     $changeSet[$propName] = array($orgValue, $actualValue);
                 }
             }
             if (isset($changeSet[$propName])) {
                 if (isset($class->associationMappings[$propName])) {
                     $assoc = $class->associationMappings[$propName];
                     if ($assoc->isOneToOne() && $assoc->isOwningSide) {
                         $entityIsDirty = true;
                     } else {
                         if ($orgValue instanceof PersistentCollection) {
                             // A PersistentCollection was de-referenced, so delete it.
                             if (!in_array($orgValue, $this->_collectionDeletions, true)) {
                                 $this->_collectionDeletions[] = $orgValue;
                             }
                         }
                     }
                 } else {
                     $entityIsDirty = true;
                 }
             }
         }
         if ($changeSet) {
             if ($entityIsDirty) {
                 $this->_entityUpdates[$oid] = $entity;
             }
             $this->_entityChangeSets[$oid] = $changeSet;
             $this->_originalEntityData[$oid] = $actualData;
         }
     }
 }
 /**
  * Computes the changes that happened to a single entity.
  *
  * Modifies/populates the following properties:
  *
  * {@link _originalEntityData}
  * If the entity is NEW or MANAGED but not yet fully persisted (only has an id)
  * then it was not fetched from the database and therefore we have no original
  * entity data yet. All of the current entity data is stored as the original entity data.
  *
  * {@link _entityChangeSets}
  * The changes detected on all properties of the entity are stored there.
  * A change is a tuple array where the first entry is the old value and the second
  * entry is the new value of the property. Changesets are used by persisters
  * to INSERT/UPDATE the persistent entity state.
  *
  * {@link _entityUpdates}
  * If the entity is already fully MANAGED (has been fetched from the database before)
  * and any changes to its properties are detected, then a reference to the entity is stored
  * there to mark it for an update.
  *
  * {@link _collectionDeletions}
  * If a PersistentCollection has been de-referenced in a fully MANAGED entity,
  * then this collection is marked for deletion.
  *
  * @param ClassMetadata $class The class descriptor of the entity.
  * @param object $entity The entity for which to compute the changes.
  */
 public function computeChangeSet(Mapping\ClassMetadata $class, $entity)
 {
     if (!$class->isInheritanceTypeNone()) {
         $class = $this->_em->getClassMetadata(get_class($entity));
     }
     $oid = spl_object_hash($entity);
     $actualData = array();
     foreach ($class->reflFields as $name => $refProp) {
         if (!$class->isIdentifier($name) || !$class->isIdGeneratorIdentity()) {
             $actualData[$name] = $refProp->getValue($entity);
         }
         if ($class->isCollectionValuedAssociation($name) && $actualData[$name] !== null && !$actualData[$name] instanceof PersistentCollection) {
             // If $actualData[$name] is not a Collection then use an ArrayCollection.
             if (!$actualData[$name] instanceof Collection) {
                 $actualData[$name] = new ArrayCollection($actualData[$name]);
             }
             $assoc = $class->associationMappings[$name];
             // Inject PersistentCollection
             $coll = new PersistentCollection($this->_em, $this->_em->getClassMetadata($assoc->targetEntityName), $actualData[$name]);
             $coll->setOwner($entity, $assoc);
             $coll->setDirty(!$coll->isEmpty());
             $class->reflFields[$name]->setValue($entity, $coll);
             $actualData[$name] = $coll;
         }
     }
     if (!isset($this->_originalEntityData[$oid])) {
         // Entity is either NEW or MANAGED but not yet fully persisted (only has an id).
         // These result in an INSERT.
         $this->_originalEntityData[$oid] = $actualData;
         $this->_entityChangeSets[$oid] = array_map(function ($e) {
             return array(null, $e);
         }, $actualData);
     } else {
         // Entity is "fully" MANAGED: it was already fully persisted before
         // and we have a copy of the original data
         $originalData = $this->_originalEntityData[$oid];
         $changeSet = array();
         $entityIsDirty = false;
         foreach ($actualData as $propName => $actualValue) {
             $orgValue = isset($originalData[$propName]) ? $originalData[$propName] : null;
             if (is_object($orgValue) && $orgValue !== $actualValue) {
                 $changeSet[$propName] = array($orgValue, $actualValue);
             } else {
                 if ($orgValue != $actualValue || $orgValue === null ^ $actualValue === null) {
                     $changeSet[$propName] = array($orgValue, $actualValue);
                 }
             }
             if (isset($changeSet[$propName])) {
                 if (isset($class->associationMappings[$propName])) {
                     $assoc = $class->associationMappings[$propName];
                     if ($assoc->isOneToOne()) {
                         if ($assoc->isOwningSide) {
                             $entityIsDirty = true;
                         }
                         if ($actualValue === null && $assoc->orphanRemoval) {
                             $this->scheduleOrphanRemoval($orgValue);
                         }
                     } else {
                         if ($orgValue instanceof PersistentCollection) {
                             // A PersistentCollection was de-referenced, so delete it.
                             if (!in_array($orgValue, $this->_collectionDeletions, true)) {
                                 $this->_collectionDeletions[] = $orgValue;
                             }
                         }
                     }
                 } else {
                     $entityIsDirty = true;
                 }
             }
         }
         if ($changeSet) {
             $this->_entityChangeSets[$oid] = $changeSet;
             $this->_originalEntityData[$oid] = $actualData;
             if ($entityIsDirty) {
                 $this->_entityUpdates[$oid] = $entity;
             }
         }
     }
     // Look for changes in associations of the entity
     foreach ($class->associationMappings as $assoc) {
         $val = $class->reflFields[$assoc->sourceFieldName]->getValue($entity);
         if ($val !== null) {
             $this->_computeAssociationChanges($assoc, $val);
         }
     }
 }
Beispiel #6
0
 /**
  * Computes the changes that happened to a single entity.
  *
  * Modifies/populates the following properties:
  *
  * {@link _originalEntityData}
  * If the entity is NEW or MANAGED but not yet fully persisted (only has an id)
  * then it was not fetched from the database and therefore we have no original
  * entity data yet. All of the current entity data is stored as the original entity data.
  *
  * {@link _entityChangeSets}
  * The changes detected on all properties of the entity are stored there.
  * A change is a tuple array where the first entry is the old value and the second
  * entry is the new value of the property. Changesets are used by persisters
  * to INSERT/UPDATE the persistent entity state.
  *
  * {@link _entityUpdates}
  * If the entity is already fully MANAGED (has been fetched from the database before)
  * and any changes to its properties are detected, then a reference to the entity is stored
  * there to mark it for an update.
  *
  * {@link _collectionDeletions}
  * If a PersistentCollection has been de-referenced in a fully MANAGED entity,
  * then this collection is marked for deletion.
  *
  * @ignore
  * @internal Don't call from the outside.
  * @param ClassMetadata $class The class descriptor of the entity.
  * @param object $entity The entity for which to compute the changes.
  */
 public function computeChangeSet(ClassMetadata $class, $entity)
 {
     $oid = spl_object_hash($entity);
     if (isset($this->readOnlyObjects[$oid])) {
         return;
     }
     if (!$class->isInheritanceTypeNone()) {
         $class = $this->em->getClassMetadata(get_class($entity));
     }
     // Fire PreFlush lifecycle callbacks
     if (isset($class->lifecycleCallbacks[Events::preFlush])) {
         $class->invokeLifecycleCallbacks(Events::preFlush, $entity);
     }
     $actualData = array();
     foreach ($class->reflFields as $name => $refProp) {
         $value = $refProp->getValue($entity);
         if ($class->isCollectionValuedAssociation($name) && $value !== null && !$value instanceof PersistentCollection) {
             // If $value is not a Collection then use an ArrayCollection.
             if (!$value instanceof Collection) {
                 $value = new ArrayCollection($value);
             }
             $assoc = $class->associationMappings[$name];
             // Inject PersistentCollection
             $value = new PersistentCollection($this->em, $this->em->getClassMetadata($assoc['targetEntity']), $value);
             $value->setOwner($entity, $assoc);
             $value->setDirty(!$value->isEmpty());
             $class->reflFields[$name]->setValue($entity, $value);
             $actualData[$name] = $value;
             continue;
         }
         if ((!$class->isIdentifier($name) || !$class->isIdGeneratorIdentity()) && $name !== $class->versionField) {
             $actualData[$name] = $value;
         }
     }
     if (!isset($this->originalEntityData[$oid])) {
         // Entity is either NEW or MANAGED but not yet fully persisted (only has an id).
         // These result in an INSERT.
         $this->originalEntityData[$oid] = $actualData;
         $changeSet = array();
         foreach ($actualData as $propName => $actualValue) {
             if (!isset($class->associationMappings[$propName])) {
                 $changeSet[$propName] = array(null, $actualValue);
                 continue;
             }
             $assoc = $class->associationMappings[$propName];
             if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
                 $changeSet[$propName] = array(null, $actualValue);
             }
         }
         $this->entityChangeSets[$oid] = $changeSet;
     } else {
         // Entity is "fully" MANAGED: it was already fully persisted before
         // and we have a copy of the original data
         $originalData = $this->originalEntityData[$oid];
         $isChangeTrackingNotify = $class->isChangeTrackingNotify();
         $changeSet = $isChangeTrackingNotify && isset($this->entityChangeSets[$oid]) ? $this->entityChangeSets[$oid] : array();
         foreach ($actualData as $propName => $actualValue) {
             // skip field, its a partially omitted one!
             if (!(isset($originalData[$propName]) || array_key_exists($propName, $originalData))) {
                 continue;
             }
             $orgValue = $originalData[$propName];
             // skip if value havent changed
             if ($orgValue === $actualValue) {
                 continue;
             }
             // if regular field
             if (!isset($class->associationMappings[$propName])) {
                 if ($isChangeTrackingNotify) {
                     continue;
                 }
                 $changeSet[$propName] = array($orgValue, $actualValue);
                 continue;
             }
             $assoc = $class->associationMappings[$propName];
             if ($orgValue instanceof PersistentCollection) {
                 // A PersistentCollection was de-referenced, so delete it.
                 $coid = spl_object_hash($orgValue);
                 if (isset($this->collectionDeletions[$coid])) {
                     continue;
                 }
                 $this->collectionDeletions[$coid] = $orgValue;
                 $changeSet[$propName] = $orgValue;
                 // Signal changeset, to-many assocs will be ignored.
                 continue;
             }
             if ($assoc['type'] & ClassMetadata::TO_ONE) {
                 if ($assoc['isOwningSide']) {
                     $changeSet[$propName] = array($orgValue, $actualValue);
                 }
                 if ($orgValue !== null && $assoc['orphanRemoval']) {
                     $this->scheduleOrphanRemoval($orgValue);
                 }
             }
         }
         if ($changeSet) {
             $this->entityChangeSets[$oid] = $changeSet;
             $this->originalEntityData[$oid] = $actualData;
             $this->entityUpdates[$oid] = $entity;
         }
     }
     // Look for changes in associations of the entity
     foreach ($class->associationMappings as $field => $assoc) {
         if (($val = $class->reflFields[$field]->getValue($entity)) !== null) {
             $this->computeAssociationChanges($assoc, $val);
         }
     }
 }
Beispiel #7
0
 /**
  * Check that collection is in right order.
  *
  * For increasing collection values must be in ascending order.
  * For decreasing collection value must be in descending order.
  *
  * @param PersistentCollection $value
  * @param CategoriesConstraint $constraint
  */
 protected function validateOrder(PersistentCollection $value, CategoriesConstraint $constraint)
 {
     if ($value->isEmpty()) {
         return;
     }
     $orderedByIndex = $value->matching(new Criteria(null, ['categoryIndex' => Criteria::ASC]));
     $isIncreasing = $this->isIncreasing($orderedByIndex);
     if ($isIncreasing) {
         $criteria = Criteria::ASC;
     } else {
         $criteria = Criteria::DESC;
     }
     $orderedByValue = $value->matching(new Criteria(null, ['minValue' => $criteria]));
     if ($orderedByValue->toArray() !== $orderedByIndex->toArray()) {
         $this->context->addViolationAt($constraint->getType(), $constraint->message, ['%order%' => $criteria]);
         return;
     }
     if (!$isIncreasing) {
         return;
     }
     $invalidItems = $orderedByValue->filter(function (RFMMetricCategory $category) {
         $maxValue = $category->getMaxValue();
         if (!$maxValue) {
             return false;
         }
         return $category->getMinValue() >= $maxValue;
     });
     if (!$invalidItems->isEmpty()) {
         $this->context->addViolationAt($constraint->getType(), $constraint->message, ['%order%' => $criteria]);
     }
 }