These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Kunstmaan\NodeBundle\Router; |
||
4 | |||
5 | use Doctrine\ORM\EntityManagerInterface; |
||
6 | use Kunstmaan\AdminBundle\Helper\DomainConfigurationInterface; |
||
7 | use Kunstmaan\NodeBundle\Controller\SlugController; |
||
8 | use Kunstmaan\NodeBundle\Entity\NodeTranslation; |
||
9 | use Kunstmaan\NodeBundle\Repository\NodeTranslationRepository; |
||
10 | use Symfony\Component\DependencyInjection\ContainerInterface; |
||
11 | use Symfony\Component\HttpFoundation\Request; |
||
12 | use Symfony\Component\HttpFoundation\RequestStack; |
||
13 | use Symfony\Component\Routing\Exception\ResourceNotFoundException; |
||
14 | use Symfony\Component\Routing\Generator\UrlGenerator; |
||
15 | use Symfony\Component\Routing\Matcher\UrlMatcher; |
||
16 | use Symfony\Component\Routing\RequestContext; |
||
17 | use Symfony\Component\Routing\Route; |
||
18 | use Symfony\Component\Routing\RouteCollection; |
||
19 | use Symfony\Component\Routing\RouterInterface; |
||
20 | |||
21 | /** |
||
22 | * The SlugRouter takes care of routing the paths for slugs. It should have the |
||
23 | * lowest priority as it's a catch-all router that routes (almost) all requests |
||
24 | * to the SlugController |
||
25 | */ |
||
26 | class SlugRouter implements RouterInterface |
||
27 | { |
||
28 | public static $SLUG = '_slug'; |
||
29 | |||
30 | public static $SLUG_PREVIEW = '_slug_preview'; |
||
31 | |||
32 | /** @var DomainConfigurationInterface */ |
||
33 | protected $domainConfiguration; |
||
34 | |||
35 | /** @var RequestStack */ |
||
36 | private $requestStack; |
||
37 | |||
38 | /** @var EntityManagerInterface */ |
||
39 | private $em; |
||
40 | |||
41 | /** @var string */ |
||
42 | protected $adminKey; |
||
43 | |||
44 | /** @var RequestContext */ |
||
45 | protected $context; |
||
46 | |||
47 | /** @var RouteCollection */ |
||
48 | protected $routeCollection; |
||
49 | |||
50 | /** @var UrlGenerator */ |
||
51 | protected $urlGenerator; |
||
52 | |||
53 | /** |
||
54 | * @var ContainerInterface |
||
55 | * |
||
56 | * @deprecated in KunstmaanNodeBundle 5.1 and will be removed in KunstmaanNodeBundle 6.0. |
||
57 | */ |
||
58 | protected $container; |
||
59 | |||
60 | /** @var string */ |
||
61 | protected $slugPattern; |
||
62 | |||
63 | /** |
||
64 | * The constructor for this service |
||
65 | * |
||
66 | * @param ContainerInterface $container |
||
67 | */ |
||
68 | 12 | View Code Duplication | public function __construct( |
69 | /* DomainConfigurationInterface */ $domainConfiguration, |
||
70 | RequestStack $requestStack = null, |
||
71 | EntityManagerInterface $em = null, |
||
72 | $adminKey = null |
||
73 | ) { |
||
74 | 12 | $this->slugPattern = "[a-zA-Z0-9\-_\/]*"; |
|
75 | |||
76 | 12 | if ($domainConfiguration instanceof ContainerInterface) { |
|
77 | @trigger_error('Container injection and the usage of the container is deprecated in KunstmaanNodeBundle 5.1 and will be removed in KunstmaanNodeBundle 6.0.', E_USER_DEPRECATED); |
||
0 ignored issues
–
show
|
|||
78 | |||
79 | $this->container = $domainConfiguration; |
||
80 | $this->domainConfiguration = $this->container->get('kunstmaan_admin.domain_configuration'); |
||
81 | $this->adminKey = $this->container->getParameter('kunstmaan_admin.admin_prefix'); |
||
82 | $this->requestStack = $this->container->get('request_stack'); |
||
83 | $this->em = $this->container->get('doctrine.orm.entity_manager'); |
||
84 | |||
85 | return; |
||
86 | } |
||
87 | |||
88 | 12 | $this->domainConfiguration = $domainConfiguration; |
|
89 | 12 | $this->adminKey = $adminKey; |
|
90 | 12 | $this->requestStack = $requestStack; |
|
91 | 12 | $this->em = $em; |
|
92 | 12 | } |
|
93 | |||
94 | /** |
||
95 | * Match given urls via the context to the routes we defined. |
||
96 | * This functionality re-uses the default Symfony way of routing and its |
||
97 | * components |
||
98 | * |
||
99 | * @param string $pathinfo |
||
100 | * |
||
101 | * @throws ResourceNotFoundException |
||
102 | * |
||
103 | * @return array |
||
104 | */ |
||
105 | 2 | public function match($pathinfo) |
|
106 | { |
||
107 | 2 | $urlMatcher = new UrlMatcher( |
|
108 | 2 | $this->getRouteCollection(), |
|
109 | 2 | $this->getContext() |
|
110 | ); |
||
111 | 2 | $result = $urlMatcher->match($pathinfo); |
|
112 | |||
113 | 2 | if (!empty($result)) { |
|
114 | 2 | $nodeTranslation = $this->getNodeTranslation($result); |
|
115 | 2 | if (\is_null($nodeTranslation)) { |
|
116 | 1 | throw new ResourceNotFoundException('No page found for slug ' . $pathinfo); |
|
117 | } |
||
118 | 1 | $result['_nodeTranslation'] = $nodeTranslation; |
|
119 | } |
||
120 | |||
121 | 1 | return $result; |
|
122 | } |
||
123 | |||
124 | /** |
||
125 | * Gets the request context. |
||
126 | * |
||
127 | * @return RequestContext The context |
||
128 | * |
||
129 | * @api |
||
130 | */ |
||
131 | 10 | public function getContext() |
|
132 | { |
||
133 | 10 | if (!isset($this->context)) { |
|
134 | /** @var Request $request */ |
||
135 | 9 | $request = $this->getMasterRequest(); |
|
136 | |||
137 | 9 | $this->context = new RequestContext(); |
|
138 | 9 | $this->context->fromRequest($request); |
|
139 | } |
||
140 | |||
141 | 10 | return $this->context; |
|
142 | } |
||
143 | |||
144 | /** |
||
145 | * Sets the request context. |
||
146 | * |
||
147 | * @param RequestContext $context The context |
||
148 | * |
||
149 | * @api |
||
150 | */ |
||
151 | 1 | public function setContext(RequestContext $context) |
|
152 | { |
||
153 | 1 | $this->context = $context; |
|
154 | 1 | } |
|
155 | |||
156 | /** |
||
157 | * Generate an url for a supplied route. |
||
158 | * |
||
159 | * @param string $name The path |
||
160 | * @param array $parameters The route parameters |
||
161 | * @param int|bool $referenceType The type of reference to be generated (one of the UrlGeneratorInterface constants) |
||
162 | * |
||
163 | * @return null|string |
||
164 | */ |
||
165 | 2 | public function generate($name, $parameters = array(), $referenceType = UrlGenerator::ABSOLUTE_PATH) |
|
166 | { |
||
167 | 2 | $this->urlGenerator = new UrlGenerator( |
|
168 | 2 | $this->getRouteCollection(), |
|
169 | 2 | $this->getContext() |
|
170 | ); |
||
171 | |||
172 | 2 | return $this->urlGenerator->generate($name, $parameters, $referenceType); |
|
173 | } |
||
174 | |||
175 | /** |
||
176 | * Getter for routeCollection |
||
177 | * |
||
178 | * @return \Symfony\Component\Routing\RouteCollection |
||
179 | */ |
||
180 | 4 | public function getRouteCollection() |
|
181 | { |
||
182 | 4 | if (\is_null($this->routeCollection)) { |
|
183 | 4 | $this->routeCollection = new RouteCollection(); |
|
184 | |||
185 | 4 | $this->addPreviewRoute(); |
|
186 | 4 | $this->addSlugRoute(); |
|
187 | } |
||
188 | |||
189 | 4 | return $this->routeCollection; |
|
190 | } |
||
191 | |||
192 | /** |
||
193 | * @return null|\Symfony\Component\HttpFoundation\Request |
||
194 | */ |
||
195 | 9 | protected function getMasterRequest() |
|
196 | { |
||
197 | 9 | if (\is_null($this->requestStack)) { |
|
198 | return null; |
||
199 | } |
||
200 | |||
201 | 9 | return $this->requestStack->getMasterRequest(); |
|
202 | } |
||
203 | |||
204 | /** |
||
205 | * Add the preview route to the route collection |
||
206 | */ |
||
207 | 5 | protected function addPreviewRoute() |
|
208 | { |
||
209 | 5 | $routeParameters = $this->getPreviewRouteParameters(); |
|
210 | 5 | $this->addRoute(self::$SLUG_PREVIEW, $routeParameters); |
|
211 | 5 | } |
|
212 | |||
213 | /** |
||
214 | * Add the slug route to the route collection |
||
215 | */ |
||
216 | 4 | protected function addSlugRoute() |
|
217 | { |
||
218 | 4 | $routeParameters = $this->getSlugRouteParameters(); |
|
219 | 4 | $this->addRoute(self::$SLUG, $routeParameters); |
|
220 | 4 | } |
|
221 | |||
222 | /** |
||
223 | * Return preview route parameters |
||
224 | * |
||
225 | * @return array |
||
226 | */ |
||
227 | 11 | View Code Duplication | protected function getPreviewRouteParameters() |
228 | { |
||
229 | 11 | $previewPath = sprintf('/%s/preview/{url}', $this->adminKey); |
|
230 | $previewDefaults = array( |
||
231 | 11 | '_controller' => SlugController::class.'::slugAction', |
|
232 | 'preview' => true, |
||
233 | 11 | 'url' => '', |
|
234 | 11 | '_locale' => $this->getDefaultLocale(), |
|
235 | ); |
||
236 | $previewRequirements = array( |
||
237 | 11 | 'url' => $this->getSlugPattern(), |
|
238 | ); |
||
239 | |||
240 | 11 | if ($this->isMultiLanguage()) { |
|
241 | 8 | $previewPath = '/{_locale}' . $previewPath; |
|
242 | 8 | unset($previewDefaults['_locale']); |
|
243 | 8 | $previewRequirements['_locale'] = $this->getEscapedLocales($this->getBackendLocales()); |
|
244 | } |
||
245 | |||
246 | return array( |
||
247 | 11 | 'path' => $previewPath, |
|
248 | 11 | 'defaults' => $previewDefaults, |
|
249 | 11 | 'requirements' => $previewRequirements, |
|
250 | ); |
||
251 | } |
||
252 | |||
253 | /** |
||
254 | * Return slug route parameters |
||
255 | * |
||
256 | * @return array |
||
257 | */ |
||
258 | 4 | View Code Duplication | protected function getSlugRouteParameters() |
259 | { |
||
260 | 4 | $slugPath = '/{url}'; |
|
261 | $slugDefaults = array( |
||
262 | 4 | '_controller' => SlugController::class.'::slugAction', |
|
263 | 'preview' => false, |
||
264 | 4 | 'url' => '', |
|
265 | 4 | '_locale' => $this->getDefaultLocale(), |
|
266 | ); |
||
267 | $slugRequirements = array( |
||
268 | 4 | 'url' => $this->getSlugPattern(), |
|
269 | ); |
||
270 | |||
271 | 4 | if ($this->isMultiLanguage()) { |
|
272 | 2 | $slugPath = '/{_locale}' . $slugPath; |
|
273 | 2 | unset($slugDefaults['_locale']); |
|
274 | 2 | $slugRequirements['_locale'] = $this->getEscapedLocales($this->getFrontendLocales()); |
|
275 | } |
||
276 | |||
277 | return array( |
||
278 | 4 | 'path' => $slugPath, |
|
279 | 4 | 'defaults' => $slugDefaults, |
|
280 | 4 | 'requirements' => $slugRequirements, |
|
281 | ); |
||
282 | } |
||
283 | |||
284 | /** |
||
285 | * @return bool |
||
286 | */ |
||
287 | 11 | protected function isMultiLanguage($host = null) |
|
288 | { |
||
289 | 11 | return $this->domainConfiguration->isMultiLanguage($host); |
|
290 | } |
||
291 | |||
292 | /** |
||
293 | * @return array |
||
294 | */ |
||
295 | 7 | protected function getFrontendLocales() |
|
296 | { |
||
297 | 7 | return $this->domainConfiguration->getFrontendLocales(); |
|
298 | } |
||
299 | |||
300 | /** |
||
301 | * @return array |
||
302 | */ |
||
303 | 8 | protected function getBackendLocales() |
|
304 | { |
||
305 | 8 | return $this->domainConfiguration->getBackendLocales(); |
|
306 | } |
||
307 | |||
308 | /** |
||
309 | * @return string |
||
310 | */ |
||
311 | 11 | protected function getDefaultLocale() |
|
312 | { |
||
313 | 11 | return $this->domainConfiguration->getDefaultLocale(); |
|
314 | } |
||
315 | |||
316 | /** |
||
317 | * @return string |
||
318 | */ |
||
319 | protected function getHost() |
||
320 | { |
||
321 | return $this->domainConfiguration->getHost(); |
||
322 | } |
||
323 | |||
324 | /** |
||
325 | * @return string |
||
326 | */ |
||
327 | 11 | protected function getSlugPattern() |
|
328 | { |
||
329 | 11 | return $this->slugPattern; |
|
330 | } |
||
331 | |||
332 | /** |
||
333 | * @param string $name |
||
334 | * @param array $parameters |
||
335 | */ |
||
336 | 5 | View Code Duplication | protected function addRoute($name, array $parameters = array()) |
337 | { |
||
338 | 5 | $this->routeCollection->add( |
|
339 | 5 | $name, |
|
340 | 5 | new Route( |
|
341 | 5 | $parameters['path'], |
|
342 | 5 | $parameters['defaults'], |
|
343 | 5 | $parameters['requirements'] |
|
344 | ) |
||
345 | ); |
||
346 | 5 | } |
|
347 | |||
348 | /** |
||
349 | * @param array $matchResult |
||
350 | * |
||
351 | * @return \Kunstmaan\NodeBundle\Entity\NodeTranslation |
||
352 | */ |
||
353 | 2 | protected function getNodeTranslation($matchResult) |
|
354 | { |
||
355 | // The route matches, now check if it actually exists (needed for proper chain router chaining!) |
||
356 | 2 | $nodeTranslationRepo = $this->getNodeTranslationRepository(); |
|
357 | |||
358 | /* @var NodeTranslation $nodeTranslation */ |
||
359 | 2 | $nodeTranslation = $nodeTranslationRepo->getNodeTranslationForUrl( |
|
360 | 2 | $matchResult['url'], |
|
361 | 2 | $matchResult['_locale'] |
|
362 | ); |
||
363 | |||
364 | 2 | return $nodeTranslation; |
|
365 | } |
||
366 | |||
367 | /** |
||
368 | * @return \Kunstmaan\NodeBundle\Repository\NodeTranslationRepository |
||
369 | */ |
||
370 | 4 | protected function getNodeTranslationRepository() |
|
371 | { |
||
372 | /* @var NodeTranslationRepository $nodeTranslationRepo */ |
||
373 | 4 | $nodeTranslationRepo = $this->em->getRepository( |
|
374 | 4 | 'KunstmaanNodeBundle:NodeTranslation' |
|
375 | ); |
||
376 | |||
377 | 4 | return $nodeTranslationRepo; |
|
378 | } |
||
379 | |||
380 | /** |
||
381 | * @param array $locales |
||
382 | * |
||
383 | * @return string |
||
384 | */ |
||
385 | 8 | protected function getEscapedLocales($locales) |
|
386 | { |
||
387 | 8 | $escapedLocales = array(); |
|
388 | 8 | foreach ($locales as $locale) { |
|
389 | 8 | $escapedLocales[] = str_replace('-', '\-', $locale); |
|
390 | } |
||
391 | |||
392 | 8 | return implode('|', $escapedLocales); |
|
393 | } |
||
394 | } |
||
395 |
If you suppress an error, we recommend checking for the error condition explicitly: