Completed
Push — master ( 9c45fe...2e51e7 )
by
unknown
29:13 queued 13:18
created

assertUrlAliasPropertiesCorrect()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 5
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
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 View Code Duplication
    protected function setUp(): void
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
            'eZ\\Publish\\API\\Repository\\Values\\Content\\URLAlias',
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
            'eZ\\Publish\\API\\Repository\\Values\\Content\\URLAlias',
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
            'eZ\\Publish\\API\\Repository\\Values\\Content\\URLAlias',
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
     */
241
    public function testCreateUrlAliasThrowsInvalidArgumentException()
242
    {
243
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
244
245
        $repository = $this->getRepository();
246
247
        $locationId = $this->generateId('location', 5);
248
249
        /* BEGIN: Use Case */
250
        // $locationId is the ID of an existing location
251
252
        $locationService = $repository->getLocationService();
253
        $urlAliasService = $repository->getURLAliasService();
254
255
        $location = $locationService->loadLocation($locationId);
256
257
        // Throws InvalidArgumentException, since this path already exists for the
258
        // language
259
        $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...
260
        /* END: Use Case */
261
    }
262
263
    /**
264
     * Test for the createGlobalUrlAlias() method.
265
     *
266
     * @see \eZ\Publish\API\Repository\URLAliasService::createGlobalUrlAlias()
267
     */
268 View Code Duplication
    public function testCreateGlobalUrlAlias()
269
    {
270
        $repository = $this->getRepository();
271
272
        /* BEGIN: Use Case */
273
        $urlAliasService = $repository->getURLAliasService();
274
275
        $createdUrlAlias = $urlAliasService->createGlobalUrlAlias(
276
            'module:content/search?SearchText=eZ',
277
            '/Home/My-New-Site',
278
            'eng-US'
279
        );
280
        /* END: Use Case */
281
282
        $this->assertInstanceOf(
283
            'eZ\\Publish\\API\\Repository\\Values\\Content\\URLAlias',
284
            $createdUrlAlias
285
        );
286
287
        return $createdUrlAlias;
288
    }
289
290
    /**
291
     * @param \eZ\Publish\API\Repository\Values\Content\URLAlias
292
     *
293
     * @depends testCreateGlobalUrlAlias
294
     */
295 View Code Duplication
    public function testCreateGlobalUrlAliasPropertyValues(URLAlias $createdUrlAlias)
296
    {
297
        $this->assertNotNull($createdUrlAlias->id);
298
299
        $this->assertPropertiesCorrect(
300
            [
301
                'type' => URLAlias::RESOURCE,
302
                'destination' => 'content/search?SearchText=eZ',
303
                'path' => '/Home/My-New-Site',
304
                'languageCodes' => ['eng-US'],
305
                'alwaysAvailable' => false,
306
                'isHistory' => false,
307
                'isCustom' => true,
308
                'forward' => false,
309
            ],
310
            $createdUrlAlias
311
        );
312
    }
313
314
    /**
315
     * Test for the createGlobalUrlAlias() method.
316
     *
317
     * @see \eZ\Publish\API\Repository\URLAliasService::createGlobalUrlAlias($resource, $path, $languageCode, $forward)
318
     */
319 View Code Duplication
    public function testCreateGlobalUrlAliasWithForward()
320
    {
321
        $repository = $this->getRepository();
322
323
        /* BEGIN: Use Case */
324
        $urlAliasService = $repository->getURLAliasService();
325
326
        $createdUrlAlias = $urlAliasService->createGlobalUrlAlias(
327
            'module:content/search?SearchText=eZ',
328
            '/Home/My-New-Site',
329
            'eng-US',
330
            true
331
        );
332
        /* END: Use Case */
333
334
        $this->assertInstanceOf(
335
            'eZ\\Publish\\API\\Repository\\Values\\Content\\URLAlias',
336
            $createdUrlAlias
337
        );
338
339
        return $createdUrlAlias;
340
    }
341
342
    /**
343
     * @param \eZ\Publish\API\Repository\Values\Content\URLAlias
344
     *
345
     * @depends testCreateGlobalUrlAliasWithForward
346
     */
347 View Code Duplication
    public function testCreateGlobalUrlAliasWithForwardPropertyValues(URLAlias $createdUrlAlias)
348
    {
349
        $this->assertNotNull($createdUrlAlias->id);
350
351
        $this->assertPropertiesCorrect(
352
            [
353
                'type' => URLAlias::RESOURCE,
354
                'destination' => 'content/search?SearchText=eZ',
355
                'path' => '/Home/My-New-Site',
356
                'languageCodes' => ['eng-US'],
357
                'alwaysAvailable' => false,
358
                'isHistory' => false,
359
                'isCustom' => true,
360
                'forward' => true,
361
            ],
362
            $createdUrlAlias
363
        );
364
    }
365
366
    /**
367
     * Test for the createGlobalUrlAlias() method.
368
     *
369
     * @see \eZ\Publish\API\Repository\URLAliasService::createGlobalUrlAlias($resource, $path, $languageCode, $forwarding, $alwaysAvailable)
370
     */
371 View Code Duplication
    public function testCreateGlobalUrlAliasWithAlwaysAvailable()
372
    {
373
        $repository = $this->getRepository();
374
375
        /* BEGIN: Use Case */
376
        $urlAliasService = $repository->getURLAliasService();
377
378
        $createdUrlAlias = $urlAliasService->createGlobalUrlAlias(
379
            'module:content/search?SearchText=eZ',
380
            '/Home/My-New-Site',
381
            'eng-US',
382
            false,
383
            true
384
        );
385
        /* END: Use Case */
386
387
        $this->assertInstanceOf(
388
            'eZ\\Publish\\API\\Repository\\Values\\Content\\URLAlias',
389
            $createdUrlAlias
390
        );
391
392
        return $createdUrlAlias;
393
    }
394
395
    /**
396
     * @param \eZ\Publish\API\Repository\Values\Content\URLAlias
397
     *
398
     * @depends testCreateGlobalUrlAliasWithAlwaysAvailable
399
     */
400 View Code Duplication
    public function testCreateGlobalUrlAliasWithAlwaysAvailablePropertyValues(URLAlias $createdUrlAlias)
401
    {
402
        $this->assertNotNull($createdUrlAlias->id);
403
404
        $this->assertPropertiesCorrect(
405
            [
406
                'type' => URLAlias::RESOURCE,
407
                'destination' => 'content/search?SearchText=eZ',
408
                'path' => '/Home/My-New-Site',
409
                'languageCodes' => ['eng-US'],
410
                'alwaysAvailable' => true,
411
                'isHistory' => false,
412
                'isCustom' => true,
413
                'forward' => false,
414
            ],
415
            $createdUrlAlias
416
        );
417
    }
418
419
    /**
420
     * Test for the createUrlAlias() method.
421
     *
422
     * @see \eZ\Publish\API\Repository\URLAliasService::createGlobalUrlAlias($resource, $path, $languageCode, $forwarding, $alwaysAvailable)
423
     */
424 View Code Duplication
    public function testCreateGlobalUrlAliasForLocation()
