Skip to content

Instantly share code, notes, and snippets.

@Sebobo
Last active February 21, 2018 11:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sebobo/7b12f8e46778321f7b1b02d4b9aaad85 to your computer and use it in GitHub Desktop.
Save Sebobo/7b12f8e46778321f7b1b02d4b9aaad85 to your computer and use it in GitHub Desktop.
Modified node route part handler for Neos 2.* for hiding url path segments of specific pages in the frontend url generation
<?php
namespace Vendor\Package\Routing;
use TYPO3\Flow\Annotations as Flow;
use TYPO3\Neos\Domain\Service\SiteService;
use TYPO3\TYPO3CR\Domain\Model\NodeInterface;
use TYPO3\Neos\Routing\Exception as Exception;
/**
* A route part handler for finding nodes specifically in the website's frontend.
*/
class FrontendNodeRoutePartHandler extends \TYPO3\Neos\Routing\FrontendNodeRoutePartHandler
{
/**
* @param string $requestPath
* @return string
*/
protected function getWorkspaceName($requestPath)
{
$contextPathParts = array();
if ($requestPath !== '' && strpos($requestPath, '@') !== false) {
preg_match(NodeInterface::MATCH_PATTERN_CONTEXTPATH, $requestPath, $contextPathParts);
}
return isset($contextPathParts['WorkspaceName']) && $contextPathParts['WorkspaceName'] !== '' ? $contextPathParts['WorkspaceName'] : 'live';
}
/**
* @inheritdoc
*/
protected function getRelativeNodePathByUriPathSegmentProperties(NodeInterface $siteNode, $relativeRequestPath)
{
/** @var NodeInterface $node */
$node = $siteNode;
$relativeNodePathSegments = array();
$workspaceName = $this->getWorkspaceName($relativeRequestPath);
foreach (explode('/', $relativeRequestPath) as $pathSegment) {
$node = $this->findNextNodeWithPathSegmentRecursively($node, $pathSegment, $relativeNodePathSegments,
$workspaceName);
if ($node === null) {
return false;
}
}
return implode('/', $relativeNodePathSegments);
}
/**
* @param NodeInterface $startingNode
* @param string $pathSegment
* @param array $relativeNodePathSegments
* @param string $workspaceName
* @return NodeInterface
*/
protected function findNextNodeWithPathSegmentRecursively(
NodeInterface $startingNode,
$pathSegment,
&$relativeNodePathSegments,
$workspaceName
) {
/** @var NodeInterface $node */
foreach ($startingNode->getChildNodes('TYPO3.Neos:Document') as $node) {
if ($workspaceName == 'live' && $node->hasProperty('hideSegmentInUriPath') && $node->getProperty('hideSegmentInUriPath') == true) {
$foundNode = $this->findNextNodeWithPathSegmentRecursively($node, $pathSegment,
$relativeNodePathSegments, $workspaceName);
if ($foundNode !== null) {
array_unshift($relativeNodePathSegments, $node->getName());
return $foundNode;
}
}
if ($node->getProperty('uriPathSegment') === $pathSegment) {
$relativeNodePathSegments[] = $node->getName();
return $node;
}
}
return null;
}
/**
* @inheritdoc
*/
protected function getRequestPathByNode(NodeInterface $node)
{
if ($node->getParentPath() === SiteService::SITES_ROOT_PATH) {
return '';
}
$startingNode = $node;
$workspaceName = $node->getContext()->getWorkspaceName();
if ($workspaceName !== 'live') {
return parent::getRequestPathByNode($node);
}
$requestPathSegments = array();
while ($node->getParentPath() !== SiteService::SITES_ROOT_PATH && $node instanceof NodeInterface) {
if (!$node->hasProperty('uriPathSegment')) {
throw new Exception\MissingNodePropertyException(sprintf('Missing "uriPathSegment" property for node "%s". Nodes can be migrated with the "flow node:repair" command.',
$node->getPath()), 1415020326);
}
if ($startingNode === $node || !$node->hasProperty('hideSegmentInUriPath') || !$node->getProperty('hideSegmentInUriPath') == true) {
$pathSegment = $node->getProperty('uriPathSegment');
$requestPathSegments[] = $pathSegment;
}
$node = $node->getParent();
if ($node === null || !$node->isVisible()) {
return '';
}
}
return implode('/', array_reverse($requestPathSegments));
}
}
'Vendor.Package:HideSegmentMixin':
abstract: true
properties:
hideSegmentInUriPath:
type: boolean
ui:
label: 'Hide page url segment in URLs'
inspector:
group: 'redirect'
TYPO3\Neos\Routing\FrontendNodeRoutePartHandlerInterface:
className: Vendor\Package\Routing\FrontendNodeRoutePartHandler
@Sebobo
Copy link
Author

Sebobo commented Jan 29, 2018

This handler is for Neos 2.* but can be upgraded to work with Neos 3.*.

The script allows to hide the path segment of pages in the creation of urls.
This is only happening in the frontend. So it shouldn't be possible to break the backend when doing a mistake with this functionality.

Of course if you create two pages with the same segment with two different parent pages which use this function, Neos will show the first page if you try to access it in the frontend!

@breadlesscode
Copy link

breadlesscode commented Feb 21, 2018

Thanks for this nice gist!

I made a package of this feature: https://github.com/breadlesscode/neos-nodetypes-folder

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment