Version 1
[yaffs-website] / vendor / symfony / routing / Matcher / TraceableUrlMatcher.php
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\HttpFoundation\Request;
15 use Symfony\Component\Routing\Exception\ExceptionInterface;
16 use Symfony\Component\Routing\Route;
17 use Symfony\Component\Routing\RouteCollection;
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     public function getTracesForRequest(Request $request)
45     {
46         $this->request = $request;
47         $traces = $this->getTraces($request->getPathInfo());
48         $this->request = null;
49
50         return $traces;
51     }
52
53     protected function matchCollection($pathinfo, RouteCollection $routes)
54     {
55         foreach ($routes as $name => $route) {
56             $compiledRoute = $route->compile();
57
58             if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) {
59                 // does it match without any requirements?
60                 $r = new Route($route->getPath(), $route->getDefaults(), array(), $route->getOptions());
61                 $cr = $r->compile();
62                 if (!preg_match($cr->getRegex(), $pathinfo)) {
63                     $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route);
64
65                     continue;
66                 }
67
68                 foreach ($route->getRequirements() as $n => $regex) {
69                     $r = new Route($route->getPath(), $route->getDefaults(), array($n => $regex), $route->getOptions());
70                     $cr = $r->compile();
71
72                     if (in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) {
73                         $this->addTrace(sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route);
74
75                         continue 2;
76                     }
77                 }
78
79                 continue;
80             }
81
82             // check host requirement
83             $hostMatches = array();
84             if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) {
85                 $this->addTrace(sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route);
86
87                 continue;
88             }
89
90             // check HTTP method requirement
91             if ($requiredMethods = $route->getMethods()) {
92                 // HEAD and GET are equivalent as per RFC
93                 if ('HEAD' === $method = $this->context->getMethod()) {
94                     $method = 'GET';
95                 }
96
97                 if (!in_array($method, $requiredMethods)) {
98                     $this->allow = array_merge($this->allow, $requiredMethods);
99
100                     $this->addTrace(sprintf('Method "%s" does not match any of the required methods (%s)', $this->context->getMethod(), implode(', ', $requiredMethods)), self::ROUTE_ALMOST_MATCHES, $name, $route);
101
102                     continue;
103                 }
104             }
105
106             // check condition
107             if ($condition = $route->getCondition()) {
108                 if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request))) {
109                     $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $condition), self::ROUTE_ALMOST_MATCHES, $name, $route);
110
111                     continue;
112                 }
113             }
114
115             // check HTTP scheme requirement
116             if ($requiredSchemes = $route->getSchemes()) {
117                 $scheme = $this->context->getScheme();
118
119                 if (!$route->hasScheme($scheme)) {
120                     $this->addTrace(sprintf('Scheme "%s" does not match any of the required schemes (%s); the user will be redirected to first required scheme', $scheme, implode(', ', $requiredSchemes)), self::ROUTE_ALMOST_MATCHES, $name, $route);
121
122                     return true;
123                 }
124             }
125
126             $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route);
127
128             return true;
129         }
130     }
131
132     private function addTrace($log, $level = self::ROUTE_DOES_NOT_MATCH, $name = null, $route = null)
133     {
134         $this->traces[] = array(
135             'log' => $log,
136             'name' => $name,
137             'level' => $level,
138             'path' => null !== $route ? $route->getPath() : null,
139         );
140     }
141 }