The target node can be provided as string or as a Node object; if not specified
at all, the generated URI will refer to the current document node inside the TypoScript context.
When specifying the node argument as string, the following conventions apply:
*node starts with /:*
The given path is an absolute node path and is treated as such.
Example: /sites/acmecom/home/about/us
*node does not start with /:*
The given path is treated as a path relative to the current node.
Examples: given that the current node is /sites/acmecom/products/,
stapler results in /sites/acmecom/products/stapler,
../about results in /sites/acmecom/about/,
./neos/info results in /sites/acmecom/products/neos/info.
*node starts with a tilde character (~):*
The given path is treated as a path relative to the current site node.
Example: given that the current node is /sites/acmecom/products/,
~/about/us results in /sites/acmecom/about/us,
~ results in /sites/acmecom.
/** * Resolves a shortcut node to the target. The return value can be * * * a NodeInterface instance if the target is a node or a node:// URI * * a string (in case the target is a plain text URI or an asset:// URI) * * NULL in case the shortcut cannot be resolved * * @param NodeInterface $node * @return NodeInterface|string|NULL */ public function resolveShortcutTarget(NodeInterface $node) { $infiniteLoopPrevention = 0; while ($node->getNodeType()->isOfType('Neos.Neos:Shortcut') && $infiniteLoopPrevention < 50) { $infiniteLoopPrevention++; switch ($node->getProperty('targetMode')) { case 'selectedTarget': $target = $node->getProperty('target'); if ($this->linkingService->hasSupportedScheme($target)) { $targetObject = $this->linkingService->convertUriToObject($target, $node); if ($targetObject instanceof NodeInterface) { $node = $targetObject; } elseif ($targetObject instanceof AssetInterface) { return $this->linkingService->resolveAssetUri($target); } } else { return $target; } break; case 'parentNode': $node = $node->getParent(); break; case 'firstChildNode': default: $childNodes = $node->getChildNodes('Neos.Neos:Document'); if ($childNodes !== array()) { $node = reset($childNodes); } else { return null; } } } return $node; }
/** * Redirects to the Neos backend on the given site, passing a one-time login token * * @param Site $site * @return void */ public function switchSiteAction($site) { $token = Algorithms::generateRandomToken(32); $this->loginTokenCache->set($token, $this->currentSession->getId()); $siteUri = $this->linkingService->createSiteUri($this->controllerContext, $site); $loginUri = $this->controllerContext->getUriBuilder()->reset()->uriFor('tokenLogin', ['token' => $token], 'Login', 'Neos.Neos'); $this->redirectToUri($siteUri . $loginUri); }
/** * Render the Uri. * * @return string The rendered URI or NULL if no URI could be resolved for the given node * @throws NeosException */ public function evaluate() { $baseNode = null; $baseNodeName = $this->getBaseNodeName() ?: 'documentNode'; $currentContext = $this->tsRuntime->getCurrentContext(); if (isset($currentContext[$baseNodeName])) { $baseNode = $currentContext[$baseNodeName]; } else { throw new NeosException(sprintf('Could not find a node instance in TypoScript context with name "%s" and no node instance was given to the node argument. Set a node instance in the TypoScript context or pass a node object to resolve the URI.', $baseNodeName), 1373100400); } try { return $this->linkingService->createNodeUri($this->tsRuntime->getControllerContext(), $this->getNode(), $baseNode, $this->getFormat(), $this->isAbsolute(), $this->getAdditionalParams(), $this->getSection(), $this->getAddQueryString(), $this->getArgumentsToBeExcludedFromQueryString()); } catch (NeosException $exception) { $this->systemLogger->logException($exception); return ''; } }
/** * This test checks that targets for resource links are correctly replaced * * @test */ public function evaluateReplaceResourceLinkTargets() { $assetIdentifier = 'aeabe76a-551a-495f-a324-ad9a86b2aff8'; $resourceLinkTarget = '_blank'; $value = 'This string contains two asset links and an external link: one with a target set <a target="top" href="asset://' . $assetIdentifier . '">example</a> and one without a target <a href="asset://' . $assetIdentifier . '">example2</a> and an external link <a href="http://www.example.org">example3</a>'; $this->addValueExpectation($value, null, false, null, $resourceLinkTarget); $this->mockWorkspace->expects($this->any())->method('getName')->will($this->returnValue('live')); $self = $this; $this->mockLinkingService->expects($this->atLeastOnce())->method('resolveAssetUri')->will($this->returnCallback(function ($assetUri) use($self, $assetIdentifier) { if ($assetUri !== 'asset://' . $assetIdentifier) { $self->fail('Unexpected asset URI "' . $assetUri . '"'); } return 'http://localhost/_Resources/01'; })); $expectedResult = 'This string contains two asset links and an external link: one with a target set <a target="' . $resourceLinkTarget . '" href="http://localhost/_Resources/01">example</a> and one without a target <a target="' . $resourceLinkTarget . '" href="http://localhost/_Resources/01">example2</a> and an external link <a href="http://www.example.org">example3</a>'; $actualResult = $this->convertUrisImplementation->evaluate(); $this->assertSame($expectedResult, $actualResult); }
/** * Renders the URI. * * @param mixed $node A node object, a string node path (absolute or relative), a string node://-uri or NULL * @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 string $baseNodeName The name of the base node inside the TypoScript context to use for the ContentContext or resolving relative paths * @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 or NULL if no URI could be resolved for the given node * @throws ViewHelperException */ public function render($node = null, $format = null, $absolute = false, array $arguments = array(), $section = '', $addQueryString = false, array $argumentsToBeExcludedFromQueryString = array(), $baseNodeName = 'documentNode', $resolveShortcuts = true) { $baseNode = null; if (!$node instanceof NodeInterface) { $baseNode = $this->getContextVariable($baseNodeName); if (is_string($node) && substr($node, 0, 7) === 'node://') { $node = $this->linkingService->convertUriToObject($node, $baseNode); } } try { return $this->linkingService->createNodeUri($this->controllerContext, $node, $baseNode, $format, $absolute, $arguments, $section, $addQueryString, $argumentsToBeExcludedFromQueryString, $resolveShortcuts); } catch (NeosException $exception) { $this->systemLogger->logException($exception); } catch (NoMatchingRouteException $exception) { $this->systemLogger->logException($exception); } return ''; }
/** * @param string|Uri $uri * @param NodeInterface $contextNode * @return NodeInterface|AssetInterface|NULL */ public function convertUriToObject($uri, NodeInterface $contextNode = null) { return $this->linkingService->convertUriToObject($uri, $contextNode); }
/** * Renders the link. Renders the linked node's label if there's no child content. * * @param mixed $node A node object, a string node path (absolute or relative), a string node://-uri or NULL * @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 The anchor to be added to the URI * @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 string $nodeVariableName The variable the node will be assigned to for the rendered child content * @param string $baseNodeName The name of the base node inside the TypoScript context to use for the ContentContext or resolving relative paths * @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 link * @throws ViewHelperException */ public function render($node = null, $format = null, $absolute = false, array $arguments = array(), $section = '', $addQueryString = false, array $argumentsToBeExcludedFromQueryString = array(), $baseNodeName = 'documentNode', $nodeVariableName = 'linkedNode', $resolveShortcuts = true) { $baseNode = null; if (!$node instanceof NodeInterface) { $baseNode = $this->getContextVariable($baseNodeName); if (is_string($node) && substr($node, 0, 7) === 'node://') { $node = $this->linkingService->convertUriToObject($node, $baseNode); } } try { $uri = $this->linkingService->createNodeUri($this->controllerContext, $node, $baseNode, $format, $absolute, $arguments, $section, $addQueryString, $argumentsToBeExcludedFromQueryString, $resolveShortcuts); $this->tag->addAttribute('href', $uri); } catch (NeosException $exception) { $this->systemLogger->logException($exception); } catch (NoMatchingRouteException $exception) { $this->systemLogger->logException($exception); } $linkedNode = $this->linkingService->getLastLinkedNode(); $this->templateVariableContainer->add($nodeVariableName, $linkedNode); $content = $this->renderChildren(); $this->templateVariableContainer->remove($nodeVariableName); if ($content === null && $linkedNode !== null) { $content = $linkedNode->getLabel(); } $this->tag->setContent($content); $this->tag->forceClosingTag(true); return $this->tag->render(); }