Completed
Push — master ( 06c1ce...67d37c )
by Jeroen
06:20
created

src/Kunstmaan/NodeBundle/Router/SlugRouter.php (1 issue)

Upgrade to new PHP Analysis Engine

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);
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);
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 \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