]>
Commit | Line | Data |
---|---|---|
4f5b44bd NL |
1 | <?php |
2 | ||
3 | /* | |
4 | * This file is part of the Symfony package. | |
5 | * | |
6 | * (c) Fabien Potencier <fabien@symfony.com> | |
7 | * | |
8 | * For the full copyright and license information, please view the LICENSE | |
9 | * file that was distributed with this source code. | |
10 | */ | |
11 | ||
12 | namespace Symfony\Component\Routing\Matcher; | |
13 | ||
14 | use Symfony\Component\Routing\Exception\ExceptionInterface; | |
15 | use Symfony\Component\Routing\Route; | |
16 | use Symfony\Component\Routing\RouteCollection; | |
17 | use Symfony\Component\Routing\Matcher\UrlMatcher; | |
18 | ||
19 | /** | |
20 | * TraceableUrlMatcher helps debug path info matching by tracing the match. | |
21 | * | |
22 | * @author Fabien Potencier <fabien@symfony.com> | |
23 | */ | |
24 | class TraceableUrlMatcher extends UrlMatcher | |
25 | { | |
26 | const ROUTE_DOES_NOT_MATCH = 0; | |
27 | const ROUTE_ALMOST_MATCHES = 1; | |
28 | const ROUTE_MATCHES = 2; | |
29 | ||
30 | protected $traces; | |
31 | ||
32 | public function getTraces($pathinfo) | |
33 | { | |
34 | $this->traces = array(); | |
35 | ||
36 | try { | |
37 | $this->match($pathinfo); | |
38 | } catch (ExceptionInterface $e) { | |
39 | } | |
40 | ||
41 | return $this->traces; | |
42 | } | |
43 | ||
44 | protected function matchCollection($pathinfo, RouteCollection $routes) | |
45 | { | |
46 | foreach ($routes as $name => $route) { | |
47 | $compiledRoute = $route->compile(); | |
48 | ||
49 | if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) { | |
50 | // does it match without any requirements? | |
51 | $r = new Route($route->getPath(), $route->getDefaults(), array(), $route->getOptions()); | |
52 | $cr = $r->compile(); | |
53 | if (!preg_match($cr->getRegex(), $pathinfo)) { | |
54 | $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); | |
55 | ||
56 | continue; | |
57 | } | |
58 | ||
59 | foreach ($route->getRequirements() as $n => $regex) { | |
60 | $r = new Route($route->getPath(), $route->getDefaults(), array($n => $regex), $route->getOptions()); | |
61 | $cr = $r->compile(); | |
62 | ||
63 | if (in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) { | |
64 | $this->addTrace(sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route); | |
65 | ||
66 | continue 2; | |
67 | } | |
68 | } | |
69 | ||
70 | continue; | |
71 | } | |
72 | ||
73 | // check host requirement | |
74 | $hostMatches = array(); | |
75 | if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { | |
76 | $this->addTrace(sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route); | |
77 | ||
78 | return true; | |
79 | } | |
80 | ||
81 | // check HTTP method requirement | |
82 | if ($req = $route->getRequirement('_method')) { | |
83 | // HEAD and GET are equivalent as per RFC | |
84 | if ('HEAD' === $method = $this->context->getMethod()) { | |
85 | $method = 'GET'; | |
86 | } | |
87 | ||
88 | if (!in_array($method, $req = explode('|', strtoupper($req)))) { | |
89 | $this->allow = array_merge($this->allow, $req); | |
90 | ||
91 | $this->addTrace(sprintf('Method "%s" does not match the requirement ("%s")', $this->context->getMethod(), implode(', ', $req)), self::ROUTE_ALMOST_MATCHES, $name, $route); | |
92 | ||
93 | continue; | |
94 | } | |
95 | } | |
96 | ||
97 | // check HTTP scheme requirement | |
98 | if ($scheme = $route->getRequirement('_scheme')) { | |
99 | if ($this->context->getScheme() !== $scheme) { | |
100 | $this->addTrace(sprintf('Scheme "%s" does not match the requirement ("%s"); the user will be redirected', $this->context->getScheme(), $scheme), self::ROUTE_ALMOST_MATCHES, $name, $route); | |
101 | ||
102 | return true; | |
103 | } | |
104 | } | |
105 | ||
106 | $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); | |
107 | ||
108 | return true; | |
109 | } | |
110 | } | |
111 | ||
112 | private function addTrace($log, $level = self::ROUTE_DOES_NOT_MATCH, $name = null, $route = null) | |
113 | { | |
114 | $this->traces[] = array( | |
115 | 'log' => $log, | |
116 | 'name' => $name, | |
117 | 'level' => $level, | |
118 | 'path' => null !== $route ? $route->getPath() : null, | |
119 | ); | |
120 | } | |
121 | } |