Completed
Push — missing_siteaccess_aware_tests ( c030ea...f3bf75 )
by
unknown
29:08 queued 08:31
created

URLAliasServiceTest::testLookupOnRenamedParent()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 61

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 61
rs 8.8509
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * File containing the URLAliasServiceTest 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\API\Repository\Tests;
10
11
use Doctrine\DBAL\Connection;
12
use eZ\Publish\API\Repository\Exceptions\InvalidArgumentException;
13
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
14
use eZ\Publish\API\Repository\Tests\Common\SlugConverter as TestSlugConverter;
15
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
16
use eZ\Publish\API\Repository\Values\Content\Location;
17
use eZ\Publish\API\Repository\Values\Content\URLAlias;
18
use Exception;
19
use PDO;
20
use RuntimeException;
21
22
/**
23
 * Test case for operations in the URLAliasService using in memory storage.
24
 *
25
 * @see \eZ\Publish\API\Repository\URLAliasService
26
 * @group url-alias
27
 */
28
class URLAliasServiceTest extends BaseTest
29
{
30
    /**
31
     * Tests that the required <b>LocationService::loadLocation()</b>
32
     * at least returns an object, because this method is utilized in several
33
     * tests.
34
     */
35
    protected function setUp()
36
    {
37
        parent::setUp();
38
39
        try {
40
            // Load the LocationService
41
            $locationService = $this->getRepository()->getLocationService();
42
43
            $membersUserGroupLocationId = 12;
44
45
            // Load a location instance
46
            $location = $locationService->loadLocation(
47
                $membersUserGroupLocationId
48
            );
49
50
            if (false === is_object($location)) {
51
                $this->markTestSkipped(
52
                    'This test cannot be executed, because the utilized ' .
53
                    'LocationService::loadLocation() does not ' .
54
                    'return an object.'
55
                );
56
            }
57
        } catch (Exception $e) {
58
            $this->markTestSkipped(
59
                'This test cannot be executed, because the utilized ' .
60
                'LocationService::loadLocation() failed with ' .
61
                PHP_EOL . PHP_EOL .
62
                $e->getTraceAsString()
63
            );
64
        }
65
    }
66
67
    /**
68
     * Test for the createUrlAlias() method.
69
     *
70
     * @see \eZ\Publish\API\Repository\URLAliasService::createUrlAlias()
71
     */
72
    public function testCreateUrlAlias()
73
    {
74
        $repository = $this->getRepository();
75
76
        $locationId = $this->generateId('location', 5);
77
78
        /* BEGIN: Use Case */
79
        // $locationId is the ID of an existing location
80
81
        $locationService = $repository->getLocationService();
82
        $urlAliasService = $repository->getURLAliasService();
83
84
        $location = $locationService->loadLocation($locationId);
85
86
        $createdUrlAlias = $urlAliasService->createUrlAlias($location, '/Home/My-New-Site', 'eng-US');
87
        /* END: Use Case */
88
89
        $this->assertInstanceOf(
90
            URLAlias::class,
91
            $createdUrlAlias
92
        );
93
94
        return [$createdUrlAlias, $location->id];
95
    }
96
97
    /**
98
     * @param array $testData
99
     *
100
     * @depends testCreateUrlAlias
101
     */
102 View Code Duplication
    public function testCreateUrlAliasPropertyValues(array $testData)
103
    {
104
        list($createdUrlAlias, $locationId) = $testData;
105
106
        $this->assertNotNull($createdUrlAlias->id);
107
108
        $this->assertPropertiesCorrect(
109
            [
110
                'type' => URLAlias::LOCATION,
111
                'destination' => $locationId,
112
                'path' => '/Home/My-New-Site',
113
                'languageCodes' => ['eng-US'],
114
                'alwaysAvailable' => false,
115
                'isHistory' => false,
116
                'isCustom' => true,
117
                'forward' => false,
118
            ],
119
            $createdUrlAlias
120
        );
121
    }
122
123
    /**
124
     * Test for the createUrlAlias() method.
125
     *
126
     * @see \eZ\Publish\API\Repository\URLAliasService::createUrlAlias($location, $path, $languageCode, $forwarding)
127
     * @depends testCreateUrlAliasPropertyValues
128
     */
129 View Code Duplication
    public function testCreateUrlAliasWithForwarding()
130
    {
131
        $repository = $this->getRepository();
132
133
        $locationId = $this->generateId('location', 5);
134
135
        /* BEGIN: Use Case */
136
        // $locationId is the ID of an existing location
137
138
        $locationService = $repository->getLocationService();
139
        $urlAliasService = $repository->getURLAliasService();
140
141
        $location = $locationService->loadLocation($locationId);
142
143
        $createdUrlAlias = $urlAliasService->createUrlAlias($location, '/Home/My-New-Site', 'eng-US', true);
144
        /* END: Use Case */
145
146
        $this->assertInstanceOf(
147
            URLAlias::class,
148
            $createdUrlAlias
149
        );
150
151
        return [$createdUrlAlias, $location->id];
152
    }
153
154
    /**
155
     * @param array $testData
156
     *
157
     * @depends testCreateUrlAliasWithForwarding
158
     */
159 View Code Duplication
    public function testCreateUrlAliasPropertyValuesWithForwarding(array $testData)
160
    {
161
        list($createdUrlAlias, $locationId) = $testData;
162
163
        $this->assertNotNull($createdUrlAlias->id);
164
165
        $this->assertPropertiesCorrect(
166
            [
167
                'type' => URLAlias::LOCATION,
168
                'destination' => $locationId,
169
                'path' => '/Home/My-New-Site',
170
                'languageCodes' => ['eng-US'],
171
                'alwaysAvailable' => false,
172
                'isHistory' => false,
173
                'isCustom' => true,
174
                'forward' => true,
175
            ],
176
            $createdUrlAlias
177
        );
178
    }
179
180
    /**
181
     * Test for the createUrlAlias() method.
182
     *
183
     * @see \eZ\Publish\API\Repository\URLAliasService::createUrlAlias($location, $path, $languageCode, $forwarding, $alwaysAvailable)
184
     */
185 View Code Duplication
    public function testCreateUrlAliasWithAlwaysAvailable()
186
    {
187
        $repository = $this->getRepository();
188
189
        $locationId = $this->generateId('location', 5);
190
191
        /* BEGIN: Use Case */
192
        // $locationId is the ID of an existing location
193
194
        $locationService = $repository->getLocationService();
195
        $urlAliasService = $repository->getURLAliasService();
196
197
        $location = $locationService->loadLocation($locationId);
198
199
        $createdUrlAlias = $urlAliasService->createUrlAlias($location, '/Home/My-New-Site', 'eng-US', false, true);
200
        /* END: Use Case */
201
202
        $this->assertInstanceOf(
203
            URLAlias::class,
204
            $createdUrlAlias
205
        );
206
207
        return [$createdUrlAlias, $location->id];
208
    }
209
210
    /**
211
     * @param array $testData
212
     *
213
     * @depends testCreateUrlAliasWithAlwaysAvailable
214
     */
215 View Code Duplication
    public function testCreateUrlAliasPropertyValuesWithAlwaysAvailable(array $testData)
216
    {
217
        list($createdUrlAlias, $locationId) = $testData;
218
219
        $this->assertNotNull($createdUrlAlias->id);
220
221
        $this->assertPropertiesCorrect(
222
            [
223
                'type' => URLAlias::LOCATION,
224
                'destination' => $locationId,
225
                'path' => '/Home/My-New-Site',
226
                'languageCodes' => ['eng-US'],
227
                'alwaysAvailable' => true,
228
                'isHistory' => false,
229
                'isCustom' => true,
230
                'forward' => false,
231
            ],
232
            $createdUrlAlias
233
        );
234
    }
235
236
    /**
237
     * Test for the createUrlAlias() method.
238
     *
239
     * @see \eZ\Publish\API\Repository\URLAliasService::createUrlAlias()
240
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
241
     */
242
    public function testCreateUrlAliasThrowsInvalidArgumentException()
243
    {
244
        $repository = $this->getRepository();
245
246
        $locationId = $this->generateId('location', 5);
247
248
        /* BEGIN: Use Case */
249
        // $locationId is the ID of an existing location
250
251
        $locationService = $repository->getLocationService();
252
        $urlAliasService = $repository->getURLAliasService();
253
254
        $location = $locationService->loadLocation($locationId);
255
256
        // Throws InvalidArgumentException, since this path already exists for the
257
        // language
258
        $createdUrlAlias = $urlAliasService->createUrlAlias($location, '/Design/Plain-site', 'eng-US');
0 ignored issues
show
Unused Code introduced by
$createdUrlAlias is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
259
        /* END: Use Case */
260
    }
261
262
    /**
263
     * Test for the createGlobalUrlAlias() method.
264
     *
265
     * @see \eZ\Publish\API\Repository\URLAliasService::createGlobalUrlAlias()
266
     */
267 View Code Duplication
    public function testCreateGlobalUrlAlias()
268
    {
269
        $repository = $this->getRepository();
270
271
        /* BEGIN: Use Case */
272
        $urlAliasService = $repository->getURLAliasService();
273
274
        $createdUrlAlias = $urlAliasService->createGlobalUrlAlias(
275
            'module:content/search?SearchText=eZ',
276
            '/Home/My-New-Site',
277
            'eng-US'
278
        );
279
        /* END: Use Case */
280
281
        $this->assertInstanceOf(
282
            URLAlias::class,
283
            $createdUrlAlias
284
        );
285
286
        return $createdUrlAlias;
287
    }
288
289
    /**
290
     * @param \eZ\Publish\API\Repository\Values\Content\URLAlias
291
     *
292
     * @depends testCreateGlobalUrlAlias
293
     */
294 View Code Duplication
    public function testCreateGlobalUrlAliasPropertyValues(URLAlias $createdUrlAlias)
295
    {
296
        $this->assertNotNull($createdUrlAlias->id);
297
298
        $this->assertPropertiesCorrect(
299
            [
300
                'type' => URLAlias::RESOURCE,
301
                'destination' => 'content/search?SearchText=eZ',
302
                'path' => '/Home/My-New-Site',
303
                'languageCodes' => ['eng-US'],
304
                'alwaysAvailable' => false,
305
                'isHistory' => false,
306
                'isCustom' => true,
307
                'forward' => false,
308
            ],
309
            $createdUrlAlias
310
        );
311
    }
312
313
    /**
314
     * Test for the createGlobalUrlAlias() method.
315
     *
316
     * @see \eZ\Publish\API\Repository\URLAliasService::createGlobalUrlAlias($resource, $path, $languageCode, $forward)
317
     */
318 View Code Duplication
    public function testCreateGlobalUrlAliasWithForward()
319
    {
320
        $repository = $this->getRepository();
321
322
        /* BEGIN: Use Case */
323
        $urlAliasService = $repository->getURLAliasService();
324
325
        $createdUrlAlias = $urlAliasService->createGlobalUrlAlias(
326
            'module:content/search?SearchText=eZ',
327
            '/Home/My-New-Site',
328
            'eng-US',
329
            true
330
        );
331
        /* END: Use Case */
332
333
        $this->assertInstanceOf(
334
            URLAlias::class,
335
            $createdUrlAlias
336
        );
337
338
        return $createdUrlAlias;
339
    }
340
341
    /**
342
     * @param \eZ\Publish\API\Repository\Values\Content\URLAlias
343
     *
344
     * @depends testCreateGlobalUrlAliasWithForward
345
     */
346 View Code Duplication
    public function testCreateGlobalUrlAliasWithForwardPropertyValues(URLAlias $createdUrlAlias)
347
    {
348
        $this->assertNotNull($createdUrlAlias->id);
349
350
        $this->assertPropertiesCorrect(
351
            [
352
                'type' => URLAlias::RESOURCE,
353
                'destination' => 'content/search?SearchText=eZ',
354
                'path' => '/Home/My-New-Site',
355
                'languageCodes' => ['eng-US'],
356
                'alwaysAvailable' => false,
357
                'isHistory' => false,
358
                'isCustom' => true,
359
                'forward' => true,
360
            ],
361
            $createdUrlAlias
362
        );
363
    }
364
365
    /**
366
     * Test for the createGlobalUrlAlias() method.
367
     *
368
     * @see \eZ\Publish\API\Repository\URLAliasService::createGlobalUrlAlias($resource, $path, $languageCode, $forwarding, $alwaysAvailable)
369
     */
370 View Code Duplication
    public function testCreateGlobalUrlAliasWithAlwaysAvailable()
371
    {
372
        $repository = $this->getRepository();
373
374
        /* BEGIN: Use Case */
375
        $urlAliasService = $repository->getURLAliasService();
376
377
        $createdUrlAlias = $urlAliasService->createGlobalUrlAlias(
378
            'module:content/search?SearchText=eZ',
379
            '/Home/My-New-Site',
380
            'eng-US',
381
            false,
382
            true
383
        );
384
        /* END: Use Case */
385
386
        $this->assertInstanceOf(
387
            URLAlias::class,
388
            $createdUrlAlias
389
        );
390
391
        return $createdUrlAlias;
392
    }
393
394
    /**
395
     * @param \eZ\Publish\API\Repository\Values\Content\URLAlias
396
     *
397
     * @depends testCreateGlobalUrlAliasWithAlwaysAvailable
398
     */
399 View Code Duplication
    public function testCreateGlobalUrlAliasWithAlwaysAvailablePropertyValues(URLAlias $createdUrlAlias)
400
    {
401
        $this->assertNotNull($createdUrlAlias->id);
402
403
        $this->assertPropertiesCorrect(
404
            [
405
                'type' => URLAlias::RESOURCE,
406
                'destination' => 'content/search?SearchText=eZ',
407
                'path' => '/Home/My-New-Site',
408
                'languageCodes' => ['eng-US'],
409
                'alwaysAvailable' => true,
410
                'isHistory' => false,
411
                'isCustom' => true,
412
                'forward' => false,
413
            ],
414
            $createdUrlAlias
415
        );
416
    }
417
418
    /**
419
     * Test for the createUrlAlias() method.
420
     *
421
     * @see \eZ\Publish\API\Repository\URLAliasService::createGlobalUrlAlias($resource, $path, $languageCode, $forwarding, $alwaysAvailable)
422
     */
423 View Code Duplication
    public function testCreateGlobalUrlAliasForLocation()
424
    {
425
        $repository = $this->getRepository();
426
427
        $locationId = $this->generateId('location', 5);
428
        $locationService = $repository->getLocationService();
429
        $location = $locationService->loadLocation($locationId);
430
431
        /* BEGIN: Use Case */
432
        // $locationId is the ID of an existing location
433
434
        $urlAliasService = $repository->getURLAliasService();
435
436
        $createdUrlAlias = $urlAliasService->createGlobalUrlAlias(
437
            'module:content/view/full/' . $locationId,
438
            '/Home/My-New-Site-global',
439
            'eng-US',
440
            false,
441
            true
442
        );
443
        /* END: Use Case */
444
445
        $this->assertInstanceOf(
446
            URLAlias::class,
447
            $createdUrlAlias
448
        );
449
450
        return [$createdUrlAlias, $location->id];
451
    }
452
453
    /**
454
     * Test for the createUrlAlias() method.
455
     *
456
     * @see \eZ\Publish\API\Repository\URLAliasService::createGlobalUrlAlias($resource, $path, $languageCode, $forwarding, $alwaysAvailable)
457
     */
458 View Code Duplication
    public function testCreateGlobalUrlAliasForLocationVariation()
459
    {
460
        $repository = $this->getRepository();
461
462
        $locationId = $this->generateId('location', 5);
463
        $locationService = $repository->getLocationService();
464
        $location = $locationService->loadLocation($locationId);
465
466
        /* BEGIN: Use Case */
467
        // $locationId is the ID of an existing location
468
469
        $urlAliasService = $repository->getURLAliasService();
470
471
        $createdUrlAlias = $urlAliasService->createGlobalUrlAlias(
472
            'eznode:' . $locationId,
473
            '/Home/My-New-Site-global',
474
            'eng-US',
475
            false,
476
            true
477
        );
478
        /* END: Use Case */
479
480
        $this->assertInstanceOf(
481
            URLAlias::class,
482
            $createdUrlAlias
483
        );
484
485
        return [$createdUrlAlias, $location->id];
486
    }
487
488
    /**
489
     * @param \eZ\Publish\API\Repository\Values\Content\URLAlias
490
     *
491
     * @depends testCreateGlobalUrlAliasForLocation
492
     */
493 View Code Duplication
    public function testCreateGlobalUrlAliasForLocationPropertyValues($testData)
494
    {
495
        list($createdUrlAlias, $locationId) = $testData;
496
497
        $this->assertNotNull($createdUrlAlias->id);
498
499
        $this->assertPropertiesCorrect(
500
            [
501
                'type' => URLAlias::LOCATION,
502
                'destination' => $locationId,
503
                'path' => '/Home/My-New-Site-global',
504
                'languageCodes' => ['eng-US'],
505
                'alwaysAvailable' => true,
506
                'isHistory' => false,
507
                'isCustom' => true,
508
                'forward' => false,
509
            ],
510
            $createdUrlAlias
511
        );
512
    }
513
514
    /**
515
     * @param \eZ\Publish\API\Repository\Values\Content\URLAlias
516
     *
517
     * @depends testCreateGlobalUrlAliasForLocationVariation
518
     */
519
    public function testCreateGlobalUrlAliasForLocationVariationPropertyValues($testData)
520
    {
521
        $this->testCreateGlobalUrlAliasForLocationPropertyValues($testData);
522
    }
523
524
    /**
525
     * Test for the createGlobalUrlAlias() method.
526
     *
527
     * @see \eZ\Publish\API\Repository\URLAliasService::createGlobalUrlAlias()
528
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
529
     */
530
    public function testCreateGlobalUrlAliasThrowsInvalidArgumentException()
531
    {
532
        $repository = $this->getRepository();
533
534
        /* BEGIN: Use Case */
535
        $urlAliasService = $repository->getURLAliasService();
536
537
        // Throws InvalidArgumentException, since this path already exists for the
538
        // language
539
        $createdUrlAlias = $urlAliasService->createGlobalUrlAlias(
0 ignored issues
show
Unused Code introduced by
$createdUrlAlias is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
540
            'module:content/search?SearchText=eZ',
541
            '/Design/Plain-site',
542
            'eng-US'
543
        );
544
        /* END: Use Case */
545
    }
546
547
    /**
548
     * Test for the listLocationAliases() method.
549
     *
550
     * @see \eZ\Publish\API\Repository\URLAliasService::listLocationAliases()
551
     */
552 View Code Duplication
    public function testListLocationAliases()
553
    {
554
        $repository = $this->getRepository();
555
556
        $locationId = $this->generateId('location', 12);
557
558
        /* BEGIN: Use Case */
559
        // $locationId contains the ID of an existing Location
560
        $urlAliasService = $repository->getURLAliasService();
561
        $locationService = $repository->getLocationService();
562
563
        $location = $locationService->loadLocation($locationId);
564
565
        // Create a custom URL alias for $location
566
        $urlAliasService->createUrlAlias($location, '/My/Great-new-Site', 'eng-US');
567
568
        // $loadedAliases will contain an array of custom URLAlias objects
569
        $loadedAliases = $urlAliasService->listLocationAliases($location);
570
        /* END: Use Case */
571
572
        $this->assertIsArray($loadedAliases);
573
574
        // Only 1 non-history alias
575
        $this->assertCount(1, $loadedAliases);
576
577
        return [$loadedAliases, $location];
578
    }
579
580
    /**
581
     * @param array $testData
582
     *
583
     * @depends testListLocationAliases
584
     */
585
    public function testListLocationAliasesLoadsCorrectly(array $testData)
586
    {
587
        list($loadedAliases, $location) = $testData;
588
589
        foreach ($loadedAliases as $loadedAlias) {
590
            $this->assertInstanceOf(
591
                URLAlias::class,
592
                $loadedAlias
593
            );
594
            $this->assertEquals(
595
                $location->id,
596
                $loadedAlias->destination
597
            );
598
        }
599
    }
600
601
    /**
602
     * Test for the listLocationAliases() method.
603
     *
604
     * @see \eZ\Publish\API\Repository\URLAliasService::listLocationAliases($location, $custom, $languageCode)
605
     */
606 View Code Duplication
    public function testListLocationAliasesWithCustomFilter()
607
    {
608
        $repository = $this->getRepository();
609
610
        $locationId = $this->generateId('location', 12);
611
612
        /* BEGIN: Use Case */
613
        // $locationId contains the ID of an existing Location
614
        $urlAliasService = $repository->getURLAliasService();
615
        $locationService = $repository->getLocationService();
616
617
        $location = $locationService->loadLocation($locationId);
618
619
        // Create a second URL alias for $location, this is a "custom" one
620
        $urlAliasService->createUrlAlias($location, '/My/Great-new-Site', 'ger-DE');
621
622
        // $loadedAliases will contain 1 aliases in eng-US only
623
        $loadedAliases = $urlAliasService->listLocationAliases($location, false, 'eng-US');
624
        /* END: Use Case */
625
626
        $this->assertIsArray($loadedAliases);
627
        $this->assertCount(1, $loadedAliases);
628
    }
629
630
    /**
631
     * Test for the listLocationAliases() method.
632
     *
633
     * @see \eZ\Publish\API\Repository\URLAliasService::listLocationAliases($location, $custom)
634
     */
635 View Code Duplication
    public function testListLocationAliasesWithLanguageCodeFilter()
636
    {
637
        $repository = $this->getRepository();
638
639
        $locationId = $this->generateId('location', 12);
640
641
        /* BEGIN: Use Case */
642
        // $locationId contains the ID of an existing Location
643
        $urlAliasService = $repository->getURLAliasService();
644
        $locationService = $repository->getLocationService();
645
646
        $location = $locationService->loadLocation($locationId);
647
        // Create a custom URL alias for $location
648
        $urlAliasService->createUrlAlias($location, '/My/Great-new-Site', 'eng-US');
649
650
        // $loadedAliases will contain only 1 of 3 aliases (custom in eng-US)
651
        $loadedAliases = $urlAliasService->listLocationAliases($location, true, 'eng-US');
652
        /* END: Use Case */
653
654
        $this->assertIsArray($loadedAliases);
655
        $this->assertCount(1, $loadedAliases);
656
    }
657
658
    /**
659
     * Test for the listGlobalAliases() method.
660
     *
661
     * @see \eZ\Publish\API\Repository\URLAliasService::listGlobalAliases()
662
     */
663 View Code Duplication
    public function testListGlobalAliases()
664
    {
665
        $repository = $this->getRepository();
666
667
        /* BEGIN: Use Case */
668
        $urlAliasService = $repository->getURLAliasService();
669
670
        // Create some global aliases
671
        $this->createGlobalAliases();
672
673
        // $loadedAliases will contain all 3 global aliases
674
        $loadedAliases = $urlAliasService->listGlobalAliases();
675
        /* END: Use Case */
676
677
        $this->assertIsArray($loadedAliases);
678
        $this->assertCount(3, $loadedAliases);
679
    }
680
681
    /**
682
     * Creates 3 global aliases.
683
     */
684
    private function createGlobalAliases()
685
    {
686
        $repository = $this->getRepository();
687
        $urlAliasService = $repository->getURLAliasService();
688
689
        /* BEGIN: Inline */
690
        $urlAliasService->createGlobalUrlAlias(
691
            'module:content/search?SearchText=eZ',
692
            '/My/Special-Support',
693
            'eng-US'
694
        );
695
        $urlAliasService->createGlobalUrlAlias(
696
            'module:content/search?SearchText=eZ',
697
            '/My/London-Office',
698
            'eng-GB'
699
        );
700
        $urlAliasService->createGlobalUrlAlias(
701
            'module:content/search?SearchText=Sindelfingen',
702
            '/My/Fancy-Site',
703
            'eng-US'
704
        );
705
        /* END: Inline */
706
    }
707
708
    /**
709
     * Test for the listGlobalAliases() method.
710
     *
711
     * @see \eZ\Publish\API\Repository\URLAliasService::listGlobalAliases($languageCode)
712
     */
713 View Code Duplication
    public function testListGlobalAliasesWithLanguageFilter()
714
    {
715
        $repository = $this->getRepository();
716
717
        /* BEGIN: Use Case */
718
        $urlAliasService = $repository->getURLAliasService();
719
720
        // Create some global aliases
721
        $this->createGlobalAliases();
722
723
        // $loadedAliases will contain only 2 of 3 global aliases
724
        $loadedAliases = $urlAliasService->listGlobalAliases('eng-US');
725
        /* END: Use Case */
726
727
        $this->assertIsArray($loadedAliases);
728
        $this->assertCount(2, $loadedAliases);
729
    }
730
731
    /**
732
     * Test for the listGlobalAliases() method.
733
     *
734
     * @see \eZ\Publish\API\Repository\URLAliasService::listGlobalAliases($languageCode, $offset)
735
     */
736 View Code Duplication
    public function testListGlobalAliasesWithOffset()
737
    {
738
        $repository = $this->getRepository();
739
740
        /* BEGIN: Use Case */
741
        $urlAliasService = $repository->getURLAliasService();
742
743
        // Create some global aliases
744
        $this->createGlobalAliases();
745
746
        // $loadedAliases will contain only 2 of 3 global aliases
747
        $loadedAliases = $urlAliasService->listGlobalAliases(null, 1);
748
        /* END: Use Case */
749
750
        $this->assertIsArray($loadedAliases);
751
        $this->assertCount(2, $loadedAliases);
752
    }
753
754
    /**
755
     * Test for the listGlobalAliases() method.
756
     *
757
     * @see \eZ\Publish\API\Repository\URLAliasService::listGlobalAliases($languageCode, $offset, $limit)
758
     */
759 View Code Duplication
    public function testListGlobalAliasesWithLimit()
760
    {
761
        $repository = $this->getRepository();
762
763
        /* BEGIN: Use Case */
764
        $urlAliasService = $repository->getURLAliasService();
765
766
        // Create some global aliases
767
        $this->createGlobalAliases();
768
769
        // $loadedAliases will contain only 1 of 3 global aliases
770
        $loadedAliases = $urlAliasService->listGlobalAliases(null, 0, 1);
771
        /* END: Use Case */
772
773
        $this->assertIsArray($loadedAliases);
774
        $this->assertCount(1, $loadedAliases);
775
    }
776
777
    /**
778
     * Test for the removeAliases() method.
779
     *
780
     * @see \eZ\Publish\API\Repository\URLAliasService::removeAliases()
781
     */
782 View Code Duplication
    public function testRemoveAliases()
783
    {
784
        $repository = $this->getRepository();
785
786
        $locationService = $repository->getLocationService();
787
        $someLocation = $locationService->loadLocation(
788
            $this->generateId('location', 12)
789
        );
790
791
        /* BEGIN: Use Case */
792
        // $someLocation contains a location with automatically generated
793
        // aliases assigned
794
        $urlAliasService = $repository->getURLAliasService();
795
796
        $initialAliases = $urlAliasService->listLocationAliases($someLocation);
797
798
        // Creates a custom alias for $someLocation
799
        $urlAliasService->createUrlAlias(
800
            $someLocation,
801
            '/my/fancy/url/alias/sindelfingen',
802
            'eng-US'
803
        );
804
805
        $customAliases = $urlAliasService->listLocationAliases($someLocation);
806
807
        // The custom alias just created will be removed
808
        // the automatic aliases stay in tact
809
        $urlAliasService->removeAliases($customAliases);
810
        /* END: Use Case */
811
812
        $this->assertEquals(
813
            $initialAliases,
814
            $urlAliasService->listLocationAliases($someLocation)
815
        );
816
    }
817
818
    /**
819
     * Test for the removeAliases() method.
820
     *
821
     * @see \eZ\Publish\API\Repository\URLAliasService::removeAliases()
822
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
823
     */
824
    public function testRemoveAliasesThrowsInvalidArgumentExceptionIfAutogeneratedAliasesAreToBeRemoved()
825
    {
826
        $repository = $this->getRepository();
827
828
        $locationService = $repository->getLocationService();
829
        $someLocation = $locationService->loadLocation(
830
            $this->generateId('location', 12)
831
        );
832
833
        /* BEGIN: Use Case */
834
        // $someLocation contains a location with automatically generated
835
        // aliases assigned
836
        $urlAliasService = $repository->getURLAliasService();
837
838
        $autogeneratedAliases = $urlAliasService->listLocationAliases($someLocation, false);
839
840
        // Throws an InvalidArgumentException, since autogeneratedAliases
841
        // cannot be removed with this method
842
        $urlAliasService->removeAliases($autogeneratedAliases);
843
        /* END: Use Case */
844
    }
845
846
    /**
847
     * Test for the lookUp() method.
848
     *
849
     * @see \eZ\Publish\API\Repository\URLAliasService::lookUp()
850
     */
851
    public function testLookUp()
852
    {
853
        $repository = $this->getRepository();
854
855
        /* BEGIN: Use Case */
856
        $urlAliasService = $repository->getURLAliasService();
857
858
        $loadedAlias = $urlAliasService->lookup('/Setup2');
859
        /* END: Use Case */
860
861
        $this->assertInstanceOf(
862
            URLAlias::class,
863
            $loadedAlias
864
        );
865
866
        return $loadedAlias;
867
    }
868
869
    /**
870
     * Test for the lookUp() method.
871
     *
872
     * @see \eZ\Publish\API\Repository\URLAliasService::lookUp($url, $languageCode)
873
     */
874
    public function testLookUpWithLanguageFilter()
875
    {
876
        $repository = $this->getRepository();
877
878
        /* BEGIN: Use Case */
879
        $urlAliasService = $repository->getURLAliasService();
880
881
        // Create aliases in multiple languages
882
        $this->createGlobalAliases();
883
884
        $loadedAlias = $urlAliasService->lookup('/My/Special-Support', 'eng-US');
885
        /* END: Use Case */
886
887
        $this->assertInstanceOf(
888
            URLAlias::class,
889
            $loadedAlias
890
        );
891
        $this->assertEquals(
892
            'content/search?SearchText=eZ',
893
            $loadedAlias->destination
894
        );
895
    }
896
897
    /**
898
     * Test for the lookUp() method.
899
     *
900
     * @see \eZ\Publish\API\Repository\URLAliasService::lookUp()
901
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
902
     */
903
    public function testLookUpThrowsNotFoundException()
904
    {
905
        $repository = $this->getRepository();
906
907
        /* BEGIN: Use Case */
908
        $urlAliasService = $repository->getURLAliasService();
909
910
        // Throws NotFoundException
911
        $urlAliasService->lookup('/non-existent-url');
912
        /* END: Use Case */
913
    }
914
915
    /**
916
     * Test for the lookUp() method.
917
     *
918
     * @see \eZ\Publish\API\Repository\URLAliasService::lookUp($url, $languageCode)
919
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
920
     */
921
    public function testLookUpThrowsNotFoundExceptionWithLanguageFilter()
922
    {
923
        $repository = $this->getRepository();
924
925
        /* BEGIN: Use Case */
926
        $urlAliasService = $repository->getURLAliasService();
927
928
        // Throws NotFoundException
929
        $urlAliasService->lookup('/Contact-Us', 'ger-DE');
930
        /* END: Use Case */
931
    }
932
933
    /**
934
     * Test for the lookUp() method.
935
     *
936
     * @see \eZ\Publish\API\Repository\URLAliasService::lookUp($url, $languageCode)
937
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
938
     */
939
    public function testLookUpThrowsInvalidArgumentException()
940
    {
941
        $repository = $this->getRepository();
942
943
        /* BEGIN: Use Case */
944
        $urlAliasService = $repository->getURLAliasService();
945
946
        // Throws InvalidArgumentException
947
        $loadedAlias = $urlAliasService->lookup(str_repeat('/1', 99), 'ger-DE');
0 ignored issues
show
Unused Code introduced by
$loadedAlias is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
948
        /* END: Use Case */
949
    }
950
951
    /**
952
     * Test for the lookUp() method after renaming parent which is a part of the lookup path.
953
     *
954
     * @see https://jira.ez.no/browse/EZP-28046
955
     * @covers \eZ\Publish\API\Repository\URLAliasService::lookUp
956
     * @covers \eZ\Publish\API\Repository\URLAliasService::listLocationAliases
957
     */
958
    public function testLookupOnRenamedParent()
959
    {
960
        $urlAliasService = $this->getRepository()->getURLAliasService();
961
        $locationService = $this->getRepository()->getLocationService();
962
        $contentTypeService = $this->getRepository()->getContentTypeService();
963
        $contentService = $this->getRepository()->getContentService();
964
965
        // 1. Create new container object (e.g. Folder "My Folder").
966
        $folderContentType = $contentTypeService->loadContentTypeByIdentifier('folder');
967
        $folderCreateStruct = $contentService->newContentCreateStruct($folderContentType, 'eng-GB');
968
        $folderCreateStruct->setField('name', 'My-Folder');
969
970
        $folderDraft = $contentService->createContent($folderCreateStruct, [
971
            $locationService->newLocationCreateStruct(2),
972
        ]);
973
974
        $folder = $contentService->publishVersion($folderDraft->versionInfo);
975
976
        // 2. Create new object inside this container (e.g. article "My Article").
977
        $folderLocation = $locationService->loadLocation($folder->contentInfo->mainLocationId);
978
979
        $articleContentType = $contentTypeService->loadContentTypeByIdentifier('article');
980
        $articleCreateStruct = $contentService->newContentCreateStruct($articleContentType, 'eng-GB');
981
        $articleCreateStruct->setField('title', 'My Article');
982
        $articleCreateStruct->setField(
983
            'intro',
984
            <<< DOCBOOK
985
<?xml version="1.0" encoding="UTF-8"?>
986
<section xmlns="http://docbook.org/ns/docbook" version="5.0-variant ezpublish-1.0">
987
    <para>Cache invalidation in eZ</para>
988
</section>
989
DOCBOOK
990
        );
991
        $article = $contentService->publishVersion(
992
            $contentService->createContent($articleCreateStruct, [
993
                $locationService->newLocationCreateStruct($folderLocation->id),
994
            ])->versionInfo
995
        );
996
        $articleLocation = $locationService->loadLocation($article->contentInfo->mainLocationId);
997
998
        // 3. Navigate to both of them
999
        $urlAliasService->lookup('/My-Folder');
1000
        $urlAliasService->listLocationAliases($folderLocation, false);
1001
        $urlAliasService->lookup('/My-Folder/My-Article');
1002
        $urlAliasService->listLocationAliases($articleLocation, false);
1003
1004
        // 4. Rename "My Folder" to "My Folder Modified".
1005
        $folderDraft = $contentService->createContentDraft($folder->contentInfo);
1006
        $folderUpdateStruct = $contentService->newContentUpdateStruct();
1007
        $folderUpdateStruct->setField('name', 'My Folder Modified');
1008
1009
        $contentService->publishVersion(
1010
            $contentService->updateContent($folderDraft->versionInfo, $folderUpdateStruct)->versionInfo
1011
        );
1012
1013
        // 5. Navigate to "Article"
1014
        $urlAliasService->lookup('/My-Folder/My-Article');
1015
        $aliases = $urlAliasService->listLocationAliases($articleLocation, false);
1016
1017
        $this->assertEquals('/My-Folder-Modified/My-Article', $aliases[0]->path);
1018
    }
1019
1020
    /**
1021
     * Test lookup on multilingual nested Locations returns proper UrlAlias Value.
1022
     *
1023
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1024
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1025
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1026
     */
1027
    public function testLookupOnMultilingualNestedLocations()
1028
    {
1029
        $urlAliasService = $this->getRepository()->getURLAliasService();
1030
        $locationService = $this->getRepository()->getLocationService();
1031
1032
        $topFolderNames = [
1033
            'eng-GB' => 'My folder Name',
1034
            'ger-DE' => 'Ger folder Name',
1035
            'eng-US' => 'My folder Name',
1036
        ];
1037
        $nestedFolderNames = [
1038
            'eng-GB' => 'nested Folder name',
1039
            'ger-DE' => 'Ger Nested folder Name',
1040
            'eng-US' => 'nested Folder name',
1041
        ];
1042
        $topFolderLocation = $locationService->loadLocation(
1043
            $this->createFolder($topFolderNames, 2)->contentInfo->mainLocationId
1044
        );
1045
        $nestedFolderLocation = $locationService->loadLocation(
1046
            $this->createFolder(
1047
                $nestedFolderNames,
1048
                $topFolderLocation->id
1049
            )->contentInfo->mainLocationId
1050
        );
1051
        $urlAlias = $urlAliasService->lookup('/My-Folder-Name/Nested-Folder-Name');
1052
        self::assertPropertiesCorrect(
1053
            [
1054
                'destination' => $nestedFolderLocation->id,
1055
                'path' => '/My-folder-Name/nested-Folder-name',
1056
                'languageCodes' => ['eng-US', 'eng-GB'],
1057
                'isHistory' => false,
1058
                'isCustom' => false,
1059
                'forward' => false,
1060
            ],
1061
            $urlAlias
1062
        );
1063
        $urlAlias = $urlAliasService->lookup('/Ger-Folder-Name/Ger-Nested-Folder-Name');
1064
        self::assertPropertiesCorrect(
1065
            [
1066
                'destination' => $nestedFolderLocation->id,
1067
                'path' => '/Ger-folder-Name/Ger-Nested-folder-Name',
1068
                'languageCodes' => ['ger-DE'],
1069
                'isHistory' => false,
1070
                'isCustom' => false,
1071
                'forward' => false,
1072
            ],
1073
            $urlAlias
1074
        );
1075
1076
        return [$topFolderLocation, $nestedFolderLocation];
1077
    }
1078
1079
    /**
1080
     * Test refreshSystemUrlAliasesForLocation historizes and changes current URL alias after
1081
     * changing SlugConverter configuration.
1082
     *
1083
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1084
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1085
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1086
     * @throws \ErrorException
1087
     */
1088
    public function testRefreshSystemUrlAliasesForLocationWithChangedSlugConverterConfiguration()
1089
    {
1090
        list($topFolderLocation, $nestedFolderLocation) = $this->testLookupOnMultilingualNestedLocations();
1091
1092
        $urlAliasService = $this->getRepository(false)->getURLAliasService();
1093
1094
        $this->changeSlugConverterConfiguration('transformation', 'urlalias_compat');
1095
        $this->changeSlugConverterConfiguration('wordSeparatorName', 'underscore');
1096
1097
        try {
1098
            $urlAliasService->refreshSystemUrlAliasesForLocation($topFolderLocation);
1099
            $urlAliasService->refreshSystemUrlAliasesForLocation($nestedFolderLocation);
1100
1101
            $urlAlias = $urlAliasService->lookup('/My-Folder-Name/Nested-Folder-Name');
1102
            $this->assertUrlAliasPropertiesCorrect(
1103
                $nestedFolderLocation,
1104
                '/My-folder-Name/nested-Folder-name',
1105
                ['eng-US', 'eng-GB'],
1106
                true,
1107
                $urlAlias
1108
            );
1109
1110
            $urlAlias = $urlAliasService->lookup('/my_folder_name/nested_folder_name');
1111
            $this->assertUrlAliasPropertiesCorrect(
1112
                $nestedFolderLocation,
1113
                '/my_folder_name/nested_folder_name',
1114
                ['eng-US', 'eng-GB'],
1115
                false,
1116
                $urlAlias
1117
            );
1118
1119
            $urlAlias = $urlAliasService->lookup('/Ger-Folder-Name/Ger-Nested-Folder-Name');
1120
            $this->assertUrlAliasPropertiesCorrect(
1121
                $nestedFolderLocation,
1122
                '/Ger-folder-Name/Ger-Nested-folder-Name',
1123
                ['ger-DE'],
1124
                true,
1125
                $urlAlias
1126
            );
1127
1128
            $urlAlias = $urlAliasService->lookup('/ger_folder_name/ger_nested_folder_name');
1129
            $this->assertUrlAliasPropertiesCorrect(
1130
                $nestedFolderLocation,
1131
                '/ger_folder_name/ger_nested_folder_name',
1132
                ['ger-DE'],
1133
                false,
1134
                $urlAlias
1135
            );
1136
        } finally {
1137
            // restore configuration
1138
            $this->changeSlugConverterConfiguration('transformation', 'urlalias');
1139
            $this->changeSlugConverterConfiguration('wordSeparatorName', 'dash');
1140
        }
1141
    }
1142
1143
    /**
1144
     * Test that URL aliases are refreshed after changing URL alias schema Field name of a Content Type.
1145
     *
1146
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1147
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1148
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1149
     */
1150
    public function testRefreshSystemUrlAliasesForContentsWithUpdatedContentTypes()
1151
    {
1152
        list($topFolderLocation, $nestedFolderLocation) = $this->testLookupOnMultilingualNestedLocations();
1153
        /** @var \eZ\Publish\API\Repository\Values\Content\Location $topFolderLocation */
1154
        /** @var \eZ\Publish\API\Repository\Values\Content\Location $nestedFolderLocation */
1155
1156
        // Default URL Alias schema is <short_name|name> which messes up this test, so:
1157
        $this->changeContentTypeUrlAliasSchema('folder', '<name>');
1158
1159
        $urlAliasService = $this->getRepository(false)->getURLAliasService();
1160
1161
        $this->updateContentField(
1162
            $topFolderLocation->getContentInfo(),
1163
            'short_name',
1164
            ['eng-GB' => 'EN Short Name', 'ger-DE' => 'DE Short Name']
1165
        );
1166
        $this->updateContentField(
1167
            $nestedFolderLocation->getContentInfo(),
1168
            'short_name',
1169
            ['eng-GB' => 'EN Nested Short Name', 'ger-DE' => 'DE Nested Short Name']
1170
        );
1171
1172
        $this->changeContentTypeUrlAliasSchema('folder', '<short_name>');
1173
1174
        // sanity test, done after updating CT, because it does not update existing entries by design
1175
        $this->assertUrlIsCurrent('/My-folder-Name', $topFolderLocation->id);
1176
        $this->assertUrlIsCurrent('/Ger-folder-Name', $topFolderLocation->id);
1177
        $this->assertUrlIsCurrent('/My-folder-Name/nested-Folder-name', $nestedFolderLocation->id);
1178
        $this->assertUrlIsCurrent('/Ger-folder-Name/Ger-Nested-folder-Name', $nestedFolderLocation->id);
1179
1180
        // Call API being tested
1181
        $urlAliasService->refreshSystemUrlAliasesForLocation($topFolderLocation);
1182
        $urlAliasService->refreshSystemUrlAliasesForLocation($nestedFolderLocation);
1183
1184
        // check archived aliases
1185
        $this->assertUrlIsHistory('/My-folder-Name', $topFolderLocation->id);
1186
        $this->assertUrlIsHistory('/Ger-folder-Name', $topFolderLocation->id);
1187
        $this->assertUrlIsHistory('/My-folder-Name/nested-Folder-name', $nestedFolderLocation->id);
1188
        $this->assertUrlIsHistory('/Ger-folder-Name/Ger-Nested-folder-Name', $nestedFolderLocation->id);
1189
1190
        // check new current aliases
1191
        $this->assertUrlIsCurrent('/EN-Short-Name', $topFolderLocation->id);
1192
        $this->assertUrlIsCurrent('/DE-Short-Name', $topFolderLocation->id);
1193
        $this->assertUrlIsCurrent('/EN-Short-Name/EN-Nested-Short-Name', $nestedFolderLocation->id);
1194
        $this->assertUrlIsCurrent('/DE-Short-Name/DE-Nested-Short-Name', $nestedFolderLocation->id);
1195
    }
1196
1197
    /**
1198
     * Test that created non-latin aliases are non-empty and unique.
1199
     *
1200
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1201
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1202
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1203
     */
1204
    public function testCreateNonLatinNonEmptyUniqueAliases()
1205
    {
1206
        $repository = $this->getRepository();
1207
        $urlAliasService = $repository->getURLAliasService();
1208
        $locationService = $repository->getLocationService();
1209
1210
        $folderNames = [
1211
            'eng-GB' => 'ひらがな',
1212
        ];
1213
1214
        $folderLocation1 = $locationService->loadLocation(
1215
            $this->createFolder($folderNames, 2)->contentInfo->mainLocationId
1216
        );
1217
        $urlAlias1 = $urlAliasService->lookup('/1');
1218
        self::assertPropertiesCorrect(
1219
            [
1220
                'destination' => $folderLocation1->id,
1221
                'path' => '/1',
1222
                'languageCodes' => ['eng-GB'],
1223
                'isHistory' => false,
1224
                'isCustom' => false,
1225
                'forward' => false,
1226
            ],
1227
            $urlAlias1
1228
        );
1229
1230
        $folderLocation2 = $locationService->loadLocation(
1231
            $this->createFolder($folderNames, 2)->contentInfo->mainLocationId
1232
        );
1233
        $urlAlias2 = $urlAliasService->lookup('/2');
1234
        self::assertPropertiesCorrect(
1235
            [
1236
                'destination' => $folderLocation2->id,
1237
                'path' => '/2',
1238
                'languageCodes' => ['eng-GB'],
1239
                'isHistory' => false,
1240
                'isCustom' => false,
1241
                'forward' => false,
1242
            ],
1243
            $urlAlias2
1244
        );
1245
    }
1246
1247
    /**
1248
     * Test restoring missing current URL which has existing history.
1249
     *
1250
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1251
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1252
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1253
     * @throws \Exception
1254
     */
1255
    public function testRefreshSystemUrlAliasesForMissingUrlWithHistory()
1256
    {
1257
        $repository = $this->getRepository();
1258
        $urlAliasService = $repository->getURLAliasService();
1259
        $locationService = $repository->getLocationService();
1260
1261
        $folderNames = ['eng-GB' => 'My folder Name'];
1262
        $folder = $this->createFolder($folderNames, 2);
1263
        $folderLocation = $locationService->loadLocation($folder->contentInfo->mainLocationId);
1264
        $nestedFolder = $this->createFolder(['eng-GB' => 'Nested folder'], $folderLocation->id);
1265
        $nestedFolderLocation = $locationService->loadLocation($nestedFolder->contentInfo->mainLocationId);
1266
1267
        $folder = $this->updateContentField(
1268
            $folder->contentInfo,
1269
            'name',
1270
            ['eng-GB' => 'Updated Name']
1271
        );
1272
        // create more historical entries
1273
        $this->updateContentField(
1274
            $folder->contentInfo,
1275
            'name',
1276
            ['eng-GB' => 'Updated Again Name']
1277
        );
1278
        // create historical entry for nested folder
1279
        $this->updateContentField(
1280
            $nestedFolder->contentInfo,
1281
            'name',
1282
            ['eng-GB' => 'Updated Nested folder']
1283
        );
1284
1285
        // perform sanity check
1286
        $this->assertUrlIsHistory('/My-folder-Name', $folderLocation->id);
1287
        $this->assertUrlIsHistory('/Updated-Name', $folderLocation->id);
1288
        $this->assertUrlIsHistory('/My-folder-Name/Nested-folder', $nestedFolderLocation->id);
1289
        $this->assertUrlIsHistory('/Updated-Name/Nested-folder', $nestedFolderLocation->id);
1290
        $this->assertUrlIsHistory('/Updated-Again-Name/Nested-folder', $nestedFolderLocation->id);
1291
1292
        $this->assertUrlIsCurrent('/Updated-Again-Name', $folderLocation->id);
1293
        $this->assertUrlIsCurrent('/Updated-Again-Name/Updated-Nested-folder', $nestedFolderLocation->id);
1294
1295
        self::assertNotEmpty($urlAliasService->listLocationAliases($folderLocation, false));
1296
1297
        // corrupt database by removing original entry, keeping its history
1298
        $this->performRawDatabaseOperation(
1299
            function (Connection $connection) use ($folderLocation) {
1300
                $queryBuilder = $connection->createQueryBuilder();
1301
                $expr = $queryBuilder->expr();
1302
                $queryBuilder
1303
                    ->delete('ezurlalias_ml')
1304
                    ->where(
1305
                        $expr->andX(
1306
                            $expr->eq(
1307
                                'action',
1308
                                $queryBuilder->createPositionalParameter(
1309
                                    "eznode:{$folderLocation->id}"
1310
                                )
1311
                            ),
1312
                            $expr->eq(
1313
                                'is_original',
1314
                                $queryBuilder->createPositionalParameter(1)
1315
                            )
1316
                        )
1317
                    );
1318
1319
                return $queryBuilder->execute();
1320
            }
1321
        );
1322
1323
        // perform sanity check
1324
        self::assertEmpty($urlAliasService->listLocationAliases($folderLocation, false));
1325
1326
        // Begin the actual test
1327
        $urlAliasService->refreshSystemUrlAliasesForLocation($folderLocation);
1328
        $urlAliasService->refreshSystemUrlAliasesForLocation($nestedFolderLocation);
1329
1330
        // make sure there is no corrupted data that could affect the test
1331
        $urlAliasService->deleteCorruptedUrlAliases();
1332
1333
        // test if history was restored
1334
        $this->assertUrlIsHistory('/My-folder-Name', $folderLocation->id);
1335
        $this->assertUrlIsHistory('/Updated-Name', $folderLocation->id);
1336
        $this->assertUrlIsHistory('/My-folder-Name/Nested-folder', $nestedFolderLocation->id);
1337
        $this->assertUrlIsHistory('/Updated-Name/Nested-folder', $nestedFolderLocation->id);
1338
        $this->assertUrlIsHistory('/Updated-Again-Name/Nested-folder', $nestedFolderLocation->id);
1339
1340
        $this->assertUrlIsCurrent('/Updated-Again-Name', $folderLocation->id);
1341
        $this->assertUrlIsCurrent('/Updated-Again-Name/Updated-Nested-folder', $nestedFolderLocation->id);
1342
    }
1343
1344
    /**
1345
     * Test edge case when updated and archived entry gets moved to another subtree.
1346
     *
1347
     * @see https://jira.ez.no/browse/EZP-30004
1348
     *
1349
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1350
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1351
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1352
     * @throws \Exception
1353
     */
1354
    public function testRefreshSystemUrlAliasesForMovedLocation()
1355
    {
1356
        $repository = $this->getRepository();
1357
        $urlAliasService = $repository->getURLAliasService();
1358
        $locationService = $repository->getLocationService();
1359
1360
        $folderNames = ['eng-GB' => 'folder'];
1361
        $folder = $this->createFolder($folderNames, 2);
1362
        $nestedFolder = $this->createFolder($folderNames, $folder->contentInfo->mainLocationId);
1363
1364
        $nestedFolder = $this->updateContentField(
1365
            $nestedFolder->contentInfo,
1366
            'name',
1367
            ['eng-GB' => 'folder2']
1368
        );
1369
1370
        $nestedFolderLocation = $locationService->loadLocation(
1371
            $nestedFolder->contentInfo->mainLocationId
1372
        );
1373
        $rootLocation = $locationService->loadLocation(2);
1374
1375
        $locationService->moveSubtree($nestedFolderLocation, $rootLocation);
1376
        // reload nested Location to get proper parent information
1377
        $nestedFolderLocation = $locationService->loadLocation($nestedFolderLocation->id);
1378
1379
        // corrupt database by breaking link to the original URL alias
1380
        $this->performRawDatabaseOperation(
1381
            function (Connection $connection) use ($nestedFolderLocation) {
1382
                $queryBuilder = $connection->createQueryBuilder();
1383
                $expr = $queryBuilder->expr();
1384
                $queryBuilder
1385
                    ->update('ezurlalias_ml')
1386
                    ->set('link', $queryBuilder->createPositionalParameter(666, \PDO::PARAM_INT))
1387
                    ->where(
1388
                        $expr->eq(
1389
                            'action',
1390
                            $queryBuilder->createPositionalParameter(
1391
                                "eznode:{$nestedFolderLocation->id}"
1392
                            )
1393
                        )
1394
                    )
1395
                    ->andWhere(
1396
                        $expr->eq(
1397
                            'is_original',
1398
                            $queryBuilder->createPositionalParameter(0, \PDO::PARAM_INT)
1399
                        )
1400
                    )
1401
                    ->andWhere(
1402
                        $expr->eq('text', $queryBuilder->createPositionalParameter('folder'))
1403
                    )
1404
                ;
1405
1406
                return $queryBuilder->execute();
1407
            }
1408
        );
1409
1410
        $urlAliasService->refreshSystemUrlAliasesForLocation($nestedFolderLocation);
1411
    }
1412
1413
    /**
1414
     * Lookup given URL and check if it is archived and points to the given Location Id.
1415
     *
1416
     * @param string $lookupUrl
1417
     * @param int $expectedDestination Expected Location ID
1418
     */
1419
    protected function assertUrlIsHistory($lookupUrl, $expectedDestination)
1420
    {
1421
        $this->assertLookupHistory(true, $expectedDestination, $lookupUrl);
1422
    }
1423
1424
    /**
1425
     * Lookup given URL and check if it is current (not archived) and points to the given Location Id.
1426
     *
1427
     * @param string $lookupUrl
1428
     * @param int $expectedDestination Expected Location ID
1429
     */
1430
    protected function assertUrlIsCurrent($lookupUrl, $expectedDestination)
1431
    {
1432
        $this->assertLookupHistory(false, $expectedDestination, $lookupUrl);
1433
    }
1434
1435
    /**
1436
     * Lookup and URLAlias VO history and destination properties.
1437
     *
1438
     * @see assertUrlIsHistory
1439
     * @see assertUrlIsCurrent
1440
     *
1441
     * @param bool $expectedIsHistory
1442
     * @param int $expectedDestination Expected Location ID
1443
     * @param string $lookupUrl
1444
     */
1445
    protected function assertLookupHistory($expectedIsHistory, $expectedDestination, $lookupUrl)
1446
    {
1447
        $urlAliasService = $this->getRepository(false)->getURLAliasService();
1448
1449
        try {
1450
            $urlAlias = $urlAliasService->lookup($lookupUrl);
1451
            self::assertPropertiesCorrect(
1452
                [
1453
                    'destination' => $expectedDestination,
1454
                    'path' => $lookupUrl,
1455
                    'isHistory' => $expectedIsHistory,
1456
                ],
1457
                $urlAlias
1458
            );
1459
        } catch (InvalidArgumentException $e) {
1460
            self::fail("Failed to lookup {$lookupUrl}: $e");
1461
        } catch (NotFoundException $e) {
1462
            self::fail("Failed to lookup {$lookupUrl}: $e");
1463
        }
1464
    }
1465
1466
    /**
1467
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
1468
     * @param $fieldDefinitionIdentifier
1469
     * @param array $fieldValues
1470
     *
1471
     * @return \eZ\Publish\API\Repository\Values\Content\Content
1472
     *
1473
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1474
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1475
     */
1476
    protected function updateContentField(ContentInfo $contentInfo, $fieldDefinitionIdentifier, array $fieldValues)
1477
    {
1478
        $contentService = $this->getRepository(false)->getContentService();
1479
1480
        $contentUpdateStruct = $contentService->newContentUpdateStruct();
1481
        foreach ($fieldValues as $languageCode => $fieldValue) {
1482
            $contentUpdateStruct->setField($fieldDefinitionIdentifier, $fieldValue, $languageCode);
1483
        }
1484
        $contentDraft = $contentService->updateContent(
1485
            $contentService->createContentDraft($contentInfo)->versionInfo,
1486
            $contentUpdateStruct
1487
        );
1488
1489
        return $contentService->publishVersion($contentDraft->versionInfo);
1490
    }
1491
1492
    /**
1493
     * Test deleting corrupted URL aliases.
1494
     *
1495
     * Note: this test will not be needed once we introduce Improved Storage with Foreign keys support.
1496
     *
1497
     * Note: test depends on already broken URL aliases: eznode:59, eznode:59, eznode:60.
1498
     *
1499
     * @throws \ErrorException
1500
     */
1501
    public function testDeleteCorruptedUrlAliases()
1502
    {
1503
        $repository = $this->getRepository();
1504
        $urlAliasService = $repository->getURLAliasService();
1505
        $connection = $this->getRawDatabaseConnection();
1506
1507
        $query = $connection->createQueryBuilder()->select('*')->from('ezurlalias_ml');
1508
        $originalRows = $query->execute()->fetchAll(PDO::FETCH_ASSOC);
1509
1510
        $expectedCount = count($originalRows);
1511
        $expectedCount += $this->insertBrokenUrlAliasTableFixtures($connection);
1512
1513
        // sanity check
1514
        $updatedRows = $query->execute()->fetchAll(PDO::FETCH_ASSOC);
1515
        self::assertCount($expectedCount, $updatedRows, 'Found unexpected number of new rows');
1516
1517
        // BEGIN API use case
1518
        $urlAliasService->deleteCorruptedUrlAliases();
1519
        // END API use case
1520
1521
        $updatedRows = $query->execute()->fetchAll(PDO::FETCH_ASSOC);
1522
        self::assertCount(
1523
            // API should also remove already broken pre-existing URL aliases to Locations 50 and 2x 59
1524
            count($originalRows) - 3,
1525
            $updatedRows,
1526
            'Number of rows after cleanup is not the same as the original number of rows'
1527
        );
1528
    }
1529
1530
    /**
1531
     * Mutate 'ezpublish.persistence.slug_converter' Service configuration.
1532
     *
1533
     * @param string $key
1534
     * @param string $value
1535
     *
1536
     * @throws \ErrorException
1537
     * @throws \Exception
1538
     */
1539
    protected function changeSlugConverterConfiguration($key, $value)
1540
    {
1541
        $testSlugConverter = $this
1542
            ->getSetupFactory()
1543
            ->getServiceContainer()
1544
            ->getInnerContainer()
1545
            ->get('ezpublish.persistence.slug_converter');
1546
1547
        if (!$testSlugConverter instanceof TestSlugConverter) {
1548
            throw new RuntimeException(
1549
                sprintf(
1550
                    '%s: expected instance of %s, got %s',
1551
                    __METHOD__,
1552
                    TestSlugConverter::class,
1553
                    get_class($testSlugConverter)
1554
                )
1555
            );
1556
        }
1557
1558
        $testSlugConverter->setConfigurationValue($key, $value);
1559
    }
1560
1561
    /**
1562
     * Update Content Type URL alias schema pattern.
1563
     *
1564
     * @param string $contentTypeIdentifier
1565
     * @param string $newUrlAliasSchema
1566
     *
1567
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1568
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1569
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1570
     */
1571
    protected function changeContentTypeUrlAliasSchema($contentTypeIdentifier, $newUrlAliasSchema)
1572
    {
1573
        $contentTypeService = $this->getRepository(false)->getContentTypeService();
1574
1575
        $contentType = $contentTypeService->loadContentTypeByIdentifier($contentTypeIdentifier);
1576
1577
        $contentTypeDraft = $contentTypeService->createContentTypeDraft($contentType);
1578
        $contentTypeUpdateStruct = $contentTypeService->newContentTypeUpdateStruct();
1579
        $contentTypeUpdateStruct->urlAliasSchema = $newUrlAliasSchema;
1580
1581
        $contentTypeService->updateContentTypeDraft($contentTypeDraft, $contentTypeUpdateStruct);
1582
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
1583
    }
1584
1585
    private function assertUrlAliasPropertiesCorrect(
1586
        Location $expectedDestinationLocation,
1587
        $expectedPath,
1588
        array $expectedLanguageCodes,
0 ignored issues
show
Unused Code introduced by
The parameter $expectedLanguageCodes is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1589
        $expectedIsHistory,
1590
        URLAlias $actualUrlAliasValue
1591
    ) {
1592
        self::assertPropertiesCorrect(
1593
            [
1594
                'destination' => $expectedDestinationLocation->id,
1595
                'path' => $expectedPath,
1596
                // @todo uncomment after fixing EZP-27124
1597
                //'languageCodes' => $expectedLanguageCodes,
1598
                'isHistory' => $expectedIsHistory,
1599
                'isCustom' => false,
1600
                'forward' => false,
1601
            ],
1602
            $actualUrlAliasValue
1603
        );
1604
    }
1605
1606
    /**
1607
     * Insert intentionally broken rows into ezurlalias_ml table to test cleanup API.
1608
     *
1609
     * @see \eZ\Publish\API\Repository\URLAliasService::deleteCorruptedUrlAliases
1610
     * @see testDeleteCorruptedUrlAliases
1611
     *
1612
     * @param \Doctrine\DBAL\Connection $connection
1613
     *
1614
     * @return int Number of new rows
1615
     */
1616
    private function insertBrokenUrlAliasTableFixtures(Connection $connection)
1617
    {
1618
        $rows = [
1619
            // link to non-existent location
1620
            [
1621
                'action' => 'eznode:9999',
1622
                'action_type' => 'eznode',
1623
                'alias_redirects' => 0,
1624
                'id' => 9997,
1625
                'is_alias' => 0,
1626
                'is_original' => 1,
1627
                'lang_mask' => 3,
1628
                'link' => 9997,
1629
                'parent' => 0,
1630
                'text' => 'my-location',
1631
                'text_md5' => '19d12b1b9994619cd8e90f00a6f5834e',
1632
            ],
1633
            // link to non-existent target URL alias (`link` column)
1634
            [
1635
                'action' => 'nop:',
1636
                'action_type' => 'nop',
1637
                'alias_redirects' => 0,
1638
                'id' => 9998,
1639
                'is_alias' => 1,
1640
                'is_original' => 1,
1641
                'lang_mask' => 2,
1642
                'link' => 9995,
1643
                'parent' => 0,
1644
                'text' => 'my-alias1',
1645
                'text_md5' => 'a29dd95ccf4c1bc7ebbd61086863b632',
1646
            ],
1647
            // link to non-existent parent URL alias
1648
            [
1649
                'action' => 'nop:',
1650
                'action_type' => 'nop',
1651
                'alias_redirects' => 0,
1652
                'id' => 9999,
1653
                'is_alias' => 0,
1654
                'is_original' => 1,
1655
                'lang_mask' => 3,
1656
                'link' => 9999,
1657
                'parent' => 9995,
1658
                'text' => 'my-alias2',
1659
                'text_md5' => 'e5dea18481e4f86857865d9fc94e4ce9',
1660
            ],
1661
        ];
1662
1663
        $query = $connection->createQueryBuilder()->insert('ezurlalias_ml');
1664
1665
        foreach ($rows as $row) {
1666
            foreach ($row as $columnName => $value) {
1667
                $row[$columnName] = $query->createNamedParameter($value);
1668
            }
1669
            $query->values($row);
1670
            $query->execute();
1671
        }
1672
1673
        return count($rows);
1674
    }
1675
}
1676