/**
  * 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'] = $this->nodeUriPathSegmentGenerator->generateUriPathSegment($referenceNode, $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;
 }
 /**
  * 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 = $this->nodeUriPathSegmentGenerator->generateUriPathSegment($node);
         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);
     }
 }
 /**
  * @param Bootstrap $bootstrap The current bootstrap
  * @return void
  */
 public function boot(Bootstrap $bootstrap)
 {
     $dispatcher = $bootstrap->getSignalSlotDispatcher();
     $flushConfigurationCache = function () use($bootstrap) {
         $cacheManager = $bootstrap->getEarlyInstance('TYPO3\\Flow\\Cache\\CacheManager');
         $cacheManager->getCache('TYPO3_Neos_Configuration_Version')->flush();
     };
     $flushXliffServiceCache = function () use($bootstrap) {
         $cacheManager = $bootstrap->getEarlyInstance('TYPO3\\Flow\\Cache\\CacheManager');
         $cacheManager->getCache('TYPO3_Neos_XliffToJsonTranslations')->flush();
     };
     $dispatcher->connect('TYPO3\\Flow\\Monitor\\FileMonitor', 'filesHaveChanged', function ($fileMonitorIdentifier, array $changedFiles) use($flushConfigurationCache, $flushXliffServiceCache) {
         switch ($fileMonitorIdentifier) {
             case 'TYPO3CR_NodeTypesConfiguration':
             case 'Flow_ConfigurationFiles':
                 $flushConfigurationCache();
                 break;
             case 'Flow_TranslationFiles':
                 $flushConfigurationCache();
                 $flushXliffServiceCache();
         }
     });
     $dispatcher->connect('TYPO3\\Neos\\Domain\\Model\\Site', 'siteChanged', $flushConfigurationCache);
     $dispatcher->connect('TYPO3\\Neos\\Domain\\Model\\Site', 'siteChanged', 'TYPO3\\Flow\\Mvc\\Routing\\RouterCachingService', 'flushCaches');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'nodeUpdated', 'TYPO3\\Neos\\TypoScript\\Cache\\ContentCacheFlusher', 'registerNodeChange');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'nodeAdded', 'TYPO3\\Neos\\TypoScript\\Cache\\ContentCacheFlusher', 'registerNodeChange');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'nodeRemoved', 'TYPO3\\Neos\\TypoScript\\Cache\\ContentCacheFlusher', 'registerNodeChange');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'beforeNodeMove', 'TYPO3\\Neos\\TypoScript\\Cache\\ContentCacheFlusher', 'registerNodeChange');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'nodeAdded', NodeUriPathSegmentGenerator::class, '::setUniqueUriPathSegment');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'nodePropertyChanged', Service\ImageVariantGarbageCollector::class, 'removeUnusedImageVariant');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'nodePropertyChanged', function (NodeInterface $node, $propertyName) use($bootstrap) {
         if ($propertyName === 'uriPathSegment') {
             NodeUriPathSegmentGenerator::setUniqueUriPathSegment($node);
             $bootstrap->getObjectManager()->get('TYPO3\\Neos\\Routing\\Cache\\RouteCacheFlusher')->registerNodeChange($node);
         }
     });
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'nodePathChanged', function (NodeInterface $node, $oldPath, $newPath, $recursion) {
         if (!$recursion) {
             NodeUriPathSegmentGenerator::setUniqueUriPathSegment($node);
         }
     });
     $dispatcher->connect('TYPO3\\Neos\\Service\\PublishingService', 'nodePublished', 'TYPO3\\Neos\\TypoScript\\Cache\\ContentCacheFlusher', 'registerNodeChange');
     $dispatcher->connect('TYPO3\\Neos\\Service\\PublishingService', 'nodeDiscarded', 'TYPO3\\Neos\\TypoScript\\Cache\\ContentCacheFlusher', 'registerNodeChange');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'nodePathChanged', 'TYPO3\\Neos\\Routing\\Cache\\RouteCacheFlusher', 'registerNodePathChange');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'nodeRemoved', 'TYPO3\\Neos\\Routing\\Cache\\RouteCacheFlusher', 'registerNodeChange');
     $dispatcher->connect('TYPO3\\Neos\\Service\\PublishingService', 'nodePublished', 'TYPO3\\Neos\\Routing\\Cache\\RouteCacheFlusher', 'registerNodeChange');
     $dispatcher->connect('TYPO3\\Neos\\Service\\PublishingService', 'nodePublished', function ($node, $targetWorkspace) use($bootstrap) {
         $cacheManager = $bootstrap->getObjectManager()->get(CacheManager::class);
         if ($cacheManager->hasCache('Flow_Persistence_Doctrine')) {
             $cacheManager->getCache('Flow_Persistence_Doctrine')->flush();
         }
     });
     $dispatcher->connect('TYPO3\\Flow\\Persistence\\Doctrine\\PersistenceManager', 'allObjectsPersisted', 'TYPO3\\Neos\\Routing\\Cache\\RouteCacheFlusher', 'commit');
     $dispatcher->connect('TYPO3\\Neos\\Domain\\Service\\SiteService', 'sitePruned', 'TYPO3\\TypoScript\\Core\\Cache\\ContentCache', 'flush');
     $dispatcher->connect('TYPO3\\Neos\\Domain\\Service\\SiteService', 'sitePruned', 'TYPO3\\Flow\\Mvc\\Routing\\RouterCachingService', 'flushCaches');
     $dispatcher->connect('TYPO3\\Neos\\Domain\\Service\\SiteImportService', 'siteImported', 'TYPO3\\TypoScript\\Core\\Cache\\ContentCache', 'flush');
     $dispatcher->connect('TYPO3\\Neos\\Domain\\Service\\SiteImportService', 'siteImported', 'TYPO3\\Flow\\Mvc\\Routing\\RouterCachingService', 'flushCaches');
     // Eventlog
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'beforeNodeCreate', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'beforeNodeCreate');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'afterNodeCreate', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'afterNodeCreate');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'nodeUpdated', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'nodeUpdated');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'nodeRemoved', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'nodeRemoved');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'beforeNodePropertyChange', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'beforeNodePropertyChange');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'nodePropertyChanged', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'nodePropertyChanged');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'beforeNodeCopy', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'beforeNodeCopy');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'afterNodeCopy', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'afterNodeCopy');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'beforeNodeMove', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'beforeNodeMove');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Node', 'afterNodeMove', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'afterNodeMove');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Service\\Context', 'beforeAdoptNode', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'beforeAdoptNode');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Service\\Context', 'afterAdoptNode', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'afterAdoptNode');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Workspace', 'beforeNodePublishing', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'beforeNodePublishing');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Model\\Workspace', 'afterNodePublishing', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'afterNodePublishing');
     $dispatcher->connect('TYPO3\\Flow\\Persistence\\Doctrine\\PersistenceManager', 'allObjectsPersisted', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'updateEventsAfterPublish');
     $dispatcher->connect('TYPO3\\TYPO3CR\\Domain\\Repository\\NodeDataRepository', 'repositoryObjectsPersisted', 'TYPO3\\Neos\\EventLog\\Integrations\\TYPO3CRIntegrationService', 'updateEventsAfterPublish');
 }