425
    {
426
        $repository = $this->getRepository();
427
428
        $locationId = $this->generateId('location', 5);
429
        $locationService = $repository->getLocationService();
430
        $location = $locationService->loadLocation($locationId);
431
432
        /* BEGIN: Use Case */
433
        // $locationId is the ID of an existing location
434
435
        $urlAliasService = $repository->getURLAliasService();
436
437
        $createdUrlAlias = $urlAliasService->createGlobalUrlAlias(
438
            'module:content/view/full/' . $locationId,
439
            '/Home/My-New-Site-global',
440
            'eng-US',
441
            false,
442
            true
443
        );
444
        /* END: Use Case */
445
446
        $this->assertInstanceOf(
447
            'eZ\\Publish\\API\\Repository\\Values\\Content\\URLAlias',
448
            $createdUrlAlias
449
        );
450
451
        return [$createdUrlAlias, $location->id];
452
    }
453
454
    /**
455
     * Test for the createUrlAlias() method.
456
     *
457
     * @see \eZ\Publish\API\Repository\URLAliasService::createGlobalUrlAlias($resource, $path, $languageCode, $forwarding, $alwaysAvailable)
458
     */
459 View Code Duplication
    public function testCreateGlobalUrlAliasForLocationVariation()
460
    {
461
        $repository = $this->getRepository();
462
463
        $locationId = $this->generateId('location', 5);
464
        $locationService = $repository->getLocationService();
465
        $location = $locationService->loadLocation($locationId);
466
467
        /* BEGIN: Use Case */
468
        // $locationId is the ID of an existing location
469
470
        $urlAliasService = $repository->getURLAliasService();
471
472
        $createdUrlAlias = $urlAliasService->createGlobalUrlAlias(
473
            'eznode:' . $locationId,
474
            '/Home/My-New-Site-global',
475
            'eng-US',
476
            false,
477
            true
478
        );
479
        /* END: Use Case */
480
481
        $this->assertInstanceOf(
482
            'eZ\\Publish\\API\\Repository\\Values\\Content\\URLAlias',
483
            $createdUrlAlias
484
        );
485
486
        return [$createdUrlAlias, $location->id];
487
    }
488
489
    /**
490
     * @param \eZ\Publish\API\Repository\Values\Content\URLAlias
491
     *
492
     * @depends testCreateGlobalUrlAliasForLocation
493
     */
494 View Code Duplication
    public function testCreateGlobalUrlAliasForLocationPropertyValues($testData)
495
    {
496
        list($createdUrlAlias, $locationId) = $testData;
497
498
        $this->assertNotNull($createdUrlAlias->id);
499
500
        $this->assertPropertiesCorrect(
501
            [
502
                'type' => URLAlias::LOCATION,
503
                'destination' => $locationId,
504
                'path' => '/Home/My-New-Site-global',
505
                'languageCodes' => ['eng-US'],
506
                'alwaysAvailable' => true,
507
                'isHistory' => false,
508
                'isCustom' => true,
509
                'forward' => false,
510
            ],
511
            $createdUrlAlias
512
        );
513
    }
514
515
    /**
516
     * @param \eZ\Publish\API\Repository\Values\Content\URLAlias
517
     *
518
     * @depends testCreateGlobalUrlAliasForLocationVariation
519
     */
520
    public function testCreateGlobalUrlAliasForLocationVariationPropertyValues($testData)
521
    {
522
        $this->testCreateGlobalUrlAliasForLocationPropertyValues($testData);
523
    }
524
525
    /**
526
     * Test for the createGlobalUrlAlias() method.
527
     *
528
     * @see \eZ\Publish\API\Repository\URLAliasService::createGlobalUrlAlias()
529
     */
530
    public function testCreateGlobalUrlAliasThrowsInvalidArgumentException()
531
    {
532
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
533
534
        $repository = $this->getRepository();
535
536
        /* BEGIN: Use Case */
537
        $urlAliasService = $repository->getURLAliasService();
538
539
        // Throws InvalidArgumentException, since this path already exists for the
540
        // language
541
        $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...
542
            'module:content/search?SearchText=eZ',
543
            '/Design/Plain-site',
544
            'eng-US'
545
        );
546
        /* END: Use Case */
547
    }
548
549
    /**
550
     * Test for the listLocationAliases() method.
551
     *
552
     * @see \eZ\Publish\API\Repository\URLAliasService::listLocationAliases()
553
     */
554
    public function testListLocationAliases()
555
    {
556
        $repository = $this->getRepository();
557
558
        $locationId = $this->generateId('location', 12);
559
560
        /* BEGIN: Use Case */
561
        // $locationId contains the ID of an existing Location
562
        $urlAliasService = $repository->getURLAliasService();
563
        $locationService = $repository->getLocationService();
564
565
        $location = $locationService->loadLocation($locationId);
566
567
        // Create a custom URL alias for $location
568
        $urlAliasService->createUrlAlias($location, '/My/Great-new-Site', 'eng-US');
569
570
        // $loadedAliases will contain an array of custom URLAlias objects
571
        $loadedAliases = $urlAliasService->listLocationAliases($location);
572
        /* END: Use Case */
573
574
        $this->assertIsArray($loadedAliases
575
        );
576
577
        // Only 1 non-history alias
578
        $this->assertCount(1, $loadedAliases);
579
580
        return [$loadedAliases, $location];
581
    }
582
583
    /**
584
     * @param array $testData
585
     *
586
     * @depends testListLocationAliases
587
     */
588
    public function testListLocationAliasesLoadsCorrectly(array $testData)
589
    {
590
        list($loadedAliases, $location) = $testData;
591
592
        foreach ($loadedAliases as $loadedAlias) {
593
            $this->assertInstanceOf(
594
                'eZ\\Publish\\API\\Repository\\Values\\Content\\URLAlias',
595
                $loadedAlias
596
            );
597
            $this->assertEquals(
598
                $location->id,
599
                $loadedAlias->destination
600
            );
601
        }
602
    }
603
604
    /**
605
     * Test for the listLocationAliases() method.
606
     *
607
     * @see \eZ\Publish\API\Repository\URLAliasService::listLocationAliases($location, $custom, $languageCode)
608
     */
609 View Code Duplication
    public function testListLocationAliasesWithCustomFilter()
610
    {
611
        $repository = $this->getRepository();
612
613
        $locationId = $this->generateId('location', 12);
614
615
        /* BEGIN: Use Case */
616
        // $locationId contains the ID of an existing Location
617
        $urlAliasService = $repository->getURLAliasService();
618
        $locationService = $repository->getLocationService();
619
620
        $location = $locationService->loadLocation($locationId);
621
622
        // Create a second URL alias for $location, this is a "custom" one
623
        $urlAliasService->createUrlAlias($location, '/My/Great-new-Site', 'ger-DE');
624
625
        // $loadedAliases will contain 1 aliases in eng-US only
626
        $loadedAliases = $urlAliasService->listLocationAliases($location, false, 'eng-US');
627
        /* END: Use Case */
628
629
        $this->assertIsArray($loadedAliases
630
        );
631
        $this->assertCount(1, $loadedAliases);
632
    }
633
634
    /**
635
     * Test for the listLocationAliases() method.
636
     *
637
     * @see \eZ\Publish\API\Repository\URLAliasService::listLocationAliases($location, $custom)
638
     */
639 View Code Duplication
    public function testListLocationAliasesWithLanguageCodeFilter()
640
    {
641
        $repository = $this->getRepository();
642
643
        $locationId = $this->generateId('location', 12);
644
645
        /* BEGIN: Use Case */
646
        // $locationId contains the ID of an existing Location
647
        $urlAliasService = $repository->getURLAliasService();
648
        $locationService = $repository->getLocationService();
649
650
        $location = $locationService->loadLocation($locationId);
651
        // Create a custom URL alias for $location
652
        $urlAliasService->createUrlAlias($location, '/My/Great-new-Site', 'eng-US');
653
654
        // $loadedAliases will contain only 1 of 3 aliases (custom in eng-US)
655
        $loadedAliases = $urlAliasService->listLocationAliases($location, true, 'eng-US');
656
        /* END: Use Case */
657
658
        $this->assertIsArray($loadedAliases
659
        );
660
        $this->assertCount(1, $loadedAliases);
661
    }
662
663
    /**
664
     * Test for the listGlobalAliases() method.
665
     *
666
     * @see \eZ\Publish\API\Repository\URLAliasService::listGlobalAliases()
667
     */
668 View Code Duplication
    public function testListGlobalAliases()
669
    {
670
        $repository = $this->getRepository();
671
672
        /* BEGIN: Use Case */
673
        $urlAliasService = $repository->getURLAliasService();
674
675
        // Create some global aliases
676
        $this->createGlobalAliases();
677
678
        // $loadedAliases will contain all 3 global aliases
679
        $loadedAliases = $urlAliasService->listGlobalAliases();
680
        /* END: Use Case */
681
682
        $this->assertIsArray($loadedAliases
683
        );
684
        $this->assertCount(3, $loadedAliases);
685
    }
686
687
    /**
688
     * Creates 3 global aliases.
689
     */
690
    private function createGlobalAliases()
691
    {
692
        $repository = $this->getRepository();
693
        $urlAliasService = $repository->getURLAliasService();
694
695
        /* BEGIN: Inline */
696
        $urlAliasService->createGlobalUrlAlias(
697
            'module:content/search?SearchText=eZ',
698
            '/My/Special-Support',
699
            'eng-US'
700
        );
701
        $urlAliasService->createGlobalUrlAlias(
702
            'module:content/search?SearchText=eZ',
703
            '/My/London-Office',
704
            'eng-GB'
705
        );
706
        $urlAliasService->createGlobalUrlAlias(
707
            'module:content/search?SearchText=Sindelfingen',
708
            '/My/Fancy-Site',
709
            'eng-US'
710
        );
711
        /* END: Inline */
712
    }
713
714
    /**
715
     * Test for the listGlobalAliases() method.
716
     *
717
     * @see \eZ\Publish\API\Repository\URLAliasService::listGlobalAliases($languageCode)
718
     */
719 View Code Duplication
    public function testListGlobalAliasesWithLanguageFilter()
720
    {
721
        $repository = $this->getRepository();
722
723
        /* BEGIN: Use Case */
724
        $urlAliasService = $repository->getURLAliasService();
725
726
        // Create some global aliases
727
        $this->createGlobalAliases();
728
729
        // $loadedAliases will contain only 2 of 3 global aliases
730
        $loadedAliases = $urlAliasService->listGlobalAliases('eng-US');
731
        /* END: Use Case */
732
733
        $this->assertIsArray($loadedAliases
734
        );
735
        $this->assertCount(2, $loadedAliases);
736
    }
737
738
    /**
739
     * Test for the listGlobalAliases() method.
740
     *
741
     * @see \eZ\Publish\API\Repository\URLAliasService::listGlobalAliases($languageCode, $offset)
742
     */
743 View Code Duplication
    public function testListGlobalAliasesWithOffset()
744
    {
745
        $repository = $this->getRepository();
746
747
        /* BEGIN: Use Case */
748
        $urlAliasService = $repository->getURLAliasService();
749
750
        // Create some global aliases
751
        $this->createGlobalAliases();
752
753
        // $loadedAliases will contain only 2 of 3 global aliases
754
        $loadedAliases = $urlAliasService->listGlobalAliases(null, 1);
755
        /* END: Use Case */
756
757
        $this->assertIsArray($loadedAliases
758
        );
759
        $this->assertCount(2, $loadedAliases);
760
    }
761
762
    /**
763
     * Test for the listGlobalAliases() method.
764
     *
765
     * @see \eZ\Publish\API\Repository\URLAliasService::listGlobalAliases($languageCode, $offset, $limit)
766
     */
767 View Code Duplication
    public function testListGlobalAliasesWithLimit()
768
    {
769
        $repository = $this->getRepository();
770
771
        /* BEGIN: Use Case */
772
        $urlAliasService = $repository->getURLAliasService();
773
774
        // Create some global aliases
775
        $this->createGlobalAliases();
776
777
        // $loadedAliases will contain only 1 of 3 global aliases
778
        $loadedAliases = $urlAliasService->listGlobalAliases(null, 0, 1);
779
        /* END: Use Case */
780
781
        $this->assertIsArray($loadedAliases
782
        );
783
        $this->assertCount(1, $loadedAliases);
784
    }
785
786
    /**
787
     * Test for the removeAliases() method.
788
     *
789
     * @see \eZ\Publish\API\Repository\URLAliasService::removeAliases()
790
     */
791
    public function testRemoveAliases()
792
    {
793
        $repository = $this->getRepository();
794
795
        $locationService = $repository->getLocationService();
796
        $someLocation = $locationService->loadLocation(
797
            $this->generateId('location', 12)
798
        );
799
800
        /* BEGIN: Use Case */
801
        // $someLocation contains a location with automatically generated
802
        // aliases assigned
803
        $urlAliasService = $repository->getURLAliasService();
804
805
        $initialAliases = $urlAliasService->listLocationAliases($someLocation);
806
807
        // Creates a custom alias for $someLocation
808
        $urlAliasService->createUrlAlias(
809
            $someLocation,
810
            '/my/fancy/url/alias/sindelfingen',
811
            'eng-US'
812
        );
813
814
        $customAliases = $urlAliasService->listLocationAliases($someLocation);
815
816
        // The custom alias just created will be removed
817
        // the automatic aliases stay in tact
818
        $urlAliasService->removeAliases($customAliases);
819
        /* END: Use Case */
820
821
        $this->assertEquals(
822
            $initialAliases,
823
            $urlAliasService->listLocationAliases($someLocation)
824
        );
825
    }
826
827
    /**
828
     * Test for the removeAliases() method.
829
     *
830
     * @see \eZ\Publish\API\Repository\URLAliasService::removeAliases()
831
     */
832
    public function testRemoveAliasesThrowsInvalidArgumentExceptionIfAutogeneratedAliasesAreToBeRemoved()
