Completed
Push — EZP-31110 ( 682d94...63ed61 )
by
unknown
20:06
created

UrlAliasRouterTest   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 443
Duplicated Lines 25.73 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
dl 114
loc 443
rs 10
c 0
b 0
f 0
wmc 11
lcom 1
cbo 8

11 Methods

Rating   Name   Duplication   Size   Complexity  
B testMatchRequestWithRootLocation() 0 55 1
A setUp() 0 17 1
A getRouter() 0 7 1
A resetConfigResolver() 0 6 1
A testMatchRequestDeactivatedUrlAlias() 0 15 1
B testMatchRequestWithRootLocationAndSiteRoot() 0 61 1
B testMatchRequestLocationCaseRedirectWithRootLocation() 57 57 1
B testMatchRequestLocationCaseRedirectWithRootRootLocation() 57 57 1
A testMatchRequestResourceCaseRedirectWithRootLocation() 0 47 1
A testMatchRequestVirtualCaseRedirectWithRootLocation() 0 45 1
A testMatchRequestWithRootLocationAndExclusion() 0 54 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
5
 * @license For full copyright and license information view LICENSE file distributed with this source code.
6
 */
7
namespace eZ\Bundle\EzPublishCoreBundle\Tests\Routing;
8
9
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
10
use eZ\Publish\API\Repository\LocationService;
11
use eZ\Publish\API\Repository\URLAliasService;
12
use eZ\Publish\API\Repository\ContentService;
13
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
14
use eZ\Publish\Core\MVC\ConfigResolverInterface;
15
use eZ\Publish\Core\Repository\Values\Content\Location;
16
use Symfony\Component\DependencyInjection\ContainerInterface;
17
use Symfony\Component\Routing\RequestContext;
18
use eZ\Bundle\EzPublishCoreBundle\Routing\UrlAliasRouter;
19
use eZ\Publish\API\Repository\Values\Content\URLAlias;
20
use eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator;
21
use eZ\Publish\Core\MVC\Symfony\Routing\Tests\UrlAliasRouterTest as BaseUrlAliasRouterTest;
22
use eZ\Publish\Core\MVC\Symfony\View\Manager as ViewManager;
23
24
class UrlAliasRouterTest extends BaseUrlAliasRouterTest
25
{
26
    /** @var \PHPUnit\Framework\MockObject\MockObject */
27
    private $configResolver;
28
29
    protected function setUp()
30
    {
31
        $this->configResolver = $this->createMock(ConfigResolverInterface::class);
32
        $this->configResolver
33
            ->expects($this->any())
34
            ->method('getParameter')
35
            ->will(
36
                $this->returnValueMap(
37
                    [
38
                        ['url_alias_router', null, null, true],
39
                        ['content.tree_root.location_id', null, null, null],
40
                        ['content.tree_root.excluded_uri_prefixes', null, null, []],
41
                    ]
42
                )
43
            );
44
        parent::setUp();
45
    }
46
47
    protected function getRouter(LocationService $locationService, URLAliasService $urlAliasService, ContentService $contentService, UrlAliasGenerator $urlAliasGenerator, RequestContext $requestContext)
48
    {
49
        $router = new UrlAliasRouter($locationService, $urlAliasService, $contentService, $urlAliasGenerator, $requestContext);
50
        $router->setConfigResolver($this->configResolver);
51
52
        return $router;
53
    }
54
55
    /**
56
     * Resets container and configResolver mocks.
57
     */
58
    protected function resetConfigResolver()
59
    {
60
        $this->configResolver = $this->createMock(ConfigResolverInterface::class);
61
        $this->container = $this->createMock(ContainerInterface::class);
0 ignored issues
show
Bug introduced by
The property container does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
62
        $this->router->setConfigResolver($this->configResolver);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class eZ\Publish\Core\MVC\Symfony\Routing\UrlAliasRouter as the method setConfigResolver() does only exist in the following sub-classes of eZ\Publish\Core\MVC\Symfony\Routing\UrlAliasRouter: eZ\Bundle\EzPublishCoreB...\Routing\UrlAliasRouter. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
63
    }
64
65
    /**
66
     * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException
67
     */
68
    public function testMatchRequestDeactivatedUrlAlias()
69
    {
70
        $this->resetConfigResolver();
71
        $this->configResolver
72
            ->expects($this->any())
73
            ->method('getParameter')
74
            ->will(
75
                $this->returnValueMap(
76
                    [
77
                        ['url_alias_router', null, null, false],
78
                    ]
79
                )
80
            );
81
        $this->router->matchRequest($this->getRequestByPathInfo('/foo'));
82
    }
83
84
    public function testMatchRequestWithRootLocation()
85
    {
86
        $rootLocationId = 123;
87
        $this->resetConfigResolver();
88
        $this->configResolver
89
            ->expects($this->any())
90
            ->method('getParameter')
91
            ->will(
92
                $this->returnValueMap(
93
                    [
94
                        ['url_alias_router', null, null, true],
95
                    ]
96
                )
97
            );
98
        $this->router->setRootLocationId($rootLocationId);
99
100
        $prefix = '/root/prefix';
101
        $this->urlALiasGenerator
102
            ->expects($this->exactly(2))
103
            ->method('getPathPrefixByRootLocationId')
104
            ->with($rootLocationId)
105
            ->will($this->returnValue($prefix));
106
107
        $locationId = 789;
108
        $path = '/foo/bar';
109
        $urlAlias = new URLAlias(
110
            [
111
                'destination' => $locationId,
112
                'path' => $prefix . $path,
113
                'type' => URLAlias::LOCATION,
114
                'isHistory' => false,
115
            ]
116
        );
117
        $this->urlAliasService
118
            ->expects($this->once())
119
            ->method('lookup')
120
            ->with($prefix . $path)
121
            ->will($this->returnValue($urlAlias));
122
123
        $this->urlALiasGenerator
124
            ->expects($this->once())
125
            ->method('loadLocation')
126
            ->will($this->returnValue(new Location(['contentInfo' => new ContentInfo(['id' => 456])])));
127
128
        $expected = [
129
            '_route' => UrlAliasRouter::URL_ALIAS_ROUTE_NAME,
130
            '_controller' => UrlAliasRouter::VIEW_ACTION,
131
            'locationId' => $locationId,
132
            'contentId' => 456,
133
            'viewType' => ViewManager::VIEW_TYPE_FULL,
134
            'layout' => true,
135
        ];
136
        $request = $this->getRequestByPathInfo($path);
137
        $this->assertEquals($expected, $this->router->matchRequest($request));
138
    }
139
140
    public function testMatchRequestWithRootLocationAndSiteRoot()
141
    {
142
        $rootLocationId = 123;
143
        $this->resetConfigResolver();
144
        $this->configResolver
145
            ->expects($this->any())
146
            ->method('getParameter')
147
            ->will(
148
                $this->returnValueMap(
149
                    [
150
                        ['url_alias_router', null, null, true],
151
                    ]
152
                )
153
            );
154
        $this->router->setRootLocationId($rootLocationId);
155
156
        $prefix = '/root/prefix';
157
        $this->urlALiasGenerator
158
            ->expects($this->exactly(3))
159
            ->method('getPathPrefixByRootLocationId')
160
            ->with($rootLocationId)
161
            ->will($this->returnValue($prefix));
162
163
        $locationId = 789;
164
        $path = '/foo/bar';
165
        $urlAlias = new URLAlias(
166
            [
167
                'destination' => $locationId,
168
                'path' => $path,
169
                'type' => URLAlias::LOCATION,
170
                'isHistory' => false,
171
            ]
172
        );
173
        $this->urlAliasService
174
            ->expects($this->at(0))
175
            ->method('lookup')
176
            ->with($prefix . $path)
177
            ->willThrowException($this->createMock(NotFoundException::class));
178
179
        $this->urlAliasService
180
            ->expects($this->at(1))
181
            ->method('lookup')
182
            ->with($path)
183
            ->will($this->returnValue($urlAlias));
184
185
        $this->urlALiasGenerator
186
            ->expects($this->once())
187
            ->method('loadLocation')
188
            ->will($this->returnValue(new Location(['contentInfo' => new ContentInfo(['id' => 456])])));
189
190
        $expected = [
191
            '_route' => UrlAliasRouter::URL_ALIAS_ROUTE_NAME,
192
            '_controller' => UrlAliasRouter::VIEW_ACTION,
193
            'locationId' => $locationId,
194
            'contentId' => 456,
195
            'viewType' => ViewManager::VIEW_TYPE_FULL,
196
            'layout' => true,
197
        ];
198
        $request = $this->getRequestByPathInfo($path);
199
        $this->assertEquals($expected, $this->router->matchRequest($request));
200
    }
201
202 View Code Duplication
    public function testMatchRequestLocationCaseRedirectWithRootLocation()
203
    {
204
        $rootLocationId = 123;
205
        $this->resetConfigResolver();
206
        $this->configResolver
207
            ->expects($this->any())
208
            ->method('getParameter')
209
            ->will(
210
                $this->returnValueMap(
211
                    [
212
                        ['url_alias_router', null, null, true],
213
                    ]
214
                )
215
            );
216
        $this->router->setRootLocationId($rootLocationId);
217
218
        $prefix = '/root/prefix';
219
        $this->urlALiasGenerator
220
            ->expects($this->exactly(2))
221
            ->method('getPathPrefixByRootLocationId')
222
            ->with($rootLocationId)
223
            ->will($this->returnValue($prefix));
224
        $this->urlALiasGenerator
225
            ->expects($this->once())
226
            ->method('loadLocation')
227
            ->will($this->returnValue(new Location(['contentInfo' => new ContentInfo(['id' => 456])])));
228
229
        $locationId = 789;
230
        $path = '/foo/bar';
231
        $requestedPath = '/Foo/Bar';
232
        $urlAlias = new URLAlias(
233
            [
234
                'destination' => $locationId,
235
                'path' => $prefix . $path,
236
                'type' => URLAlias::LOCATION,
237
                'isHistory' => false,
238
            ]
239
        );
240
        $this->urlAliasService
241
            ->expects($this->once())
242
            ->method('lookup')
243
            ->with($prefix . $requestedPath)
244
            ->will($this->returnValue($urlAlias));
245
246
        $expected = [
247
            '_route' => UrlAliasRouter::URL_ALIAS_ROUTE_NAME,
248
            '_controller' => UrlAliasRouter::VIEW_ACTION,
249
            'locationId' => $locationId,
250
            'contentId' => 456,
251
            'viewType' => ViewManager::VIEW_TYPE_FULL,
252
            'layout' => true,
253
            'semanticPathinfo' => $path,
254
            'needsRedirect' => true,
255
        ];
256
        $request = $this->getRequestByPathInfo($requestedPath);
257
        $this->assertEquals($expected, $this->router->matchRequest($request));
258
    }
259
260 View Code Duplication
    public function testMatchRequestLocationCaseRedirectWithRootRootLocation()
261
    {
262
        $rootLocationId = 123;
263
        $this->resetConfigResolver();
264
        $this->configResolver
265
            ->expects($this->any())
266
            ->method('getParameter')
267
            ->will(
268
                $this->returnValueMap(
269
                    [
270
                        ['url_alias_router', null, null, true],
271
                    ]
272
                )
273
            );
274
        $this->router->setRootLocationId($rootLocationId);
275
276
        $prefix = '/';
277
        $this->urlALiasGenerator
278
            ->expects($this->exactly(2))
279
            ->method('getPathPrefixByRootLocationId')
280
            ->with($rootLocationId)
281
            ->will($this->returnValue($prefix));
282
283
        $locationId = 789;
284
        $path = '/foo/bar';
285
        $requestedPath = '/Foo/Bar';
286
        $urlAlias = new URLAlias(
287
            [
288
                'destination' => $locationId,
289
                'path' => $path,
290
                'type' => URLAlias::LOCATION,
291
                'isHistory' => false,
292
            ]
293
        );
294
        $this->urlAliasService
295
            ->expects($this->once())
296
            ->method('lookup')
297
            ->with($requestedPath)
298
            ->will($this->returnValue($urlAlias));
299
        $this->urlALiasGenerator
300
            ->expects($this->once())
301
            ->method('loadLocation')
302
            ->will($this->returnValue(new Location(['contentInfo' => new ContentInfo(['id' => 456])])));
303
304
        $expected = [
305
            '_route' => UrlAliasRouter::URL_ALIAS_ROUTE_NAME,
306
            '_controller' => UrlAliasRouter::VIEW_ACTION,
307
            'locationId' => $locationId,
308
            'contentId' => 456,
309
            'viewType' => ViewManager::VIEW_TYPE_FULL,
310
            'layout' => true,
311
            'semanticPathinfo' => $path,
312
            'needsRedirect' => true,
313
        ];
314
        $request = $this->getRequestByPathInfo($requestedPath);
315
        $this->assertEquals($expected, $this->router->matchRequest($request));
316
    }
317
318
    public function testMatchRequestResourceCaseRedirectWithRootLocation()
319
    {
320
        $rootLocationId = 123;
321
        $this->resetConfigResolver();
322
        $this->configResolver
323
            ->expects($this->any())
324
            ->method('getParameter')
325
            ->will(
326
                $this->returnValueMap(
327
                    [
328
                        ['url_alias_router', null, null, true],
329
                    ]
330
                )
331
            );
332
        $this->router->setRootLocationId($rootLocationId);
333
334
        $prefix = '/root/prefix';
335
        $this->urlALiasGenerator
336
            ->expects($this->exactly(2))
337
            ->method('getPathPrefixByRootLocationId')
338
            ->with($rootLocationId)
339
            ->will($this->returnValue($prefix));
340
341
        $path = '/foo/bar';
342
        $requestedPath = '/Foo/Bar';
343
        $urlAlias = new URLAlias(
344
            [
345
                'destination' => '/content/search',
346
                'path' => $prefix . $path,
347
                'type' => URLAlias::RESOURCE,
348
                'isHistory' => false,
349
            ]
350
        );
351
        $this->urlAliasService
352
            ->expects($this->once())
353
            ->method('lookup')
354
            ->with($prefix . $requestedPath)
355
            ->will($this->returnValue($urlAlias));
356
357
        $expected = [
358
            '_route' => UrlAliasRouter::URL_ALIAS_ROUTE_NAME,
359
            'semanticPathinfo' => $path,
360
            'needsRedirect' => true,
361
        ];
362
        $request = $this->getRequestByPathInfo($requestedPath);
363
        $this->assertEquals($expected, $this->router->matchRequest($request));
364
    }
365
366
    public function testMatchRequestVirtualCaseRedirectWithRootLocation()
367
    {
368
        $rootLocationId = 123;
369
        $this->resetConfigResolver();
370
        $this->configResolver
371
            ->expects($this->any())
372
            ->method('getParameter')
373
            ->will(
374
                $this->returnValueMap(
375
                    [
376
                        ['url_alias_router', null, null, true],
377
                    ]
378
                )
379
            );
380
        $this->router->setRootLocationId($rootLocationId);
381
382
        $prefix = '/root/prefix';
383
        $this->urlALiasGenerator
384
            ->expects($this->exactly(2))
385
            ->method('getPathPrefixByRootLocationId')
386
            ->with($rootLocationId)
387
            ->will($this->returnValue($prefix));
388
389
        $path = '/foo/bar';
390
        $requestedPath = '/Foo/Bar';
391
        $urlAlias = new URLAlias(
392
            [
393
                'path' => $prefix . $path,
394
                'type' => URLAlias::VIRTUAL,
395
            ]
396
        );
397
        $this->urlAliasService
398
            ->expects($this->once())
399
            ->method('lookup')
400
            ->with($prefix . $requestedPath)
401
            ->will($this->returnValue($urlAlias));
402
403
        $expected = [
404
            '_route' => UrlAliasRouter::URL_ALIAS_ROUTE_NAME,
405
            'semanticPathinfo' => $path,
406
            'needsRedirect' => true,
407
        ];
408
        $request = $this->getRequestByPathInfo($requestedPath);
409
        $this->assertEquals($expected, $this->router->matchRequest($request));
410
    }
411
412
    public function testMatchRequestWithRootLocationAndExclusion()
413
    {
414
        $this->resetConfigResolver();
415
        $this->configResolver
416
            ->expects($this->any())
417
            ->method('getParameter')
418
            ->will(
419
                $this->returnValueMap(
420
                    [
421
                        ['url_alias_router', null, null, true],
422
                        ['content.tree_root.location_id', null, null, 123],
423
                        ['content.tree_root.excluded_uri_prefixes', null, null, ['/shared/content']],
424
                    ]
425
                )
426
            );
427
        $this->router->setRootLocationId(123);
428
429
        $pathInfo = '/shared/content/foo-bar';
430
        $destinationId = 789;
431
        $this->urlALiasGenerator
432
            ->expects($this->any())
433
            ->method('isUriPrefixExcluded')
434
            ->with($pathInfo)
435
            ->will($this->returnValue(true));
436
437
        $urlAlias = new URLAlias(
438
            [
439
                'path' => $pathInfo,
440
                'type' => UrlAlias::LOCATION,
441
                'destination' => $destinationId,
442
                'isHistory' => false,
443
            ]
444
        );
445
        $request = $this->getRequestByPathInfo($pathInfo);
446
        $this->urlAliasService
447
            ->expects($this->once())
448
            ->method('lookup')
449
            ->with($pathInfo)
450
            ->will($this->returnValue($urlAlias));
451
        $this->urlALiasGenerator
452
            ->expects($this->once())
453
            ->method('loadLocation')
454
            ->will($this->returnValue(new Location(['contentInfo' => new ContentInfo(['id' => 456])])));
455
456
        $expected = [
457
            '_route' => UrlAliasRouter::URL_ALIAS_ROUTE_NAME,
458
            '_controller' => UrlAliasRouter::VIEW_ACTION,
459
            'locationId' => $destinationId,
460
            'contentId' => 456,
461
            'viewType' => ViewManager::VIEW_TYPE_FULL,
462
            'layout' => true,
463
        ];
464
        $this->assertEquals($expected, $this->router->matchRequest($request));
465
    }
466
}
467