/** * @BeforeScenario */ public function purgeAndInitializeDatabase() { $purger = new PHPCRPurger($this->documentManager); $purger->purge(); $this->documentManager->clear(); $this->initializerManager->initialize(); }
/** * @param ResourceControllerEvent $event */ public function onEvent(ResourceControllerEvent $event) { $document = $event->getSubject(); $metadata = $this->documentManager->getClassMetadata(get_class($document)); if ($metadata->idGenerator !== ClassMetadata::GENERATOR_TYPE_PARENT) { throw new \RuntimeException(sprintf('Document of class "%s" must be using the GENERATOR_TYPE_PARENT identificatio strategy (value %s), it is current using "%s" (this may be an automatic configuration: be sure to map both the `nodename` and the `parentDocument`).', get_class($document), ClassMetadata::GENERATOR_TYPE_PARENT, $metadata->idGenerator)); } // NOTE: that the PHPCR-ODM requires these two fields to be set when // when the GENERATOR_TYPE_PARENT "ID" strategy is used. $nameField = $metadata->nodename; $parentField = $metadata->parentMapping; $parentDocument = $metadata->getFieldValue($document, $parentField); $phpcrNode = $this->documentManager->getNodeForDocument($parentDocument); $parentPath = $phpcrNode->getPath(); $baseCandidateName = $metadata->getFieldValue($document, $nameField); $candidateName = $baseCandidateName; $index = 1; while (true) { $candidatePath = sprintf('%s/%s', $parentPath, $candidateName); $existing = $this->documentManager->find(null, $candidatePath); // if the existing document is the document we are updating, then thats great. if ($existing === $document) { return; } if (null === $existing) { $metadata->setFieldValue($document, $nameField, $candidateName); return; } $candidateName = sprintf('%s-%d', $baseCandidateName, $index); $index++; } }
/** * Constructor * * @param SessionInterface $session * @param DocumentManagerInterface $dm */ public function __construct(SessionInterface $session = null, DocumentManagerInterface $dm = null) { if (!$session && $dm) { $session = $dm->getPhpcrSession(); } parent::__construct($session); $this->dm = $dm; }
protected function initPhpcr(DocumentManagerInterface $documentManager) { $session = $documentManager->getPhpcrSession(); $rootNode = $session->getRootNode(); if ($rootNode->hasNode('test')) { $rootNode->getNode('test')->remove(); } $rootNode->addNode('test'); }
/** * {@inheritdoc} */ public function getDataSource(array $configuration, Parameters $parameters) { if (!array_key_exists('class', $configuration)) { throw new \InvalidArgumentException('"class" must be configured.'); } $repository = $this->documentManager->getRepository($configuration['class']); $queryBuilder = $repository->createQueryBuilder(self::QB_SOURCE_ALIAS); return new DataSource($queryBuilder); }
function it_should_clean_the_name(ResourceControllerEvent $event, DocumentManagerInterface $documentManager, ClassMetadata $metadata) { $document = new \stdClass(); $event->getSubject()->willReturn($document); $documentManager->getClassMetadata('stdClass')->willReturn($metadata); $metadata->nodename = 'foobar'; $metadata->getFieldValue($document, 'foobar')->willReturn('Hello//Foo'); $metadata->setFieldValue($document, 'foobar', 'Hello Foo')->shouldBeCalled(); $this->onEvent($event); }
private function expandClassName(DocumentManagerInterface $dm, $className = null) { if (null === $className) { return null; } if (false !== strstr($className, ':')) { $className = $dm->getClassMetadata($className)->getName(); } return $className; }
/** * Create a new repository instance for a document class. * * @param DocumentManagerInterface $dm The DocumentManager instance. * @param string $documentName The name of the document. * * @return \Doctrine\Common\Persistence\ObjectRepository */ protected function createRepository(DocumentManagerInterface $dm, $documentName) { $metadata = $dm->getClassMetadata($documentName); $repositoryClassName = $metadata->customRepositoryClassName; if ($repositoryClassName === null) { $configuration = $dm->getConfiguration(); $repositoryClassName = $configuration->getDefaultRepositoryClassName(); } return new $repositoryClassName($dm, $metadata); }
/** * @param ResourceControllerEvent $event */ public function onEvent(ResourceControllerEvent $event) { $document = $event->getSubject(); $metadata = $this->documentManager->getClassMetadata(get_class($document)); if (null === ($nameField = $metadata->nodename)) { throw new \RuntimeException(sprintf('In order to use the node name filter on "%s" it is necessary to map a field as the "nodename"', get_class($document))); } $name = $metadata->getFieldValue($document, $nameField); $name = preg_replace('/\\/|:|\\[|\\]|\\||\\*/', $this->replacementCharacter, $name); $metadata->setFieldValue($document, $nameField, $name); }
public function update(DocumentManagerInterface $documentManager, $document) { $metadataFactory = $documentManager->getMetadataFactory(); $classFqn = ClassUtils::getRealClass(get_class($document)); // PHPCR-ODM will throw an exception if the document is not mapped. $odmMetadata = $metadataFactory->getMetadataFor($classFqn); if (null === ($ctMetadata = $this->metadataFactory->getMetadataForClass($classFqn))) { return; } $this->doUpdate($metadataFactory, $odmMetadata, $ctMetadata, $document); }
protected function buildName($document, ClassMetadata $class, DocumentManagerInterface $dm, $parent, $name) { // get the id of the parent document $id = $dm->getUnitOfWork()->getDocumentId($parent); if (!$id) { throw IdException::parentIdCouldNotBeDetermined($document, $class->parentMapping, $parent); } // edge case parent is root if ('/' === $id) { $id = ''; } return $id . '/' . $name; }
/** * Check each mapped PHPCR-ODM document for the given document manager, * throwing an exception if any document is set to use a unique node * type but the node type is re-used. Returns an array of debug information. * * @param DocumentManagerInterface $documentManager The document manager to check mappings for. * * @return array * * @throws MappingException */ public function checkNodeTypeMappings(DocumentManagerInterface $documentManager) { $knownNodeTypes = array(); $debugInformation = array(); $allMetadata = $documentManager->getMetadataFactory()->getAllMetadata(); foreach ($allMetadata as $classMetadata) { if ($classMetadata->hasUniqueNodeType() && isset($knownNodeTypes[$classMetadata->getNodeType()])) { throw new MappingException(sprintf('The class "%s" is mapped with uniqueNodeType set to true, but the node type "%s" is used by "%s" as well.', $classMetadata->name, $classMetadata->getNodeType(), $knownNodeTypes[$classMetadata->getNodeType()])); } $knownNodeTypes[$classMetadata->getNodeType()] = $classMetadata->name; $debugInformation[$classMetadata->name] = array('unique_node_type' => $classMetadata->hasUniqueNodeType(), 'node_type' => $classMetadata->getNodeType()); } return $debugInformation; }
/** * @inheritDoc */ public function saveTranslation(array $data, NodeInterface $node, ClassMetadata $metadata, $locale) { foreach ($data as $field => $propValue) { $mapping = $metadata->mappings[$field]; $propName = $mapping['property']; if ($mapping['multivalue'] && $propValue) { $propValue = (array) $propValue; if (isset($mapping['assoc'])) { $propValue = $this->dm->getUnitOfWork()->processAssoc($node, $mapping, $propValue); } } $node->setProperty($propName, $propValue); } }
/** * Use a repository that implements RepositoryIdGenerator to generate the id. * * {@inheritDoc} */ public function generate($document, ClassMetadata $class, DocumentManagerInterface $dm, $parent = null) { if (null === $parent) { $parent = $class->parentMapping ? $class->getFieldValue($document, $class->parentMapping) : null; } $repository = $dm->getRepository($class->name); if (!$repository instanceof RepositoryIdInterface) { throw new IdException("ID could not be determined. Make sure the that the Repository '" . ClassUtils::getClass($repository) . "' implements RepositoryIdInterface"); } $id = $repository->generateId($document, $parent); if (!$id) { throw new IdException("ID could not be determined. Repository was unable to generate an ID"); } return $id; }
/** * Executes the query and returns the result based on the hydration mode. * * @param array $parameters Parameters, alternative to calling setParameters. * @param int $hydrationMode Processing mode to be used during the hydration * process. One of the Query::HYDRATE_* constants. * * @return mixed A Collection for HYDRATE_DOCUMENT, \PHPCR\Query\QueryResultInterface for HYDRATE_PHPCR * * @throws QueryException If $hydrationMode is not known. */ public function execute($parameters = null, $hydrationMode = null) { if (!empty($parameters)) { $this->setParameters($parameters); } if (null !== $hydrationMode) { $this->setHydrationMode($hydrationMode); } if (null !== $this->maxResults) { $this->query->setLimit($this->maxResults); } if (null !== $this->firstResult) { $this->query->setOffset($this->firstResult); } foreach ($this->parameters as $key => $value) { $this->query->bindValue($key, $value); } switch ($this->hydrationMode) { case self::HYDRATE_PHPCR: $data = $this->query->execute(); break; case self::HYDRATE_DOCUMENT: $data = $this->dm->getDocumentsByPhpcrQuery($this->query, $this->documentClass, $this->primaryAlias); break; default: throw QueryException::hydrationModeNotKnown($this->hydrationMode); } if (is_array($data)) { $data = new ArrayCollection($data); } return $data; }
/** * {@inheritDoc} */ protected function walkSourceDocument(SourceDocument $node) { $alias = $node->getAlias(); $documentFqn = $node->getDocumentFqn(); // cache the metadata for this document /** @var $meta ClassMetadata */ $meta = $this->mdf->getMetadataFor($documentFqn); if (null === $meta->getName()) { throw new \RuntimeException(sprintf('%s is not a mapped document', $documentFqn)); } $this->aliasMetadata[$alias] = $meta; if ($this->locale && $meta->translator) { $this->translator[$alias] = $this->dm->getTranslationStrategy($meta->translator); } $nodeType = $meta->getNodeType(); // make sure we add the phpcr:{class,classparents} constraints // unless the document has a unique type; From is dispatched first, // so these will always be the primary constraints. if (!$meta->hasUniqueNodeType()) { $this->sourceDocumentNodes[$alias] = $node; } // get the PHPCR Alias $alias = $this->qomf->selector($alias, $nodeType); return $alias; }
/** * Just make one field of a document untranslated again */ public function testPartialUntranslateChild() { $article = new ChildTranslationArticle(); $article->id = '/functional/convert'; $article->topic = 'Some interesting subject'; $article->setText('Lorem ipsum...'); $this->dm->persist($article); $this->dm->flush(); $this->dm->clear(); $class = 'Doctrine\\Tests\\Models\\Translation\\ChildTranslationArticle'; $field = 'author'; $node = $this->node->getNode('convert'); $node->getNode('phpcr_locale:en')->setProperty($field, 'Move to untranslated'); $this->session->save(); $this->assertFalse($this->converter->convert($class, array('en'), array($field))); $this->session->save(); $this->dm->clear(); $this->dm = $this->createDocumentManager(); $this->dm->setLocaleChooserStrategy(new LocaleChooser($this->localePrefs, 'en')); $this->assertTrue($node->hasProperty($field), 'new property was not created'); $this->assertTrue($node->hasNode('phpcr_locale:en'), 'lost translation'); $this->assertFalse($node->getNode('phpcr_locale:en')->hasProperty($field), 'old property was not removed'); $article = $this->dm->find(null, '/functional/convert'); $this->assertInstanceof($class, $article); $this->assertEquals('Move to untranslated', $article->author); $this->assertEquals('Lorem ipsum...', $article->getText()); $this->dm->clear(); $article = $this->dm->find(null, '/functional/convert'); $this->assertInstanceof($class, $article); $this->assertEquals('Move to untranslated', $article->author); $this->assertEquals('Lorem ipsum...', $article->getText()); }
/** * @param object $document The document to convert * @param TranslationStrategyInterface $previousStrategy Translation strategy to remove fields from old location * @param ClassMetadata $previousMeta Metadata for old translation strategy * @param TranslationStrategyInterface $currentStrategy Translation strategy to save new translations * @param ClassMetadata $currentMeta Metadata for new translation strategy * @param array $fields The fields to handle * @param array $locales Target locales to copy translations to. * @param bool $partialUntranslate Whether we are only a subset of fields back to untranslated */ private function convertDocument($document, TranslationStrategyInterface $previousStrategy, ClassMetadata $previousMeta, TranslationStrategyInterface $currentStrategy, ClassMetadata $currentMeta, array $fields, array $locales, $partialUntranslate) { $node = $this->dm->getNodeForDocument($document); $data = array(); foreach ($fields as $field) { $data[$field] = $currentMeta->getFieldValue($document, $field); } if ($currentStrategy instanceof NonTranslatedStrategy) { $currentStrategy->saveTranslation($data, $node, $currentMeta, null); } else { foreach ($locales as $locale) { $currentStrategy->saveTranslation($data, $node, $currentMeta, $locale); } } if ($partialUntranslate && $previousStrategy instanceof ChildTranslationStrategy) { // the child translation strategy would remove the whole child node foreach ($previousStrategy->getLocalesFor($document, $node, $previousMeta) as $locale) { $translation = $node->getNode(Translation::LOCALE_NAMESPACE . ':' . $locale); foreach ($fields as $field) { $translation->setProperty($previousMeta->mappings[$field]['property'], null); } } } else { $previousStrategy->removeAllTranslations($document, $node, $previousMeta); } }
/** * {@inheritdoc} */ public function build(MetadataInterface $metadata, FormBuilderInterface $formBuilder, array $options) { $classMetadata = $this->documentManager->getClassMetadata($metadata->getClass('model')); // the field mappings should only contain standard value mappings foreach ($classMetadata->fieldMappings as $fieldName) { if ($fieldName === $classMetadata->uuidFieldName) { continue; } if ($fieldName === $classMetadata->nodename) { continue; } $options = []; $mapping = $classMetadata->mappings[$fieldName]; if ($mapping['nullable'] === false) { $options['required'] = true; } $formBuilder->add($fieldName, null, $options); } }
private function resolveParent($document, ClassMetadata $metadata) { if (!($parentField = $metadata->parentMapping)) { throw new \RuntimeException(sprintf('A default parent path has been specified, but no parent mapping has been applied to document "%s"', get_class($document))); } if (false === $this->force) { $actualParent = $metadata->getFieldValue($document, $parentField); if ($actualParent) { return; } } $parentDocument = $this->documentManager->find(null, $this->parentPath); if (true === $this->autocreate && null === $parentDocument) { NodeHelper::createPath($this->documentManager->getPhpcrSession(), $this->parentPath); $parentDocument = $this->documentManager->find(null, $this->parentPath); } if (null === $parentDocument) { throw new \RuntimeException(sprintf('Document at default parent path "%s" does not exist. `autocreate` was set to "%s"', $this->parentPath, $this->autocreate ? 'true' : 'false')); } $metadata->setFieldValue($document, $parentField, $parentDocument); }
/** * Use the parent field together with an auto generated name to generate the id * * {@inheritDoc} */ public function generate($document, ClassMetadata $class, DocumentManagerInterface $dm, $parent = null) { if (null === $parent) { $parent = $class->parentMapping ? $class->getFieldValue($document, $class->parentMapping) : null; } $id = $class->getFieldValue($document, $class->identifier); if (empty($id) && null === $parent) { throw IdException::noIdNoParent($document, $class->parentMapping); } if (empty($parent)) { return $id; } try { $parentNode = $dm->getNodeForDocument($parent); $existingNames = (array) $parentNode->getNodeNames(); } catch (RepositoryException $e) { // this typically happens while cascading persisting documents $existingNames = array(); } $name = NodeHelper::generateAutoNodeName($existingNames, $dm->getPhpcrSession()->getWorkspace()->getNamespaceRegistry()->getNamespaces(), '', ''); return $this->buildName($document, $class, $dm, $parent, $name); }
private function getVersionedNodePath($document) { $path = $this->getDocumentId($document); $metadata = $this->dm->getClassMetadata(get_class($document)); if (!$metadata->versionable) { throw new InvalidArgumentException(sprintf("The document at path '%s' is not versionable", $path)); } $node = $this->session->getNode($path); $mixin = $metadata->versionable === 'simple' ? 'mix:simpleVersionable' : 'mix:versionable'; if (!$node->isNodeType($mixin)) { $node->addMixin($mixin); } return $path; }
/** * @param NodeInterface[] $nodes */ public function prefetch(DocumentManagerInterface $dm, $nodes, $locale = null) { if (!count($nodes)) { return; } $uuids = array(); $paths = array(); $documentClassMapper = $dm->getConfiguration()->getDocumentClassMapper(); foreach ($nodes as $node) { $className = $documentClassMapper->getClassName($dm, $node); $class = $dm->getClassMetadata($className); if (!$locale && $class->translator) { $locale = $dm->getLocaleChooserStrategy()->getLocale(); } $uuids = array_merge($uuids, $this->collectPrefetchReferences($class, $node)); $paths = array_merge($paths, $this->collectPrefetchHierarchy($class, $node, $locale)); } if (count($uuids)) { $node->getSession()->getNodesByIdentifier($uuids); } if (count($paths)) { $node->getSession()->getNodes($paths); } }
function it_should_auto_increment_the_name_if_a_conflict_exists(DocumentManagerInterface $documentManager, ResourceControllerEvent $event, ClassMetadata $metadata, NodeInterface $node) { $document = new \stdClass(); $parentDocument = new \stdClass(); $existingDocument = new \stdClass(); $event->getSubject()->willReturn($document); $documentManager->getClassMetadata('stdClass')->willReturn($metadata); $metadata->idGenerator = ClassMetadata::GENERATOR_TYPE_PARENT; $metadata->nodename = 'title'; $metadata->parentMapping = 'parent'; $metadata->getFieldValue($document, 'parent')->willReturn($parentDocument); $documentManager->getNodeForDocument($parentDocument)->willReturn($node); $node->getPath()->willReturn('/path/to'); $metadata->getFieldValue($document, 'title')->willReturn('Hello World'); $documentManager->find(null, '/path/to/Hello World')->willReturn($existingDocument); $documentManager->find(null, '/path/to/Hello World-1')->willReturn($existingDocument); $documentManager->find(null, '/path/to/Hello World-2')->willReturn($existingDocument); $documentManager->find(null, '/path/to/Hello World-3')->willReturn(null); $metadata->setFieldValue($document, 'title', 'Hello World-3')->shouldBeCalled(); $this->onEvent($event); }
function it_should_return_early_if_force_is_false_and_subject_already_has_a_parent(ResourceControllerEvent $event, ClassMetadata $documentMetadata, DocumentManagerInterface $documentManager) { $subjectDocument = new \stdClass(); $event->getSubject()->willReturn($subjectDocument); $documentManager->getClassMetadata(\stdClass::class)->willReturn($documentMetadata); $documentMetadata->parentMapping = 'parent'; $documentMetadata->getFieldValue($subjectDocument, 'parent')->willReturn(new \stdClass()); $documentManager->find(null, '/path/to')->shouldNotBeCalled(); $this->onPreCreate($event); }
/** * {@inheritDoc} */ public function transactional($callback) { return $this->wrapped->transactional($callback); }
/** * Initializes a new ListenersInvoker instance. * * @param DocumentManagerInterface $dm */ public function __construct(DocumentManagerInterface $dm) { $this->eventManager = $dm->getEventManager(); $this->dm = $dm; }
/** * If the parent node has child restrictions, ensure that the given * class name is within them. * * @param NodeInterface $parentNode * @param string $classFqn */ private function validateChildClass(NodeInterface $parentNode, ClassMetadata $class) { $parentClass = $this->documentClassMapper->getClassName($this->dm, $parentNode); if (null === $parentClass) { return; } $metadata = $this->dm->getClassMetadata($parentClass); $metadata->assertValidChildClass($class); }
/** * {@inheritDoc} */ public function getNodeForDocument($document) { return $this->wrapped->getNodeForDocument($document); }
function it_creates_data_source_via_doctrine_phpcrodm_query_builder(DocumentManagerInterface $documentManager, DocumentRepository $documentRepository, QueryBuilder $queryBuilder, Parameters $parameters) { $documentManager->getRepository('App:Book')->willReturn($documentRepository); $documentRepository->createQueryBuilder('o')->willReturn($queryBuilder); $this->getDataSource(['class' => 'App:Book'], $parameters)->shouldHaveType(DataSource::class); }