Doctrine\ORM\UnitOfWork::computeChangeSet PHP Method

computeChangeSet() public method

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.
public computeChangeSet ( Doctrine\ORM\Mapping\ClassMetadata $class, object $entity )
$class Doctrine\ORM\Mapping\ClassMetadata The class descriptor of the entity.
$entity object 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;
                        }
                    }
                } 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);
            }
        }
    }

Usage Example

 /**
  * @param OnFlushEventArgs $args
  */
 public function onFlush(OnFlushEventArgs $args)
 {
     $this->initializeFromEventArgs($args);
     $entities = array_merge($this->uow->getScheduledEntityInsertions(), $this->uow->getScheduledEntityDeletions(), $this->uow->getScheduledEntityUpdates());
     /** @var Opportunity[] $entities */
     $entities = array_filter($entities, function ($entity) {
         return 'OroCRM\\Bundle\\SalesBundle\\Entity\\Opportunity' === ClassUtils::getClass($entity);
     });
     foreach ($entities as $entity) {
         if (!$entity->getId() && $this->isValuable($entity)) {
             // handle creation, just add to prev lifetime value and recalculate change set
             $b2bCustomer = $entity->getCustomer();
             $b2bCustomer->setLifetime($b2bCustomer->getLifetime() + $entity->getCloseRevenue());
             $this->scheduleUpdate($b2bCustomer);
             $this->uow->computeChangeSet($this->em->getClassMetadata(ClassUtils::getClass($b2bCustomer)), $b2bCustomer);
         } elseif ($this->uow->isScheduledForDelete($entity) && $this->isValuable($entity)) {
             $this->scheduleUpdate($entity->getCustomer());
         } elseif ($this->uow->isScheduledForUpdate($entity)) {
             // handle update
             $changeSet = $this->uow->getEntityChangeSet($entity);
             if ($this->isChangeSetValuable($changeSet)) {
                 if (!empty($changeSet['customer']) && $changeSet['customer'][0] instanceof B2bCustomer && B2bCustomerRepository::VALUABLE_STATUS === $this->getOldStatus($entity, $changeSet)) {
                     // handle change of b2b customer
                     $this->scheduleUpdate($changeSet['customer'][0]);
                 }
                 if ($this->isValuable($entity, isset($changeSet['closeRevenue'])) || B2bCustomerRepository::VALUABLE_STATUS === $this->getOldStatus($entity, $changeSet) && $entity->getCustomer()) {
                     $this->scheduleUpdate($entity->getCustomer());
                 }
             }
         }
     }
 }
All Usage Examples Of Doctrine\ORM\UnitOfWork::computeChangeSet