/** * @param object $document * @param string $class * @param string $oid * @param boolean $isNew * @param array $changeSet * @param string $assocType * @throws Exception\RuntimeException * @throws Exception\InvalidArgumentException * @throws PHPCRException */ private function computeAssociationChanges($document, $class, $oid, $isNew, $changeSet, $assocType) { switch ($assocType) { case 'reference': $mappings = $class->referenceMappings; $computeMethod = 'computeReferenceChanges'; break; case 'referrer': $mappings = $class->referrersMappings; $computeMethod = 'computeReferrerChanges'; break; default: throw new InvalidArgumentException('Unsupported association type used: ' . $assocType); } foreach ($mappings as $fieldName) { $mapping = $class->mappings[$fieldName]; if (ClassMetadata::MANY_TO_MANY === $mapping['type'] && 'reference' === $assocType || 'referrers' === $mapping['type'] && 'referrer' === $assocType) { if ($changeSet[$fieldName] instanceof PersistentCollection) { if (!$changeSet[$fieldName]->isInitialized()) { continue; } } else { if (null === $changeSet[$fieldName]) { $changeSet[$fieldName] = array(); } if (!is_array($changeSet[$fieldName]) && !$changeSet[$fieldName] instanceof Collection) { throw PHPCRException::associationFieldNoArray(self::objToStr($document, $this->dm), $fieldName); } // convert to a PersistentCollection switch ($assocType) { case 'reference': $targetDocument = isset($mapping['targetDocument']) ? $mapping['targetDocument'] : null; $changeSet[$fieldName] = ReferenceManyCollection::createFromCollection($this->dm, $document, $mapping['property'], $changeSet[$fieldName], $targetDocument, !$isNew); break; case 'referrer': $referringMeta = $this->dm->getClassMetadata($mapping['referringDocument']); $referringField = $referringMeta->mappings[$mapping['referencedBy']]; $changeSet[$fieldName] = ReferrersCollection::createFromCollection($this->dm, $document, $changeSet[$fieldName], $referringField['strategy'], $referringField['property'], $mapping['referringDocument'], !$isNew); break; } $class->setFieldValue($document, $fieldName, $changeSet[$fieldName]); $this->originalData[$oid][$fieldName] = $changeSet[$fieldName]; } $coid = spl_object_hash($changeSet[$fieldName]); $this->visitedCollections[$coid] = $changeSet[$fieldName]; foreach ($changeSet[$fieldName] as $association) { if ($association !== null) { $this->{$computeMethod}($mapping, $association); } } if (!$isNew && $mapping['cascade'] & ClassMetadata::CASCADE_REMOVE) { if (!$this->originalData[$oid][$fieldName] instanceof PersistentCollection) { throw new RuntimeException("OriginalData for a collection association contains something else than a PersistentCollection."); } $associations = $this->originalData[$oid][$fieldName]->getOriginalPaths(); foreach ($associations as $association) { $association = $this->getDocumentById($association); if ($association && !$this->originalData[$oid][$fieldName]->contains($association)) { $this->scheduleRemove($association); } } } } elseif ($changeSet[$fieldName] && ClassMetadata::MANY_TO_ONE === $mapping['type'] && 'reference' === $assocType) { $this->computeReferenceChanges($mapping, $changeSet[$fieldName]); } } }