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