/** * Computes the changes of an association. * * @param AssociationMapping $mapping * @param mixed $value The value of the association. */ private function _computeAssociationChanges($mapping, $value) { if ($value instanceof PersistentCollection && $value->isDirty()) { $this->_visitedCollections[] = $value; } if (!$mapping['isCascadePersist']) { return; // "Persistence by reachability" only if persist cascade specified } // Look through the documents, and in any of their reference, for transient // enities, recursively. ("Persistence by reachability") if ($mapping['type'] === 'one') { if ($value instanceof Proxy && !$value->__isInitialized__) { return; // Ignore uninitialized proxy objects } $value = array($value); } elseif ($value instanceof PersistentCollection) { $value = $value->unwrap(); } $targetClass = $this->_dm->getClassMetadata($mapping['targetDocument']); foreach ($value as $entry) { $state = $this->getDocumentState($entry, self::STATE_NEW); $oid = spl_object_hash($entry); if ($state == self::STATE_NEW) { if (isset($targetClass->lifecycleCallbacks[Events::prePersist])) { $targetClass->invokeLifecycleCallbacks(Events::prePersist, $entry); } if ($this->_evm->hasListeners(Events::prePersist)) { $this->_evm->dispatchEvent(Events::prePersist, new LifecycleEventArgs($entry, $this->_dm)); } $this->_documentStates[$oid] = self::STATE_MANAGED; $this->_documentInsertions[$oid] = $entry; $this->computeChangeSet($targetClass, $entry); } elseif ($state == self::STATE_REMOVED) { throw MongoDBException::removedDocumentInCollectionDetected($entry, $mapping); } // MANAGED associated documents are already taken into account // during changeset calculation anyway, since they are in the identity map. } }