/**
  * Set the node title for the newly created Document node
  *
  * @param NodeInterface $node The newly created node
  * @param array $data incoming data from the creationDialog
  * @return void
  */
 public function handle(NodeInterface $node, array $data)
 {
     if (isset($data['title']) && $node->getNodeType()->isOfType('TYPO3.Neos:Document')) {
         $node->setProperty('title', $data['title']);
         $node->setProperty('uriPathSegment', NodeUtility::renderValidNodeName($data['title']));
     }
 }
 /**
  * Helper method for creating a new node.
  *
  * @param NodeInterface $referenceNode
  * @param array $nodeData
  * @param string $position
  * @return NodeInterface
  * @throws \InvalidArgumentException
  */
 public function create(NodeInterface $referenceNode, array $nodeData, $position)
 {
     if (!in_array($position, array('before', 'into', 'after'), true)) {
         throw new \InvalidArgumentException('The position should be one of the following: "before", "into", "after".', 1347133640);
     }
     $nodeType = $this->nodeTypeManager->getNodeType($nodeData['nodeType']);
     if ($nodeType->isOfType('TYPO3.Neos:Document') && !isset($nodeData['properties']['uriPathSegment']) && isset($nodeData['properties']['title'])) {
         $nodeData['properties']['uriPathSegment'] = Utility::renderValidNodeName($nodeData['properties']['title']);
     }
     $proposedNodeName = isset($nodeData['nodeName']) ? $nodeData['nodeName'] : null;
     $nodeData['nodeName'] = $this->nodeService->generateUniqueNodeName($this->getDesignatedParentNode($referenceNode, $position)->getPath(), $proposedNodeName);
     if ($position === 'into') {
         $newNode = $referenceNode->createNode($nodeData['nodeName'], $nodeType);
     } else {
         $parentNode = $referenceNode->getParent();
         $newNode = $parentNode->createNode($nodeData['nodeName'], $nodeType);
         if ($position === 'before') {
             $newNode->moveBefore($referenceNode);
         } else {
             $newNode->moveAfter($referenceNode);
         }
     }
     if (isset($nodeData['properties']) && is_array($nodeData['properties'])) {
         foreach ($nodeData['properties'] as $propertyName => $propertyValue) {
             $newNode->setProperty($propertyName, $propertyValue);
         }
     }
     return $newNode;
 }
 /**
  * @param NodeInterface $parentNode
  * @param NodeType $nodeType
  * @return NodeInterface|void
  */
 public function create(NodeInterface $parentNode, NodeType $nodeType)
 {
     $title = Company::name();
     $name = Utility::renderValidNodeName($title);
     $childrenNode = $parentNode->createNode($name, $nodeType);
     $childrenNode->setProperty('title', $title);
     return $childrenNode;
 }
