1: <?php
2: /*************************************************************************************/
3: /* */
4: /* Thelia */
5: /* */
6: /* Copyright (c) OpenStudio */
7: /* email : info@thelia.net */
8: /* web : http://www.thelia.net */
9: /* */
10: /* This program is free software; you can redistribute it and/or modify */
11: /* it under the terms of the GNU General Public License as published by */
12: /* the Free Software Foundation; either version 3 of the License */
13: /* */
14: /* This program is distributed in the hope that it will be useful, */
15: /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
16: /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
17: /* GNU General Public License for more details. */
18: /* */
19: /* You should have received a copy of the GNU General Public License */
20: /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
21: /* */
22: /*************************************************************************************/
23: namespace Thelia\Routing;
24:
25: use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
26: use Symfony\Component\Routing\Exception\ResourceNotFoundException;
27: use Symfony\Component\Routing\Exception\MethodNotAllowedException;
28: use Symfony\Component\Routing\RequestContextAwareInterface;
29: use Symfony\Component\Routing\RequestContext;
30: use Symfony\Component\HttpFoundation\Request;
31:
32: /**
33: *
34: * Collection of Matcher.
35: *
36: * Matcher resolve request into controller::method
37: * exemple of Matcher : UrlMatcher of HttpKernel component (but it implements UrlMatcherInterface and not RequestMatcherInterface.
38: *
39: * @author Manuel Raynaud <mraynaud@openstudio.fr>
40: */
41:
42: class TheliaMatcherCollection implements RequestMatcherInterface, RequestContextAwareInterface
43: {
44: protected $context;
45: protected $matchers = array();
46: protected $defaultMatcher;
47:
48: protected $sortedMatchers = array();
49:
50: /**
51: * Constructor
52: *
53: * Check if this constructor is needed (is RequestContext needed ? )
54: */
55: public function __construct()
56: {
57: $this->context = new RequestContext();
58: }
59:
60: /**
61: * allow to add a matcher routing class to the matchers collection
62: * matcher must implement RequestMatcherInterface
63: *
64: * priority can be fixed with $priority parameter
65: *
66: * @param RequestMatcherInterface $matcher
67: * @param int $priority set the priority of the added matcher
68: *
69: */
70: public function add(RequestMatcherInterface $matcher, $priority = 0)
71: {
72: if (!is_object($matcher)) {
73: $matcher = new $matcher();
74: }
75:
76: if (!isset($this->matchers[$priority])) {
77: $this->matchers[$priority] = array();
78: }
79:
80: $this->matchers[$priority][] = $matcher;
81: $this->sortedMatchers = array();
82: }
83:
84: /**
85: *
86: * Sort Matchers by priority
87: *
88: * @return array Array of matchers sorted by priority.
89: */
90: public function getSortedMatchers()
91: {
92: if (empty($this->sortedMatchers)) {
93: $this->sortedMatchers = $this->sortMatchers();
94: }
95:
96: return $this->sortedMatchers;
97: }
98:
99: /**
100: *
101: * Sort the matcher by priority
102: *
103: * @return array Array of matchers sorted by priority.
104: */
105: public function sortMatchers()
106: {
107: $sortedMatchers = array();
108: krsort($this->matchers);
109:
110: foreach ($this->matchers as $matcher) {
111: $sortedMatchers = array_merge($sortedMatchers,$matcher);
112: }
113:
114: return $sortedMatchers;
115: }
116:
117: /**
118: * Tries to match a request with a set of routes.
119: *
120: * If the matcher can not find information, it must throw one of the exceptions documented
121: * below.
122: *
123: * @param Request $request The request to match
124: *
125: * @return array An array of parameters
126: *
127: * @throws ResourceNotFoundException If no matching resource could be found
128: * @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed
129: */
130: public function matchRequest(Request $request)
131: {
132: if (empty($this->matchers)) {
133: throw new \InvalidArgumentException('there is no matcher added to the TheliaMatcherCollection');
134: }
135:
136: foreach ($this->getSortedMatchers() as $matcher) {
137: try {
138: return $matcher->matchRequest($request);
139: } catch (ResourceNotFoundException $e) {
140: //no action, wait for next matcher
141: } catch (MethodNotAllowedException $e) {
142: /**
143: * @todo what todo with a MethodNotAllowedException ?
144: */
145: }
146: }
147:
148: throw new ResourceNotFoundException('No one matcher in this collection matched the current request');
149: }
150:
151: /**
152: * Sets the request context.
153: *
154: * @param RequestContext $context The context
155: *
156: */
157: public function setContext(RequestContext $context)
158: {
159: $this->context = $context;
160:
161: }
162:
163: /**
164: * Gets the request context.
165: *
166: * @return RequestContext The context
167: *
168: */
169: public function getContext()
170: {
171: return $this->context;
172: }
173: }
174: