/**
  * @param string $searchWord
  * @param Site $selectedSite
  * @return void
  */
 public function searchForNodeAction($searchWord, Site $selectedSite = NULL)
 {
     $documentNodeTypes = $this->nodeTypeManager->getSubNodeTypes('TYPO3.Neos:Document');
     $shortcutNodeType = $this->nodeTypeManager->getNodeType('TYPO3.Neos:Shortcut');
     $nodeTypes = array_diff($documentNodeTypes, array($shortcutNodeType));
     $sites = array();
     $activeSites = $this->siteRepository->findOnline();
     foreach ($selectedSite ? array($selectedSite) : $activeSites as $site) {
         /** @var Site $site */
         $contextProperties = array('workspaceName' => 'live', 'currentSite' => $site);
         $contentDimensionPresets = $this->contentDimensionPresetSource->getAllPresets();
         if (count($contentDimensionPresets) > 0) {
             $mergedContentDimensions = array();
             foreach ($contentDimensionPresets as $contentDimensionIdentifier => $contentDimension) {
                 $mergedContentDimensions[$contentDimensionIdentifier] = array($contentDimension['default']);
                 foreach ($contentDimension['presets'] as $contentDimensionPreset) {
                     $mergedContentDimensions[$contentDimensionIdentifier] = array_merge($mergedContentDimensions[$contentDimensionIdentifier], $contentDimensionPreset['values']);
                 }
                 $mergedContentDimensions[$contentDimensionIdentifier] = array_values(array_unique($mergedContentDimensions[$contentDimensionIdentifier]));
             }
             $contextProperties['dimensions'] = $mergedContentDimensions;
         }
         /** @var ContentContext $liveContext */
         $liveContext = $this->contextFactory->create($contextProperties);
         $firstActiveDomain = $site->getFirstActiveDomain();
         $nodes = $this->nodeSearchService->findByProperties($searchWord, $nodeTypes, $liveContext, $liveContext->getCurrentSiteNode());
         if (count($nodes) > 0) {
             $sites[$site->getNodeName()] = array('site' => $site, 'domain' => $firstActiveDomain ? $firstActiveDomain->getHostPattern() : $this->request->getHttpRequest()->getUri()->getHost(), 'nodes' => $nodes);
         }
     }
     $this->view->assignMultiple(array('searchWord' => $searchWord, 'protocol' => $this->request->getHttpRequest()->getUri()->getScheme(), 'selectedSite' => $selectedSite, 'sites' => $sites, 'activeSites' => $activeSites));
 }
 /**
  * Generates a Context that exactly fits the given NodeData Workspace, Dimensions & Site.
  *
  * @param NodeData $nodeData
  * @return ContentContext
  */
 protected function createContextMatchingNodeData(NodeData $nodeData)
 {
     $nodePath = NodePaths::getRelativePathBetween(SiteService::SITES_ROOT_PATH, $nodeData->getPath());
     list($siteNodeName) = explode('/', $nodePath);
     $site = $this->siteRepository->findOneByNodeName($siteNodeName);
     $contextProperties = ['workspaceName' => $nodeData->getWorkspace()->getName(), 'invisibleContentShown' => true, 'inaccessibleContentShown' => true, 'removedContentShown' => true, 'dimensions' => $nodeData->getDimensionValues(), 'currentSite' => $site];
     if ($domain = $site->getFirstActiveDomain()) {
         $contextProperties['currentDomain'] = $domain;
     }
     return $this->_contextFactory->create($contextProperties);
 }
 /**
  * Retrieves the given node's corresponding node in the base workspace (that is, which would be overwritten if the
  * given node would be published)
  *
  * @param NodeInterface $modifiedNode
  * @return NodeInterface
  */
 protected function getOriginalNode(NodeInterface $modifiedNode)
 {
     $baseWorkspaceName = $modifiedNode->getWorkspace()->getBaseWorkspace()->getName();
     $contextProperties = $modifiedNode->getContext()->getProperties();
     $contextProperties['workspaceName'] = $baseWorkspaceName;
     $contentContext = $this->contextFactory->create($contextProperties);
     return $contentContext->getNodeByIdentifier($modifiedNode->getIdentifier());
 }
 /**
  * Create a ContentContext based on the given workspace name
  *
  * @param string $workspaceName Name of the workspace to set for the context
  * @param array $dimensions Optional list of dimensions and their values which should be set
  * @return \TYPO3\Neos\Domain\Service\ContentContext
  */
 protected function createContentContext($workspaceName, array $dimensions = array())
 {
     $contextProperties = array('workspaceName' => $workspaceName, 'invisibleContentShown' => true, 'inaccessibleContentShown' => true);
     if ($dimensions !== array()) {
         $contextProperties['dimensions'] = $dimensions;
         $contextProperties['targetDimensions'] = array_map(function ($dimensionValues) {
             return array_shift($dimensionValues);
         }, $dimensions);
     }
     $currentDomain = $this->_domainRepository->findOneByActiveRequest();
     if ($currentDomain !== null) {
         $contextProperties['currentSite'] = $currentDomain->getSite();
         $contextProperties['currentDomain'] = $currentDomain;
     } else {
         $contextProperties['currentSite'] = $this->_siteRepository->findFirstOnline();
     }
     return $this->_contextFactory->create($contextProperties);
 }
 /**
  * @param boolean $force
  * @return ContentContext
  */
 protected function getContentContext($force = false)
 {
     if ($force) {
         $currentContext = $this->contentContextContainer->getContentContext();
         return $this->contentContextFactory->create(['invisibleContentShown' => true, 'inaccessibleContentShown' => true, 'currentDomain' => $currentContext->getCurrentDomain(), 'currentSite' => $currentContext->getCurrentSite()]);
     } else {
         return $this->contentContextContainer->getContentContext();
     }
 }
 /**
  * Sets context properties like "invisibleContentShown" according to the workspace (live or not) and returns a
  * ContentContext object.
  *
  * @param string $workspaceName Name of the workspace to use in the context
  * @param array $dimensionsAndDimensionValues An array of dimension names (index) and their values (array of strings). See also: ContextFactory
  * @return ContentContext
  */
 protected function buildContextFromWorkspaceNameAndDimensions($workspaceName, array $dimensionsAndDimensionValues)
 {
     $contextProperties = array('workspaceName' => $workspaceName, 'invisibleContentShown' => $workspaceName !== 'live', 'inaccessibleContentShown' => $workspaceName !== 'live', 'dimensions' => $dimensionsAndDimensionValues);
     $currentDomain = $this->domainRepository->findOneByActiveRequest();
     if ($currentDomain !== NULL) {
         $contextProperties['currentSite'] = $currentDomain->getSite();
         $contextProperties['currentDomain'] = $currentDomain;
     } else {
         $contextProperties['currentSite'] = $this->siteRepository->findFirstOnline();
     }
     return $this->contextFactory->create($contextProperties);
 }
 /**
  * Display a list of unpublished content
  *
  * @param Workspace $workspace
  * @return void
  * @todo Pagination
  * @todo Tree filtering + level limit
  * @todo Search field
  * @todo Difference mechanism
  */
 public function indexAction(Workspace $workspace = NULL)
 {
     if ($workspace === NULL) {
         $workspace = $this->userService->getUserWorkspace();
     }
     $sites = array();
     foreach ($this->publishingService->getUnpublishedNodes($workspace) as $node) {
         $pathParts = explode('/', $node->getPath());
         if (count($pathParts) > 2) {
             $siteNodeName = $pathParts[2];
             $q = new FlowQuery(array($node));
             $document = $q->closest('[instanceof TYPO3.Neos:Document]')->get(0);
             // FIXME: $document will be NULL if we have a broken rootline for this node. This actually should never happen, but currently can in some scenarios.
             if ($document !== NULL) {
                 $documentPath = implode('/', array_slice(explode('/', $document->getPath()), 3));
                 $relativePath = str_replace(sprintf('/sites/%s/%s', $siteNodeName, $documentPath), '', $node->getPath());
                 if (!isset($sites[$siteNodeName]['siteNode'])) {
                     $sites[$siteNodeName]['siteNode'] = $this->siteRepository->findOneByNodeName($siteNodeName);
                 }
                 $sites[$siteNodeName]['documents'][$documentPath]['documentNode'] = $document;
                 $change = array('node' => $node);
                 if ($node->getNodeType()->isOfType('TYPO3.Neos:Node')) {
                     $change['configuration'] = $node->getNodeType()->getFullConfiguration();
                 }
                 $sites[$siteNodeName]['documents'][$documentPath]['changes'][$relativePath] = $change;
             }
         }
     }
     $liveContext = $this->contextFactory->create(array('workspaceName' => 'live'));
     ksort($sites);
     foreach ($sites as $siteKey => $site) {
         foreach ($site['documents'] as $documentKey => $document) {
             foreach ($document['changes'] as $changeKey => $change) {
                 $liveNode = $liveContext->getNodeByIdentifier($change['node']->getIdentifier());
                 $sites[$siteKey]['documents'][$documentKey]['changes'][$changeKey]['isNew'] = is_null($liveNode);
                 $sites[$siteKey]['documents'][$documentKey]['changes'][$changeKey]['isMoved'] = $liveNode && $change['node']->getPath() !== $liveNode->getPath();
             }
         }
         ksort($sites[$siteKey]['documents']);
     }
     $workspaces = array();
     foreach ($this->workspaceRepository->findAll() as $workspaceInstance) {
         array_push($workspaces, array('workspaceNode' => $workspaceInstance, 'unpublishedNodesCount' => $this->publishingService->getUnpublishedNodesCount($workspaceInstance)));
     }
     $this->view->assignMultiple(array('workspace' => $workspace, 'workspaces' => $workspaces, 'sites' => $sites));
 }
 /**
  * Builds an array of changes for sites in the given workspace
  *
  * @param Workspace $selectedWorkspace
  * @return array
  */
 protected function computeSiteChanges(Workspace $selectedWorkspace)
 {
     $siteChanges = [];
     foreach ($this->publishingService->getUnpublishedNodes($selectedWorkspace) as $node) {
         /** @var NodeInterface $node */
         if (!$node->getNodeType()->isOfType('TYPO3.Neos:ContentCollection')) {
             $pathParts = explode('/', $node->getPath());
             if (count($pathParts) > 2) {
                 $siteNodeName = $pathParts[2];
                 $q = new FlowQuery([$node]);
                 $document = $q->closest('[instanceof TYPO3.Neos:Document]')->get(0);
                 // FIXME: $document will be null if we have a broken root line for this node. This actually should never happen, but currently can in some scenarios.
                 if ($document !== null) {
                     $documentPath = implode('/', array_slice(explode('/', $document->getPath()), 3));
                     $relativePath = str_replace(sprintf(SiteService::SITES_ROOT_PATH . '/%s/%s', $siteNodeName, $documentPath), '', $node->getPath());
                     if (!isset($siteChanges[$siteNodeName]['siteNode'])) {
                         $siteChanges[$siteNodeName]['siteNode'] = $this->siteRepository->findOneByNodeName($siteNodeName);
                     }
                     $siteChanges[$siteNodeName]['documents'][$documentPath]['documentNode'] = $document;
                     $change = ['node' => $node];
                     if ($node->getNodeType()->isOfType('TYPO3.Neos:Node')) {
                         $change['configuration'] = $node->getNodeType()->getFullConfiguration();
                     }
                     $siteChanges[$siteNodeName]['documents'][$documentPath]['changes'][$relativePath] = $change;
                 }
             }
         }
     }
     $liveContext = $this->contextFactory->create(['workspaceName' => 'live']);
     ksort($siteChanges);
     foreach ($siteChanges as $siteKey => $site) {
         foreach ($site['documents'] as $documentKey => $document) {
             foreach ($document['changes'] as $changeKey => $change) {
                 $liveNode = $liveContext->getNodeByIdentifier($change['node']->getIdentifier());
                 $siteChanges[$siteKey]['documents'][$documentKey]['changes'][$changeKey]['isNew'] = is_null($liveNode);
                 $siteChanges[$siteKey]['documents'][$documentKey]['changes'][$changeKey]['isMoved'] = $liveNode && $change['node']->getPath() !== $liveNode->getPath();
             }
         }
         ksort($siteChanges[$siteKey]['documents']);
     }
     return $siteChanges;
 }
 /**
  * Sets context properties like "invisibleContentShown" according to the workspace (live or not) and returns a
  * ContentContext object.
  *
  * @param string $workspaceName Name of the workspace to use in the context
  * @param array $dimensionsAndDimensionValues An array of dimension names (index) and their values (array of strings). See also: ContextFactory
  * @return ContentContext
  */
 protected function buildContextFromWorkspaceNameAndDimensions($workspaceName, array $dimensionsAndDimensionValues)
 {
     $contextProperties = ['workspaceName' => $workspaceName, 'invisibleContentShown' => $workspaceName !== 'live', 'inaccessibleContentShown' => $workspaceName !== 'live', 'dimensions' => $dimensionsAndDimensionValues];
     return $this->contextFactory->create($contextProperties);
 }