示例#4
0
 /**
  * @param string $sitePackage
  * @param string $siteName
  * @param string $baseDomain
  * @return Site
  */
 public function importSiteFromTemplate($sitePackage, $siteName, $baseDomain = '')
 {
     if (empty($baseDomain)) {
         $request = Request::createFromEnvironment();
         $baseDomain = $request->getBaseUri()->getHost();
     }
     $siteTemplate = new StandaloneView();
     $siteTemplate->setTemplatePathAndFilename(FLOW_PATH_PACKAGES . 'Sites/' . $sitePackage . '/Resources/Private/Templates/Content/Sites.xml');
     $siteTemplate->assignMultiple(['siteName' => $siteName, 'siteNodeName' => \TYPO3\TYPO3CR\Utility::renderValidNodeName($siteName), 'packageKey' => $sitePackage]);
     $generatedSiteImportXmlContent = $siteTemplate->render();
     $dataTemporaryPath = $this->environment->getPathToTemporaryDirectory();
     $temporarySiteXml = $dataTemporaryPath . uniqid($siteName) . '.xml';
     file_put_contents($temporarySiteXml, $generatedSiteImportXmlContent);
     $site = $this->siteImportService->importFromFile($temporarySiteXml);
     $domain = new Domain();
     $domain->setActive(true);
     $domain->setSite($site);
     $domain->setHostPattern(\TYPO3\TYPO3CR\Utility::renderValidNodeName($siteName) . '.' . $baseDomain);
     $this->domainRepository->add($domain);
     return $site;
 }
 /**
  * Saves the given array as a node data entity without using the ORM.
  *
  * If the node data already exists (same dimensions, same identifier, same workspace)
  * it is replaced.
  *
  * @param array $nodeData node data to save as an associative array ( $column_name => $value )
  * @throws ImportException
  * @return void
  */
 protected function persistNodeData($nodeData)
 {
     if ($nodeData['workspace'] !== 'live') {
         throw new ImportException('Saving NodeData with workspace != "live" using direct SQL not supported yet. Workspace is "' . $nodeData['workspace'] . '".');
     }
     if ($nodeData['path'] === '/') {
         return;
     }
     // cleanup old data
     /** @var \Doctrine\DBAL\Connection $connection */
     $connection = $this->entityManager->getConnection();
     // prepare node dimensions
     $dimensionValues = $nodeData['dimensionValues'];
     $dimensionsHash = Utility::sortDimensionValueArrayAndReturnDimensionsHash($dimensionValues);
     $jsonPropertiesDataTypeHandler = JsonArrayType::getType(JsonArrayType::FLOW_JSON_ARRAY);
     // post-process node data
     $nodeData['dimensionsHash'] = $dimensionsHash;
     $nodeData['dimensionValues'] = $jsonPropertiesDataTypeHandler->convertToDatabaseValue($dimensionValues, $connection->getDatabasePlatform());
     $nodeData['properties'] = $jsonPropertiesDataTypeHandler->convertToDatabaseValue($nodeData['properties'], $connection->getDatabasePlatform());
     $nodeData['accessRoles'] = $jsonPropertiesDataTypeHandler->convertToDatabaseValue($nodeData['accessRoles'], $connection->getDatabasePlatform());
     $connection->executeQuery('DELETE FROM typo3_typo3cr_domain_model_nodedimension' . ' WHERE nodedata IN (' . '   SELECT persistence_object_identifier FROM typo3_typo3cr_domain_model_nodedata' . '   WHERE identifier = :identifier' . '   AND workspace = :workspace' . '   AND dimensionshash = :dimensionsHash' . ' )', array('identifier' => $nodeData['identifier'], 'workspace' => $nodeData['workspace'], 'dimensionsHash' => $nodeData['dimensionsHash']));
     /** @var \Doctrine\ORM\QueryBuilder $queryBuilder */
     $queryBuilder = $this->entityManager->createQueryBuilder();
     $queryBuilder->delete()->from('TYPO3\\TYPO3CR\\Domain\\Model\\NodeData', 'n')->where('n.identifier = :identifier')->andWhere('n.dimensionsHash = :dimensionsHash')->andWhere('n.workspace = :workspace')->setParameter('identifier', $nodeData['identifier'])->setParameter('workspace', $nodeData['workspace'])->setParameter('dimensionsHash', $nodeData['dimensionsHash']);
     $queryBuilder->getQuery()->execute();
     // insert new data
     // we need to use executeUpdate to execute the INSERT -- else the data types are not taken into account.
     // That's why we build a DQL INSERT statement which is then executed.
     $queryParts = array();
     $queryArguments = array();
     $queryTypes = array();
     foreach ($this->nodeDataPropertyNames as $propertyName => $propertyConfig) {
         if (isset($nodeData[$propertyName])) {
             $queryParts[$propertyName] = ':' . $propertyName;
             $queryArguments[$propertyName] = $nodeData[$propertyName];
             if (isset($propertyConfig['columnType'])) {
                 $queryTypes[$propertyName] = $propertyConfig['columnType'];
             }
         }
     }
     $connection->executeUpdate('INSERT INTO typo3_typo3cr_domain_model_nodedata (' . implode(', ', array_keys($queryParts)) . ') VALUES (' . implode(', ', $queryParts) . ')', $queryArguments, $queryTypes);
     foreach ($dimensionValues as $dimension => $values) {
         foreach ($values as $value) {
             $nodeDimension = array('persistence_object_identifier' => Algorithms::generateUUID(), 'nodedata' => $nodeData['Persistence_Object_Identifier'], 'name' => $dimension, 'value' => $value);
             $connection->insert('typo3_typo3cr_domain_model_nodedimension', $nodeDimension);
         }
     }
 }
 /**
  * Creates a new node beneath $parent
  *
  * @param  NodeInterface $parent
  * @return NodeInterface
  */
 protected function createNode(NodeInterface $parent)
 {
     $nodeType = $this->getNodeType();
     $initialProperties = $this->getInitialProperties();
     $name = $this->getName() ?: $this->nodeService->generateUniqueNodeName($parent->getPath());
     //
     // If we're about to create a document, check for the presence of the uriPathSegment property first
     // and create it, if it's missing
     //
     if ($nodeType->isOfType('TYPO3.Neos:Document') && !isset($initialProperties['uriPathSegment'])) {
         if (!isset($initialProperties['title'])) {
             throw new \IllegalArgumentException('You must either provide a title or a uriPathSegment in order to create a document.', 1452103891);
         }
         $initialProperties['uriPathSegment'] = NodeUtility::renderValidNodeName($initialProperties['title']);
     }
     $node = $parent->createNode($name, $nodeType);
     foreach ($initialProperties as $key => $value) {
         $node->setProperty($key, $value);
     }
     return $node;
 }
 /**
  * Create a workspace
  *
  * @Flow\Validate(argumentName="title", type="\TYPO3\Flow\Validation\Validator\NotEmptyValidator")
  * @param string $title Human friendly title of the workspace, for example "Christmas Campaign"
  * @param Workspace $baseWorkspace Workspace the new workspace should be based on
  * @param string $visibility Visibility of the new workspace, must be either "internal" or "shared"
  * @param string $description A description explaining the purpose of the new workspace
  * @return void
  */
 public function createAction($title, Workspace $baseWorkspace, $visibility, $description = '')
 {
     $workspace = $this->workspaceRepository->findOneByTitle($title);
     if ($workspace instanceof Workspace) {
         $this->addFlashMessage($this->translator->translateById('workspaces.workspaceWithThisTitleAlreadyExists', [], null, null, 'Modules', 'TYPO3.Neos'), '', Message::SEVERITY_WARNING);
         $this->redirect('new');
     }
     $workspaceName = Utility::renderValidNodeName($title) . '-' . substr(base_convert(microtime(false), 10, 36), -5, 5);
     while ($this->workspaceRepository->findOneByName($workspaceName) instanceof Workspace) {
         $workspaceName = Utility::renderValidNodeName($title) . '-' . substr(base_convert(microtime(false), 10, 36), -5, 5);
     }
     if ($visibility === 'private') {
         $owner = $this->userService->getCurrentUser();
     } else {
         $owner = null;
     }
     $workspace = new Workspace($workspaceName, $baseWorkspace, $owner);
     $workspace->setTitle($title);
     $workspace->setDescription($description);
     $this->workspaceRepository->add($workspace);
     $this->redirect('index');
 }
 /**
  * Traverses through the tree starting at the given root node and sets the uriPathSegment property derived from
  * the node label.
  *
  * @param NodeInterface $node The node where the traversal starts
  * @param boolean $dryRun
  * @return void
  */
 protected function generateUriPathSegmentsForNode(NodeInterface $node, $dryRun)
 {
     if ((string) $node->getProperty('uriPathSegment') === '') {
         $name = $node->getLabel() ?: $node->getName();
         $uriPathSegment = Utility::renderValidNodeName($name);
         if ($dryRun === FALSE) {
             $node->setProperty('uriPathSegment', $uriPathSegment);
             $this->output->outputLine('Added missing URI path segment for "%s" (%s) => %s', array($node->getPath(), $name, $uriPathSegment));
         } else {
             $this->output->outputLine('Found missing URI path segment for "%s" (%s) => %s', array($node->getPath(), $name, $uriPathSegment));
         }
     }
     foreach ($node->getChildNodes('TYPO3.Neos:Document') as $childNode) {
         $this->generateUriPathSegmentsForNode($childNode, $dryRun);
     }
 }
 /**
  * Checks if the given $nodeType is allowed as a childNode of the given $childNodeName
  * (which must be auto-created in $this NodeType).
  *
  * Only allowed to be called if $childNodeName is auto-created.
  *
  * @param string $childNodeName The name of a configured childNode of this NodeType
  * @param NodeType $nodeType The NodeType to check constraints for.
  * @return boolean TRUE if the $nodeType is allowed as grandchild node, FALSE otherwise.
  * @throws \InvalidArgumentException If the given $childNodeName is not configured to be auto-created in $this.
  */
 public function allowsGrandchildNodeType($childNodeName, NodeType $nodeType)
 {
     $autoCreatedChildNodes = $this->getAutoCreatedChildNodes();
     if (!isset($autoCreatedChildNodes[$childNodeName])) {
         throw new \InvalidArgumentException('The method "allowsGrandchildNodeType" can only be used on auto-created childNodes, given $childNodeName "' . $childNodeName . '" is not auto-created.', 1403858395);
     }
     $constraints = $autoCreatedChildNodes[$childNodeName]->getConfiguration('constraints.nodeTypes') ?: array();
     $childNodeConfiguration = [];
     foreach ($this->getConfiguration('childNodes') as $name => $configuration) {
         $childNodeConfiguration[Utility::renderValidNodeName($name)] = $configuration;
     }
     $childNodeConstraintConfiguration = ObjectAccess::getPropertyPath($childNodeConfiguration, $childNodeName . '.constraints.nodeTypes') ?: array();
     $constraints = Arrays::arrayMergeRecursiveOverrule($constraints, $childNodeConstraintConfiguration);
     return $this->isNodeTypeAllowedByConstraints($nodeType, $constraints);
 }
 /**
  * @param Account $account
  * @param NodeInterface $userStorageNode
  * @param PersonDto $person
  * @return NodeInterface|string
  */
 protected function createProfileNode(Account $account, NodeInterface $userStorageNode, PersonDto $person)
 {
     try {
         $profileNode = $this->findProfileNode($person->getEmailAddress());
         if ($profileNode === NULL) {
             $properties = ['title' => $person->getFirstName() . ' ' . $person->getLastName(), 'firstName' => $person->getFirstName(), 'lastName' => $person->getLastName(), 'address' => $person->getAddress(), 'zipCode' => $person->getZipCode(), 'city' => $person->getCity(), 'emailAddress' => $person->getEmailAddress(), 'phone' => $person->getPhone(), 'dateOfBirth' => $person->getDateOfBirth(), 'jiuJitsu' => $person->getJiuJitsu(), 'buJitsuDo' => $person->getBuJitsuDo(), 'jiuJitsuDegree' => $person->getJiuJitsuDegree(), 'buJitsuDoDegree' => $person->getBuJitsuDoDegree(), 'gender' => $person->getGender()];
             if ($person->getFirstName() && $person->getLastName()) {
                 $nodeName = $person->getFirstName() . ' ' . $person->getLastName();
             }
             $idealNodeName = Utility::renderValidNodeName(isset($nodeName) ? $nodeName : uniqid('node'));
             $idealNodeName = htmlspecialchars($idealNodeName, ENT_NOQUOTES, 'UTF-8');
             $profileNode = $this->nodeWriteRepository->createChildNode($userStorageNode, $idealNodeName, 'BuJitsuDo.Authentication:Person', $properties);
             if ($person->getImage() instanceof Image) {
                 $profileNode = $this->profileService->setImageToNode($profileNode, $person->getImage(), $person->getFirstName(), 'Profile images');
             }
         }
         $account->getParty()->getPreferences()->set('profileNodeIdentifier', $profileNode->getIdentifier());
         $this->partyRepository->update($account->getParty());
         $this->persistenceManager->persistAll();
         $this->emitPersonCreated($profileNode);
         return $profileNode;
     } catch (\Exception $exception) {
         $this->systemLogger->log('Profile node could not be created because: ' . $exception->getMessage(), LOG_CRIT);
         return $exception->getMessage();
     }
 }
