/** * @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); }