Skip to content

Instantly share code, notes, and snippets.

@dimaip
Last active August 29, 2015 14:05
Show Gist options
  • Select an option

  • Save dimaip/4f5c608fd15251cc77d7 to your computer and use it in GitHub Desktop.

Select an option

Save dimaip/4f5c608fd15251cc77d7 to your computer and use it in GitHub Desktop.
<?php
namespace TYPO3\Neos\Service;
/* *
* This script belongs to the TYPO3 Flow package "TYPO3.Neos". *
* *
* It is free software; you can redistribute it and/or modify it under *
* the terms of the GNU General Public License, either version 3 of the *
* License, or (at your option) any later version. *
* *
* The TYPO3 project - inspiring people to share! *
* */
use TYPO3\Flow\Annotations as Flow;
use TYPO3\Flow\Property\PropertyMapper;
use TYPO3\Neos\Exception as NeosException;
use TYPO3\TYPO3CR\Domain\Model\NodeInterface;
use TYPO3\TypoScript\Exception as TypoScriptException;
/**
* A service for creating URIs pointing to nodes.
*
* 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``.
*
*/
class NodeLinkingService {
/**
* @Flow\Inject
* @var PropertyMapper
*/
protected $propertyMapper;
/**
* Render the Uri.
*
* @param mixed $node A TYPO3\TYPO3CR\Domain\Model\NodeInterface object or a string node path or NULL to resolve the current document node
* @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 string $baseNodeName The name of the base node inside the TypoScript context to use for the ContentContext or resolving relative paths
* @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 object $currentContext
* @param object $controllerContext
* @throws \TYPO3\Neos\Exception
* @throws \InvalidArgumentException
* @return string The rendered URI or NULL if no URI could be resolved for the given node
*/
public function createNodeUri($node = NULL, $format = NULL, $absolute = FALSE, $baseNodeName = 'documentNode', array $arguments = array(), $section = '', $addQueryString = FALSE, array $argumentsToBeExcludedFromQueryString = array(), $currentContext, $controllerContext) {
if (!($node === NULL || $node instanceof NodeInterface || is_string($node))) {
throw new \InvalidArgumentException('Expected NodeInterface, string or NULL for the node argument', 1373101025);
}
if (is_string($node)) {
preg_match(NodeInterface::MATCH_PATTERN_CONTEXTPATH, $node, $matches);
if (isset($matches['WorkspaceName']) && $matches['WorkspaceName'] !== '') {
$node = $this->propertyMapper->convert($node, 'TYPO3\TYPO3CR\Domain\Model\NodeInterface');
}
}
if ($node === NULL || is_string($node)) {
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);
}
if (is_string($node)) {
$contentContext = $baseNode->getContext();
if (substr($node, 0, 2) === '~/') {
$node = $contentContext->getCurrentSiteNode()->getNode(substr($node, 2));
} else {
if (substr($node, 0, 1) === '/') {
$node = $contentContext->getNode($node);
} else {
$node = $baseNode->getNode($node);
}
}
} else {
$node = $baseNode;
}
}
if (!$node instanceof NodeInterface) {
return NULL;
}
$request = $controllerContext->getRequest()->getMainRequest();
if ($format === NULL) {
$format = $request->getFormat();
}
$uriBuilder = clone $controllerContext->getUriBuilder();
$uriBuilder->setRequest($request);
return $uriBuilder
->reset()
->setSection($section)
->setCreateAbsoluteUri($absolute)
->setArguments($arguments)
->setAddQueryString($addQueryString)
->setArgumentsToBeExcludedFromQueryString($argumentsToBeExcludedFromQueryString)
->setFormat($format)
->uriFor('show', array('node' => $node), 'Frontend\Node', 'TYPO3.Neos');
}
}
<?php
namespace TYPO3\Neos\TypoScript;
/* *
* This script belongs to the TYPO3 Flow package "TYPO3.TypoScript". *
* *
* It is free software; you can redistribute it and/or modify it under *
* the terms of the GNU General Public License, either version 3 of the *
* License, or (at your option) any later version. *
* *
* The TYPO3 project - inspiring people to share! *
* */
use TYPO3\Flow\Annotations as Flow;
use TYPO3\TypoScript\TypoScriptObjects\AbstractTypoScriptObject;
/**
* Create link to given node
*/
class NodeUriImplementation extends AbstractTypoScriptObject {
/**
* @Flow\Inject
* @var TYPO3\Neos\Service\NodeLinkingService
*/
protected $nodeLinkingService;
/**
* A TYPO3\TYPO3CR\Domain\Model\NodeInterface object or a string node path or NULL to resolve the current document node
*
* @return mixed
*/
public function getNode() {
return $this->tsValue('node');
}
/**
* Controller arguments
*
* @return array
*/
public function getArguments() {
return $this->tsValue('arguments');
}
/**
* The requested format, for example "html"
*
* @return string
*/
public function getFormat() {
return $this->tsValue('format');
}
/**
* The anchor to be appended to the URL
*
* @return string
*/
public function getSection() {
return $this->tsValue('section');
}
/**
* Additional query parameters that won't be prefixed like $arguments (overrule $arguments)
*
* @return array
*/
public function getAdditionalParams() {
return $this->tsValue('additionalParams');
}
/**
* Arguments to be removed from the URI. Only active if addQueryString = TRUE
*
* @return array
*/
public function getArgumentsToBeExcludedFromQueryString() {
return $this->tsValue('argumentsToBeExcludedFromQueryString');
}
/**
* If TRUE, the current query parameters will be kept in the URI
*
* @return boolean
*/
public function isAddQueryString() {
return (boolean)$this->tsValue('addQueryString');
}
/**
* If TRUE, an absolute URI is rendered
*
* @return boolean
*/
public function isAbsolute() {
return (boolean)$this->tsValue('absolute');
}
/**
* The name of the base node inside the TypoScript context to use for the
* ContentContext or resolving relative paths
*
* @return string
*/
public function getBaseNodeName() {
return $this->tsValue('baseNodeName');
}
/**
* Render the Uri.
*
* @throws \TYPO3\Neos\Exception
* @throws \InvalidArgumentException
* @return string The rendered URI or NULL if no URI could be resolved for the given node
*/
public function evaluate() {
$baseNodeName = $this->getBaseNodeName();
if(!$baseNodeName){
$baseNodeName = 'documentNode';
}
try {
return $this->nodeLinkingService->createNodeUri(
$this->getNode(),
$this->getFormat(),
$this->isAbsolute(),
$baseNodeName,
$this->getAdditionalParams(),
$this->getSection(),
$this->isAddQueryString(),
$this->getArgumentsToBeExcludedFromQueryString(),
$this->tsRuntime->getCurrentContext(),
$this->tsRuntime->getControllerContext()
);
} catch(\Exception $exception) {
return $this->tsRuntime->handleRenderingException($this->path, $exception);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment