Completed
Push — ezp_30981_content_info_proxy ( 6fc040...a78a98 )
by
unknown
15:33
created

testCreateSameAliasForDifferentLanguage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

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