/** * 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); }
/** * Moves the given variant or child node to the destination defined by the given path which is * the new path for the originally moved (parent|variant) node * * @param string $aggregateOriginalPath * @param string $aggregateDestinationPath * @param NodeInterface $nodeToMove * @return array NodeVariant and old and new path */ protected function moveVariantOrChild($aggregateOriginalPath, $aggregateDestinationPath, NodeInterface $nodeToMove = null) { if ($nodeToMove === null) { return null; } $variantOriginalPath = $nodeToMove->getPath(); $relativePathSegment = NodePaths::getRelativePathBetween($aggregateOriginalPath, $variantOriginalPath); $variantDestinationPath = NodePaths::addNodePathSegment($aggregateDestinationPath, $relativePathSegment); $this->moveNodeToDestinationPath($nodeToMove, $variantDestinationPath); return [$nodeToMove, $variantOriginalPath, $nodeToMove->getPath()]; }
/** * Finds all nodes of the specified workspace lying on the path specified by * (and including) the given starting point and end point and (optionally) a node type filter. * * If some node does not exist in the specified workspace, this function will * try to find a corresponding node in one of the base workspaces (if any). * * @param string $pathStartingPoint Absolute path specifying the starting point * @param string $pathEndPoint Absolute path specifying the end point * @param Workspace $workspace The containing workspace * @param array $dimensions Array of dimensions to array of dimension values * @param boolean $includeRemovedNodes Should removed nodes be included in the result (defaults to FALSE) * @param string $nodeTypeFilter Optional filter for the node type of the nodes, supports complex expressions (e.g. "Neos.Neos:Page", "!Neos.Neos:Page,Neos.Neos:Text" or NULL) * @throws \InvalidArgumentException * @return array<\Neos\ContentRepository\Domain\Model\NodeData> The nodes found on the given path * @todo findOnPath should probably not return child nodes of removed nodes unless removed nodes are included. */ public function findOnPath($pathStartingPoint, $pathEndPoint, Workspace $workspace, array $dimensions = null, $includeRemovedNodes = false, $nodeTypeFilter = null) { $pathStartingPoint = strtolower($pathStartingPoint); $pathEndPoint = strtolower($pathEndPoint); if (NodePaths::isSubPathOf($pathStartingPoint, $pathEndPoint) === false) { throw new \InvalidArgumentException('Invalid paths: path of starting point must be first part of end point path.', 1284391181); } $workspaces = $this->collectWorkspaceAndAllBaseWorkspaces($workspace); $queryBuilder = $this->createQueryBuilder($workspaces); if ($dimensions !== null) { $this->addDimensionJoinConstraintsToQueryBuilder($queryBuilder, $dimensions); } else { $dimensions = []; } if ($nodeTypeFilter !== null) { $this->addNodeTypeFilterConstraintsToQueryBuilder($queryBuilder, $nodeTypeFilter); } $pathConstraints = []; $constraintPath = $pathStartingPoint; $pathConstraints[] = md5($constraintPath); $pathSegments = explode('/', NodePaths::getRelativePathBetween($pathStartingPoint, $pathEndPoint)); foreach ($pathSegments as $pathSegment) { $constraintPath = NodePaths::addNodePathSegment($constraintPath, $pathSegment); $pathConstraints[] = md5($constraintPath); } if (count($pathConstraints) > 0) { $queryBuilder->andWhere('n.pathHash IN (:paths)')->setParameter('paths', $pathConstraints); } $query = $queryBuilder->getQuery(); $foundNodes = $query->getResult(); $foundNodes = $this->reduceNodeVariantsByWorkspacesAndDimensions($foundNodes, $workspaces, $dimensions); $foundNodes = $this->filterNodeDataByBestMatchInContext($foundNodes, $workspaces[0], $dimensions, $includeRemovedNodes); if ($includeRemovedNodes === false) { $foundNodes = $this->filterRemovedNodes($foundNodes, false); } $nodesByDepth = []; /** @var NodeData $node */ foreach ($foundNodes as $node) { $nodesByDepth[$node->getDepth()] = $node; } ksort($nodesByDepth); return array_values($nodesByDepth); }
/** * Renders the URI to a given node instance or -path. * * @param ControllerContext $controllerContext * @param mixed $node A node object or a string node path, if a relative path is provided the baseNode argument is required * @param NodeInterface $baseNode * @param string $format Format to use for the URL, for example "html" or "json" * @param boolean $absolute If set, an absolute URI is rendered * @param array $arguments Additional arguments to be passed to the UriBuilder (for example pagination parameters) * @param string $section * @param boolean $addQueryString If set, the current query parameters will be kept in the URI * @param array $argumentsToBeExcludedFromQueryString arguments to be removed from the URI. Only active if $addQueryString = TRUE * @param boolean $resolveShortcuts INTERNAL Parameter - if FALSE, shortcuts are not redirected to their target. Only needed on rare backend occasions when we want to link to the shortcut itself. * @return string The rendered URI * @throws \InvalidArgumentException if the given node/baseNode is not valid * @throws NeosException if no URI could be resolved for the given node */ public function createNodeUri(ControllerContext $controllerContext, $node = null, NodeInterface $baseNode = null, $format = null, $absolute = false, array $arguments = array(), $section = '', $addQueryString = false, array $argumentsToBeExcludedFromQueryString = array(), $resolveShortcuts = true) { $this->lastLinkedNode = null; if (!($node instanceof NodeInterface || is_string($node) || $baseNode instanceof NodeInterface)) { throw new \InvalidArgumentException('Expected an instance of NodeInterface or a string for the node argument, or alternatively a baseNode argument.', 1373101025); } if (is_string($node)) { $nodeString = $node; if ($nodeString === '') { throw new NeosException(sprintf('Empty strings can not be resolved to nodes.', $nodeString), 1415709942); } preg_match(NodeInterface::MATCH_PATTERN_CONTEXTPATH, $nodeString, $matches); if (isset($matches['WorkspaceName']) && $matches['WorkspaceName'] !== '') { $node = $this->propertyMapper->convert($nodeString, NodeInterface::class); } else { if ($baseNode === null) { throw new NeosException('The baseNode argument is required for linking to nodes with a relative path.', 1407879905); } /** @var ContentContext $contentContext */ $contentContext = $baseNode->getContext(); $normalizedPath = $this->nodeService->normalizePath($nodeString, $baseNode->getPath(), $contentContext->getCurrentSiteNode()->getPath()); $node = $contentContext->getNode($normalizedPath); } if (!$node instanceof NodeInterface) { throw new NeosException(sprintf('The string "%s" could not be resolved to an existing node.', $nodeString), 1415709674); } } elseif (!$node instanceof NodeInterface) { $node = $baseNode; } if (!$node instanceof NodeInterface) { throw new NeosException(sprintf('Node must be an instance of NodeInterface or string, given "%s".', gettype($node)), 1414772029); } $this->lastLinkedNode = $node; if ($resolveShortcuts === true) { $resolvedNode = $this->nodeShortcutResolver->resolveShortcutTarget($node); } else { // this case is only relevant in extremely rare occasions in the Neos Backend, when we want to generate // a link towards the *shortcut itself*, and not to its target. $resolvedNode = $node; } if (is_string($resolvedNode)) { return $resolvedNode; } if (!$resolvedNode instanceof NodeInterface) { throw new NeosException(sprintf('Could not resolve shortcut target for node "%s"', $node->getPath()), 1414771137); } /** @var ActionRequest $request */ $request = $controllerContext->getRequest()->getMainRequest(); $uriBuilder = clone $controllerContext->getUriBuilder(); $uriBuilder->setRequest($request); $uri = $uriBuilder->reset()->setSection($section)->setArguments($arguments)->setAddQueryString($addQueryString)->setArgumentsToBeExcludedFromQueryString($argumentsToBeExcludedFromQueryString)->setFormat($format ?: $request->getFormat())->uriFor('show', array('node' => $resolvedNode), 'Frontend\\Node', 'Neos.Neos'); $siteNode = $resolvedNode->getContext()->getCurrentSiteNode(); if (NodePaths::isSubPathOf($siteNode->getPath(), $resolvedNode->getPath())) { /** @var Site $site */ $site = $resolvedNode->getContext()->getCurrentSite(); } else { $nodePath = NodePaths::getRelativePathBetween(SiteService::SITES_ROOT_PATH, $resolvedNode->getPath()); list($siteNodeName) = explode('/', $nodePath); $site = $this->siteRepository->findOneByNodeName($siteNodeName); } if ($site->hasActiveDomains()) { $requestUriHost = $request->getHttpRequest()->getBaseUri()->getHost(); $activeHostPatterns = $site->getActiveDomains()->map(function ($domain) { return $domain->getHostPattern(); })->toArray(); if (!in_array($requestUriHost, $activeHostPatterns, true)) { $uri = $this->createSiteUri($controllerContext, $site) . '/' . ltrim($uri, '/'); } elseif ($absolute === true) { $uri = $request->getHttpRequest()->getBaseUri() . ltrim($uri, '/'); } } elseif ($absolute === true) { $uri = $request->getHttpRequest()->getBaseUri() . ltrim($uri, '/'); } return $uri; }