/**
  * @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++;
     }
 }
Esempio n. 2
0
 /**
  * @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);
 }
 /**
  * {@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 expandClassName(DocumentManagerInterface $dm, $className = null)
 {
     if (null === $className) {
         return null;
     }
     if (false !== strstr($className, ':')) {
         $className = $dm->getClassMetadata($className)->getName();
     }
     return $className;
 }
Esempio n. 5
0
 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);
 }
 /**
  * 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);
 }
Esempio n. 7
0
 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;
 }
 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);
 }
Esempio n. 10
0
 /**
  * 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 getClassMetadata($className)
 {
     return $this->wrapped->getClassMetadata($className);
 }
 /**
  * Migrate content into the new translation format and remove the old properties.
  *
  * This does not commit the changes to the repository. Call save on the
  * PHPCR session *after each batch*. Calling flush on the document manager
  * *is not enough*.
  *
  * When translating, the new properties are copied into the languages
  * specified in $locales. When un-translating, the current locale and
  * language fallback is used, and $locales is ignored.
  *
  * To convert all fields into a translation, you can pass an empty array
  * for $fields and the information is read from the metadata. The fields
  * are mandatory when converting fields back to non-translated.
  *
  * To convert a single field from translated to non-translated, simply
  * specify that field.
  *
  * If you convert an existing translation, you need to specify the name of
  * the strategy that was previously used. The name is the one you would use
  * for DocumentManagerInterface::getTranslationStrategy, so "attribute" or
  * "child".
  *
  * The current strategy is read from the document metadata.
  *
  * Only documents that match $class exactly are converted, but not
  * descendants. You can query whether there where documents encountered
  * that could not be converted by calling getLastNotices() after each call
  * to convert().
  *
  * @param string $class                FQN of the document class
  * @param array  $locales              Locales to copy previously untranslated fields into.
  *                                     Ignored when untranslating a document.
  * @param array  $fields               List of fields to convert. Required when making a
  *                                     field not translated anymore
  * @param string $previousStrategyName Name of previous strategy or "none" if field was not
  *                                     previously translated
  *
  * @return boolean true if there are more documents to convert and this method needs to be
  *                      called again.
  *
  * @throws PHPCRExceptionInterface if the document can not be found.
  *
  * @see getLastNotices()
  */
 public function convert($class, $locales, array $fields = array(), $previousStrategyName = NonTranslatedStrategy::NAME)
 {
     /** @var ClassMetadata $currentMeta */
     $currentMeta = $this->dm->getClassMetadata($class);
     $currentStrategyName = $currentMeta->translator ?: NonTranslatedStrategy::NAME;
     // sanity check strategies
     if ($currentStrategyName === $previousStrategyName) {
         $message = 'Previous and current strategy are the same.';
         if (NonTranslatedStrategy::NAME === $currentStrategyName) {
             $message .= ' To untranslate a document, you need to specify the previous translation strategy';
         } else {
             $message .= sprintf(' Document is currently at %s', $currentStrategyName);
         }
         throw new InvalidArgumentException($message);
     }
     if (!count($locales) && NonTranslatedStrategy::NAME !== $currentStrategyName) {
         throw new InvalidArgumentException('When converting to translated content, the locales must be specified.');
     }
     $this->notices = array();
     $translated = null;
     foreach ($fields as $field) {
         $current = !empty($currentMeta->mappings[$field]['translated']);
         if (null !== $translated && $current !== $translated) {
             throw new InvalidArgumentException(sprintf('The list of specified fields %s contained both translated and untranslated fields. If you want to move back to untranslated, specify only the untranslated fields.', implode(', ', $fields)));
         }
         $translated = $current;
     }
     $partialUntranslate = false;
     if (false === $translated && NonTranslatedStrategy::NAME !== $currentStrategyName) {
         // special case, convert fields back to untranslated
         $partialUntranslate = true;
         $previousStrategyName = $currentStrategyName;
         $currentStrategyName = NonTranslatedStrategy::NAME;
         $currentMeta->translator = null;
     }
     $currentStrategy = NonTranslatedStrategy::NAME === $currentStrategyName ? new NonTranslatedStrategy($this->dm) : $this->dm->getTranslationStrategy($currentMeta->translator);
     if (NonTranslatedStrategy::NAME === $previousStrategyName) {
         $previousStrategy = new NonTranslatedStrategy($this->dm);
     } else {
         $previousStrategy = $this->dm->getTranslationStrategy($previousStrategyName);
     }
     if (!$fields) {
         if (NonTranslatedStrategy::NAME === $currentStrategyName) {
             throw new InvalidArgumentException('To untranslate a document, you need to specify the fields that where previously translated');
         }
         $fields = $currentMeta->translatableFields;
     }
     // trick query into using the previous strategy
     $currentMeta->translator = NonTranslatedStrategy::NAME === $previousStrategyName ? null : $previousStrategyName;
     if (NonTranslatedStrategy::NAME === $currentStrategyName) {
         $currentMeta->translatableFields = $fields;
         foreach ($fields as $field) {
             $currentMeta->mappings[$field]['translated'] = true;
         }
     }
     $qb = $this->dm->createQueryBuilder();
     $or = $qb->fromDocument($class, 'd')->where()->orX();
     foreach ($fields as $field) {
         $or->fieldIsset('d.' . $field);
     }
     $qb->setMaxResults($this->batchSize);
     $documents = $qb->getQuery()->execute();
     // restore meta data to the real thing
     $currentMeta->translator = NonTranslatedStrategy::NAME === $currentStrategyName ? null : $currentStrategyName;
     if (NonTranslatedStrategy::NAME === $currentStrategyName) {
         $currentMeta->translatableFields = array();
         foreach ($fields as $field) {
             unset($currentMeta->mappings[$field]['translated']);
         }
     }
     // fake metadata for previous
     $previousMeta = clone $currentMeta;
     $previousMeta->translator = NonTranslatedStrategy::NAME === $previousStrategyName ? null : $previousStrategyName;
     // even when previously not translated, we use translatableFields for the NonTranslatedStrategy
     $previousMeta->translatableFields = $fields;
     foreach ($documents as $document) {
         if (ClassUtils::getClass($document) !== $class) {
             $path = $this->dm->getUnitOfWork()->getDocumentId($document);
             $this->notices[$path] = ClassUtils::getClass($document);
             continue;
         }
         $this->convertDocument($document, $previousStrategy, $previousMeta, $currentStrategy, $currentMeta, $fields, $locales, $partialUntranslate);
     }
     return count($documents) === $this->batchSize;
 }
Esempio n. 13
0
 /**
  * @param ResourceControllerEvent $event
  */
 public function onPreCreate(ResourceControllerEvent $event)
 {
     $document = $event->getSubject();
     $class = get_class($document);
     $this->resolveParent($document, $this->documentManager->getClassMetadata($class));
 }