11<?php
22namespace Breadlesscode \ErrorPages \ViewHelpers ;
33
4- use Neos \FluidAdaptor \ Core \ ViewHelper \ AbstractViewHelper ;
4+ use Neos \ContentRepository \ Domain \ Model \ Node ;
55use Neos \ContentRepository \Domain \Service \ContextFactoryInterface ;
66use Neos \Eel \FlowQuery \FlowQuery ;
77use Neos \Flow \Annotations as Flow ;
8- use Neos \Neos \ View \ FusionView ;
8+ use Neos \FluidAdaptor \ Core \ ViewHelper \ AbstractViewHelper ;
99use Neos \Neos \Routing \FrontendNodeRoutePartHandler ;
10-
10+ use Neos \Neos \View \FusionView ;
11+ use Breadlesscode \ErrorPages \Utility \PathUtility ;
1112
1213class PageViewHelper extends AbstractViewHelper
1314{
@@ -36,11 +37,16 @@ class PageViewHelper extends AbstractViewHelper
3637 */
3738 public function render ($ exception )
3839 {
39- $ statusCode = $ exception ->getStatusCode ();
40- $ dimension = $ this ->getCurrentDimension ();
41- $ errorPage = $ this ->findErrorPage ($ statusCode , $ dimension );
40+ $ requestPath = PathUtility::cutLastPart (
41+ $ this ->controllerContext
42+ ->getRequest ()
43+ ->getHttpRequest ()
44+ ->getUri ()
45+ ->getPath ()
46+ );
47+ $ errorPage = $ this ->findErrorPage ($ requestPath , $ exception ->getStatusCode ());
4248
43- if ($ errorPage === null ) {
49+ if ($ errorPage === null ) {
4450 throw new \Exception ("Please setup a error page of type " .self ::ERROR_PAGE_TYPE ."! " , 1 );
4551 }
4652 // render error page
@@ -58,23 +64,49 @@ public function render($exception)
5864 * @param string $dimension
5965 * @return Neos\ContentRepository\Domain\Model\Node
6066 */
61- protected function findErrorPage ($ statusCode , $ dimension )
67+ protected function findErrorPage ($ requestPath , $ statusCode )
6268 {
69+ $ dimension = $ this ->getDimensionOfPath ($ requestPath );
6370 $ errorPages = collect ($ this ->getErrorPages ($ dimension ));
6471 $ statusCode = (string ) $ statusCode ;
6572 // find the correct error page
66- return $ errorPages
73+ $ errorPages = $ errorPages
6774 // filter invalid status codes
68- ->filter (function ($ page ) use ($ statusCode ) {
75+ ->filter (function ($ page ) use ($ statusCode ) {
6976 $ supportedStatusCodes = $ page ->getProperty ('statusCodes ' );
70-
7177 return $ supportedStatusCodes !== null && \in_array ($ statusCode , $ supportedStatusCodes );
7278 })
7379 // filter invalid dimensions
74- ->filter (function ($ page ) use ($ dimension ) {
80+ ->filter (function ($ page ) use ($ dimension ) {
7581 return \in_array ($ dimension , $ page ->getDimensions ()['language ' ]);
7682 })
77- ->first ();
83+ // filter all pages which not in the correct path
84+ ->sortBy (function ($ page ) use ($ requestPath , $ dimension ) {
85+ return PathUtility::compare (
86+ $ this ->getPathWithoutDimensionPrefix ($ requestPath ),
87+ PathUtility::cutLastPart ($ this ->getPathWithoutDimensionPrefix ($ this ->getUriOfNode ($ page )))
88+ );
89+ });
90+ return $ errorPages ->first ();
91+ }
92+ /**
93+ * return path without the dimension prefix
94+ *
95+ * @param string $path
96+ * @param string $dimension
97+ * @return string
98+ */
99+ protected function getPathWithoutDimensionPrefix ($ path )
100+ {
101+ $ presets = collect ($ this ->contentDimensionsConfig ['presets ' ]);
102+ $ matches = [];
103+ preg_match (FrontendNodeRoutePartHandler::DIMENSION_REQUEST_PATH_MATCHER , ltrim ($ path , '/ ' ), $ matches );
104+
105+ if ($ presets ->pluck ('uriSegment ' )->contains ($ matches ['firstUriPart ' ])) {
106+ return substr (ltrim ($ path , '/ ' ), strlen ($ matches ['firstUriPart ' ]));
107+ }
108+
109+ return $ path ;
78110 }
79111 /**
80112 * collects all error pages from the site
@@ -111,14 +143,13 @@ protected function getContext($dimension)
111143 *
112144 * @return string dimension preset key
113145 */
114- protected function getCurrentDimension ( )
146+ protected function getDimensionOfPath ( $ path )
115147 {
116148 $ matches = [];
117- $ requestPath = ltrim ($ this ->controllerContext ->getRequest ()->getHttpRequest ()->getUri ()->getPath (), '/ ' );
118- preg_match (FrontendNodeRoutePartHandler::DIMENSION_REQUEST_PATH_MATCHER , $ requestPath , $ matches );
149+ preg_match (FrontendNodeRoutePartHandler::DIMENSION_REQUEST_PATH_MATCHER , ltrim ($ path , '/ ' ), $ matches );
119150
120151 $ presets = collect ($ this ->contentDimensionsConfig ['presets ' ])
121- ->filter (function ($ value , $ key ) use ($ matches ) {
152+ ->filter (function ($ value , $ key ) use ($ matches ) {
122153 $ uriSegment = data_get ($ value , 'uriSegment ' );
123154 return (
124155 $ uriSegment !== null && (
@@ -128,15 +159,32 @@ protected function getCurrentDimension()
128159 );
129160 });
130161
131- if ($ presets ->count () > 0 ) {
162+ if ($ presets ->count () > 0 ) {
132163 return $ presets ->keys ()->first ();
133164 }
134165
135- if ($ this ->supportEmptySegmentForDimensions ) {
166+ if ($ this ->supportEmptySegmentForDimensions ) {
136167 return $ this ->contentDimensionsConfig ['defaultPreset ' ];
137168 }
138169
139170 return null ;
140171 }
172+ /**
173+ * get the uri of a node
174+ *
175+ * @param Node $node
176+ * @return string
177+ */
178+ protected function getUriOfNode (Node $ node )
179+ {
180+ static $ uriBuilder = null ;
141181
182+ if ($ uriBuilder === null ) {
183+ $ uriBuilder = $ this ->controllerContext ->getUriBuilder ();
184+ $ uriBuilder ->setRequest ($ this ->controllerContext ->getRequest ()->getMainRequest ());
185+ $ uriBuilder ->reset ();
186+ }
187+
188+ return $ uriBuilder ->uriFor ('show ' , ['node ' => $ node ], 'Frontend \\Node ' , 'Neos.Neos ' );
189+ }
142190}
0 commit comments