/** * @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++; } }
/** * @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); } }
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); }
/** * 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); }
/** * {@inheritDoc} */ public function getNodeForDocument($document) { return $this->wrapped->getNodeForDocument($document); }