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( |
0 ignored issues
–
show
|
|||
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
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
|
|||
78 | |||
79 | $this->container = $domainConfiguration; |
||
0 ignored issues
–
show
The property
Kunstmaan\NodeBundle\Router\SlugRouter::$container has been deprecated with message: in KunstmaanNodeBundle 5.1 and will be removed in KunstmaanNodeBundle 6.0.
This property has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.
Loading history...
|
|||
80 | $this->domainConfiguration = $this->container->get('kunstmaan_admin.domain_configuration'); |
||
0 ignored issues
–
show
The property
Kunstmaan\NodeBundle\Router\SlugRouter::$container has been deprecated with message: in KunstmaanNodeBundle 5.1 and will be removed in KunstmaanNodeBundle 6.0.
This property has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.
Loading history...
|
|||
81 | $this->adminKey = $this->container->getParameter('kunstmaan_admin.admin_prefix'); |
||
0 ignored issues
–
show
The property
Kunstmaan\NodeBundle\Router\SlugRouter::$container has been deprecated with message: in KunstmaanNodeBundle 5.1 and will be removed in KunstmaanNodeBundle 6.0.
This property has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.
Loading history...
|
|||
82 | $this->requestStack = $this->container->get('request_stack'); |
||
0 ignored issues
–
show
The property
Kunstmaan\NodeBundle\Router\SlugRouter::$container has been deprecated with message: in KunstmaanNodeBundle 5.1 and will be removed in KunstmaanNodeBundle 6.0.
This property has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.
Loading history...
|
|||
83 | $this->em = $this->container->get('doctrine.orm.entity_manager'); |
||
0 ignored issues
–
show
The property
Kunstmaan\NodeBundle\Router\SlugRouter::$container has been deprecated with message: in KunstmaanNodeBundle 5.1 and will be removed in KunstmaanNodeBundle 6.0.
This property has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.
Loading history...
|
|||
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); |
|
0 ignored issues
–
show
It seems like
$referenceType defined by parameter $referenceType on line 165 can also be of type boolean ; however, Symfony\Component\Routin...rlGenerator::generate() does only seem to accept integer , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
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 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 | NodeTranslation::class |
|
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 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.