833
    {
834
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
835
836
        $repository = $this->getRepository();
837
838
        $locationService = $repository->getLocationService();
839
        $someLocation = $locationService->loadLocation(
840
            $this->generateId('location', 12)
841
        );
842
843
        /* BEGIN: Use Case */
844
        // $someLocation contains a location with automatically generated
845
        // aliases assigned
846
        $urlAliasService = $repository->getURLAliasService();
847
848
        $autogeneratedAliases = $urlAliasService->listLocationAliases($someLocation, false);
849
850
        // Throws an InvalidArgumentException, since autogeneratedAliases
851
        // cannot be removed with this method
852
        $urlAliasService->removeAliases($autogeneratedAliases);
853
        /* END: Use Case */
854
    }
855
856
    /**
857
     * Test for the lookUp() method.
858
     *
859
     * @see \eZ\Publish\API\Repository\URLAliasService::lookUp()
860
     */
861
    public function testLookUp()
862
    {
863
        $repository = $this->getRepository();
864
865
        /* BEGIN: Use Case */
866
        $urlAliasService = $repository->getURLAliasService();
867
868
        $loadedAlias = $urlAliasService->lookUp('/Setup2');
869
        /* END: Use Case */
870
871
        $this->assertInstanceOf(
872
            'eZ\\Publish\\API\\Repository\\Values\\Content\\URLAlias',
873
            $loadedAlias
874
        );
875
876
        return $loadedAlias;
877
    }
878
879
    /**
880
     * Test for the lookUp() method.
881
     *
882
     * @see \eZ\Publish\API\Repository\URLAliasService::lookUp($url, $languageCode)
883
     */
884
    public function testLookUpWithLanguageFilter()
885
    {
886
        $repository = $this->getRepository();
887
888
        /* BEGIN: Use Case */
889
        $urlAliasService = $repository->getURLAliasService();
890
891
        // Create aliases in multiple languages
892
        $this->createGlobalAliases();
893
894
        $loadedAlias = $urlAliasService->lookUp('/My/Special-Support', 'eng-US');
895
        /* END: Use Case */
896
897
        $this->assertInstanceOf(
898
            'eZ\\Publish\\API\\Repository\\Values\\Content\\URLAlias',
899
            $loadedAlias
900
        );
901
        $this->assertEquals(
902
            'content/search?SearchText=eZ',
903
            $loadedAlias->destination
904
        );
905
    }
906
907
    /**
908
     * Test for the lookUp() method.
909
     *
910
     * @see \eZ\Publish\API\Repository\URLAliasService::lookUp()
911
     */
912
    public function testLookUpThrowsNotFoundException()
913
    {
914
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
915
916
        $repository = $this->getRepository();
917
918
        /* BEGIN: Use Case */
919
        $urlAliasService = $repository->getURLAliasService();
920
921
        // Throws NotFoundException
922
        $loadedAlias = $urlAliasService->lookUp('/non-existent-url');
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...
923
        /* END: Use Case */
924
    }
925
926
    /**
927
     * Test for the lookUp() method.
928
     *
929
     * @see \eZ\Publish\API\Repository\URLAliasService::lookUp($url, $languageCode)
930
     */
931
    public function testLookUpThrowsNotFoundExceptionWithLanguageFilter()
