/**
  * @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;
 }
 /**
  * Get array of node selection properties
  *
  *
  *
  * @param Node $node
  * @return array
  */
 public function prepareNodeSelectionFromNode(Node $node)
 {
     foreach ($this->contentContextFactory->getInstances() as $context) {
         $this->workspace = $context->getWorkspace();
         break;
     }
     $limit = false;
     $limit_param_name = false;
     $offset = false;
     $offset_param_name = false;
     $filter = array();
     $sort = array();
     $nodetype = false;
     $nodetypeisabstract = false;
     $entryNodes = array();
     $nodeParentPath = $node->getParentPath();
     if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')) {
         // calculate nodetype name
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('nodeType', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['nodeType'] as $key => $value) {
                 switch ($key) {
                     case 'property':
                         if ($node->getProperty($value)) {
                             $nodetype = $node->getProperty($value);
                         }
                         break;
                     case 'value':
                         $nodetype = $value;
                         break;
                     case 'param':
                         if ($this->httpRequest->hasArgument($value) || $nodetype == false) {
                             $nodetype = addslashes($this->httpRequest->getArgument($value));
                         }
                         break;
                     case 'abstract':
                         $nodetypeisabstract = TRUE;
                         break;
                     default:
                         break;
                 }
             }
         } else {
             throw new IndexedNodesException($node->getNodeData()->getNodeType()->getName() . ' has no nodeType definition.');
         }
         // calculate limit
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('limit', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['limit'] as $key => $value) {
                 switch ($key) {
                     case 'property':
                         if ($node->getProperty($value)) {
                             $limit = $node->getProperty($value);
                         }
                         break;
                     case 'value':
                         $limit = $value;
                         break;
                     case 'param':
                         if ($this->httpRequest->hasArgument($value) || $limit == false) {
                             $limit = addslashes($this->httpRequest->getArgument($value));
                         }
                         $limit_param_name = $value;
                         if (strlen($limit) == 0) {
                             $limit = false;
                         }
                         break;
                     default:
                         break;
                 }
             }
         }
         if (!$limit) {
             // fetch default limit from internal params
             $value = "_limit-" . $node->getIdentifier();
             if ($this->httpRequest->hasArgument($value)) {
                 $limit = addslashes($this->httpRequest->getArgument($value));
             }
             if (!$limit_param_name) {
                 $limit_param_name = $value;
             }
         }
         // calculate limit offset, if limit isset
         if ($limit && $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('offset', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['offset'] as $key => $value) {
                 switch ($key) {
                     case 'property':
                         if ($node->getProperty($value)) {
                             $offset = $node->getProperty($value);
                         }
                         break;
                     case 'value':
                         $offset = $value;
                         break;
                     case 'param':
                         if ($this->httpRequest->hasArgument($value) || $offset == false) {
                             $offset = addslashes($this->httpRequest->getArgument($value));
                         }
                         $offset_param_name = $value;
                         if (strlen($offset) == 0) {
                             $offset = false;
                         }
                         break;
                     default:
                         break;
                 }
             }
         }
         if (!$offset) {
             // fetch default offset from internal params
             $value = "_offset-" . $node->getIdentifier();
             if ($this->httpRequest->hasArgument($value)) {
                 $offset = addslashes($this->httpRequest->getArgument($value));
             }
             if (!$offset_param_name) {
                 $offset_param_name = $value;
             }
             if (strlen($offset) == 0) {
                 $offset = 0;
             }
         }
         // calculate filters
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['filter']) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['filter'] as $property => $arguments) {
                 foreach ($arguments as $arg => $filterValues) {
                     switch ($arg) {
                         case 'type':
                             $filter[$property]['type'] = $filterValues;
                             break;
                         case 'operand':
                             foreach ($filterValues as $key => $value) {
                                 switch ($key) {
                                     case 'property':
                                         if ($node->getProperty($value)) {
                                             $filter[$property]['operand'] = $node->getProperty($value);
                                         }
                                         break;
                                     case 'value':
                                         $filter[$property]['operand'] = $value;
                                         break;
                                     case 'param':
                                         if ($this->httpRequest->hasArgument($value) || isset($filter[$property]['operand']) == false) {
                                             $filter[$property]['operand'] = addslashes($this->httpRequest->getArgument($value));
                                         }
                                         break;
                                     default:
                                         break;
                                 }
                             }
                             break;
                         case 'operator':
                             foreach ($filterValues as $key => $value) {
                                 switch ($key) {
                                     case 'property':
                                         if ($node->getProperty($value)) {
                                             $filter[$property]['operator'] = $node->getProperty($value);
                                         }
                                         break;
                                     case 'value':
                                         $filter[$property]['operator'] = $value;
                                         break;
                                     case 'param':
                                         if ($this->httpRequest->hasArgument($value) || isset($filter[$property]['operator']) == false) {
                                             $filter[$property]['operator'] = addslashes($this->httpRequest->getArgument($value));
                                         }
                                         break;
                                     default:
                                         break;
                                 }
                             }
                             break;
                     }
                 }
                 if (isset($filter[$property]['type']) == false) {
                     $targetNodeType = $this->nodeTypeManager->getNodeType($nodetype);
                     // get sorting type by property definition
                     if (isset($targetNodeType->getConfiguration('properties')['text'])) {
                         $filter[$property]['type'] = $targetNodeType->getConfiguration('properties')['text']['type'];
                     } else {
                         $filter[$property]['type'] = 'string';
                     }
                 }
             }
         }
         // calculate entry nodes
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('entryNodes', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['entryNodes'] as $property => $filterValues) {
                 foreach ($filterValues as $key => $value) {
                     switch ($key) {
                         case 'property':
                             if ($node->getProperty($value)) {
                                 $entryNodes[$property]['value'] = $node->getProperty($value);
                             }
                             break;
                         case 'value':
                             $entryNodes[$property]['value'] = $value;
                             break;
                         case 'param':
                             if ($this->httpRequest->hasArgument($value) || isset($entryNodes[$property]['value']) == false) {
                                 $entryNodes[$property]['value'] = addslashes($this->httpRequest->getArgument($value));
                             }
                             break;
                         case 'recursive':
                             $entryNodes[$property]['recursive'] = $value;
                             break;
                         case 'childNodePath':
                             $entryNodes[$property]['childNodePath'] = $value;
                             break;
                     }
                     if (isset($entryNodes[$property]['recursive']) == false) {
                         $entryNodes[$property]['recursive'] = TRUE;
                     }
                     if (isset($entryNodes[$property]['childNodePath']) == false) {
                         $entryNodes[$property]['childNodePath'] = FALSE;
                     }
                     if (isset($entryNodes[$property]['value']) && is_array($entryNodes[$property]['value']) == false) {
                         $targetNode = $this->nodeDataRepository->findOneByIdentifier($entryNodes[$property]['value'], $this->workspace);
                         if ($targetNode) {
                             $entryNodes[$property]['path'] = $targetNode->getParentPath();
                         }
                     }
                 }
                 if (isset($entryNodes[$property]['value']) && is_array($entryNodes[$property]['value'])) {
                     $t = $entryNodes[$property];
                     unset($entryNodes[$property]);
                     foreach ($t['value'] as $key => $val) {
                         $entryNodes[$property . $key] = array('path' => $val->getPath(), 'childNodePath' => $t['childNodePath'], 'parentPath' => $val->getParentPath(), 'childNodes' => $val->getNodeType()->getChildNodes(), 'recursive' => $t['recursive']);
                     }
                 }
             }
         } else {
             // set reference to self node
             $entryNodes['self'] = array('path' => '/');
         }
         // calculate sorting
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('sort', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['sort'] as $nullkey => $sortValues) {
                 foreach ($sortValues as $key => $value) {
                     switch ($key) {
                         case 'property':
                             if ($node->getProperty($value)) {
                                 $sort[$property]['value'] = $node->getProperty($value);
                             }
                             break;
                         case 'value':
                             $sort[$property]['value'] = $value;
                             break;
                         case 'param':
                             if ($this->httpRequest->hasArgument($value) || isset($sort[$property]) == false) {
                                 $sort[$property]['value'] = addslashes($this->httpRequest->getArgument($value));
                             }
                             break;
                         case 'type':
                             $sort[$property]['type'] = $value;
                             break;
                         case 'direction':
                             foreach ($value as $k => $v) {
                                 switch ($k) {
                                     case 'property':
                                         if ($node->getProperty($v)) {
                                             $sort[$property]['direction'] = $node->getProperty($v);
                                         }
                                         break;
                                     case 'value':
                                         $sort[$property]['direction'] = $v;
                                         break;
                                     case 'param':
                                         if ($this->httpRequest->hasArgument($v) || isset($sort[$property]['direction']) == false) {
                                             $sort[$property]['direction'] = addslashes($this->httpRequest->getArgument($v));
                                         }
                                         break;
                                 }
                             }
                             break;
                         default:
                             break;
                     }
                     if (isset($sort[$property]['type']) == false) {
                         $targetNodeType = $this->nodeTypeManager->getNodeType($nodetype);
                         // get sorting type by property definition
                         if (isset($targetNodeType->getConfiguration('properties')['text'])) {
                             $sort[$property]['type'] = $targetNodeType->getConfiguration('properties')['text']['type'];
                         } else {
                             $sort[$property]['type'] = 'string';
                         }
                     }
                 }
             }
         }
     }
     return array('limit' => $limit, 'limit_param_name' => $limit_param_name, 'offset' => $offset, 'offset_param_name' => $offset_param_name, 'filter' => $filter, 'sort' => $sort, 'nodetype' => $nodetype, 'nodetypeisabstract' => $nodetypeisabstract, 'entryNodes' => $entryNodes, 'workspace' => $this->workspace);
 }
 /**
  * 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);
 }