Doctrine\ODM\PHPCR\UnitOfWork::getOrCreateDocuments PHP Метод

getOrCreateDocuments() публичный Метод

Supported hints are - refresh: reload the fields from the database if set - locale: use this locale instead of the one from the annotation or the default - fallback: whether to try other languages or throw a not found exception if the desired locale is not found. defaults to true if not set and locale is not given either. - prefetch: if set to false, do not attempt to prefetch related data. (This makes sense when the caller already did this beforehand.)
public getOrCreateDocuments ( null | string $className, Iterato\Iterator | array $nodes, array &$hints = [] ) : array
$className null | string
$nodes Iterato\Iterator | array
$hints array
Результат array
    public function getOrCreateDocuments($className, $nodes, array &$hints = array())
    {
        $refresh = isset($hints['refresh']) ? $hints['refresh'] : false;
        $locale = isset($hints['locale']) ? $hints['locale'] : null;
        $fallback = isset($hints['fallback']) ? $hints['fallback'] : isset($locale);
        $documents = array();
        $overrideLocalValuesOids = array();
        $strategies = array();
        $nodesByStrategy = array();
        $allLocales = array();
        //prepare array of document ordered by the nodes path
        $existingDocuments = 0;
        foreach ($nodes as $node) {
            $requestedClassName = $className;
            try {
                $actualClassName = $this->documentClassMapper->getClassName($this->dm, $node, $className);
            } catch (ClassMismatchException $e) {
                // ignore class mismatch, just skip that one
                continue;
            }
            $id = $node->getPath();
            $class = $this->dm->getClassMetadata($actualClassName);
            // prepare first, add later when fine
            $document = $this->getDocumentById($id);
            if ($document) {
                if (!$refresh) {
                    ++$existingDocuments;
                    $documents[$id] = $document;
                } else {
                    $overrideLocalValuesOids[$id] = spl_object_hash($document);
                }
                try {
                    $this->validateClassName($document, $requestedClassName);
                } catch (ClassMismatchException $e) {
                    continue;
                }
            } else {
                $document = $class->newInstance();
                // delay registering the new document until children proxy have been created
                $overrideLocalValuesOids[$id] = false;
            }
            $documents[$id] = $document;
            if ($this->isDocumentTranslatable($class)) {
                $currentStrategy = $this->dm->getTranslationStrategy($class->translator);
                $localesToTry = $this->dm->getLocaleChooserStrategy()->getFallbackLocales($document, $class, $locale);
                foreach ($localesToTry as $localeToTry) {
                    $allLocales[$localeToTry] = $localeToTry;
                }
                $strategies[$class->name] = $currentStrategy;
                $nodesByStrategy[$class->name][] = $node;
            }
        }
        foreach ($nodesByStrategy as $strategyClass => $nodesForLocale) {
            if (!$strategies[$strategyClass] instanceof TranslationNodesWarmer) {
                continue;
            }
            $strategies[$strategyClass]->getTranslationsForNodes($nodesForLocale, $allLocales, $this->session);
        }
        // return early
        if (count($documents) === $existingDocuments) {
            return $documents;
        }
        foreach ($nodes as $node) {
            $id = $node->getPath();
            $document = $this->getDocumentById($id) ?: (isset($documents[$id]) ? $documents[$id] : null);
            if (!$document) {
                continue;
            }
            $documents[$id] = $document;
            $class = $this->dm->getClassMetadata(get_class($document));
            $documentState = array();
            $nonMappedData = array();
            // second param is false to get uuid rather than dereference reference properties to node instances
            $properties = $node->getPropertiesValues(null, false);
            foreach ($class->fieldMappings as $fieldName) {
                $mapping = $class->mappings[$fieldName];
                if (isset($properties[$mapping['property']])) {
                    if (true === $mapping['multivalue']) {
                        if (isset($mapping['assoc'])) {
                            $documentState[$fieldName] = $this->createAssoc($properties, $mapping);
                        } else {
                            $documentState[$fieldName] = (array) $properties[$mapping['property']];
                        }
                    } else {
                        $documentState[$fieldName] = $properties[$mapping['property']];
                    }
                } elseif (true === $mapping['multivalue']) {
                    $documentState[$mapping['property']] = array();
                }
            }
            if ($class->node) {
                $documentState[$class->node] = $node;
            }
            if ($class->nodename) {
                $documentState[$class->nodename] = $node->getName();
            }
            if ($class->identifier) {
                $documentState[$class->identifier] = $node->getPath();
            }
            if (!isset($hints['prefetch']) || $hints['prefetch']) {
                $this->getPrefetchHelper()->prefetchReferences($class, $node);
            }
            // initialize inverse side collections
            foreach ($class->referenceMappings as $fieldName) {
                $mapping = $class->mappings[$fieldName];
                if ($mapping['type'] === ClassMetadata::MANY_TO_ONE) {
                    if (!$node->hasProperty($mapping['property'])) {
                        continue;
                    }
                    try {
                        $referencedNode = $node->getProperty($mapping['property'])->getNode();
                        $proxy = $this->getOrCreateProxyFromNode($referencedNode, $locale);
                        if (isset($mapping['targetDocument']) && !$proxy instanceof $mapping['targetDocument']) {
                            throw new PHPCRException("Unexpected class for referenced document at '{$referencedNode->getPath()}'. Expected '{$mapping['targetDocument']}' but got '" . ClassUtils::getClass($proxy) . "'.");
                        }
                    } catch (RepositoryException $e) {
                        if ($e instanceof ItemNotFoundException || isset($hints['ignoreHardReferenceNotFound'])) {
                            // a weak reference or an old version can have lost references
                            $proxy = null;
                        } else {
                            throw new PHPCRException($e->getMessage(), 0, $e);
                        }
                    }
                    $documentState[$fieldName] = $proxy;
                } elseif ($mapping['type'] === ClassMetadata::MANY_TO_MANY) {
                    $referencedNodes = array();
                    if ($node->hasProperty($mapping['property'])) {
                        foreach ($node->getProperty($mapping['property'])->getString() as $reference) {
                            $referencedNodes[] = $reference;
                        }
                    }
                    $targetDocument = isset($mapping['targetDocument']) ? $mapping['targetDocument'] : null;
                    $coll = new ReferenceManyCollection($this->dm, $document, $mapping['property'], $referencedNodes, $targetDocument, $locale, $this->getReferenceManyCollectionTypeFromMetadata($mapping));
                    $documentState[$fieldName] = $coll;
                }
            }
            if (!isset($hints['prefetch']) || $hints['prefetch']) {
                if ($class->translator) {
                    try {
                        $prefetchLocale = $locale ?: $this->dm->getLocaleChooserStrategy()->getLocale();
                    } catch (InvalidArgumentException $e) {
                        throw new InvalidArgumentException($e->getMessage() . ' but document ' . $class->name . ' is mapped with translations.');
                    }
                } else {
                    $prefetchLocale = null;
                }
                $this->getPrefetchHelper()->prefetchHierarchy($class, $node, $prefetchLocale);
            }
            if ($class->parentMapping && $node->getDepth() > 0) {
                // do not map parent to self if we are at root
                $documentState[$class->parentMapping] = $this->getOrCreateProxyFromNode($node->getParent(), $locale);
            }
            if ($class->depthMapping) {
                $documentState[$class->depthMapping] = $node->getDepth();
            }
            foreach ($class->childMappings as $fieldName) {
                $mapping = $class->mappings[$fieldName];
                $documentState[$fieldName] = $node->hasNode($mapping['nodeName']) ? $this->getOrCreateProxyFromNode($node->getNode($mapping['nodeName']), $locale) : null;
            }
            foreach ($class->childrenMappings as $fieldName) {
                $mapping = $class->mappings[$fieldName];
                $documentState[$fieldName] = new ChildrenCollection($this->dm, $document, $mapping['filter'], $mapping['fetchDepth'], $locale);
            }
            foreach ($class->referrersMappings as $fieldName) {
                $mapping = $class->mappings[$fieldName];
                // get the reference type strategy (weak or hard) on the fly, as we
                // can not do it in ClassMetadata
                $referringMeta = $this->dm->getClassMetadata($mapping['referringDocument']);
                $referringField = $referringMeta->mappings[$mapping['referencedBy']];
                $documentState[$fieldName] = new ReferrersCollection($this->dm, $document, $referringField['strategy'], $referringField['property'], $locale, $mapping['referringDocument']);
            }
            foreach ($class->mixedReferrersMappings as $fieldName) {
                $mapping = $class->mappings[$fieldName];
                $documentState[$fieldName] = new ImmutableReferrersCollection($this->dm, $document, $mapping['referenceType'], $locale);
            }
            // when not set then not needed
            if (!isset($overrideLocalValuesOids[$id])) {
                continue;
            }
            if (!$overrideLocalValuesOids[$id]) {
                // registering the document needs to be delayed until the children proxies where created
                $overrideLocalValuesOids[$id] = $this->registerDocument($document, $id);
            }
            $this->nonMappedData[$overrideLocalValuesOids[$id]] = $nonMappedData;
            foreach ($class->reflFields as $fieldName => $reflFields) {
                $value = isset($documentState[$fieldName]) ? $documentState[$fieldName] : null;
                $reflFields->setValue($document, $value);
                $this->originalData[$overrideLocalValuesOids[$id]][$fieldName] = $value;
            }
            // Load translations
            $this->doLoadTranslation($document, $class, $locale, $fallback, $refresh);
            if ($invoke = $this->eventListenersInvoker->getSubscribedSystems($class, Event::postLoad)) {
                $this->eventListenersInvoker->invoke($class, Event::postLoad, $document, new LifecycleEventArgs($document, $this->dm), $invoke);
            }
        }
        return $documents;
    }

Usage Example

Пример #1
0
 /**
  * {@inheritDoc}
  */
 public function findMany($className, array $ids)
 {
     $uuids = array();
     foreach ($ids as $key => $id) {
         if (UUIDHelper::isUUID($id)) {
             $uuids[$id] = $key;
         } elseif (strpos($id, '/') !== 0) {
             $ids[$key] = '/' . $id;
         }
     }
     if (!empty($uuids)) {
         $nodes = $this->session->getNodesByIdentifier(array_keys($uuids));
         foreach ($nodes as $node) {
             /** @var $node \PHPCR\NodeInterface */
             $id = $node->getPath();
             $ids[$uuids[$node->getIdentifier()]] = $id;
             unset($uuids[$id]);
         }
         if (!empty($uuids)) {
             // skip not found ids
             $ids = array_diff($ids, array_keys($uuids));
         }
     }
     $nodes = $this->session->getNodes($ids);
     $hints = array('fallback' => true);
     $documents = $this->unitOfWork->getOrCreateDocuments($className, $nodes, $hints);
     return new ArrayCollection($documents);
 }
UnitOfWork