Completed
Push — master ( f33806...7a283c )
by Andy
02:14
created

ExceptionListener   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 98
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 5
dl 0
loc 98
ccs 34
cts 34
cp 1
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
B onKernelException() 0 35 6
B getAlternativeRoute() 0 22 4
1
<?php
2
3
namespace Palmtree\CanonicalUrlBundle\EventListener;
4
5
use Palmtree\CanonicalUrlBundle\Service\CanonicalUrlGenerator;
6
use Symfony\Component\HttpFoundation\RedirectResponse;
7
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
8
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
9
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
10
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
11
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
12
use Symfony\Component\Routing\RouterInterface;
13
14
class ExceptionListener
15
{
16
    const CONTROLLER_PATTERN = '~^/app(?:_.+)*\.php~';
17
18
    /** @var RouterInterface */
19
    protected $router;
20
    /** @var bool */
21
    protected $redirect;
22
    /** @var int */
23
    protected $redirectCode;
24
    /** @var bool */
25
    protected $trailingSlash;
26
27
    /**
28
     * KernelEventListener constructor.
29
     * @param RouterInterface $router
30
     * @param array           $config
31
     */
32 5
    public function __construct(RouterInterface $router, array $config = [])
33
    {
34 5
        $this->router = $router;
35
36 5
        $this->redirect      = $config['redirect'];
37 5
        $this->redirectCode  = $config['redirect_code'];
38 5
        $this->trailingSlash = $config['trailing_slash'];
39 5
    }
40
41
    /**
42
     * Listener for the 'kernel.exception' event.
43
     *
44
     * @param GetResponseForExceptionEvent $event
45
     *
46
     * @return bool
47
     */
48 5
    public function onKernelException(GetResponseForExceptionEvent $event)
49
    {
50 5
        $exception = $event->getException();
51
52 5
        if ($exception instanceof NotFoundHttpException) {
53
            // We're about to throw a 404 error, try to resolve it
54 5
            $request = $event->getRequest();
55
56 5
            $uri = strtok($request->getRequestUri(), '?');
57
58
            // See if there's a matching route without a trailing slash
59 5
            $match = $this->getAlternativeRoute($uri);
60
61 5
            if ($match !== null) {
62 3
                if ($this->redirect) {
63 3
                    $params = $request->query->all();
64
65 3
                    foreach ($match as $key => $value) {
66 3
                        if ($key[0] !== '_') {
67 3
                            $params[$key] = $value;
68
                        }
69
                    }
70
71 3
                    $url = $this->router->generate($match['_route'], $params, UrlGeneratorInterface::ABSOLUTE_URL);
72
73 3
                    $response = new RedirectResponse($url, $this->redirectCode);
74 3
                    $event->setResponse($response);
75
76 3
                    return true;
77
                }
78
            }
79
        }
80
81 2
        return false;
82
    }
83
84
    /**
85
     * @param string $uri
86
     *
87
     * @return array|null
88
     */
89 5
    protected function getAlternativeRoute($uri)
90
    {
91 5
        $alternativeUri = rtrim($uri, '/');
92
93 5
        if ($this->trailingSlash) {
94 1
            $alternativeUri .= '/';
95
        }
96
97 5
        if ($alternativeUri === $uri) {
98 1
            return null;
99
        }
100
101 4
        $alternativeUri = preg_replace(static::CONTROLLER_PATTERN, '', $alternativeUri);
102
103
        try {
104 4
            $match = $this->router->match($alternativeUri);
105
106 3
            return $match;
107 1
        } catch (ResourceNotFoundException $e) {
108 1
            return null;
109
        }
110
    }
111
}
112