Skip to content
This repository has been archived by the owner on Aug 28, 2020. It is now read-only.

Commit

Permalink
multi error page support added (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
Marvin Kuhn authored Dec 26, 2017
1 parent 044344d commit 85aa81d
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 23 deletions.
45 changes: 45 additions & 0 deletions Classes/Utility/PathUtility.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php
namespace Breadlesscode\ErrorPages\Utility;

class PathUtility
{
public static function cutLastPart($path, $delimiter = '/')
{
$pos = strrpos($path, $delimiter);

if ($pos === false || $pos === 1) {
return null;
}

return substr($path, 0, $pos);
}
public static function path2array($path, $delimiter = '/')
{
$array = [$path];

while ($path = self::cutLastPart($path))
{
$array[] = $path;
}

if (\end($array) !== "") {
$array[] = '';
}
return $array;
}
public static function compare($pathOne, $pathTwo, $delimiter = '/')
{
$pathOne = self::path2array($pathOne);
$pathTwo = self::path2array($pathTwo);

for ($distance = 0; $distance < count($pathOne); $distance++) {
for ($p2index = 0; $p2index < count($pathTwo); $p2index++) {
if ($pathOne[$distance] === $pathTwo[$p2index]) {
return $distance + $p2index;
}
}
}

return -1;
}
}
86 changes: 67 additions & 19 deletions Classes/ViewHelpers/PageViewHelper.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<?php
namespace Breadlesscode\ErrorPages\ViewHelpers;

use Neos\FluidAdaptor\Core\ViewHelper\AbstractViewHelper;
use Neos\ContentRepository\Domain\Model\Node;
use Neos\ContentRepository\Domain\Service\ContextFactoryInterface;
use Neos\Eel\FlowQuery\FlowQuery;
use Neos\Flow\Annotations as Flow;
use Neos\Neos\View\FusionView;
use Neos\FluidAdaptor\Core\ViewHelper\AbstractViewHelper;
use Neos\Neos\Routing\FrontendNodeRoutePartHandler;

use Neos\Neos\View\FusionView;
use Breadlesscode\ErrorPages\Utility\PathUtility;

class PageViewHelper extends AbstractViewHelper
{
Expand Down Expand Up @@ -36,11 +37,16 @@ class PageViewHelper extends AbstractViewHelper
*/
public function render($exception)
{
$statusCode = $exception->getStatusCode();
$dimension = $this->getCurrentDimension();
$errorPage = $this->findErrorPage($statusCode, $dimension);
$requestPath = PathUtility::cutLastPart(
$this->controllerContext
->getRequest()
->getHttpRequest()
->getUri()
->getPath()
);
$errorPage = $this->findErrorPage($requestPath, $exception->getStatusCode());

if($errorPage === null) {
if ($errorPage === null) {
throw new \Exception("Please setup a error page of type ".self::ERROR_PAGE_TYPE."!", 1);
}
// render error page
Expand All @@ -58,23 +64,49 @@ public function render($exception)
* @param string $dimension
* @return Neos\ContentRepository\Domain\Model\Node
*/
protected function findErrorPage($statusCode, $dimension)
protected function findErrorPage($requestPath, $statusCode)
{
$dimension = $this->getDimensionOfPath($requestPath);
$errorPages = collect($this->getErrorPages($dimension));
$statusCode = (string) $statusCode;
// find the correct error page
return $errorPages
$errorPages = $errorPages
// filter invalid status codes
->filter(function($page) use($statusCode) {
->filter(function ($page) use ($statusCode) {
$supportedStatusCodes = $page->getProperty('statusCodes');

return $supportedStatusCodes !== null && \in_array($statusCode, $supportedStatusCodes);
})
// filter invalid dimensions
->filter(function($page) use($dimension) {
->filter(function ($page) use ($dimension) {
return \in_array($dimension, $page->getDimensions()['language']);
})
->first();
// filter all pages which not in the correct path
->sortBy(function ($page) use ($requestPath, $dimension) {
return PathUtility::compare(
$this->getPathWithoutDimensionPrefix($requestPath),
PathUtility::cutLastPart($this->getPathWithoutDimensionPrefix($this->getUriOfNode($page)))
);
});
return $errorPages->first();
}
/**
* return path without the dimension prefix
*
* @param string $path
* @param string $dimension
* @return string
*/
protected function getPathWithoutDimensionPrefix($path)
{
$presets = collect($this->contentDimensionsConfig['presets']);
$matches = [];
preg_match(FrontendNodeRoutePartHandler::DIMENSION_REQUEST_PATH_MATCHER, ltrim($path, '/'), $matches);

if ($presets->pluck('uriSegment')->contains($matches['firstUriPart'])) {
return substr(ltrim($path, '/'), strlen($matches['firstUriPart']));
}

return $path;
}
/**
* collects all error pages from the site
Expand Down Expand Up @@ -111,14 +143,13 @@ protected function getContext($dimension)
*
* @return string dimension preset key
*/
protected function getCurrentDimension()
protected function getDimensionOfPath($path)
{
$matches = [];
$requestPath = ltrim($this->controllerContext->getRequest()->getHttpRequest()->getUri()->getPath(), '/');
preg_match(FrontendNodeRoutePartHandler::DIMENSION_REQUEST_PATH_MATCHER, $requestPath, $matches);
preg_match(FrontendNodeRoutePartHandler::DIMENSION_REQUEST_PATH_MATCHER, ltrim($path, '/'), $matches);

$presets = collect($this->contentDimensionsConfig['presets'])
->filter(function($value, $key) use($matches) {
->filter(function ($value, $key) use ($matches) {
$uriSegment = data_get($value, 'uriSegment');
return (
$uriSegment !== null && (
Expand All @@ -128,15 +159,32 @@ protected function getCurrentDimension()
);
});

if($presets->count() > 0) {
if ($presets->count() > 0) {
return $presets->keys()->first();
}

if($this->supportEmptySegmentForDimensions) {
if ($this->supportEmptySegmentForDimensions) {
return $this->contentDimensionsConfig['defaultPreset'];
}

return null;
}
/**
* get the uri of a node
*
* @param Node $node
* @return string
*/
protected function getUriOfNode(Node $node)
{
static $uriBuilder = null;

if ($uriBuilder === null) {
$uriBuilder = $this->controllerContext->getUriBuilder();
$uriBuilder->setRequest($this->controllerContext->getRequest()->getMainRequest());
$uriBuilder->reset();
}

return $uriBuilder->uriFor('show', ['node' => $node], 'Frontend\\Node', 'Neos.Neos');
}
}
File renamed without changes.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@
[![Downloads](https://img.shields.io/packagist/dt/breadlesscode/neos-error-pages.svg)]()
[![license](https://img.shields.io/github/license/breadlesscode/neos-error-pages.svg)]()

This package provides a error page NodeType.
This package provides multible error pages for your NEOS CMS site.
You can have a error page for each sub folder, this package shows the nearest error page.

## Installation
Install this package in your NEOS project root.

```
composer require breadlesscode/neos-error-pages
composer require breadlesscode/neos-error-pages
```
Nearly zero configuration!

## Usage

1. Create your error page in your dimension.
2. Select the correct status codes in the NEOS inspector.
2. Select the correct status codes in the NEOS inspector.
3. Publish

## Todo
- [ ] Multiple error pages. Select nearest error page
- [ ] Write some tests (as always...)

## License
The MIT License (MIT). Please see [License File](LICENSE) for more information.

0 comments on commit 85aa81d

Please sign in to comment.