Completed
Push — EZP-31000 ( 2d6acd )
by
unknown
20:00
created

UrlAliasGeneratorTest::testIsPrefixExcluded()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the UrlAliasGeneratorTest class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\Core\MVC\Symfony\Routing\Tests;
10
11
use eZ\Publish\API\Repository\LocationService;
12
use eZ\Publish\API\Repository\URLAliasService;
13
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
14
use eZ\Publish\API\Repository\Values\Content\URLAlias;
15
use eZ\Publish\API\Repository\Values\User\UserReference;
16
use eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator;
17
use eZ\Publish\Core\Repository\Permission\PermissionResolver;
18
use eZ\Publish\Core\MVC\Symfony\SiteAccess;
19
use eZ\Publish\Core\MVC\Symfony\SiteAccess\SiteAccessRouterInterface;
20
use eZ\Publish\Core\MVC\ConfigResolverInterface;
21
use eZ\Publish\Core\Repository\Helper\LimitationService;
22
use eZ\Publish\Core\Repository\Helper\RoleDomainMapper;
23
use eZ\Publish\Core\Repository\Repository;
24
use eZ\Publish\Core\Repository\Values\Content\Location;
25
use eZ\Publish\SPI\Persistence\User\Handler as SPIUserHandler;
26
use PHPUnit\Framework\TestCase;
27
use Psr\Log\LoggerInterface;
28
use Symfony\Component\Routing\RouterInterface;
29
30
class UrlAliasGeneratorTest extends TestCase
31
{
32
    /** @var \PHPUnit\Framework\MockObject\MockObject */
33
    private $repository;
34
35
    /** @var \PHPUnit\Framework\MockObject\MockObject */
36
    private $urlAliasService;
37
38
    /** @var \PHPUnit\Framework\MockObject\MockObject */
39
    private $locationService;
40
41
    /** @var \PHPUnit\Framework\MockObject\MockObject */
42
    private $router;
43
44
    /** @var \PHPUnit\Framework\MockObject\MockObject */
45
    private $logger;
46
47
    /** @var UrlAliasGenerator */
48
    private $urlAliasGenerator;
49
50
    /** @var \PHPUnit\Framework\MockObject\MockObject */
51
    private $siteAccessRouter;
52
53
    /** @var \PHPUnit\Framework\MockObject\MockObject */
54
    private $configResolver;
55
56
    protected function setUp()
57
    {
58
        parent::setUp();
59
        $this->router = $this->createMock(RouterInterface::class);
60
        $this->logger = $this->createMock(LoggerInterface::class);
61
        $this->siteAccessRouter = $this->createMock(SiteAccessRouterInterface::class);
62
        $this->configResolver = $this->createMock(ConfigResolverInterface::class);
63
        $repositoryClass = Repository::class;
64
        $this->repository = $repository = $this
65
            ->getMockBuilder($repositoryClass)
66
            ->disableOriginalConstructor()
67
            ->setMethods(
68
                array_diff(
69
                    get_class_methods($repositoryClass),
70
                    ['sudo']
71
                )
72
            )
73
            ->getMock();
74
        $this->urlAliasService = $this->createMock(URLAliasService::class);
75
        $this->locationService = $this->createMock(LocationService::class);
76
        $this->repository
77
            ->expects($this->any())
78
            ->method('getURLAliasService')
79
            ->will($this->returnValue($this->urlAliasService));
80
        $this->repository
81
            ->expects($this->any())
82
            ->method('getLocationService')
83
            ->will($this->returnValue($this->locationService));
84
        $repository
85
            ->expects($this->any())
86
            ->method('getPermissionResolver')
87
            ->will($this->returnValue($this->getPermissionResolverMock()));
88
89
        $urlAliasCharmap = [
90
            '"' => '%22',
91
            "'" => '%27',
92
            '<' => '%3C',
93
            '>' => '%3E',
94
        ];
95
        $this->urlAliasGenerator = new UrlAliasGenerator(
96
            $this->repository,
97
            $this->router,
98
            $this->configResolver,
99
            $urlAliasCharmap
100
        );
101
        $this->urlAliasGenerator->setLogger($this->logger);
102
        $this->urlAliasGenerator->setSiteAccessRouter($this->siteAccessRouter);
103
    }
104
105
    public function testGetPathPrefixByRootLocationId()
106
    {
107
        $rootLocationId = 123;
108
        $rootLocation = new Location(['id' => $rootLocationId]);
109
        $pathPrefix = '/foo/bar';
110
        $rootUrlAlias = new URLAlias(['path' => $pathPrefix]);
111
        $this->locationService
112
            ->expects($this->once())
113
            ->method('loadLocation')
114
            ->with($rootLocationId)
115
            ->will($this->returnValue($rootLocation));
116
        $this->urlAliasService
117
            ->expects($this->once())
118
            ->method('reverseLookup')
119
            ->with($rootLocation)
120
            ->will($this->returnValue($rootUrlAlias));
121
122
        $this->assertSame($pathPrefix, $this->urlAliasGenerator->getPathPrefixByRootLocationId($rootLocationId));
123
    }
124
125
    /**
126
     * @dataProvider providerTestIsPrefixExcluded
127
     */
128
    public function testIsPrefixExcluded($uri, $expectedIsExcluded)
129
    {
130
        $this->urlAliasGenerator->setExcludedUriPrefixes(
131
            [
132
                '/products',
133
                '/shared/content',
134
                '/something/in-the-way/',
135
            ]
136
        );
137
        $this->assertSame($expectedIsExcluded, $this->urlAliasGenerator->isUriPrefixExcluded($uri));
138
    }
139
140
    public function providerTestIsPrefixExcluded()
141
    {
142
        return [
143
            ['/foo/bar', false],
144
            ['/products/bar', true],
145
            ['/ProDUctS/eZ-Publish', true],
146
            ['/ProductsFoo/eZ-Publish', true],
147
            ['/shared/foo', false],
148
            ['/SHARED/contenT/bar', true],
149
            ['/SomeThing/bidule/chose', false],
150
            ['/SomeThing/in-the-way/truc/', true],
151
            ['/CMS/eZ-Publish', false],
152
            ['/Lyon/Best/city', false],
153
        ];
154
    }
155
156
    public function testLoadLocation()
157
    {
158
        $locationId = 123;
159
        $location = new Location(['id' => $locationId]);
160
        $this->locationService
161
            ->expects($this->once())
162
            ->method('loadLocation')
163
            ->with($locationId)
164
            ->will($this->returnValue($location));
165
        $this->urlAliasGenerator->loadLocation($locationId);
166
    }
167
168
    /**
169
     * @dataProvider providerTestDoGenerate
170
     */
171
    public function testDoGenerate(URLAlias $urlAlias, array $parameters, $expected)
172
    {
173
        $location = new Location(['id' => 123]);
174
        $this->urlAliasService
175
            ->expects($this->once())
176
            ->method('listLocationAliases')
177
            ->with($location, false)
178
            ->will($this->returnValue([$urlAlias]));
179
180
        $this->urlAliasGenerator->setSiteAccess(new SiteAccess('test', 'fake', $this->createMock(SiteAccess\URILexer::class)));
181
182
        $this->assertSame($expected, $this->urlAliasGenerator->doGenerate($location, $parameters));
183
    }
184
185
    public function providerTestDoGenerate()
186
    {
187
        return [
188
            'without_parameters' => [
189
                new URLAlias(['path' => '/foo/bar']),
190
                [],
191
                '/foo/bar',
192
            ],
193
            'one_parameter' => [
194
                new URLAlias(['path' => '/foo/bar']),
195
                ['some' => 'thing'],
196
                '/foo/bar?some=thing',
197
            ],
198
            'two_parameters' => [
199
                new URLAlias(['path' => '/foo/bar']),
200
                ['some' => 'thing', 'truc' => 'muche'],
201
                '/foo/bar?some=thing&truc=muche',
202
            ],
203
            '_fragment in parameters' => [
204
                new URLAlias(['path' => '/foo/bar']),
205
                ['some' => 'thing', 'truc' => 'muche', '_fragment' => 'foo'],
206
                '/foo/bar?some=thing&truc=muche#foo',
207
            ],
208
        ];
209
    }
210
211
    /**
212
     * @dataProvider providerTestDoGenerateWithSiteaccess
213
     */
214 View Code Duplication
    public function testDoGenerateWithSiteAccessParam(URLAlias $urlAlias, array $parameters, $expected)
215
    {
216
        $siteaccessName = 'foo';
217
        $parameters += ['siteaccess' => $siteaccessName];
218
        $languages = ['esl-ES', 'fre-FR', 'eng-GB'];
219
220
        $saRootLocations = [
221
            'foo' => 2,
222
            'bar' => 100,
223
        ];
224
        $treeRootUrlAlias = [
225
            2 => new URLAlias(['path' => '/']),
226
            100 => new URLAlias(['path' => '/foo/bar']),
227
        ];
228
229
        $this->configResolver
230
            ->expects($this->any())
231
            ->method('getParameter')
232
            ->will(
233
                $this->returnValueMap(
234
                    [
235
                        ['languages', null, 'foo', $languages],
236
                        ['languages', null, 'bar', $languages],
237
                        ['content.tree_root.location_id', null, 'foo', $saRootLocations['foo']],
238
                        ['content.tree_root.location_id', null, 'bar', $saRootLocations['bar']],
239
                    ]
240
                )
241
            );
242
243
        $location = new Location(['id' => 123]);
244
        $this->urlAliasService
245
            ->expects($this->exactly(1))
246
            ->method('listLocationAliases')
247
            ->will(
248
                $this->returnValueMap(
249
                    [
250
                        [$location, false, null, null, $languages, [$urlAlias]],
251
                    ]
252
                )
253
            );
254
255
        $this->locationService
256
            ->expects($this->once())
257
            ->method('loadLocation')
258
            ->will(
259
                $this->returnCallback(
260
                    function ($locationId) {
261
                        return new Location(['id' => $locationId]);
262
                    }
263
                )
264
            );
265
        $this->urlAliasService
266
            ->expects($this->exactly(1))
267
            ->method('reverseLookup')
268
            ->will(
269
                $this->returnCallback(
270
                    function ($location) use ($treeRootUrlAlias) {
271
                        return $treeRootUrlAlias[$location->id];
272
                    }
273
                )
274
            );
275
276
        $this->urlAliasGenerator->setSiteAccess(new SiteAccess('test', 'fake', $this->createMock(SiteAccess\URILexer::class)));
277
278
        $this->assertSame($expected, $this->urlAliasGenerator->doGenerate($location, $parameters));
279
    }
280
281
    public function providerTestDoGenerateWithSiteaccess()
282
    {
283
        return [
284
            [
285
                new URLAlias(['path' => '/foo/bar']),
286
                [],
287
                '/foo/bar',
288
            ],
289
            [
290
                new URLAlias(['path' => '/foo/bar/baz']),
291
                ['siteaccess' => 'bar'],
292
                '/baz',
293
            ],
294
            [
295
                new UrlAlias(['path' => '/special-chars-"<>\'']),
296
                [],
297
                '/special-chars-%22%3C%3E%27',
298
            ],
299
        ];
300
    }
301
302
    /**
303
     * @dataProvider providerTestDoGenerateWithFragment
304
     */
305 View Code Duplication
    public function testDoGenerateWithFragmentParameter(URLAlias $urlAlias, array $parameters, $expected)
306
    {
307
        $siteaccessName = 'foo';
308
        $parameters += ['siteaccess' => $siteaccessName];
309
        $languages = ['esl-ES', 'fre-FR', 'eng-GB'];
310
311
        $saRootLocations = [
312
            'foo' => 2,
313
            'bar' => 100,
314
        ];
315
        $treeRootUrlAlias = [
316
            2 => new URLAlias(['path' => '/']),
317
            100 => new URLAlias(['path' => '/foo/bar']),
318
        ];
319
320
        $this->configResolver
321
            ->expects($this->any())
322
            ->method('getParameter')
323
            ->will(
324
                $this->returnValueMap(
325
                    [
326
                        ['languages', null, 'foo', $languages],
327
                        ['languages', null, 'bar', $languages],
328
                        ['content.tree_root.location_id', null, 'foo', $saRootLocations['foo']],
329
                        ['content.tree_root.location_id', null, 'bar', $saRootLocations['bar']],
330
                    ]
331
                )
332
            );
333
334
        $location = new Location(['id' => 123]);
335
        $this->urlAliasService
336
            ->expects($this->exactly(1))
337
            ->method('listLocationAliases')
338
            ->will(
339
                $this->returnValueMap(
340
                    [
341
                        [$location, false, null, null, $languages, [$urlAlias]],
342
                    ]
343
                )
344
            );
345
346
        $this->locationService
347
            ->expects($this->once())
348
            ->method('loadLocation')
349
            ->will(
350
                $this->returnCallback(
351
                    function ($locationId) {
352
                        return new Location(['id' => $locationId]);
353
                    }
354
                )
355
            );
356
        $this->urlAliasService
357
            ->expects($this->exactly(1))
358
            ->method('reverseLookup')
359
            ->will(
360
                $this->returnCallback(
361
                    function ($location) use ($treeRootUrlAlias) {
362
                        return $treeRootUrlAlias[$location->id];
363
                    }
364
                )
365
            );
366
367
        $this->urlAliasGenerator->setSiteAccess(new SiteAccess('test', 'fake', $this->createMock(SiteAccess\URILexer::class)));
368
369
        $this->assertSame($expected, $this->urlAliasGenerator->doGenerate($location, $parameters));
370
    }
371
372
    public function providerTestDoGenerateWithFragment()
373
    {
374
        return [
375
            'fragment' => [
376
                new URLAlias(['path' => '/foo/bar']),
377
                ['_fragment' => 'qux'],
378
                '/foo/bar#qux',
379
            ],
380
            'fragment_and_siteaccess' => [
381
                new URLAlias(['path' => '/foo/bar/baz']),
382
                ['_fragment' => 'qux', 'siteaccess' => 'bar'],
383
                '/baz#qux',
384
            ],
385
            'fragment_and_special_chars' => [
386
                new UrlAlias(['path' => '/special-chars-"<>\'']),
387
                ['_fragment' => 'qux'],
388
                '/special-chars-%22%3C%3E%27#qux',
389
            ],
390
            'fragment_site_siteaccess_and_params' => [
391
                new UrlAlias(['path' => '/foo/bar/baz']),
392
                ['_fragment' => 'qux', 'siteaccess' => 'bar', 'some' => 'foo'],
393
                '/baz?some=foo#qux',
394
            ],
395
        ];
396
    }
397
398
    public function testDoGenerateNoUrlAlias()
399
    {
400
        $location = new Location(['id' => 123, 'contentInfo' => new ContentInfo(['id' => 456])]);
401
        $uri = "/content/location/$location->id";
402
        $this->urlAliasService
403
            ->expects($this->once())
404
            ->method('listLocationAliases')
405
            ->with($location, false)
406
            ->will($this->returnValue([]));
407
        $this->router
408
            ->expects($this->once())
409
            ->method('generate')
410
            ->with(
411
                UrlAliasGenerator::INTERNAL_CONTENT_VIEW_ROUTE,
412
                ['contentId' => $location->contentId, 'locationId' => $location->id]
413
            )
414
            ->will($this->returnValue($uri));
415
416
        $this->assertSame($uri, $this->urlAliasGenerator->doGenerate($location, []));
417
    }
418
419
    /**
420
     * @dataProvider providerTestDoGenerateRootLocation
421
     */
422
    public function testDoGenerateRootLocation(URLAlias $urlAlias, $isOutsideAndNotExcluded, $expected, $pathPrefix)
423
    {
424
        $excludedPrefixes = ['/products', '/shared'];
425
        $rootLocationId = 456;
426
        $this->urlAliasGenerator->setRootLocationId($rootLocationId);
427
        $this->urlAliasGenerator->setExcludedUriPrefixes($excludedPrefixes);
428
        $location = new Location(['id' => 123]);
429
430
        $rootLocation = new Location(['id' => $rootLocationId]);
431
        $rootUrlAlias = new URLAlias(['path' => $pathPrefix]);
432
        $this->locationService
433
            ->expects($this->once())
434
            ->method('loadLocation')
435
            ->with($rootLocationId)
436
            ->will($this->returnValue($rootLocation));
437
        $this->urlAliasService
438
            ->expects($this->once())
439
            ->method('reverseLookup')
440
            ->with($rootLocation)
441
            ->will($this->returnValue($rootUrlAlias));
442
443
        $this->urlAliasService
444
            ->expects($this->once())
445
            ->method('listLocationAliases')
446
            ->with($location, false)
447
            ->will($this->returnValue([$urlAlias]));
448
449
        if ($isOutsideAndNotExcluded) {
450
            $this->logger
451
                ->expects($this->once())
452
                ->method('warning');
453
        }
454
455
        $this->assertSame($expected, $this->urlAliasGenerator->doGenerate($location, []));
456
    }
457
458
    public function providerTestDoGenerateRootLocation()
459
    {
460
        return [
461
            [
462
                new UrlAlias(['path' => '/my/root-folder/foo/bar']),
463
                false,
464
                '/foo/bar',
465
                '/my/root-folder',
466
            ],
467
            [
468
                new UrlAlias(['path' => '/my/root-folder/something']),
469
                false,
470
                '/something',
471
                '/my/root-folder',
472
            ],
473
            [
474
                new UrlAlias(['path' => '/my/root-folder']),
475
                false,
476
                '/',
477
                '/my/root-folder',
478
            ],
479
            [
480
                new UrlAlias(['path' => '/foo/bar']),
481
                false,
482
                '/foo/bar',
483
                '/',
484
            ],
485
            [
486
                new UrlAlias(['path' => '/something']),
487
                false,
488
                '/something',
489
                '/',
490
            ],
491
            [
492
                new UrlAlias(['path' => '/']),
493
                false,
494
                '/',
495
                '/',
496
            ],
497
            [
498
                new UrlAlias(['path' => '/outside/tree/foo/bar']),
499
                true,
500
                '/outside/tree/foo/bar',
501
                '/my/root-folder',
502
            ],
503
            [
504
                new UrlAlias(['path' => '/products/ez-publish']),
505
                false,
506
                '/products/ez-publish',
507
                '/my/root-folder',
508
            ],
509
            [
510
                new UrlAlias(['path' => '/shared/some-content']),
511
                false,
512
                '/shared/some-content',
513
                '/my/root-folder',
514
            ],
515
            [
516
                new UrlAlias(['path' => '/products/ez-publish']),
517
                false,
518
                '/products/ez-publish',
519
                '/prod',
520
            ],
521
        ];
522
    }
523
524 View Code Duplication
    protected function getPermissionResolverMock()
525
    {
526
        return $this
527
            ->getMockBuilder(PermissionResolver::class)
528
            ->setMethods(null)
529
            ->setConstructorArgs(
530
                [
531
                    $this->createMock(RoleDomainMapper::class),
532
                    $this->createMock(LimitationService::class),
533
                    $this->createMock(SPIUserHandler::class),
534
                    $this->createMock(UserReference::class),
535
                ]
536
            )
537
            ->getMock();
538
    }
539
}
540