932
    {
933
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
934
935
        $repository = $this->getRepository();
936
937
        /* BEGIN: Use Case */
938
        $urlAliasService = $repository->getURLAliasService();
939
940
        // Throws NotFoundException
941
        $loadedAlias = $urlAliasService->lookUp('/Contact-Us', '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...
942
        /* END: Use Case */
943
    }
944
945
    /**
946
     * Test for the lookUp() method.
947
     *
948
     * @see \eZ\Publish\API\Repository\URLAliasService::lookUp($url, $languageCode)
949
     */
950
    public function testLookUpThrowsInvalidArgumentException()
951
    {
952
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
953
954
        $repository = $this->getRepository();
955
956
        /* BEGIN: Use Case */
957
        $urlAliasService = $repository->getURLAliasService();
958
959
        // Throws InvalidArgumentException
960
        $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...
961
        /* END: Use Case */
962
    }
963
964
    /**
965
     * Test for the lookUp() method after renaming parent which is a part of the lookup path.
966
     *
967
     * @see https://jira.ez.no/browse/EZP-28046
968
     * @covers \eZ\Publish\API\Repository\URLAliasService::lookUp
969
     * @covers \eZ\Publish\API\Repository\URLAliasService::listLocationAliases
970
     */
971
    public function testLookupOnRenamedParent()
972
    {
973
        $urlAliasService = $this->getRepository()->getURLAliasService();
974
        $locationService = $this->getRepository()->getLocationService();
975
        $contentTypeService = $this->getRepository()->getContentTypeService();
976
        $contentService = $this->getRepository()->getContentService();
977
978
        // 1. Create new container object (e.g. Folder "My Folder").
979
        $folderContentType = $contentTypeService->loadContentTypeByIdentifier('folder');
980
        $folderCreateStruct = $contentService->newContentCreateStruct($folderContentType, 'eng-GB');
981
        $folderCreateStruct->setField('name', 'My-Folder');
982
983
        $folderDraft = $contentService->createContent($folderCreateStruct, [
984
            $locationService->newLocationCreateStruct(2),
985
        ]);
986
987
        $folder = $contentService->publishVersion($folderDraft->versionInfo);
988
989
        // 2. Create new object inside this container (e.g. article "My Article").
990
        $folderLocation = $locationService->loadLocation($folder->contentInfo->mainLocationId);
991
992
        $articleContentType = $contentTypeService->loadContentTypeByIdentifier('article');
993
        $articleCreateStruct = $contentService->newContentCreateStruct($articleContentType, 'eng-GB');
994
        $articleCreateStruct->setField('title', 'My Article');
995
        $article = $contentService->publishVersion(
996
            $contentService->createContent($articleCreateStruct, [
997
                $locationService->newLocationCreateStruct($folderLocation->id),
998
            ])->versionInfo
999
        );
1000
        $articleLocation = $locationService->loadLocation($article->contentInfo->mainLocationId);
1001
1002
        // 3. Navigate to both of them
1003
        $urlAliasService->lookup('/My-Folder');
1004
        $urlAliasService->listLocationAliases($folderLocation, false);
1005
        $urlAliasService->lookup('/My-Folder/My-Article');
1006
        $urlAliasService->listLocationAliases($articleLocation, false);
1007
1008
        // 4. Rename "My Folder" to "My Folder Modified".
1009
        $folderDraft = $contentService->createContentDraft($folder->contentInfo);
1010
        $folderUpdateStruct = $contentService->newContentUpdateStruct();
1011
        $folderUpdateStruct->setField('name', 'My Folder Modified');
1012
1013
        $contentService->publishVersion(
1014
            $contentService->updateContent($folderDraft->versionInfo, $folderUpdateStruct)->versionInfo
1015
        );
1016
1017
        // 5. Navigate to "Article"
1018
        $urlAliasService->lookup('/My-Folder/My-Article');
1019
        $aliases = $urlAliasService->listLocationAliases($articleLocation, false);
1020
1021
        $this->assertEquals('/My-Folder-Modified/My-Article', $aliases[0]->path);
1022
    }
1023
1024
    /**
1025
     * Test lookup on multilingual nested Locations returns proper UrlAlias Value.
1026
     *
1027
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1028
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1029
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1030
     */
1031
    public function testLookupOnMultilingualNestedLocations()
1032
    {
1033
        $urlAliasService = $this->getRepository()->getURLAliasService();
1034
        $locationService = $this->getRepository()->getLocationService();
1035
1036
        $topFolderNames = [
1037
            'eng-GB' => 'My folder Name',
1038
            'ger-DE' => 'Ger folder Name',
1039
            'eng-US' => 'My folder Name',
1040
        ];
1041
        $nestedFolderNames = [
1042
            'eng-GB' => 'nested Folder name',
1043
            'ger-DE' => 'Ger Nested folder Name',
1044
            'eng-US' => 'nested Folder name',
1045
        ];
1046
        $topFolderLocation = $locationService->loadLocation(
1047
            $this->createFolder($topFolderNames, 2)->contentInfo->mainLocationId
1048
        );
1049
        $nestedFolderLocation = $locationService->loadLocation(
1050
            $this->createFolder(
1051
                $nestedFolderNames,
1052
                $topFolderLocation->id
1053
            )->contentInfo->mainLocationId
1054
        );
1055
        $urlAlias = $urlAliasService->lookup('/My-Folder-Name/Nested-Folder-Name');
1056
        self::assertPropertiesCorrect(
1057
            [
1058
                'destination' => $nestedFolderLocation->id,
1059
                'path' => '/My-folder-Name/nested-Folder-name',
1060
                'languageCodes' => ['eng-US', 'eng-GB'],
1061
                'isHistory' => false,
1062
                'isCustom' => false,
1063
                'forward' => false,
1064
            ],
1065
            $urlAlias
1066
        );
1067
        $urlAlias = $urlAliasService->lookup('/Ger-Folder-Name/Ger-Nested-Folder-Name');
1068
        self::assertPropertiesCorrect(
1069
            [
1070
                'destination' => $nestedFolderLocation->id,
1071
                'path' => '/Ger-folder-Name/Ger-Nested-folder-Name',
1072
                'languageCodes' => ['ger-DE'],
1073
                'isHistory' => false,
1074
                'isCustom' => false,
1075
                'forward' => false,
1076
            ],
1077
            $urlAlias
1078
        );
1079
1080
        return [$topFolderLocation, $nestedFolderLocation];
1081
    }
1082
1083
    /**
1084
     * Test refreshSystemUrlAliasesForLocation historizes and changes current URL alias after
1085
     * changing SlugConverter configuration.
1086
     *
1087
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1088
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1089
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1090
     * @throws \ErrorException
1091
     */
1092
    public function testRefreshSystemUrlAliasesForLocationWithChangedSlugConverterConfiguration()
1093
    {
1094
        list($topFolderLocation, $nestedFolderLocation) = $this->testLookupOnMultilingualNestedLocations();
1095
1096
        $urlAliasService = $this->getRepository(false)->getURLAliasService();
1097
1098
        $this->changeSlugConverterConfiguration('transformation', 'urlalias_compat');
1099
        $this->changeSlugConverterConfiguration('wordSeparatorName', 'underscore');
1100
1101
        try {
1102
            $urlAliasService->refreshSystemUrlAliasesForLocation($topFolderLocation);
1103
            $urlAliasService->refreshSystemUrlAliasesForLocation($nestedFolderLocation);
1104
1105
            $urlAlias = $urlAliasService->lookup('/My-Folder-Name/Nested-Folder-Name');
1106
            $this->assertUrlAliasPropertiesCorrect(
1107
                $nestedFolderLocation,
1108
                '/My-folder-Name/nested-Folder-name',
1109
                ['eng-US', 'eng-GB'],
1110
                true,
1111
                $urlAlias
1112
            );
1113
1114
            $urlAlias = $urlAliasService->lookup('/my_folder_name/nested_folder_name');
1115
            $this->assertUrlAliasPropertiesCorrect(
1116
                $nestedFolderLocation,
1117
                '/my_folder_name/nested_folder_name',
1118
                ['eng-US', 'eng-GB'],
1119
                false,
1120
                $urlAlias
1121
            );
1122
1123
            $urlAlias = $urlAliasService->lookup('/Ger-Folder-Name/Ger-Nested-Folder-Name');
1124
            $this->assertUrlAliasPropertiesCorrect(
1125
                $nestedFolderLocation,
1126
                '/Ger-folder-Name/Ger-Nested-folder-Name',
1127
                ['ger-DE'],
1128
                true,
1129
                $urlAlias
1130
            );
1131
1132
            $urlAlias = $urlAliasService->lookup('/ger_folder_name/ger_nested_folder_name');
1133
            $this->assertUrlAliasPropertiesCorrect(
1134
                $nestedFolderLocation,
1135
                '/ger_folder_name/ger_nested_folder_name',
1136
                ['ger-DE'],
1137
                false,
1138
                $urlAlias
1139
            );
1140
        } finally {
1141
            // restore configuration
1142
            $this->changeSlugConverterConfiguration('transformation', 'urlalias');
1143
            $this->changeSlugConverterConfiguration('wordSeparatorName', 'dash');
1144
        }
1145
    }
1146
1147
    /**
1148
     * Test that URL aliases are refreshed after changing URL alias schema Field name of a Content Type.
1149
     *
1150
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1151
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1152
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1153
     */
1154
    public function testRefreshSystemUrlAliasesForContentsWithUpdatedContentTypes()
1155
    {
1156
        list($topFolderLocation, $nestedFolderLocation) = $this->testLookupOnMultilingualNestedLocations();
1157
        /** @var \eZ\Publish\API\Repository\Values\Content\Location $topFolderLocation */
1158
        /** @var \eZ\Publish\API\Repository\Values\Content\Location $nestedFolderLocation */
1159
1160
        // Default URL Alias schema is <short_name|name> which messes up this test, so:
1161
        $this->changeContentTypeUrlAliasSchema('folder', '<name>');
1162
1163
        $urlAliasService = $this->getRepository(false)->getURLAliasService();
1164
1165
        $this->updateContentField(
1166
            $topFolderLocation->getContentInfo(),
1167
            'short_name',
1168
            ['eng-GB' => 'EN Short Name', 'ger-DE' => 'DE Short Name']
1169
        );
1170
        $this->updateContentField(
1171
            $nestedFolderLocation->getContentInfo(),
1172
            'short_name',
1173
            ['eng-GB' => 'EN Nested Short Name', 'ger-DE' => 'DE Nested Short Name']
1174
        );
1175
1176
        $this->changeContentTypeUrlAliasSchema('folder', '<short_name>');
1177
1178
        // sanity test, done after updating CT, because it does not update existing entries by design
1179
        $this->assertUrlIsCurrent('/My-folder-Name', $topFolderLocation->id);
1180
        $this->assertUrlIsCurrent('/Ger-folder-Name', $topFolderLocation->id);
1181
        $this->assertUrlIsCurrent('/My-folder-Name/nested-Folder-name', $nestedFolderLocation->id);
1182
        $this->assertUrlIsCurrent('/Ger-folder-Name/Ger-Nested-folder-Name', $nestedFolderLocation->id);
1183
1184
        // Call API being tested
1185
        $urlAliasService->refreshSystemUrlAliasesForLocation($topFolderLocation);
1186
        $urlAliasService->refreshSystemUrlAliasesForLocation($nestedFolderLocation);
1187
1188
        // check archived aliases
1189
        $this->assertUrlIsHistory('/My-folder-Name', $topFolderLocation->id);
1190
        $this->assertUrlIsHistory('/Ger-folder-Name', $topFolderLocation->id);
1191
        $this->assertUrlIsHistory('/My-folder-Name/nested-Folder-name', $nestedFolderLocation->id);
1192
        $this->assertUrlIsHistory('/Ger-folder-Name/Ger-Nested-folder-Name', $nestedFolderLocation->id);
1193
1194
        // check new current aliases
1195
        $this->assertUrlIsCurrent('/EN-Short-Name', $topFolderLocation->id);
1196
        $this->assertUrlIsCurrent('/DE-Short-Name', $topFolderLocation->id);
1197
        $this->assertUrlIsCurrent('/EN-Short-Name/EN-Nested-Short-Name', $nestedFolderLocation->id);
1198
        $this->assertUrlIsCurrent('/DE-Short-Name/DE-Nested-Short-Name', $nestedFolderLocation->id);
1199
    }
1200
1201
    /**
1202
     * Test that created non-latin aliases are non-empty and unique.
1203
     *
1204
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1205
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1206
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1207
     */
1208
    public function testCreateNonLatinNonEmptyUniqueAliases()
1209
    {
1210
        $repository = $this->getRepository();
1211
        $urlAliasService = $repository->getURLAliasService();
1212
        $locationService = $repository->getLocationService();
1213
1214
        $folderNames = [
1215
            'eng-GB' => 'ひらがな',
1216
        ];
1217
1218
        $folderLocation1 = $locationService->loadLocation(
1219
            $this->createFolder($folderNames, 2)->contentInfo->mainLocationId
1220
        );
1221
        $urlAlias1 = $urlAliasService->lookup('/1');
1222
        self::assertPropertiesCorrect(
1223
            [
1224
                'destination' => $folderLocation1->id,
1225
                'path' => '/1',
1226
                'languageCodes' => ['eng-GB'],
1227
                'isHistory' => false,
1228
                'isCustom' => false,
1229
                'forward' => false,
1230
            ],
1231
            $urlAlias1
1232
        );
1233
1234
        $folderLocation2 = $locationService->loadLocation(
1235
            $this->createFolder($folderNames, 2)->contentInfo->mainLocationId
1236
        );
1237
        $urlAlias2 = $urlAliasService->lookup('/2');
1238
        self::assertPropertiesCorrect(
1239
            [
1240
                'destination' => $folderLocation2->id,
1241
                'path' => '/2',
1242
                'languageCodes' => ['eng-GB'],
1243
                'isHistory' => false,
1244
                'isCustom' => false,
1245
                'forward' => false,
1246
            ],
1247
            $urlAlias2
1248
        );
1249
    }
1250
1251
    /**
1252
     * Test restoring missing current URL which has existing history.
1253
     *
1254
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1255
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1256
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1257
     * @throws \Exception
1258
     */
1259
    public function testRefreshSystemUrlAliasesForMissingUrlWithHistory()
1260
    {
1261
        $repository = $this->getRepository();
1262
        $urlAliasService = $repository->getURLAliasService();
1263
        $locationService = $repository->getLocationService();
1264
1265
        $folderNames = ['eng-GB' => 'My folder Name'];
1266
        $folder = $this->createFolder($folderNames, 2);
1267
        $folderLocation = $locationService->loadLocation($folder->contentInfo->mainLocationId);
1268
        $nestedFolder = $this->createFolder(['eng-GB' => 'Nested folder'], $folderLocation->id);
1269
        $nestedFolderLocation = $locationService->loadLocation($nestedFolder->contentInfo->mainLocationId);
1270
1271
        $folder = $this->updateContentField(
1272
            $folder->contentInfo,
1273
            'name',
1274
            ['eng-GB' => 'Updated Name']
1275
        );
1276
        // create more historical entries
1277
        $this->updateContentField(
1278
            $folder->contentInfo,
1279
            'name',
1280
            ['eng-GB' => 'Updated Again Name']
1281
        );
1282
        // create historical entry for nested folder
1283
        $this->updateContentField(
1284
            $nestedFolder->contentInfo,
1285
            'name',
1286
            ['eng-GB' => 'Updated Nested folder']
1287
        );
1288
1289
        // perform sanity check
1290
        $this->assertUrlIsHistory('/My-folder-Name', $folderLocation->id);
1291
        $this->assertUrlIsHistory('/Updated-Name', $folderLocation->id);
1292
        $this->assertUrlIsHistory('/My-folder-Name/Nested-folder', $nestedFolderLocation->id);
1293
        $this->assertUrlIsHistory('/Updated-Name/Nested-folder', $nestedFolderLocation->id);
1294
        $this->assertUrlIsHistory('/Updated-Again-Name/Nested-folder', $nestedFolderLocation->id);
1295
1296
        $this->assertUrlIsCurrent('/Updated-Again-Name', $folderLocation->id);
1297
        $this->assertUrlIsCurrent('/Updated-Again-Name/Updated-Nested-folder', $nestedFolderLocation->id);
1298
1299
        self::assertNotEmpty($urlAliasService->listLocationAliases($folderLocation, false));
1300
1301
        // corrupt database by removing original entry, keeping its history
1302
        $this->performRawDatabaseOperation(
1303
            function (Connection $connection) use ($folderLocation) {
1304
                $queryBuilder = $connection->createQueryBuilder();
1305
                $expr = $queryBuilder->expr();
1306
                $queryBuilder
1307
                    ->delete('ezurlalias_ml')
1308
                    ->where(
1309
                        $expr->andX(
1310
                            $expr->eq(
1311
                                'action',
1312
                                $queryBuilder->createPositionalParameter(
1313
                                    "eznode:{$folderLocation->id}"
1314
                                )
1315
                            ),
1316
                            $expr->eq(
1317
                                'is_original',
1318
                                $queryBuilder->createPositionalParameter(1)
1319
                            )
1320
                        )
1321
                    );
1322
1323
                return $queryBuilder->execute();
1324
            }
1325
        );
1326
1327
        // perform sanity check
1328
        self::assertEmpty($urlAliasService->listLocationAliases($folderLocation, false));
1329
1330
        // Begin the actual test
1331
        $urlAliasService->refreshSystemUrlAliasesForLocation($folderLocation);
1332
        $urlAliasService->refreshSystemUrlAliasesForLocation($nestedFolderLocation);
1333
1334
        // make sure there is no corrupted data that could affect the test
1335
        $urlAliasService->deleteCorruptedUrlAliases();
1336
1337
        // test if history was restored
1338
        $this->assertUrlIsHistory('/My-folder-Name', $folderLocation->id);
1339
        $this->assertUrlIsHistory('/Updated-Name', $folderLocation->id);
1340
        $this->assertUrlIsHistory('/My-folder-Name/Nested-folder', $nestedFolderLocation->id);
1341
        $this->assertUrlIsHistory('/Updated-Name/Nested-folder', $nestedFolderLocation->id);
1342
        $this->assertUrlIsHistory('/Updated-Again-Name/Nested-folder', $nestedFolderLocation->id);
1343
1344
        $this->assertUrlIsCurrent('/Updated-Again-Name', $folderLocation->id);
1345
        $this->assertUrlIsCurrent('/Updated-Again-Name/Updated-Nested-folder', $nestedFolderLocation->id);
1346
    }
1347
1348
    /**
1349
     * Test edge case when updated and archived entry gets moved to another subtree.
1350
     *
1351
     * @see https://jira.ez.no/browse/EZP-30004
1352
     *
1353
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1354
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1355
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1356
     * @throws \Exception
1357
     */
1358
    public function testRefreshSystemUrlAliasesForMovedLocation()
1359
    {
1360
        $repository = $this->getRepository();
1361
        $urlAliasService = $repository->getURLAliasService();
1362
        $locationService = $repository->getLocationService();
1363
1364
        $folderNames = ['eng-GB' => 'folder'];
1365
        $folder = $this->createFolder($folderNames, 2);
1366
        $nestedFolder = $this->createFolder($folderNames, $folder->contentInfo->mainLocationId);
1367
1368
        $nestedFolder = $this->updateContentField(
1369
            $nestedFolder->contentInfo,
1370
            'name',
1371
            ['eng-GB' => 'folder2']
1372
        );
1373
1374
        $nestedFolderLocation = $locationService->loadLocation(
1375
            $nestedFolder->contentInfo->mainLocationId
1376
        );
1377
        $rootLocation = $locationService->loadLocation(2);
1378
1379
        $locationService->moveSubtree($nestedFolderLocation, $rootLocation);
1380
        // reload nested Location to get proper parent information
1381
        $nestedFolderLocation = $locationService->loadLocation($nestedFolderLocation->id);
1382
1383
        // corrupt database by breaking link to the original URL alias
1384
        $this->performRawDatabaseOperation(
1385
            function (Connection $connection) use ($nestedFolderLocation) {
1386
                $queryBuilder = $connection->createQueryBuilder();
1387
                $expr = $queryBuilder->expr();
1388
                $queryBuilder
1389
                    ->update('ezurlalias_ml')
1390
                    ->set('link', $queryBuilder->createPositionalParameter(666, \PDO::PARAM_INT))
1391
                    ->where(
1392
                        $expr->eq(
1393
                            'action',
1394
                            $queryBuilder->createPositionalParameter(
1395
                                "eznode:{$nestedFolderLocation->id}"
1396
                            )
1397
                        )
1398
                    )
1399
                    ->andWhere(
1400
                        $expr->eq(
1401
                            'is_original',
1402
                            $queryBuilder->createPositionalParameter(0, \PDO::PARAM_INT)
1403
                        )
1404
                    )
1405
                    ->andWhere(
1406
                        $expr->eq('text', $queryBuilder->createPositionalParameter('folder'))
1407
                    )
1408
                ;
1409
1410
                return $queryBuilder->execute();
1411
            }
1412
        );
1413
1414
        $urlAliasService->refreshSystemUrlAliasesForLocation($nestedFolderLocation);
1415
    }
1416
1417
    /**
1418
     * Lookup given URL and check if it is archived and points to the given Location Id.
1419
     *
1420
     * @param string $lookupUrl
1421
     * @param int $expectedDestination Expected Location ID
1422
     */
1423
    protected function assertUrlIsHistory($lookupUrl, $expectedDestination)
1424
    {
1425
        $this->assertLookupHistory(true, $expectedDestination, $lookupUrl);
1426
    }
1427
1428
    /**
1429
     * Lookup given URL and check if it is current (not archived) and points to the given Location Id.
1430
     *
1431
     * @param string $lookupUrl
1432
     * @param int $expectedDestination Expected Location ID
1433
     */
1434
    protected function assertUrlIsCurrent($lookupUrl, $expectedDestination)
1435
    {
1436
        $this->assertLookupHistory(false, $expectedDestination, $lookupUrl);
1437
    }
1438
1439
    /**
1440
     * Lookup and URLAlias VO history and destination properties.
1441
     *
1442
     * @see assertUrlIsHistory
1443
     * @see assertUrlIsCurrent
1444
     *
1445
     * @param bool $expectedIsHistory
1446
     * @param int $expectedDestination Expected Location ID
1447
     * @param string $lookupUrl
1448
     */
1449
    protected function assertLookupHistory($expectedIsHistory, $expectedDestination, $lookupUrl)
1450
    {
1451
        $urlAliasService = $this->getRepository(false)->getURLAliasService();
1452
1453
        try {
1454
            $urlAlias = $urlAliasService->lookup($lookupUrl);
1455
            self::assertPropertiesCorrect(
1456
                [
1457
                    'destination' => $expectedDestination,
1458
                    'path' => $lookupUrl,
1459
                    'isHistory' => $expectedIsHistory,
1460
                ],
1461
                $urlAlias
1462
            );
1463
        } catch (InvalidArgumentException $e) {
1464
            self::fail("Failed to lookup {$lookupUrl}: $e");
1465
        } catch (NotFoundException $e) {
1466
            self::fail("Failed to lookup {$lookupUrl}: $e");
1467
        }
1468
    }
1469
1470
    /**
1471
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
1472
     * @param $fieldDefinitionIdentifier
1473
     * @param array $fieldValues
1474
     *
1475
     * @return \eZ\Publish\API\Repository\Values\Content\Content
1476
     *
1477
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1478
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1479
     */
1480
    protected function updateContentField(ContentInfo $contentInfo, $fieldDefinitionIdentifier, array $fieldValues)
1481
    {
1482
        $contentService = $this->getRepository(false)->getContentService();
1483
1484
        $contentUpdateStruct = $contentService->newContentUpdateStruct();
1485
        foreach ($fieldValues as $languageCode => $fieldValue) {
1486
            $contentUpdateStruct->setField($fieldDefinitionIdentifier, $fieldValue, $languageCode);
1487
        }
1488
        $contentDraft = $contentService->updateContent(
1489
            $contentService->createContentDraft($contentInfo)->versionInfo,
1490
            $contentUpdateStruct
1491
        );
1492
1493
        return $contentService->publishVersion($contentDraft->versionInfo);
1494
    }
1495
1496
    /**
1497
     * Test deleting corrupted URL aliases.
1498
     *
1499
     * Note: this test will not be needed once we introduce Improved Storage with Foreign keys support.
1500
     *
1501
     * Note: test depends on already broken URL aliases: eznode:59, eznode:59, eznode:60.
1502
     *
1503
     * @throws \ErrorException
1504
     */
1505
    public function testDeleteCorruptedUrlAliases()
1506
    {
1507
        $repository = $this->getRepository();
1508
        $urlAliasService = $repository->getURLAliasService();
1509
        $connection = $this->getRawDatabaseConnection();
1510
1511
        $query = $connection->createQueryBuilder()->select('*')->from('ezurlalias_ml');
1512
        $originalRows = $query->execute()->fetchAll(PDO::FETCH_ASSOC);
1513
1514
        $expectedCount = count($originalRows);
1515
        $expectedCount += $this->insertBrokenUrlAliasTableFixtures($connection);
1516
1517
        // sanity check
1518
        $updatedRows = $query->execute()->fetchAll(PDO::FETCH_ASSOC);
1519
        self::assertCount($expectedCount, $updatedRows, 'Found unexpected number of new rows');
1520
1521
        // BEGIN API use case
1522
        $urlAliasService->deleteCorruptedUrlAliases();
1523
        // END API use case
1524
1525
        $updatedRows = $query->execute()->fetchAll(PDO::FETCH_ASSOC);
1526
        self::assertCount(
1527
            // API should also remove already broken pre-existing URL aliases to Locations 50 and 2x 59
1528
            count($originalRows) - 3,
1529
            $updatedRows,
1530
            'Number of rows after cleanup is not the same as the original number of rows'
1531
        );
1532
    }
1533
1534
    /**
1535
     * Mutate 'ezpublish.persistence.slug_converter' Service configuration.
1536
     *
1537
     * @param string $key
1538
     * @param string $value
1539
     *
1540
     * @throws \ErrorException
1541
     * @throws \Exception
1542
     */
1543
    protected function changeSlugConverterConfiguration($key, $value)
1544
    {
1545
        $testSlugConverter = $this
1546
            ->getSetupFactory()
1547
            ->getServiceContainer()
1548
            ->getInnerContainer()
1549
            ->get('ezpublish.persistence.slug_converter');
1550
1551
        if (!$testSlugConverter instanceof TestSlugConverter) {
1552
            throw new RuntimeException(
1553
                sprintf(
1554
                    '%s: expected instance of %s, got %s',
1555
                    __METHOD__,
1556
                    TestSlugConverter::class,
1557
                    get_class($testSlugConverter)
1558
                )
1559
            );
1560
        }
1561
1562
        $testSlugConverter->setConfigurationValue($key, $value);
1563
    }
1564
1565
    /**
1566
     * Update Content Type URL alias schema pattern.
1567
     *
1568
     * @param string $contentTypeIdentifier
1569
     * @param string $newUrlAliasSchema
1570
     *
1571
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1572
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1573
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1574
     */
1575
    protected function changeContentTypeUrlAliasSchema($contentTypeIdentifier, $newUrlAliasSchema)
1576
    {
1577
        $contentTypeService = $this->getRepository(false)->getContentTypeService();
1578
1579
        $contentType = $contentTypeService->loadContentTypeByIdentifier($contentTypeIdentifier);
1580
1581
        $contentTypeDraft = $contentTypeService->createContentTypeDraft($contentType);
1582
        $contentTypeUpdateStruct = $contentTypeService->newContentTypeUpdateStruct();
1583
        $contentTypeUpdateStruct->urlAliasSchema = $newUrlAliasSchema;
1584
1585
        $contentTypeService->updateContentTypeDraft($contentTypeDraft, $contentTypeUpdateStruct);
1586
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
1587
    }
1588
1589
    private function assertUrlAliasPropertiesCorrect(
1590
        Location $expectedDestinationLocation,
1591
        $expectedPath,
1592
        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...
1593
        $expectedIsHistory,
1594
        URLAlias $actualUrlAliasValue
1595
    ) {
1596
        self::assertPropertiesCorrect(
1597
            [
1598
                'destination' => $expectedDestinationLocation->id,
1599
                'path' => $expectedPath,
1600
                // @todo uncomment after fixing EZP-27124
1601
                //'languageCodes' => $expectedLanguageCodes,
1602
                'isHistory' => $expectedIsHistory,
1603
                'isCustom' => false,
1604
                'forward' => false,
1605
            ],
1606
            $actualUrlAliasValue
1607
        );
1608
    }
1609
1610
    /**
1611
     * Insert intentionally broken rows into ezurlalias_ml table to test cleanup API.
1612
     *
1613
     * @see \eZ\Publish\API\Repository\URLAliasService::deleteCorruptedUrlAliases
1614
     * @see testDeleteCorruptedUrlAliases
1615
     *
1616
     * @param \Doctrine\DBAL\Connection $connection
1617
     *
1618
     * @return int Number of new rows
1619
     */
1620
    private function insertBrokenUrlAliasTableFixtures(Connection $connection)
1621
    {
1622
        $rows = [
1623
            // link to non-existent location
1624
            [
1625
                'action' => 'eznode:9999',
1626
                'action_type' => 'eznode',
1627
                'alias_redirects' => 0,
1628
                'id' => 9997,
1629
                'is_alias' => 0,
1630
                'is_original' => 1,
1631
                'lang_mask' => 3,
1632
                'link' => 9997,
1633
                'parent' => 0,
1634
                'text' => 'my-location',
1635
                'text_md5' => '19d12b1b9994619cd8e90f00a6f5834e',
1636
            ],
1637
            // link to non-existent target URL alias (`link` column)
1638
            [
1639
                'action' => 'nop:',
1640
                'action_type' => 'nop',
1641
                'alias_redirects' => 0,
1642
                'id' => 9998,
1643
                'is_alias' => 1,
1644
                'is_original' => 1,
1645
                'lang_mask' => 2,
1646
                'link' => 9995,
1647
                'parent' => 0,
1648
                'text' => 'my-alias1',
1649
                'text_md5' => 'a29dd95ccf4c1bc7ebbd61086863b632',
1650
            ],
1651
            // link to non-existent parent URL alias
1652
            [
1653
                'action' => 'nop:',
1654
                'action_type' => 'nop',
1655
                'alias_redirects' => 0,
1656
                'id' => 9999,
1657
                'is_alias' => 0,
1658
                'is_original' => 1,
1659
                'lang_mask' => 3,
1660
                'link' => 9999,
1661
                'parent' => 9995,
1662
                'text' => 'my-alias2',
1663
                'text_md5' => 'e5dea18481e4f86857865d9fc94e4ce9',
1664
            ],
1665
        ];
1666
1667
        $query = $connection->createQueryBuilder()->insert('ezurlalias_ml');
1668
1669
        foreach ($rows as $row) {
1670
            foreach ($row as $columnName => $value) {
1671
                $row[$columnName] = $query->createNamedParameter($value);
1672
            }
1673
            $query->values($row);
1674
            $query->execute();
1675
        }
1676
1677
        return count($rows);
1678
    }
1679
}
1680