示例#11
0
 /**
  * Get the name of this node template.
  *
  * If a name has been set using setName(), it is returned. If not, but the
  * template has a (non-empty) title property, this property is used to
  * generate a valid name. As a last resort a random name is returned (in
  * the form "nameXXXXX").
  *
  * @return string
  * @api
  */
 public function getName()
 {
     if ($this->name !== NULL) {
         return $this->name;
     }
     if ($this->hasProperty('title') && strlen($this->getProperty('title')) > 0) {
         return \TYPO3\TYPO3CR\Utility::renderValidNodeName($this->getProperty('title'));
     }
     return uniqid('node');
 }
示例#12
0
 /**
  * Returns a camelcase version of $name with the first letter uppercase.
  *
  * @param string $name
  * @return string
  */
 public static function renderValidName($name)
 {
     return preg_replace('/\\s+/', '', ucwords(str_replace('-', ' ', \TYPO3\TYPO3CR\Utility::renderValidNodeName($name))));
 }
 /**
  * @test
  * @dataProvider sourcesAndNodeNames
  */
 public function renderValidNodeNameWorks($source, $expectedNodeName)
 {
     $this->assertEquals($expectedNodeName, Utility::renderValidNodeName($source));
 }
 /**
  * Create missing child nodes for the given node type
  *
  * @param NodeType $nodeType
  * @param string $workspaceName
  * @param boolean $dryRun
  * @return void
  */
 protected function createChildNodesByNodeType(NodeType $nodeType, $workspaceName, $dryRun)
 {
     $createdNodesCount = 0;
     $updatedNodesCount = 0;
     $nodeCreationExceptions = 0;
     $nodeIdentifiersWhichNeedUpdate = [];
     $nodeTypes = $this->nodeTypeManager->getSubNodeTypes($nodeType->getName(), false);
     $nodeTypes[$nodeType->getName()] = $nodeType;
     if ($this->nodeTypeManager->hasNodeType((string) $nodeType)) {
         $nodeType = $this->nodeTypeManager->getNodeType((string) $nodeType);
         $nodeTypeNames[$nodeType->getName()] = $nodeType;
     } else {
         $this->output->outputLine('Node type "%s" does not exist', array((string) $nodeType));
         exit(1);
     }
     /** @var $nodeType NodeType */
     foreach ($nodeTypes as $nodeTypeName => $nodeType) {
         $childNodes = $nodeType->getAutoCreatedChildNodes();
         foreach ($this->getNodeDataByNodeTypeAndWorkspace($nodeTypeName, $workspaceName) as $nodeData) {
             $context = $this->nodeFactory->createContextMatchingNodeData($nodeData);
             $node = $this->nodeFactory->createFromNodeData($nodeData, $context);
             if (!$node instanceof NodeInterface) {
                 continue;
             }
             foreach ($childNodes as $childNodeName => $childNodeType) {
                 try {
                     $childNode = $node->getNode($childNodeName);
                     $childNodeIdentifier = Utility::buildAutoCreatedChildNodeIdentifier($childNodeName, $node->getIdentifier());
                     if ($childNode === null) {
                         if ($dryRun === false) {
                             $node->createNode($childNodeName, $childNodeType, $childNodeIdentifier);
                             $this->output->outputLine('Auto created node named "%s" in "%s"', array($childNodeName, $node->getPath()));
                         } else {
                             $this->output->outputLine('Missing node named "%s" in "%s"', array($childNodeName, $node->getPath()));
                         }
                         $createdNodesCount++;
                     } elseif ($childNode->getIdentifier() !== $childNodeIdentifier) {
                         $nodeIdentifiersWhichNeedUpdate[$childNode->getIdentifier()] = $childNodeIdentifier;
                     }
                 } catch (\Exception $exception) {
                     $this->output->outputLine('Could not create node named "%s" in "%s" (%s)', array($childNodeName, $node->getPath(), $exception->getMessage()));
                     $nodeCreationExceptions++;
                 }
             }
         }
     }
     if (count($nodeIdentifiersWhichNeedUpdate) > 0) {
         if ($dryRun === false) {
             foreach ($nodeIdentifiersWhichNeedUpdate as $oldNodeIdentifier => $newNodeIdentifier) {
                 $queryBuilder = $this->entityManager->createQueryBuilder();
                 $queryBuilder->update(NodeData::class, 'n')->set('n.identifier', $queryBuilder->expr()->literal($newNodeIdentifier))->where('n.identifier = ?1')->setParameter(1, $oldNodeIdentifier);
                 $result = $queryBuilder->getQuery()->getResult();
                 $updatedNodesCount++;
                 $this->output->outputLine('Updated node identifier from %s to %s because it was not a "stable" identifier', [$oldNodeIdentifier, $newNodeIdentifier]);
             }
         } else {
             foreach ($nodeIdentifiersWhichNeedUpdate as $oldNodeIdentifier => $newNodeIdentifier) {
                 $this->output->outputLine('Child nodes with identifier "%s" need to change their identifier to "%s"', [$oldNodeIdentifier, $newNodeIdentifier]);
                 $updatedNodesCount++;
             }
         }
     }
     if ($createdNodesCount !== 0 || $nodeCreationExceptions !== 0 || $updatedNodesCount !== 0) {
         if ($dryRun === false) {
             if ($createdNodesCount > 0) {
                 $this->output->outputLine('Created %s new child nodes', array($createdNodesCount));
             }
             if ($updatedNodesCount > 0) {
                 $this->output->outputLine('Updated identifier of %s child nodes', array($updatedNodesCount));
             }
             if ($nodeCreationExceptions > 0) {
                 $this->output->outputLine('%s Errors occurred during child node creation', array($nodeCreationExceptions));
             }
             $this->persistenceManager->persistAll();
         } else {
             if ($createdNodesCount > 0) {
                 $this->output->outputLine('%s missing child nodes need to be created', array($createdNodesCount));
             }
             if ($updatedNodesCount > 0) {
                 $this->output->outputLine('%s identifiers of child nodes need to be updated', array($updatedNodesCount));
             }
         }
     }
 }
 /**
  * Create missing child nodes for the given node type
  *
  * @param NodeType $nodeType
  * @param string $workspaceName
  * @param boolean $dryRun
  * @return void
  */
 protected function createChildNodesByNodeType(NodeType $nodeType, $workspaceName, $dryRun)
 {
     $createdNodesCount = 0;
     $updatedNodesCount = 0;
     $nodeCreationExceptions = 0;
     $nodeTypes = $this->nodeTypeManager->getSubNodeTypes($nodeType->getName(), false);
     $nodeTypes[$nodeType->getName()] = $nodeType;
     if ($this->nodeTypeManager->hasNodeType((string) $nodeType)) {
         $nodeType = $this->nodeTypeManager->getNodeType((string) $nodeType);
         $nodeTypeNames[$nodeType->getName()] = $nodeType;
     } else {
         $this->output->outputLine('Node type "%s" does not exist', array((string) $nodeType));
         exit(1);
     }
     /** @var $nodeType NodeType */
     foreach ($nodeTypes as $nodeTypeName => $nodeType) {
         $childNodes = $nodeType->getAutoCreatedChildNodes();
         foreach ($this->getNodeDataByNodeTypeAndWorkspace($nodeTypeName, $workspaceName) as $nodeData) {
             $context = $this->nodeFactory->createContextMatchingNodeData($nodeData);
             $node = $this->nodeFactory->createFromNodeData($nodeData, $context);
             if (!$node instanceof NodeInterface) {
                 continue;
             }
             foreach ($childNodes as $childNodeName => $childNodeType) {
                 try {
                     $childNode = $node->getNode($childNodeName);
                     $childNodeIdentifier = Utility::buildAutoCreatedChildNodeIdentifier($childNodeName, $node->getIdentifier());
                     if ($childNode === null) {
                         if ($dryRun === false) {
                             $node->createNode($childNodeName, $childNodeType, $childNodeIdentifier);
                             $this->output->outputLine('Auto created node named "%s" in "%s"', array($childNodeName, $node->getPath()));
                         } else {
                             $this->output->outputLine('Missing node named "%s" in "%s"', array($childNodeName, $node->getPath()));
                         }
                         $createdNodesCount++;
                     } elseif ($childNode->getIdentifier() !== $childNodeIdentifier) {
                         if ($dryRun === false) {
                             $nodeData = $childNode->getNodeData();
                             $nodeData->setIdentifier($childNodeIdentifier);
                             $this->nodeDataRepository->update($nodeData);
                             $this->output->outputLine('Updated identifier to %s for child node "%s" in "%s"', array($childNodeIdentifier, $childNodeName, $node->getPath()));
                         } else {
                             $this->output->outputLine('Child node "%s" in "%s" does not have a stable identifier', array($childNodeName, $node->getPath()));
                         }
                         $updatedNodesCount++;
                     }
                 } catch (\Exception $exception) {
                     $this->output->outputLine('Could not create node named "%s" in "%s" (%s)', array($childNodeName, $node->getPath(), $exception->getMessage()));
                     $nodeCreationExceptions++;
                 }
             }
         }
     }
     if ($createdNodesCount !== 0 || $nodeCreationExceptions !== 0 || $updatedNodesCount !== 0) {
         if ($dryRun === false) {
             if ($createdNodesCount > 0) {
                 $this->output->outputLine('Created %s new child nodes', array($createdNodesCount));
             }
             if ($updatedNodesCount > 0) {
                 $this->output->outputLine('Updated identifier of %s child nodes', array($updatedNodesCount));
             }
             if ($nodeCreationExceptions > 0) {
                 $this->output->outputLine('%s Errors occurred during child node creation', array($nodeCreationExceptions));
             }
             $this->persistenceManager->persistAll();
         } else {
             if ($createdNodesCount > 0) {
                 $this->output->outputLine('%s missing child nodes need to be created', array($createdNodesCount));
             }
             if ($updatedNodesCount > 0) {
                 $this->output->outputLine('%s identifiers of child nodes need to be updated', array($updatedNodesCount));
             }
         }
     }
 }
 /**
  * Create a recursive copy of this node below $referenceNode with $nodeName.
  *
  * $detachedCopy only has an influence if we are copying from one dimension to the other, possibly creating a new
  * node variant:
  *
  * - If $detachedCopy is TRUE, the whole (recursive) copy is done without connecting original and copied node,
  *   so NOT CREATING a new node variant.
  * - If $detachedCopy is FALSE, and the node does not yet have a variant in the target dimension, we are CREATING
  *   a new node variant.
  *
  * As a caller of this method, $detachedCopy should be TRUE if $this->getNodeType()->isAggregate() is TRUE, and FALSE
  * otherwise.
  *
  * @param NodeInterface $referenceNode
  * @param boolean $detachedCopy
  * @param string $nodeName
  * @return NodeInterface
  */
 protected function createRecursiveCopy(NodeInterface $referenceNode, $nodeName, $detachedCopy)
 {
     $identifier = null;
     $referenceNodeDimensions = $referenceNode->getDimensions();
     $referenceNodeDimensionsHash = Utility::sortDimensionValueArrayAndReturnDimensionsHash($referenceNodeDimensions);
     $thisDimensions = $this->getDimensions();
     $thisNodeDimensionsHash = Utility::sortDimensionValueArrayAndReturnDimensionsHash($thisDimensions);
     if ($detachedCopy === false && $referenceNodeDimensionsHash !== $thisNodeDimensionsHash && $referenceNode->getContext()->getNodeByIdentifier($this->getIdentifier()) === null) {
         // If the target dimensions are different than this one, and there is no node shadowing this one in the target dimension yet, we use the same
         // node identifier, effectively creating a new node variant.
         $identifier = $this->getIdentifier();
     }
     $copiedNode = $referenceNode->createSingleNode($nodeName, null, $identifier);
     $copiedNode->similarize($this, true);
     /** @var $childNode Node */
     foreach ($this->getChildNodes() as $childNode) {
         // Prevent recursive copy when copying into itself
         if ($childNode->getIdentifier() !== $copiedNode->getIdentifier()) {
             $childNode->copyIntoInternal($copiedNode, $childNode->getName(), $detachedCopy);
         }
     }
     return $copiedNode;
 }
 /**
  * Generate possible node name. When an idealNodeName is given then this is put into a valid format for a node name,
  * otherwise a random node name in the form "node-alphanumeric" is generated.
  *
  * @param string $idealNodeName
  * @return string
  */
 protected function generatePossibleNodeName($idealNodeName = null)
 {
     if ($idealNodeName !== null) {
         $possibleNodeName = \TYPO3\TYPO3CR\Utility::renderValidNodeName($idealNodeName);
     } else {
         $possibleNodeName = NodePaths::generateRandomNodeName();
     }
     return $possibleNodeName;
 }
 /**
  * Build a cached array of dimension values and a hash to search for it.
  *
  * @return void
  */
 protected function buildDimensionValues()
 {
     $dimensionValues = array();
     foreach ($this->dimensions as $dimension) {
         /** @var NodeDimension $dimension */
         $dimensionValues[$dimension->getName()][] = $dimension->getValue();
     }
     $this->dimensionsHash = Utility::sortDimensionValueArrayAndReturnDimensionsHash($dimensionValues);
     $this->dimensionValues = $dimensionValues;
 }
 /**
  * @param string $idealNodeName
  * @param NodeInterface $referenceNode
  * @return string
  */
 protected function getFreeNodeName($idealNodeName, NodeInterface $referenceNode)
 {
     $idealNodeName = NodeUtility::renderValidNodeName($idealNodeName);
     $possibleNodeName = $idealNodeName;
     $counter = 1;
     while ($referenceNode->getNode($possibleNodeName) !== null) {
         $possibleNodeName = $idealNodeName . '-' . $counter;
         $counter++;
     }
     return $possibleNodeName;
 }