DeClemo
8/6/2015 - 2:23 PM

eZ Publish 5 Router-based 404 Custom Handling

eZ Publish 5 Router-based 404 Custom Handling

parameters:
    project.routing.siterouter.class: Project\SiteBundle\Routing\SiteRouter

services:
    project.routing.siterouter:
        class: %project.routing.siterouter.class%
        arguments:
            - @service_container
            - @ezpublish.api.repository.lazy
            - @ezpublish.urlalias_generator
            - @?router.request_context
            - @?logger
        tags:
            - {name: router, priority: 10}
<?php

namespace Project\SiteBundle\Routing;

use Symfony\Component\Routing\RouterInterface;
use Symfony\Cmf\Component\Routing\ChainedRouterInterface;
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Routing\RequestContext;
use Psr\Log\LoggerInterface;
use eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator;

class SiteRouter implements RouterInterface, ChainedRouterInterface, RequestMatcherInterface
{

    /**
     * @var \Symfony\Component\DependencyInjection\ContainerInterface
     */
    protected $Container;

    /**
     * @var \Symfony\Component\Routing\RequestContext
     */
    protected $RequestContext;

    /**
     * @var \Psr\Log\LoggerInterface
     */
    protected $Logger;

    /**
     * @var \Closure
     */
    protected $eZRepository;

    /**
     * @var \eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator
     */
    protected $Generator;

    /**
     * @var \eZ\Publish\API\Repository\URLAliasService
     */
    protected $URLAliasService;

    public function __construct(ContainerInterface $container, \Closure $ez_repository, UrlAliasGenerator $generator, RequestContext $request_context, LoggerInterface $logger = null) {
        $this->Container = $container;
        $this->RequestContext = (
            $request_context !== NULL ? $request_context : new RequestContext()
        );
        $this->Logger = $logger;
        $this->eZRepository = $ez_repository;
        $this->Generator = $generator;
    }

    /**
     * @return \eZ\Publish\API\Repository\Repository
     */
    protected function getRepository()
    {
        return call_user_func(
            $this->eZRepository
        );
    }

    /**
     * Tries to match a request with a set of routes.
     *
     * If the matcher can not find information, it must throw one of the exceptions documented
     * below.
     *
     * @param Request $request The request to match
     *
     * @return array An array of parameters
     *
     * @throws ResourceNotFoundException If no matching resource could be found
     * @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed
     */
    public function matchRequest(Request $request) {
        $SiteAccess = $this->Container->get('ezpublish.siteaccess');
        if($SiteAccess->name !== 'site_admin') {
            try {

                $URLAlias = $this->getRepository()->getURLAliasService()->lookup(
                    $RequestPathInfo = $request->attributes->get(
                        'semanticPathinfo', $request->getPathInfo()
                    )
                );

            } catch (\Exception $e) {

                $RequestPathInfoComponents = explode(
                    '/' , trim($RequestPathInfo, '/')
                );

                $eZPublishLegacyKernel = call_user_func(
                    $this->Container->get('ezpublish_legacy.kernel')
                );

                $LegacyModuleCheck = $eZPublishLegacyKernel->runCallback(
                    function() use ($RequestPathInfoComponents) {
                        return (bool) \eZModule::exists($RequestPathInfoComponents[0]);
                    }
                );

                if($LegacyModuleCheck) {
                    throw new ResourceNotFoundException(
                        'Page Not Found', 404
                    );
                }

                return array(
                    '_route' => 'error',
                    '_controller' => 'ProjectSiteBundle:Error:NotFound',
                );

            }
        }

        throw new ResourceNotFoundException(
            'Page Not Found', 404
        );
    }


    /**
     * Gets the RouteCollection instance associated with this Router.
     *
     * @return RouteCollection A RouteCollection instance
     */
    public function getRouteCollection() {
        
    }


    /**
     * Generates a URL or path for a specific route based on the given parameters.
     *
     * Parameters that reference placeholders in the route pattern will substitute them in the
     * path or host. Extra params are added as query string to the URL.
     *
     * When the passed reference type cannot be generated for the route because it requires a different
     * host or scheme than the current one, the method will return a more comprehensive reference
     * that includes the required params. For example, when you call this method with $referenceType = ABSOLUTE_PATH
     * but the route requires the https scheme whereas the current scheme is http, it will instead return an
     * ABSOLUTE_URL with the https scheme and the current host. This makes sure the generated URL matches
     * the route in any case.
     *
     * If there is no route with the given name, the generator must throw the RouteNotFoundException.
     *
     * @param string         $name            The name of the route
     * @param mixed          $parameters      An array of parameters
     * @param Boolean|string $referenceType   The type of reference to be generated (one of the constants)
     *
     * @return string The generated URL
     *
     * @throws RouteNotFoundException              If the named route doesn't exist
     * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route
     * @throws InvalidParameterException           When a parameter value for a placeholder is not correct because
     *                                             it does not match the requirement
     *
     * @api
     */
    public function generate($name, $parameters = array(), $reference_type = false) {
        return '';
    }

    /**
     * Sets the request context.
     *
     * @param RequestContext $context The context
     *
     * @api
     */
    public function setContext(RequestContext $context) {
        $this->RequestContext = $context;
    }

    /**
     * Gets the request context.
     *
     * @return RequestContext The context
     *
     * @api
     */
    public function getContext() {
        return $this->RequestContext;
    }

    /**
     * Tries to match a URL path with a set of routes.
     *
     * If the matcher can not find information, it must throw one of the exceptions documented
     * below.
     *
     * @param string $pathinfo The path info to be parsed (raw format, i.e. not urldecoded)
     *
     * @return array An array of parameters
     *
     * @throws ResourceNotFoundException If the resource could not be found
     * @throws MethodNotAllowedException If the resource was found but the request method is not allowed
     *
     * @api
     */
    public function match($pathinfo) {
        return array();
    }

    /** Symfony\Cmf\Component\Routing\VersatileGeneratorInterface
     * Whether this generator supports the supplied $name.
     *
     * This check does not need to look if the specific instance can be
     * resolved to a route, only whether the router can generate routes from
     * objects of this class.
     *
     * @param mixed $name The route "name" which may also be an object or anything
     *
     * @return bool
     */
    public function supports($name) {
        return false;
    }

    /** Symfony\Cmf\Component\Routing\VersatileGeneratorInterface
     * Convert a route identifier (name, content object etc) into a string
     * usable for logging and other debug/error messages
     *
     * @param mixed $name
     * @param array $parameters which should contain a content field containing
     *                          a RouteReferrersReadInterface object
     *
     * @return string
     */
    public function getRouteDebugMessage($name, array $parameters = array()) {
        return '';
    }

}