Completed
Push — master ( 01e425...9680ce )
by
unknown
13:57 queued 15s
created

testDeleteUnusedLocationWhichPreviousHadContentWithRelativeAlias()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 64

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 64
rs 8.7853
c 0
b 0
f 0

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * File containing the LocationServiceTest 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 Exception;
12
use eZ\Publish\API\Repository\Exceptions\BadStateException;
13
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
14
use eZ\Publish\API\Repository\URLAliasService as URLAliasServiceInterface;
15
use eZ\Publish\API\Repository\Values\Content\Content;
16
use eZ\Publish\API\Repository\Values\Content\ContentCreateStruct;
17
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
18
use eZ\Publish\API\Repository\Values\Content\Language;
19
use eZ\Publish\API\Repository\Values\Content\Location;
20
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
21
use eZ\Publish\API\Repository\Values\Content\LocationList;
22
use eZ\Publish\API\Repository\Values\Content\LocationUpdateStruct;
23
use eZ\Publish\API\Repository\Values\Content\Query;
24
use eZ\Publish\API\Repository\Values\Content\Search\SearchHit;
25
use eZ\Publish\API\Repository\Values\Content\URLAlias;
26
27
/**
28
 * Test case for operations in the LocationService using in memory storage.
29
 *
30
 * @see eZ\Publish\API\Repository\LocationService
31
 * @group location
32
 */
33
class LocationServiceTest extends BaseTest
34
{
35
    /**
36
     * Test for the newLocationCreateStruct() method.
37
     *
38
     * @return \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct
39
     *
40
     * @see \eZ\Publish\API\Repository\LocationService::newLocationCreateStruct()
41
     */
42
    public function testNewLocationCreateStruct()
43
    {
44
        $repository = $this->getRepository();
45
46
        $parentLocationId = $this->generateId('location', 1);
47
        /* BEGIN: Use Case */
48
        // $parentLocationId is the ID of an existing location
49
        $locationService = $repository->getLocationService();
50
51
        $locationCreate = $locationService->newLocationCreateStruct(
52
            $parentLocationId
53
        );
54
        /* END: Use Case */
55
56
        $this->assertInstanceOf(
57
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\LocationCreateStruct',
58
            $locationCreate
59
        );
60
61
        return $locationCreate;
62
    }
63
64
    /**
65
     * Test for the newLocationCreateStruct() method.
66
     *
67
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct $locationCreate
68
     *
69
     * @see \eZ\Publish\API\Repository\LocationService::newLocationCreateStruct()
70
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
71
     */
72
    public function testNewLocationCreateStructValues(LocationCreateStruct $locationCreate)
73
    {
74
        $this->assertPropertiesCorrect(
75
            [
76
                'priority' => 0,
77
                'hidden' => false,
78
                // remoteId should be initialized with a default value
79
                //'remoteId' => null,
80
                'sortField' => null,
81
                'sortOrder' => null,
82
                'parentLocationId' => $this->generateId('location', 1),
83
            ],
84
            $locationCreate
85
        );
86
    }
87
88
    /**
89
     * Test for the createLocation() method.
90
     *
91
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
92
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
93
     */
94
    public function testCreateLocation()
95
    {
96
        $repository = $this->getRepository();
97
98
        $contentId = $this->generateId('object', 41);
99
        $parentLocationId = $this->generateId('location', 5);
100
        /* BEGIN: Use Case */
101
        // $contentId is the ID of an existing content object
102
        // $parentLocationId is the ID of an existing location
103
        $contentService = $repository->getContentService();
104
        $locationService = $repository->getLocationService();
105
106
        // ContentInfo for "How to use eZ Publish"
107
        $contentInfo = $contentService->loadContentInfo($contentId);
108
109
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
110
        $locationCreate->priority = 23;
111
        $locationCreate->hidden = true;
112
        $locationCreate->remoteId = 'sindelfingen';
113
        $locationCreate->sortField = Location::SORT_FIELD_NODE_ID;
114
        $locationCreate->sortOrder = Location::SORT_ORDER_DESC;
115
116
        $location = $locationService->createLocation(
117
            $contentInfo,
118
            $locationCreate
119
        );
120
        /* END: Use Case */
121
122
        $this->assertInstanceOf(
123
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
124
            $location
125
        );
126
127
        return [
128
            'locationCreate' => $locationCreate,
129
            'createdLocation' => $location,
130
            'contentInfo' => $contentInfo,
131
            'parentLocation' => $locationService->loadLocation($this->generateId('location', 5)),
132
        ];
133
    }
134
135
    /**
136
     * Test for the createLocation() method with utilizing default ContentType sorting options.
137
     *
138
     * @covers \eZ\Publish\API\Repository\LocationService::createLocation
139
     */
140
    public function testCreateLocationWithContentTypeSortingOptions(): void
141
    {
142
        $repository = $this->getRepository();
143
144
        $contentId = $this->generateId('object', 41);
145
        $parentLocationId = $this->generateId('location', 5);
146
        // $contentId is the ID of an existing content object
147
        // $parentLocationId is the ID of an existing location
148
        $contentService = $repository->getContentService();
149
        $contentTypeService = $repository->getContentTypeService();
150
        $locationService = $repository->getLocationService();
151
152
        // ContentInfo for "How to use eZ Publish"
153
        $contentInfo = $contentService->loadContentInfo($contentId);
154
155
        // ContentType loading
156
        $contentType = $contentTypeService->loadContentType($contentInfo->contentTypeId);
157
158
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
159
        $locationCreate->priority = 23;
160
        $locationCreate->hidden = true;
161
        $locationCreate->remoteId = 'sindelfingen';
162
163
        $location = $locationService->createLocation(
164
            $contentInfo,
165
            $locationCreate
166
        );
167
168
        $this->assertEquals($contentType->defaultSortField, $location->sortField);
169
        $this->assertEquals($contentType->defaultSortOrder, $location->sortOrder);
170
    }
171
172
    /**
173
     * Test for the createLocation() method.
174
     *
175
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
176
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
177
     */
178
    public function testCreateLocationStructValues(array $data)
179
    {
180
        $locationCreate = $data['locationCreate'];
181
        $createdLocation = $data['createdLocation'];
182
        $contentInfo = $data['contentInfo'];
183
184
        $this->assertPropertiesCorrect(
185
            [
186
                'priority' => $locationCreate->priority,
187
                'hidden' => $locationCreate->hidden,
188
                'invisible' => $locationCreate->hidden,
189
                'remoteId' => $locationCreate->remoteId,
190
                'contentInfo' => $contentInfo,
191
                'parentLocationId' => $locationCreate->parentLocationId,
192
                'pathString' => '/1/5/' . $this->parseId('location', $createdLocation->id) . '/',
193
                'depth' => 2,
194
                'sortField' => $locationCreate->sortField,
195
                'sortOrder' => $locationCreate->sortOrder,
196
            ],
197
            $createdLocation
198
        );
199
200
        $this->assertNotNull($createdLocation->id);
201
    }
202
203
    /**
204
     * Test for the createLocation() method.
205
     *
206
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
207
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
208
     */
209
    public function testCreateLocationThrowsInvalidArgumentExceptionContentAlreadyBelowParent()
210
    {
211
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
212
213
        $repository = $this->getRepository();
214
215
        $contentId = $this->generateId('object', 11);
216
        $parentLocationId = $this->generateId('location', 5);
217
        /* BEGIN: Use Case */
218
        // $contentId is the ID of an existing content object
219
        // $parentLocationId is the ID of an existing location which already
220
        // has the content assigned to one of its descendant locations
221
        $contentService = $repository->getContentService();
222
        $locationService = $repository->getLocationService();
223
224
        // ContentInfo for "How to use eZ Publish"
225
        $contentInfo = $contentService->loadContentInfo($contentId);
226
227
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
228
229
        // Throws exception, since content is already located at "/1/2/107/110/"
230
        $locationService->createLocation(
231
            $contentInfo,
232
            $locationCreate
233
        );
234
        /* END: Use Case */
235
    }
236
237
    /**
238
     * Test for the createLocation() method.
239
     *
240
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
241
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
242
     */
243
    public function testCreateLocationThrowsInvalidArgumentExceptionParentIsSubLocationOfContent()
244
    {
245
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
246
247
        $repository = $this->getRepository();
248
249
        $contentId = $this->generateId('object', 4);
250
        $parentLocationId = $this->generateId('location', 12);
251
        /* BEGIN: Use Case */
252
        // $contentId is the ID of an existing content object
253
        // $parentLocationId is the ID of an existing location which is below a
254
        // location that is assigned to the content
255
        $contentService = $repository->getContentService();
256
        $locationService = $repository->getLocationService();
257
258
        // ContentInfo for "How to use eZ Publish"
259
        $contentInfo = $contentService->loadContentInfo($contentId);
260
261
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
262
263
        // Throws exception, since content is already located at "/1/2/"
264
        $locationService->createLocation(
265
            $contentInfo,
266
            $locationCreate
267
        );
268
        /* END: Use Case */
269
    }
270
271
    /**
272
     * Test for the createLocation() method.
273
     *
274
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
275
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
276
     */
277
    public function testCreateLocationThrowsInvalidArgumentExceptionRemoteIdExists()
278
    {
279
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
280
281
        $repository = $this->getRepository();
282
283
        $contentId = $this->generateId('object', 41);
284
        $parentLocationId = $this->generateId('location', 5);
285
        /* BEGIN: Use Case */
286
        // $contentId is the ID of an existing content object
287
        $contentService = $repository->getContentService();
288
        $locationService = $repository->getLocationService();
289
290
        // ContentInfo for "How to use eZ Publish"
291
        $contentInfo = $contentService->loadContentInfo($contentId);
292
293
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
294
        // This remote ID already exists
295
        $locationCreate->remoteId = 'f3e90596361e31d496d4026eb624c983';
296
297
        // Throws exception, since remote ID is already in use
298
        $locationService->createLocation(
299
            $contentInfo,
300
            $locationCreate
301
        );
302
        /* END: Use Case */
303
    }
304
305
    /**
306
     * Test for the createLocation() method.
307
     *
308
     * @covers \eZ\Publish\API\Repository\LocationService::createLocation()
309
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
310
     * @dataProvider dataProviderForOutOfRangeLocationPriority
311
     */
312 View Code Duplication
    public function testCreateLocationThrowsInvalidArgumentExceptionPriorityIsOutOfRange($priority)
313
    {
314
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
315
316
        $repository = $this->getRepository();
317
318
        $contentId = $this->generateId('object', 41);
319
        $parentLocationId = $this->generateId('location', 5);
320
        /* BEGIN: Use Case */
321
        // $contentId is the ID of an existing content object
322
        // $parentLocationId is the ID of an existing location
323
        $contentService = $repository->getContentService();
324
        $locationService = $repository->getLocationService();
325
326
        // ContentInfo for "How to use eZ Publish"
327
        $contentInfo = $contentService->loadContentInfo($contentId);
328
329
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
330
        $locationCreate->priority = $priority;
331
        $locationCreate->hidden = true;
332
        $locationCreate->remoteId = 'sindelfingen';
333
        $locationCreate->sortField = Location::SORT_FIELD_NODE_ID;
334
        $locationCreate->sortOrder = Location::SORT_ORDER_DESC;
335
336
        // Throws exception, since priority is out of range
337
        $locationService->createLocation(
338
            $contentInfo,
339
            $locationCreate
340
        );
341
        /* END: Use Case */
342
    }
343
344
    public function dataProviderForOutOfRangeLocationPriority()
345
    {
346
        return [[-2147483649], [2147483648]];
347
    }
348
349
    /**
350
     * Test for the createLocation() method.
351
     *
352
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
353
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
354
     */
355
    public function testCreateLocationInTransactionWithRollback()
356
    {
357
        $repository = $this->getRepository();
358
359
        $contentId = $this->generateId('object', 41);
360
        $parentLocationId = $this->generateId('location', 5);
361
        /* BEGIN: Use Case */
362
        // $contentId is the ID of an existing content object
363
        // $parentLocationId is the ID of an existing location
364
        $contentService = $repository->getContentService();
365
        $locationService = $repository->getLocationService();
366
367
        $repository->beginTransaction();
368
369
        try {
370
            // ContentInfo for "How to use eZ Publish"
371
            $contentInfo = $contentService->loadContentInfo($contentId);
372
373
            $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
374
            $locationCreate->remoteId = 'sindelfingen';
375
376
            $createdLocationId = $locationService->createLocation(
377
                $contentInfo,
378
                $locationCreate
379
            )->id;
380
        } catch (Exception $e) {
381
            // Cleanup hanging transaction on error
382
            $repository->rollback();
383
            throw $e;
384
        }
385
386
        $repository->rollback();
387
388
        try {
389
            // Throws exception since creation of location was rolled back
390
            $location = $locationService->loadLocation($createdLocationId);
0 ignored issues
show
Unused Code introduced by
$location 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...
391
        } catch (NotFoundException $e) {
392
            return;
393
        }
394
        /* END: Use Case */
395
396
        $this->fail('Objects still exists after rollback.');
397
    }
398
399
    /**
400
     * Test for the loadLocation() method.
401
     *
402
     * @return \eZ\Publish\API\Repository\Values\Content\Location
403
     *
404
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocation
405
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
406
     */
407
    public function testLoadLocation()
408
    {
409
        $repository = $this->getRepository();
410
411
        $locationId = $this->generateId('location', 5);
412
        /* BEGIN: Use Case */
413
        // $locationId is the ID of an existing location
414
        $locationService = $repository->getLocationService();
415
416
        $location = $locationService->loadLocation($locationId);
417
        /* END: Use Case */
418
419
        $this->assertInstanceOf(
420
            Location::class,
421
            $location
422
        );
423
        self::assertEquals(5, $location->id);
424
425
        return $location;
426
    }
427
428
    /**
429
     * Test for the loadLocation() method.
430
     *
431
     * @see \eZ\Publish\API\Repository\LocationService::loadLocation()
432
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
433
     */
434
    public function testLoadLocationRootStructValues()
435
    {
436
        $repository = $this->getRepository();
437
        $locationService = $repository->getLocationService();
438
        $location = $locationService->loadLocation($this->generateId('location', 1));
439
440
        $this->assertRootLocationStructValues($location);
441
    }
442
443
    public function testLoadLocationRootStructValuesWithPrioritizedLanguages(): void
444
    {
445
        $repository = $this->getRepository();
446
447
        $rootLocation = $repository
448
            ->getLocationService()
449
            ->loadLocation(
450
                $this->generateId('location', 1),
451
                [
452
                    'eng-GB',
453
                    'ger-DE',
454
                ]
455
            );
456
457
        $this->assertRootLocationStructValues($rootLocation);
458
    }
459
460
    private function assertRootLocationStructValues(Location $location): void
461
    {
462
        $legacyDateTime = new \DateTime();
463
        $legacyDateTime->setTimestamp(1030968000);
464
465
        $this->assertInstanceOf(Location::class, $location);
466
        $this->assertPropertiesCorrect(
467
            [
468
                'id' => $this->generateId('location', 1),
469
                'status' => 1,
470
                'priority' => 0,
471
                'hidden' => false,
472
                'invisible' => false,
473
                'remoteId' => '629709ba256fe317c3ddcee35453a96a',
474
                'parentLocationId' => $this->generateId('location', 1),
475
                'pathString' => '/1/',
476
                'depth' => 0,
477
                'sortField' => 1,
478
                'sortOrder' => 1,
479
            ],
480
            $location
481
        );
482
483
        $this->assertInstanceOf(ContentInfo::class, $location->contentInfo);
484
        $this->assertPropertiesCorrect(
485
            [
486
                'id' => $this->generateId('content', 0),
487
                'name' => 'Top Level Nodes',
488
                'sectionId' => 1,
489
                'mainLocationId' => 1,
490
                'contentTypeId' => 1,
491
                'currentVersionNo' => 1,
492
                'published' => 1,
493
                'ownerId' => 14,
494
                'modificationDate' => $legacyDateTime,
495
                'publishedDate' => $legacyDateTime,
496
                'alwaysAvailable' => 1,
497
                'remoteId' => null,
498
                'mainLanguageCode' => 'eng-GB',
499
            ],
500
            $location->contentInfo
501
        );
502
    }
503
504
    /**
505
     * Test for the loadLocation() method.
506
     *
507
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
508
     *
509
     * @see \eZ\Publish\API\Repository\LocationService::loadLocation()
510
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
511
     */
512
    public function testLoadLocationStructValues(Location $location)
513
    {
514
        $this->assertPropertiesCorrect(
515
            [
516
                'id' => $this->generateId('location', 5),
517
                'priority' => 0,
518
                'hidden' => false,
519
                'invisible' => false,
520
                'remoteId' => '3f6d92f8044aed134f32153517850f5a',
521
                'parentLocationId' => $this->generateId('location', 1),
522
                'pathString' => '/1/5/',
523
                'depth' => 1,
524
                'sortField' => 1,
525
                'sortOrder' => 1,
526
            ],
527
            $location
528
        );
529
530
        $this->assertInstanceOf(ContentInfo::class, $location->contentInfo);
531
        $this->assertEquals($this->generateId('object', 4), $location->contentInfo->id);
532
533
        $this->assertInstanceOf(Location::class, $location->getParentLocation());
534
        $this->assertEquals($this->generateId('location', 1), $location->getParentLocation()->id);
535
536
        // Check lazy loaded proxy on ->content
537
        $this->assertInstanceOf(
538
            Content::class,
539
            $content = $location->getContent()
540
        );
541
        $this->assertEquals(4, $content->contentInfo->id);
542
    }
543
544
    public function testLoadLocationPrioritizedLanguagesFallback()
545
    {
546
        $repository = $this->getRepository();
547
548
        // Add a language
549
        $this->createLanguage('nor-NO', 'Norsk');
550
551
        $locationService = $repository->getLocationService();
552
        $contentService = $repository->getContentService();
553
        $location = $locationService->loadLocation(5);
554
555
        // Translate "Users"
556
        $draft = $contentService->createContentDraft($location->contentInfo);
557
        $struct = $contentService->newContentUpdateStruct();
558
        $struct->setField('name', 'Brukere', 'nor-NO');
559
        $draft = $contentService->updateContent($draft->getVersionInfo(), $struct);
560
        $contentService->publishVersion($draft->getVersionInfo());
561
562
        // Load with priority language (fallback will be the old one)
563
        $location = $locationService->loadLocation(5, ['nor-NO']);
564
565
        $this->assertInstanceOf(
566
            Location::class,
567
            $location
568
        );
569
        self::assertEquals(5, $location->id);
570
        $this->assertInstanceOf(
571
            Content::class,
572
            $content = $location->getContent()
573
        );
574
        $this->assertEquals(4, $content->contentInfo->id);
575
576
        $this->assertEquals($content->getVersionInfo()->getName(), 'Brukere');
577
        $this->assertEquals($content->getVersionInfo()->getName('eng-US'), 'Users');
578
    }
579
580
    /**
581
     * Test that accessing lazy-loaded Content without a translation in the specific
582
     * not available language throws NotFoundException.
583
     */
584
    public function testLoadLocationThrowsNotFoundExceptionForNotAvailableContent(): void
585
    {
586
        $repository = $this->getRepository();
587
588
        $locationService = $repository->getLocationService();
589
590
        $this->createLanguage('pol-PL', 'Polski');
591
592
        $this->expectException(NotFoundException::class);
593
594
        // Note: relying on existing database fixtures to make test case more readable
595
        $locationService->loadLocation(60, ['pol-PL']);
596
    }
597
598
    /**
599
     * Test for the loadLocation() method.
600
     *
601
     * @see \eZ\Publish\API\Repository\LocationService::loadLocation()
602
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
603
     */
604 View Code Duplication
    public function testLoadLocationThrowsNotFoundException()
605
    {
606
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
607
608
        $repository = $this->getRepository();
609
610
        $nonExistentLocationId = $this->generateId('location', 2342);
611
        /* BEGIN: Use Case */
612
        $locationService = $repository->getLocationService();
613
614
        // Throws exception, if Location with $nonExistentLocationId does not
615
        // exist
616
        $location = $locationService->loadLocation($nonExistentLocationId);
0 ignored issues
show
Unused Code introduced by
$location 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...
617
        /* END: Use Case */
618
    }
619
620
    /**
621
     * Test for the loadLocationList() method.
622
     *
623
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
624
     */
625 View Code Duplication
    public function testLoadLocationList(): void
626
    {
627
        $repository = $this->getRepository();
628
629
        // 5 is the ID of an existing location, 442 is a non-existing id
630
        $locationService = $repository->getLocationService();
631
        $locations = $locationService->loadLocationList([5, 442]);
632
633
        self::assertIsIterable($locations);
634
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLocationList(array(5, 442)) on line 631 can also be of type array<integer,object<eZ\...lues\Content\Location>>; however, PHPUnit\Framework\Assert::assertCount() does only seem to accept object<Countable>|object...nit\Framework\iterable>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
635
        self::assertEquals([5], array_keys($locations));
636
        self::assertInstanceOf(Location::class, $locations[5]);
637
        self::assertEquals(5, $locations[5]->id);
638
    }
639
640
    /**
641
     * Test for the loadLocationList() method.
642
     *
643
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
644
     * @depends testLoadLocationList
645
     */
646
    public function testLoadLocationListPrioritizedLanguagesFallback(): void
647
    {
648
        $repository = $this->getRepository();
649
650
        $this->createLanguage('pol-PL', 'Polski');
651
652
        // 5 is the ID of an existing location, 442 is a non-existing id
653
        $locationService = $repository->getLocationService();
654
        $locations = $locationService->loadLocationList([5, 442], ['pol-PL'], false);
655
656
        self::assertIsIterable($locations);
657
        self::assertCount(0, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLo...array('pol-PL'), false) on line 654 can also be of type array<integer,object<eZ\...lues\Content\Location>>; however, PHPUnit\Framework\Assert::assertCount() does only seem to accept object<Countable>|object...nit\Framework\iterable>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
658
    }
659
660
    /**
661
     * Test for the loadLocationList() method.
662
     *
663
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
664
     * @depends testLoadLocationListPrioritizedLanguagesFallback
665
     */
666
    public function testLoadLocationListPrioritizedLanguagesFallbackAndAlwaysAvailable(): void
667
    {
668
        $repository = $this->getRepository();
669
670
        $this->createLanguage('pol-PL', 'Polski');
671
672
        // 5 is the ID of an existing location, 442 is a non-existing id
673
        $locationService = $repository->getLocationService();
674
        $locations = $locationService->loadLocationList([5, 442], ['pol-PL'], true);
675
676
        self::assertIsIterable($locations);
677
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLo... array('pol-PL'), true) on line 674 can also be of type array<integer,object<eZ\...lues\Content\Location>>; however, PHPUnit\Framework\Assert::assertCount() does only seem to accept object<Countable>|object...nit\Framework\iterable>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
678
        self::assertEquals([5], array_keys($locations));
679
        self::assertInstanceOf(Location::class, $locations[5]);
680
        self::assertEquals(5, $locations[5]->id);
681
    }
682
683
    /**
684
     * Test for the loadLocationList() method.
685
     *
686
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
687
     */
688 View Code Duplication
    public function testLoadLocationListWithRootLocationId()
689
    {
690
        $repository = $this->getRepository();
691
692
        // 1 is the ID of an root location
693
        $locationService = $repository->getLocationService();
694
        $locations = $locationService->loadLocationList([1]);
695
696
        self::assertIsIterable($locations);
697
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLocationList(array(1)) on line 694 can also be of type array<integer,object<eZ\...lues\Content\Location>>; however, PHPUnit\Framework\Assert::assertCount() does only seem to accept object<Countable>|object...nit\Framework\iterable>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
698
        self::assertEquals([1], array_keys($locations));
699
        self::assertInstanceOf(Location::class, $locations[1]);
700
        self::assertEquals(1, $locations[1]->id);
701
    }
702
703
    /**
704
     * Test for the loadLocationList() method.
705
     *
706
     * Ensures the list is returned in the same order as passed IDs array.
707
     *
708
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
709
     */
710
    public function testLoadLocationListInCorrectOrder()
711
    {
712
        $repository = $this->getRepository();
713
        $locationService = $repository->getLocationService();
714
715
        $cachedLocationId = 2;
716
        $locationIdsToLoad = [43, $cachedLocationId, 5];
717
718
        // Call loadLocation to cache it in memory as it might possibly affect list order
719
        $locationService->loadLocation($cachedLocationId);
720
721
        $locations = $locationService->loadLocationList($locationIdsToLoad);
722
        $locationIds = array_column($locations, 'id');
723
724
        self::assertEquals($locationIdsToLoad, $locationIds);
725
    }
726
727
    /**
728
     * Test for the loadLocationByRemoteId() method.
729
     *
730
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationByRemoteId()
731
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
732
     */
733 View Code Duplication
    public function testLoadLocationByRemoteId()
734
    {
735
        $repository = $this->getRepository();
736
737
        /* BEGIN: Use Case */
738
        $locationService = $repository->getLocationService();
739
740
        $location = $locationService->loadLocationByRemoteId(
741
            '3f6d92f8044aed134f32153517850f5a'
742
        );
743
        /* END: Use Case */
744
745
        $this->assertEquals(
746
            $locationService->loadLocation($this->generateId('location', 5)),
747
            $location
748
        );
749
    }
750
751
    /**
752
     * Test for the loadLocationByRemoteId() method.
753
     *
754
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationByRemoteId()
755
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
756
     */
757 View Code Duplication
    public function testLoadLocationByRemoteIdThrowsNotFoundException()
758
    {
759
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
760
761
        $repository = $this->getRepository();
762
763
        /* BEGIN: Use Case */
764
        $locationService = $repository->getLocationService();
765
766
        // Throws exception, since Location with remote ID does not exist
767
        $location = $locationService->loadLocationByRemoteId(
0 ignored issues
show
Unused Code introduced by
$location 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...
768
            'not-exists'
769
        );
770
        /* END: Use Case */
771
    }
772
773
    /**
774
     * Test for the loadLocations() method.
775
     *
776
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
777
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
778
     */
779
    public function testLoadLocations()
780
    {
781
        $repository = $this->getRepository();
782
783
        $contentId = $this->generateId('object', 4);
784
        /* BEGIN: Use Case */
785
        // $contentId contains the ID of an existing content object
786
        $contentService = $repository->getContentService();
787
        $locationService = $repository->getLocationService();
788
789
        $contentInfo = $contentService->loadContentInfo($contentId);
790
791
        $locations = $locationService->loadLocations($contentInfo);
792
        /* END: Use Case */
793
794
        $this->assertIsArray($locations);
795
        self::assertNotEmpty($locations);
796
797
        foreach ($locations as $location) {
798
            self::assertInstanceOf(Location::class, $location);
799
            self::assertEquals($contentInfo->id, $location->getContentInfo()->id);
800
        }
801
802
        return $locations;
803
    }
804
805
    /**
806
     * Test for the loadLocations() method.
807
     *
808
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
809
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
810
     */
811
    public function testLoadLocationsContent(array $locations)
812
    {
813
        $repository = $this->getRepository();
814
        $locationService = $repository->getLocationService();
0 ignored issues
show
Unused Code introduced by
$locationService 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...
815
816
        $this->assertCount(1, $locations);
817
        foreach ($locations as $loadedLocation) {
818
            $this->assertInstanceOf(
819
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
820
                $loadedLocation
821
            );
822
        }
823
824
        usort(
825
            $locations,
826
            function ($a, $b) {
827
                strcmp($a->id, $b->id);
828
            }
829
        );
830
831
        $this->assertEquals(
832
            [$this->generateId('location', 5)],
833
            array_map(
834
                function (Location $location) {
835
                    return $location->id;
836
                },
837
                $locations
838
            )
839
        );
840
    }
841
842
    /**
843
     * Test for the loadLocations() method.
844
     *
845
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
846
     *
847
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations($contentInfo, $rootLocation)
848
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
849
     */
850
    public function testLoadLocationsLimitedSubtree()
851
    {
852
        $repository = $this->getRepository();
853
854
        $originalLocationId = $this->generateId('location', 54);
855
        $originalParentLocationId = $this->generateId('location', 48);
856
        $newParentLocationId = $this->generateId('location', 43);
857
        /* BEGIN: Use Case */
858
        // $originalLocationId is the ID of an existing location
859
        // $originalParentLocationId is the ID of the parent location of
860
        //     $originalLocationId
861
        // $newParentLocationId is the ID of an existing location outside the tree
862
        // of $originalLocationId and $originalParentLocationId
863
        $locationService = $repository->getLocationService();
864
865
        // Location at "/1/48/54"
866
        $originalLocation = $locationService->loadLocation($originalLocationId);
867
868
        // Create location under "/1/43/"
869
        $locationCreate = $locationService->newLocationCreateStruct($newParentLocationId);
870
        $locationService->createLocation(
871
            $originalLocation->contentInfo,
872
            $locationCreate
873
        );
874
875
        $findRootLocation = $locationService->loadLocation($originalParentLocationId);
876
877
        // Returns an array with only $originalLocation
878
        $locations = $locationService->loadLocations(
879
            $originalLocation->contentInfo,
880
            $findRootLocation
881
        );
882
        /* END: Use Case */
883
884
        $this->assertIsArray($locations);
885
886
        return $locations;
887
    }
888
889
    /**
890
     * Test for the loadLocations() method.
891
     *
892
     * @param \eZ\Publish\API\Repository\Values\Content\Location[] $locations
893
     *
894
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
895
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationsLimitedSubtree
896
     */
897
    public function testLoadLocationsLimitedSubtreeContent(array $locations)
898
    {
899
        $this->assertCount(1, $locations);
900
901
        $this->assertEquals(
902
            $this->generateId('location', 54),
903
            reset($locations)->id
904
        );
905
    }
906
907
    /**
908
     * Test for the loadLocations() method.
909
     *
910
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
911
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
912
     */
913 View Code Duplication
    public function testLoadLocationsThrowsBadStateException()
914
    {
915
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\BadStateException::class);
916
917
        $repository = $this->getRepository();
918
919
        /* BEGIN: Use Case */
920
        $contentTypeService = $repository->getContentTypeService();
921
        $contentService = $repository->getContentService();
922
        $locationService = $repository->getLocationService();
923
924
        // Create new content, which is not published
925
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
926
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
927
        $contentCreate->setField('name', 'New Folder');
928
        $content = $contentService->createContent($contentCreate);
929
930
        // Throws Exception, since $content has no published version, yet
931
        $locationService->loadLocations(
932
            $content->contentInfo
933
        );
934
        /* END: Use Case */
935
    }
936
937
    /**
938
     * Test for the loadLocations() method.
939
     *
940
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations($contentInfo, $rootLocation)
941
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
942
     */
943
    public function testLoadLocationsThrowsBadStateExceptionLimitedSubtree()
944
    {
945
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\BadStateException::class);
946
947
        $repository = $this->getRepository();
948
949
        $someLocationId = $this->generateId('location', 2);
950
        /* BEGIN: Use Case */
951
        // $someLocationId is the ID of an existing location
952
        $contentTypeService = $repository->getContentTypeService();
953
        $contentService = $repository->getContentService();
954
        $locationService = $repository->getLocationService();
955
956
        // Create new content, which is not published
957
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
958
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
959
        $contentCreate->setField('name', 'New Folder');
960
        $content = $contentService->createContent($contentCreate);
961
962
        $findRootLocation = $locationService->loadLocation($someLocationId);
963
964
        // Throws Exception, since $content has no published version, yet
965
        $locationService->loadLocations(
966
            $content->contentInfo,
967
            $findRootLocation
968
        );
969
        /* END: Use Case */
970
    }
971
972
    /**
973
     * Test for the loadLocationChildren() method.
974
     *
975
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationChildren
976
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
977
     */
978
    public function testLoadLocationChildren()
979
    {
980
        $repository = $this->getRepository();
981
982
        $locationId = $this->generateId('location', 5);
983
        /* BEGIN: Use Case */
984
        // $locationId is the ID of an existing location
985
        $locationService = $repository->getLocationService();
986
987
        $location = $locationService->loadLocation($locationId);
988
989
        $childLocations = $locationService->loadLocationChildren($location);
990
        /* END: Use Case */
991
992
        $this->assertInstanceOf(LocationList::class, $childLocations);
993
        $this->assertIsArray($childLocations->locations);
994
        $this->assertNotEmpty($childLocations->locations);
995
        $this->assertIsInt($childLocations->totalCount);
996
997
        foreach ($childLocations->locations as $childLocation) {
998
            $this->assertInstanceOf(Location::class, $childLocation);
999
            $this->assertEquals($location->id, $childLocation->parentLocationId);
1000
        }
1001
1002
        return $childLocations;
1003
    }
1004
1005
    /**
1006
     * Test loading parent Locations for draft Content.
1007
     *
1008
     * @covers \eZ\Publish\API\Repository\LocationService::loadParentLocationsForDraftContent
1009
     */
1010
    public function testLoadParentLocationsForDraftContent()
1011
    {
1012
        $repository = $this->getRepository();
1013
        $locationService = $repository->getLocationService();
1014
        $contentService = $repository->getContentService();
1015
        $contentTypeService = $repository->getContentTypeService();
1016
1017
        // prepare locations
1018
        $locationCreateStructs = [
1019
            $locationService->newLocationCreateStruct(2),
1020
            $locationService->newLocationCreateStruct(5),
1021
        ];
1022
1023
        // Create new content
1024
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
1025
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
1026
        $contentCreate->setField('name', 'New Folder');
1027
        $contentDraft = $contentService->createContent($contentCreate, $locationCreateStructs);
1028
1029
        // Test loading parent Locations
1030
        $locations = $locationService->loadParentLocationsForDraftContent($contentDraft->versionInfo);
1031
1032
        self::assertCount(2, $locations);
1033
        foreach ($locations as $location) {
1034
            // test it is one of the given parent locations
1035
            self::assertTrue($location->id === 2 || $location->id === 5);
1036
        }
1037
1038
        return $contentDraft;
1039
    }
1040
1041
    /**
1042
     * Test that trying to load parent Locations throws Exception if Content is not a draft.
1043
     *
1044
     * @depends testLoadParentLocationsForDraftContent
1045
     *
1046
     * @param \eZ\Publish\API\Repository\Values\Content\Content $contentDraft
1047
     */
1048
    public function testLoadParentLocationsForDraftContentThrowsBadStateException(Content $contentDraft)
1049
    {
1050
        $this->expectException(BadStateException::class);
1051
        $this->expectExceptionMessageMatches('/is already published/');
1052
1053
        $repository = $this->getRepository(false);
1054
        $locationService = $repository->getLocationService();
1055
        $contentService = $repository->getContentService();
1056
1057
        $content = $contentService->publishVersion($contentDraft->versionInfo);
1058
1059
        $locationService->loadParentLocationsForDraftContent($content->versionInfo);
1060
    }
1061
1062
    /**
1063
     * Test for the getLocationChildCount() method.
1064
     *
1065
     * @see \eZ\Publish\API\Repository\LocationService::getLocationChildCount()
1066
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1067
     */
1068
    public function testGetLocationChildCount()
1069
    {
1070
        // $locationId is the ID of an existing location
1071
        $locationService = $this->getRepository()->getLocationService();
1072
1073
        $this->assertSame(
1074
            5,
1075
            $locationService->getLocationChildCount(
1076
                $locationService->loadLocation($this->generateId('location', 5))
1077
            )
1078
        );
1079
    }
1080
1081
    /**
1082
     * Test for the loadLocationChildren() method.
1083
     *
1084
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren()
1085
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
1086
     */
1087
    public function testLoadLocationChildrenData(LocationList $locations)
1088
    {
1089
        $this->assertCount(5, $locations->locations);
1090
        $this->assertEquals(5, $locations->totalCount);
1091
1092
        foreach ($locations->locations as $location) {
1093
            $this->assertInstanceOf(
1094
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1095
                $location
1096
            );
1097
        }
1098
1099
        $this->assertEquals(
1100
            [
1101
                $this->generateId('location', 12),
1102
                $this->generateId('location', 13),
1103
                $this->generateId('location', 14),
1104
                $this->generateId('location', 44),
1105
                $this->generateId('location', 61),
1106
            ],
1107
            array_map(
1108
                function (Location $location) {
1109
                    return $location->id;
1110
                },
1111
                $locations->locations
1112
            )
1113
        );
1114
    }
1115
1116
    /**
1117
     * Test for the loadLocationChildren() method.
1118
     *
1119
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
1120
     *
1121
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset)
1122
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
1123
     */
1124
    public function testLoadLocationChildrenWithOffset()
1125
    {
1126
        $repository = $this->getRepository();
1127
1128
        $locationId = $this->generateId('location', 5);
1129
        /* BEGIN: Use Case */
1130
        // $locationId is the ID of an existing location
1131
        $locationService = $repository->getLocationService();
1132
1133
        $location = $locationService->loadLocation($locationId);
1134
1135
        $childLocations = $locationService->loadLocationChildren($location, 2);
1136
        /* END: Use Case */
1137
1138
        $this->assertInstanceOf('\\eZ\\Publish\\API\\Repository\\Values\\Content\\LocationList', $childLocations);
1139
        $this->assertIsArray($childLocations->locations);
1140
        $this->assertIsInt($childLocations->totalCount);
1141
1142
        return $childLocations;
1143
    }
1144
1145
    /**
1146
     * Test for the loadLocationChildren() method.
1147
     *
1148
     * @param \eZ\Publish\API\Repository\Values\Content\LocationList $locations
1149
     *
1150
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset)
1151
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildrenWithOffset
1152
     */
1153 View Code Duplication
    public function testLoadLocationChildrenDataWithOffset(LocationList $locations)
1154
    {
1155
        $this->assertCount(3, $locations->locations);
1156
        $this->assertEquals(5, $locations->totalCount);
1157
1158
        foreach ($locations->locations as $location) {
1159
            $this->assertInstanceOf(
1160
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1161
                $location
1162
            );
1163
        }
1164
1165
        $this->assertEquals(
1166
            [
1167
                $this->generateId('location', 14),
1168
                $this->generateId('location', 44),
1169
                $this->generateId('location', 61),
1170
            ],
1171
            array_map(
1172
                function (Location $location) {
1173
                    return $location->id;
1174
                },
1175
                $locations->locations
1176
            )
1177
        );
1178
    }
1179
1180
    /**
1181
     * Test for the loadLocationChildren() method.
1182
     *
1183
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
1184
     *
1185
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset, $limit)
1186
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
1187
     */
1188
    public function testLoadLocationChildrenWithOffsetAndLimit()
1189
    {
1190
        $repository = $this->getRepository();
1191
1192
        $locationId = $this->generateId('location', 5);
1193
        /* BEGIN: Use Case */
1194
        // $locationId is the ID of an existing location
1195
        $locationService = $repository->getLocationService();
1196
1197
        $location = $locationService->loadLocation($locationId);
1198
1199
        $childLocations = $locationService->loadLocationChildren($location, 2, 2);
1200
        /* END: Use Case */
1201
1202
        $this->assertInstanceOf('\\eZ\\Publish\\API\\Repository\\Values\\Content\\LocationList', $childLocations);
1203
        $this->assertIsArray($childLocations->locations);
1204
        $this->assertIsInt($childLocations->totalCount);
1205
1206
        return $childLocations;
1207
    }
1208
1209
    /**
1210
     * Test for the loadLocationChildren() method.
1211
     *
1212
     * @param \eZ\Publish\API\Repository\Values\Content\Location[] $locations
1213
     *
1214
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset, $limit)
1215
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildrenWithOffsetAndLimit
1216
     */
1217 View Code Duplication
    public function testLoadLocationChildrenDataWithOffsetAndLimit(LocationList $locations)
1218
    {
1219
        $this->assertCount(2, $locations->locations);
1220
        $this->assertEquals(5, $locations->totalCount);
1221
1222
        foreach ($locations->locations as $location) {
1223
            $this->assertInstanceOf(
1224
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1225
                $location
1226
            );
1227
        }
1228
1229
        $this->assertEquals(
1230
            [
1231
                $this->generateId('location', 14),
1232
                $this->generateId('location', 44),
1233
            ],
1234
            array_map(
1235
                function (Location $location) {
1236
                    return $location->id;
1237
                },
1238
                $locations->locations
1239
            )
1240
        );
1241
    }
1242
1243
    /**
1244
     * Test for the newLocationUpdateStruct() method.
1245
     *
1246
     * @covers \eZ\Publish\API\Repository\LocationService::newLocationUpdateStruct
1247
     */
1248 View Code Duplication
    public function testNewLocationUpdateStruct()
1249
    {
1250
        $repository = $this->getRepository();
1251
1252
        /* BEGIN: Use Case */
1253
        $locationService = $repository->getLocationService();
1254
1255
        $updateStruct = $locationService->newLocationUpdateStruct();
1256
        /* END: Use Case */
1257
1258
        $this->assertInstanceOf(
1259
            LocationUpdateStruct::class,
1260
            $updateStruct
1261
        );
1262
1263
        $this->assertPropertiesCorrect(
1264
            [
1265
                'priority' => null,
1266
                'remoteId' => null,
1267
                'sortField' => null,
1268
                'sortOrder' => null,
1269
            ],
1270
            $updateStruct
1271
        );
1272
    }
1273
1274
    /**
1275
     * Test for the updateLocation() method.
1276
     *
1277
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1278
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1279
     */
1280
    public function testUpdateLocation()
1281
    {
1282
        $repository = $this->getRepository();
1283
1284
        $originalLocationId = $this->generateId('location', 5);
1285
        /* BEGIN: Use Case */
1286
        // $originalLocationId is the ID of an existing location
1287
        $locationService = $repository->getLocationService();
1288
1289
        $originalLocation = $locationService->loadLocation($originalLocationId);
1290
1291
        $updateStruct = $locationService->newLocationUpdateStruct();
1292
        $updateStruct->priority = 3;
1293
        $updateStruct->remoteId = 'c7adcbf1e96bc29bca28c2d809d0c7ef69272651';
1294
        $updateStruct->sortField = Location::SORT_FIELD_PRIORITY;
1295
        $updateStruct->sortOrder = Location::SORT_ORDER_DESC;
1296
1297
        $updatedLocation = $locationService->updateLocation($originalLocation, $updateStruct);
1298
        /* END: Use Case */
1299
1300
        $this->assertInstanceOf(
1301
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1302
            $updatedLocation
1303
        );
1304
1305
        return [
1306
            'originalLocation' => $originalLocation,
1307
            'updateStruct' => $updateStruct,
1308
            'updatedLocation' => $updatedLocation,
1309
        ];
1310
    }
1311
1312
    /**
1313
     * Test for the updateLocation() method.
1314
     *
1315
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1316
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testUpdateLocation
1317
     */
1318
    public function testUpdateLocationStructValues(array $data)
1319
    {
1320
        $originalLocation = $data['originalLocation'];
1321
        $updateStruct = $data['updateStruct'];
1322
        $updatedLocation = $data['updatedLocation'];
1323
1324
        $this->assertPropertiesCorrect(
1325
            [
1326
                'id' => $originalLocation->id,
1327
                'priority' => $updateStruct->priority,
1328
                'hidden' => $originalLocation->hidden,
1329
                'invisible' => $originalLocation->invisible,
1330
                'remoteId' => $updateStruct->remoteId,
1331
                'contentInfo' => $originalLocation->contentInfo,
1332
                'parentLocationId' => $originalLocation->parentLocationId,
1333
                'pathString' => $originalLocation->pathString,
1334
                'depth' => $originalLocation->depth,
1335
                'sortField' => $updateStruct->sortField,
1336
                'sortOrder' => $updateStruct->sortOrder,
1337
            ],
1338
            $updatedLocation
1339
        );
1340
    }
1341
1342
    /**
1343
     * Test for the updateLocation() method.
1344
     *
1345
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1346
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1347
     */
1348
    public function testUpdateLocationWithSameRemoteId()
1349
    {
1350
        $repository = $this->getRepository();
1351
1352
        $locationId = $this->generateId('location', 5);
1353
        /* BEGIN: Use Case */
1354
        // $locationId and remote ID is the IDs of the same, existing location
1355
        $locationService = $repository->getLocationService();
1356
1357
        $originalLocation = $locationService->loadLocation($locationId);
1358
1359
        $updateStruct = $locationService->newLocationUpdateStruct();
1360
1361
        // Remote ID of an existing location with the same locationId
1362
        $updateStruct->remoteId = $originalLocation->remoteId;
1363
1364
        // Sets one of the properties to be able to confirm location gets updated, here: priority
1365
        $updateStruct->priority = 2;
1366
1367
        $location = $locationService->updateLocation($originalLocation, $updateStruct);
1368
1369
        // Checks that the location was updated
1370
        $this->assertEquals(2, $location->priority);
1371
1372
        // Checks that remoteId remains the same
1373
        $this->assertEquals($originalLocation->remoteId, $location->remoteId);
1374
        /* END: Use Case */
1375
    }
1376
1377
    /**
1378
     * Test for the updateLocation() method.
1379
     *
1380
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1381
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1382
     */
1383
    public function testUpdateLocationThrowsInvalidArgumentException()
1384
    {
1385
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
1386
1387
        $repository = $this->getRepository();
1388
1389
        $locationId = $this->generateId('location', 5);
1390
        /* BEGIN: Use Case */
1391
        // $locationId and remoteId is the IDs of an existing, but not the same, location
1392
        $locationService = $repository->getLocationService();
1393
1394
        $originalLocation = $locationService->loadLocation($locationId);
1395
1396
        $updateStruct = $locationService->newLocationUpdateStruct();
1397
1398
        // Remote ID of an existing location with a different locationId
1399
        $updateStruct->remoteId = 'f3e90596361e31d496d4026eb624c983';
1400
1401
        // Throws exception, since remote ID is already taken
1402
        $locationService->updateLocation($originalLocation, $updateStruct);
1403
        /* END: Use Case */
1404
    }
1405
1406
    /**
1407
     * Test for the updateLocation() method.
1408
     *
1409
     * @covers \eZ\Publish\API\Repository\LocationService::updateLocation()
1410
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1411
     * @dataProvider dataProviderForOutOfRangeLocationPriority
1412
     */
1413
    public function testUpdateLocationThrowsInvalidArgumentExceptionPriorityIsOutOfRange($priority)
1414
    {
1415
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
1416
1417
        $repository = $this->getRepository();
1418
1419
        $locationId = $this->generateId('location', 5);
1420
        /* BEGIN: Use Case */
1421
        // $locationId and remoteId is the IDs of an existing, but not the same, location
1422
        $locationService = $repository->getLocationService();
1423
1424
        $originalLocation = $locationService->loadLocation($locationId);
1425
1426
        $updateStruct = $locationService->newLocationUpdateStruct();
1427
1428
        // Priority value is out of range
1429
        $updateStruct->priority = $priority;
1430
1431
        // Throws exception, since remote ID is already taken
1432
        $locationService->updateLocation($originalLocation, $updateStruct);
1433
        /* END: Use Case */
1434
    }
1435
1436
    /**
1437
     * Test for the updateLocation() method.
1438
     * Ref EZP-23302: Update Location fails if no change is performed with the update.
1439
     *
1440
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1441
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1442
     */
1443 View Code Duplication
    public function testUpdateLocationTwice()
1444
    {
1445
        $repository = $this->getRepository();
1446
        $permissionResolver = $repository->getPermissionResolver();
1447
1448
        $locationId = $this->generateId('location', 5);
1449
        /* BEGIN: Use Case */
1450
        $locationService = $repository->getLocationService();
1451
        $permissionResolver->setCurrentUserReference($repository->getUserService()->loadUser(14));
1452
1453
        $originalLocation = $locationService->loadLocation($locationId);
1454
1455
        $updateStruct = $locationService->newLocationUpdateStruct();
1456
        $updateStruct->priority = 42;
1457
1458
        $updatedLocation = $locationService->updateLocation($originalLocation, $updateStruct);
1459
1460
        // Repeated update with the same, unchanged struct
1461
        $secondUpdatedLocation = $locationService->updateLocation($updatedLocation, $updateStruct);
1462
        /* END: Use Case */
1463
1464
        $this->assertEquals($updatedLocation->priority, 42);
1465
        $this->assertEquals($secondUpdatedLocation->priority, 42);
1466
    }
1467
1468
    /**
1469
     * Test for the swapLocation() method.
1470
     *
1471
     * @see \eZ\Publish\API\Repository\LocationService::swapLocation()
1472
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1473
     */
1474
    public function testSwapLocation()
1475
    {
1476
        $repository = $this->getRepository();
1477
        $locationService = $repository->getLocationService();
1478
1479
        $mediaLocationId = $this->generateId('location', 43);
1480
        $demoDesignLocationId = $this->generateId('location', 56);
1481
1482
        $mediaContentInfo = $locationService->loadLocation($mediaLocationId)->getContentInfo();
1483
        $demoDesignContentInfo = $locationService->loadLocation($demoDesignLocationId)->getContentInfo();
1484
1485
        /* BEGIN: Use Case */
1486
        // $mediaLocationId is the ID of the "Media" page location in
1487
        // an eZ Publish demo installation
1488
1489
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
1490
        // Publish demo installation
1491
1492
        // Load the location service
1493
        $locationService = $repository->getLocationService();
1494
1495
        $mediaLocation = $locationService->loadLocation($mediaLocationId);
1496
        $demoDesignLocation = $locationService->loadLocation($demoDesignLocationId);
1497
1498
        // Swaps the content referred to by the locations
1499
        $locationService->swapLocation($mediaLocation, $demoDesignLocation);
1500
        /* END: Use Case */
1501
1502
        // Reload Locations, IDs swapped
1503
        $demoDesignLocation = $locationService->loadLocation($mediaLocationId);
1504
        $mediaLocation = $locationService->loadLocation($demoDesignLocationId);
1505
1506
        // Assert Location's Content is updated
1507
        $this->assertEquals(
1508
            $mediaContentInfo->id,
1509
            $mediaLocation->getContentInfo()->id
1510
        );
1511
        $this->assertEquals(
1512
            $demoDesignContentInfo->id,
1513
            $demoDesignLocation->getContentInfo()->id
1514
        );
1515
1516
        // Assert URL aliases are updated
1517
        $this->assertEquals(
1518
            $mediaLocation->id,
1519
            $repository->getURLAliasService()->lookup('/Design/Media')->destination
1520
        );
1521
        $this->assertEquals(
1522
            $demoDesignLocation->id,
1523
            $repository->getURLAliasService()->lookup('/eZ-Publish-Demo-Design-without-demo-content')->destination
1524
        );
1525
    }
1526
1527
    /**
1528
     * Test swapping secondary Location with main Location.
1529
     *
1530
     * @covers \eZ\Publish\API\Repository\LocationService::swapLocation
1531
     *
1532
     * @see https://jira.ez.no/browse/EZP-28663
1533
     *
1534
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1535
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1536
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1537
     *
1538
     * @return int[]
1539
     */
1540
    public function testSwapLocationForMainAndSecondaryLocation(): array
1541
    {
1542
        $repository = $this->getRepository();
1543
        $locationService = $repository->getLocationService();
1544
        $contentService = $repository->getContentService();
1545
1546
        $folder1 = $this->createFolder(['eng-GB' => 'Folder1'], 2);
1547
        $folder2 = $this->createFolder(['eng-GB' => 'Folder2'], 2);
1548
        $folder3 = $this->createFolder(['eng-GB' => 'Folder3'], 2);
1549
1550
        $primaryLocation = $locationService->loadLocation($folder1->contentInfo->mainLocationId);
1551
        $parentLocation = $locationService->loadLocation($folder2->contentInfo->mainLocationId);
1552
        $secondaryLocation = $locationService->createLocation(
1553
            $folder1->contentInfo,
1554
            $locationService->newLocationCreateStruct($parentLocation->id)
1555
        );
1556
1557
        $targetLocation = $locationService->loadLocation($folder3->contentInfo->mainLocationId);
1558
1559
        // perform sanity checks
1560
        $this->assertContentHasExpectedLocations([$primaryLocation, $secondaryLocation], $folder1);
1561
1562
        // begin use case
1563
        $locationService->swapLocation($secondaryLocation, $targetLocation);
1564
1565
        // test results
1566
        $primaryLocation = $locationService->loadLocation($primaryLocation->id);
1567
        $secondaryLocation = $locationService->loadLocation($secondaryLocation->id);
1568
        $targetLocation = $locationService->loadLocation($targetLocation->id);
1569
1570
        self::assertEquals($folder1->id, $primaryLocation->contentInfo->id);
1571
        self::assertEquals($folder1->id, $targetLocation->contentInfo->id);
1572
        self::assertEquals($folder3->id, $secondaryLocation->contentInfo->id);
1573
1574
        $this->assertContentHasExpectedLocations([$primaryLocation, $targetLocation], $folder1);
1575
1576
        self::assertEquals(
1577
            $folder1,
1578
            $contentService->loadContent($folder1->id, Language::ALL)
1579
        );
1580
1581
        self::assertEquals(
1582
            $folder2,
1583
            $contentService->loadContent($folder2->id, Language::ALL)
1584
        );
1585
1586
        // only in case of Folder 3, main location id changed due to swap
1587
        self::assertEquals(
1588
            $secondaryLocation->id,
1589
            $contentService->loadContent($folder3->id)->contentInfo->mainLocationId
1590
        );
1591
1592
        return [$folder1, $folder2, $folder3];
1593
    }
1594
1595
    /**
1596
     * Compare Ids of expected and loaded Locations for the given Content.
1597
     *
1598
     * @param \eZ\Publish\API\Repository\Values\Content\Location[] $expectedLocations
1599
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
1600
     *
1601
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
1602
     */
1603
    private function assertContentHasExpectedLocations(array $expectedLocations, Content $content)
1604
    {
1605
        $repository = $this->getRepository(false);
1606
        $locationService = $repository->getLocationService();
1607
1608
        $expectedLocationIds = array_map(
1609
            function (Location $location) {
1610
                return (int)$location->id;
1611
            },
1612
            $expectedLocations
1613
        );
1614
1615
        $actualLocationsIds = array_map(
1616
            function (Location $location) {
1617
                return $location->id;
1618
            },
1619
            $locationService->loadLocations($content->contentInfo)
1620
        );
1621
        self::assertCount(count($expectedLocations), $actualLocationsIds);
1622
1623
        // perform unordered equality assertion
1624
        self::assertEqualsCanonicalizing(
1625
            $expectedLocationIds,
1626
            $actualLocationsIds,
1627
            sprintf(
1628
                'Content %d contains Locations %s, not expected Locations: %s',
1629
                $content->id,
1630
                implode(', ', $actualLocationsIds),
1631
                implode(', ', $expectedLocationIds)
1632
            )
1633
        );
1634
    }
1635
1636
    /**
1637
     * @depends testSwapLocationForMainAndSecondaryLocation
1638
     *
1639
     * @param \eZ\Publish\API\Repository\Values\Content\Content[] $contentItems Content items created by testSwapLocationForSecondaryLocation
1640
     *
1641
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1642
     */
1643
    public function testSwapLocationDoesNotCorruptSearchResults(array $contentItems)
1644
    {
1645
        $repository = $this->getRepository(false);
1646
        $searchService = $repository->getSearchService();
1647
1648
        $this->refreshSearch($repository);
1649
1650
        $contentIds = array_map(
1651
            function (Content $content) {
1652
                return $content->id;
1653
            },
1654
            $contentItems
1655
        );
1656
1657
        $query = new Query();
1658
        $query->filter = new Query\Criterion\ContentId($contentIds);
1659
1660
        $searchResult = $searchService->findContent($query);
1661
1662
        self::assertEquals(count($contentItems), $searchResult->totalCount);
1663
        self::assertEquals(
1664
            $searchResult->totalCount,
1665
            count($searchResult->searchHits),
1666
            'Total count of search result hits does not match the actual number of found results'
1667
        );
1668
        $foundContentIds = array_map(
1669
            function (SearchHit $searchHit) {
1670
                return $searchHit->valueObject->id;
0 ignored issues
show
Documentation introduced by
The property id does not exist on object<eZ\Publish\API\Re...ory\Values\ValueObject>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1671
            },
1672
            $searchResult->searchHits
1673
        );
1674
        sort($contentIds);
1675
        sort($foundContentIds);
1676
        self::assertSame(
1677
            $contentIds,
1678
            $foundContentIds,
1679
            'Got different than expected Content item Ids'
1680
        );
1681
    }
1682
1683
    /**
1684
     * Test swapping two secondary (non-main) Locations.
1685
     *
1686
     * @covers \eZ\Publish\API\Repository\LocationService::swapLocation
1687
     *
1688
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1689
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1690
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1691
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1692
     */
1693
    public function testSwapLocationForSecondaryLocations()
1694
    {
1695
        $repository = $this->getRepository();
1696
        $locationService = $repository->getLocationService();
1697
        $contentService = $repository->getContentService();
1698
1699
        $folder1 = $this->createFolder(['eng-GB' => 'Folder1'], 2);
1700
        $folder2 = $this->createFolder(['eng-GB' => 'Folder2'], 2);
1701
        $parentFolder1 = $this->createFolder(['eng-GB' => 'Parent1'], 2);
1702
        $parentFolder2 = $this->createFolder(['eng-GB' => 'Parent2'], 2);
1703
1704
        $parentLocation1 = $locationService->loadLocation($parentFolder1->contentInfo->mainLocationId);
1705
        $parentLocation2 = $locationService->loadLocation($parentFolder2->contentInfo->mainLocationId);
1706
        $secondaryLocation1 = $locationService->createLocation(
1707
            $folder1->contentInfo,
1708
            $locationService->newLocationCreateStruct($parentLocation1->id)
1709
        );
1710
        $secondaryLocation2 = $locationService->createLocation(
1711
            $folder2->contentInfo,
1712
            $locationService->newLocationCreateStruct($parentLocation2->id)
1713
        );
1714
1715
        // begin use case
1716
        $locationService->swapLocation($secondaryLocation1, $secondaryLocation2);
1717
1718
        // test results
1719
        $secondaryLocation1 = $locationService->loadLocation($secondaryLocation1->id);
1720
        $secondaryLocation2 = $locationService->loadLocation($secondaryLocation2->id);
1721
1722
        self::assertEquals($folder2->id, $secondaryLocation1->contentInfo->id);
1723
        self::assertEquals($folder1->id, $secondaryLocation2->contentInfo->id);
1724
1725
        self::assertEquals(
1726
            $folder1,
1727
            $contentService->loadContent($folder1->id, Language::ALL)
1728
        );
1729
1730
        self::assertEquals(
1731
            $folder2,
1732
            $contentService->loadContent($folder2->id, Language::ALL)
1733
        );
1734
    }
1735
1736
    /**
1737
     * Test swapping Main Location of a Content with another one updates Content item Main Location.
1738
     *
1739
     * @covers \eZ\Publish\API\Repository\LocationService::swapLocation
1740
     */
1741
    public function testSwapLocationUpdatesMainLocation()
1742
    {
1743
        $repository = $this->getRepository();
1744
        $locationService = $repository->getLocationService();
1745
        $contentService = $repository->getContentService();
1746
1747
        $mainLocationParentId = 60;
1748
        $secondaryLocationId = 43;
1749
1750
        $publishedContent = $this->publishContentWithParentLocation(
1751
            'Content for Swap Location Test', $mainLocationParentId
1752
        );
1753
1754
        // sanity check
1755
        $mainLocation = $locationService->loadLocation($publishedContent->contentInfo->mainLocationId);
1756
        self::assertEquals($mainLocationParentId, $mainLocation->parentLocationId);
1757
1758
        // load another pre-existing location
1759
        $secondaryLocation = $locationService->loadLocation($secondaryLocationId);
1760
1761
        // swap the Main Location with a secondary one
1762
        $locationService->swapLocation($mainLocation, $secondaryLocation);
1763
1764
        // check if Main Location has been updated
1765
        $mainLocation = $locationService->loadLocation($secondaryLocation->id);
1766
        self::assertEquals($publishedContent->contentInfo->id, $mainLocation->contentInfo->id);
1767
        self::assertEquals($mainLocation->id, $mainLocation->contentInfo->mainLocationId);
1768
1769
        $reloadedContent = $contentService->loadContentByContentInfo($publishedContent->contentInfo);
1770
        self::assertEquals($mainLocation->id, $reloadedContent->contentInfo->mainLocationId);
1771
    }
1772
1773
    /**
1774
     * Test if location swap affects related bookmarks.
1775
     *
1776
     * @covers \eZ\Publish\API\Repository\LocationService::swapLocation
1777
     */
1778
    public function testBookmarksAreSwappedAfterSwapLocation()
1779
    {
1780
        $repository = $this->getRepository();
1781
1782
        $mediaLocationId = $this->generateId('location', 43);
1783
        $demoDesignLocationId = $this->generateId('location', 56);
1784
1785
        /* BEGIN: Use Case */
1786
        $locationService = $repository->getLocationService();
1787
        $bookmarkService = $repository->getBookmarkService();
1788
1789
        $mediaLocation = $locationService->loadLocation($mediaLocationId);
1790
        $demoDesignLocation = $locationService->loadLocation($demoDesignLocationId);
1791
1792
        // Bookmark locations
1793
        $bookmarkService->createBookmark($mediaLocation);
1794
        $bookmarkService->createBookmark($demoDesignLocation);
1795
1796
        $beforeSwap = $bookmarkService->loadBookmarks();
1797
1798
        // Swaps the content referred to by the locations
1799
        $locationService->swapLocation($mediaLocation, $demoDesignLocation);
1800
1801
        $afterSwap = $bookmarkService->loadBookmarks();
1802
        /* END: Use Case */
1803
1804
        $this->assertEquals($beforeSwap->items[0]->id, $afterSwap->items[1]->id);
1805
        $this->assertEquals($beforeSwap->items[1]->id, $afterSwap->items[0]->id);
1806
    }
1807
1808
    /**
1809
     * Test for the hideLocation() method.
1810
     *
1811
     * @see \eZ\Publish\API\Repository\LocationService::hideLocation()
1812
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1813
     */
1814
    public function testHideLocation()
1815
    {
1816
        $repository = $this->getRepository();
1817
1818
        $locationId = $this->generateId('location', 5);
1819
        /* BEGIN: Use Case */
1820
        // $locationId is the ID of an existing location
1821
        $locationService = $repository->getLocationService();
1822
1823
        $visibleLocation = $locationService->loadLocation($locationId);
1824
1825
        $hiddenLocation = $locationService->hideLocation($visibleLocation);
1826
        /* END: Use Case */
1827
1828
        $this->assertInstanceOf(
1829
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1830
            $hiddenLocation
1831
        );
1832
1833
        $this->assertTrue(
1834
            $hiddenLocation->hidden,
1835
            sprintf(
1836
                'Location with ID "%s" is not hidden.',
1837
                $hiddenLocation->id
1838
            )
1839
        );
1840
1841
        $this->refreshSearch($repository);
1842
1843
        foreach ($locationService->loadLocationChildren($hiddenLocation)->locations as $child) {
1844
            $this->assertSubtreeProperties(
1845
                ['invisible' => true],
1846
                $child
1847
            );
1848
        }
1849
    }
1850
1851
    /**
1852
     * Assert that $expectedValues are set in the subtree starting at $location.
1853
     *
1854
     * @param array $expectedValues
1855
     * @param Location $location
1856
     */
1857
    protected function assertSubtreeProperties(array $expectedValues, Location $location, $stopId = null)
1858
    {
1859
        $repository = $this->getRepository();
1860
        $locationService = $repository->getLocationService();
1861
1862
        if ($location->id === $stopId) {
1863
            return;
1864
        }
1865
1866
        foreach ($expectedValues as $propertyName => $propertyValue) {
1867
            $this->assertEquals(
1868
                $propertyValue,
1869
                $location->$propertyName
1870
            );
1871
1872
            foreach ($locationService->loadLocationChildren($location)->locations as $child) {
1873
                $this->assertSubtreeProperties($expectedValues, $child);
1874
            }
1875
        }
1876
    }
1877
1878
    /**
1879
     * Test for the unhideLocation() method.
1880
     *
1881
     * @see \eZ\Publish\API\Repository\LocationService::unhideLocation()
1882
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testHideLocation
1883
     */
1884
    public function testUnhideLocation()
1885
    {
1886
        $repository = $this->getRepository();
1887
1888
        $locationId = $this->generateId('location', 5);
1889
        /* BEGIN: Use Case */
1890
        // $locationId is the ID of an existing location
1891
        $locationService = $repository->getLocationService();
1892
1893
        $visibleLocation = $locationService->loadLocation($locationId);
1894
        $hiddenLocation = $locationService->hideLocation($visibleLocation);
1895
1896
        $unHiddenLocation = $locationService->unhideLocation($hiddenLocation);
1897
        /* END: Use Case */
1898
1899
        $this->assertInstanceOf(
1900
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1901
            $unHiddenLocation
1902
        );
1903
1904
        $this->assertFalse(
1905
            $unHiddenLocation->hidden,
1906
            sprintf(
1907
                'Location with ID "%s" is hidden.',
1908
                $unHiddenLocation->id
1909
            )
1910
        );
1911
1912
        $this->refreshSearch($repository);
1913
1914
        foreach ($locationService->loadLocationChildren($unHiddenLocation)->locations as $child) {
1915
            $this->assertSubtreeProperties(
1916
                ['invisible' => false],
1917
                $child
1918
            );
1919
        }
1920
    }
1921
1922
    /**
1923
     * Test for the unhideLocation() method.
1924
     *
1925
     * @see \eZ\Publish\API\Repository\LocationService::unhideLocation()
1926
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testUnhideLocation
1927
     */
1928
    public function testUnhideLocationNotUnhidesHiddenSubtree()
1929
    {
1930
        $repository = $this->getRepository();
1931
1932
        $higherLocationId = $this->generateId('location', 5);
1933
        $lowerLocationId = $this->generateId('location', 13);
1934
        /* BEGIN: Use Case */
1935
        // $higherLocationId is the ID of a location
1936
        // $lowerLocationId is the ID of a location below $higherLocationId
1937
        $locationService = $repository->getLocationService();
1938
1939
        $higherLocation = $locationService->loadLocation($higherLocationId);
1940
        $hiddenHigherLocation = $locationService->hideLocation($higherLocation);
1941
1942
        $lowerLocation = $locationService->loadLocation($lowerLocationId);
1943
        $hiddenLowerLocation = $locationService->hideLocation($lowerLocation);
0 ignored issues
show
Unused Code introduced by
$hiddenLowerLocation 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...
1944
1945
        $unHiddenHigherLocation = $locationService->unhideLocation($hiddenHigherLocation);
1946
        /* END: Use Case */
1947
1948
        $this->assertInstanceOf(
1949
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1950
            $unHiddenHigherLocation
1951
        );
1952
1953
        $this->assertFalse(
1954
            $unHiddenHigherLocation->hidden,
1955
            sprintf(
1956
                'Location with ID "%s" is hidden.',
1957
                $unHiddenHigherLocation->id
1958
            )
1959
        );
1960
1961
        $this->refreshSearch($repository);
1962
1963
        foreach ($locationService->loadLocationChildren($unHiddenHigherLocation)->locations as $child) {
1964
            $this->assertSubtreeProperties(
1965
                ['invisible' => false],
1966
                $child,
1967
                $this->generateId('location', 13)
1968
            );
1969
        }
1970
1971
        $stillHiddenLocation = $locationService->loadLocation($this->generateId('location', 13));
1972
        $this->assertTrue(
1973
            $stillHiddenLocation->hidden,
1974
            sprintf(
1975
                'Hidden sub-location with ID %s unhidden unexpectedly.',
1976
                $stillHiddenLocation->id
1977
            )
1978
        );
1979
        foreach ($locationService->loadLocationChildren($stillHiddenLocation)->locations as $child) {
1980
            $this->assertSubtreeProperties(
1981
                ['invisible' => true],
1982
                $child
1983
            );
1984
        }
1985
    }
1986
1987
    /**
1988
     * Test for the deleteLocation() method.
1989
     *
1990
     * @see \eZ\Publish\API\Repository\LocationService::deleteLocation()
1991
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1992
     */
1993
    public function testDeleteLocation()
1994
    {
1995
        $repository = $this->getRepository();
1996
1997
        $mediaLocationId = $this->generateId('location', 43);
1998
        /* BEGIN: Use Case */
1999
        // $mediaLocationId is the ID of the location of the
2000
        // "Media" location in an eZ Publish demo installation
2001
        $locationService = $repository->getLocationService();
2002
2003
        $location = $locationService->loadLocation($mediaLocationId);
2004
2005
        $locationService->deleteLocation($location);
2006
        /* END: Use Case */
2007
2008
        try {
2009
            $locationService->loadLocation($mediaLocationId);
2010
            $this->fail("Location $mediaLocationId not deleted.");
2011
        } catch (NotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
2012
        }
2013
2014
        // The following IDs are IDs of child locations of $mediaLocationId location
2015
        // ( Media/Images, Media/Files, Media/Multimedia respectively )
2016
        foreach ([51, 52, 53] as $childLocationId) {
2017
            try {
2018
                $locationService->loadLocation($this->generateId('location', $childLocationId));
2019
                $this->fail("Location $childLocationId not deleted.");
2020
            } catch (NotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
2021
            }
2022
        }
2023
2024
        // The following IDs are IDs of content below $mediaLocationId location
2025
        // ( Media/Images, Media/Files, Media/Multimedia respectively )
2026
        $contentService = $this->getRepository()->getContentService();
2027
        foreach ([49, 50, 51] as $childContentId) {
2028
            try {
2029
                $contentService->loadContentInfo($this->generateId('object', $childContentId));
2030
                $this->fail("Content $childContentId not deleted.");
2031
            } catch (NotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
2032
            }
2033
        }
2034
    }
2035
2036
    /**
2037
     * Test for the deleteLocation() method.
2038
     *
2039
     * @see \eZ\Publish\API\Repository\LocationService::deleteLocation()
2040
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testDeleteLocation
2041
     */
2042
    public function testDeleteLocationDecrementsChildCountOnParent()
2043
    {
2044
        $repository = $this->getRepository();
2045
2046
        $mediaLocationId = $this->generateId('location', 43);
2047
        /* BEGIN: Use Case */
2048
        // $mediaLocationId is the ID of the location of the
2049
        // "Media" location in an eZ Publish demo installation
2050
2051
        $locationService = $repository->getLocationService();
2052
2053
        // Load the current the user group location
2054
        $location = $locationService->loadLocation($mediaLocationId);
2055
2056
        // Load the parent location
2057
        $parentLocation = $locationService->loadLocation(
2058
            $location->parentLocationId
2059
        );
2060
2061
        // Get child count
2062
        $childCountBefore = $locationService->getLocationChildCount($parentLocation);
2063
2064
        // Delete the user group location
2065
        $locationService->deleteLocation($location);
2066
2067
        $this->refreshSearch($repository);
2068
2069
        // Reload parent location
2070
        $parentLocation = $locationService->loadLocation(
2071
            $location->parentLocationId
2072
        );
2073
2074
        // This will be $childCountBefore - 1
2075
        $childCountAfter = $locationService->getLocationChildCount($parentLocation);
2076
        /* END: Use Case */
2077
2078
        $this->assertEquals($childCountBefore - 1, $childCountAfter);
2079
    }
2080
2081
    /**
2082
     * Test for the deleteLocation() method.
2083
     *
2084
     * Related issue: EZP-21904
2085
     *
2086
     * @see \eZ\Publish\API\Repository\LocationService::deleteLocation()
2087
     */
2088
    public function testDeleteContentObjectLastLocation()
2089
    {
2090
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
2091
2092
        $repository = $this->getRepository();
2093
2094
        /* BEGIN: Use case */
2095
        $contentService = $repository->getContentService();
2096
        $locationService = $repository->getLocationService();
2097
        $contentTypeService = $repository->getContentTypeService();
2098
        $urlAliasService = $repository->getURLAliasService();
2099
2100
        // prepare Content object
2101
        $createStruct = $contentService->newContentCreateStruct(
2102
            $contentTypeService->loadContentTypeByIdentifier('folder'),
2103
            'eng-GB'
2104
        );
2105
        $createStruct->setField('name', 'Test folder');
2106
2107
        // creata Content object
2108
        $content = $contentService->publishVersion(
2109
            $contentService->createContent(
2110
                $createStruct,
2111
                [$locationService->newLocationCreateStruct(2)]
2112
            )->versionInfo
2113
        );
2114
2115
        // delete location
2116
        $locationService->deleteLocation(
2117
            $locationService->loadLocation(
2118
                $urlAliasService->lookup('/Test-folder')->destination
2119
            )
2120
        );
2121
2122
        // this should throw a not found exception
2123
        $contentService->loadContent($content->versionInfo->contentInfo->id);
2124
        /* END: Use case*/
2125
    }
2126
2127
    /**
2128
     * Test for the deleteLocation() method.
2129
     *
2130
     * @covers  \eZ\Publish\API\Repository\LocationService::deleteLocation()
2131
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testDeleteLocation
2132
     */
2133
    public function testDeleteLocationDeletesRelatedBookmarks()
2134
    {
2135
        $repository = $this->getRepository();
2136
2137
        $parentLocationId = $this->generateId('location', 43);
2138
        $childLocationId = $this->generateId('location', 53);
2139
2140
        /* BEGIN: Use Case */
2141
        $locationService = $repository->getLocationService();
2142
        $bookmarkService = $repository->getBookmarkService();
2143
2144
        // Load location
2145
        $childLocation = $locationService->loadLocation($childLocationId);
2146
        // Add location to bookmarks
2147
        $bookmarkService->createBookmark($childLocation);
2148
        // Load parent location
2149
        $parentLocation = $locationService->loadLocation($parentLocationId);
2150
        // Delete parent location
2151
        $locationService->deleteLocation($parentLocation);
2152
        /* END: Use Case */
2153
2154
        // Location isn't bookmarked anymore
2155
        foreach ($bookmarkService->loadBookmarks(0, 9999) as $bookmarkedLocation) {
2156
            $this->assertNotEquals($childLocation->id, $bookmarkedLocation->id);
2157
        }
2158
    }
2159
2160
    /**
2161
     * @covers \eZ\Publish\API\Repository\LocationService::deleteLocation
2162
     */
2163
    public function testDeleteUnusedLocationWhichPreviousHadContentWithRelativeAlias(): void
2164
    {
2165
        $repository = $this->getRepository(false);
2166
2167
        $contentService = $repository->getContentService();
2168
        $locationService = $repository->getLocationService();
2169
        $urlAliasService = $repository->getURLAliasService();
2170
2171
        $originalFolder = $this->createFolder(['eng-GB' => 'Original folder'], 2);
2172
        $newFolder = $this->createFolder(['eng-GB' => 'New folder'], 2);
2173
        $originalFolderLocationId = $originalFolder->contentInfo->mainLocationId;
2174
2175
        $forum = $contentService->publishVersion(
2176
            $contentService->createContent(
2177
                $this->createForumStruct('Some forum'),
2178
                [
2179
                    $locationService->newLocationCreateStruct($originalFolderLocationId),
2180
                ]
2181
            )->versionInfo
2182
        );
2183
2184
        $forumMainLocation = $locationService->loadLocation(
2185
            $forum->contentInfo->mainLocationId
2186
        );
2187
2188
        $customRelativeAliasPath = '/Original-folder/some-forum-alias';
2189
2190
        $urlAliasService->createUrlAlias(
2191
            $forumMainLocation,
2192
            $customRelativeAliasPath,
2193
            'eng-GB',
2194
            true,
2195
            true
2196
        );
2197
2198
        $locationService->moveSubtree(
2199
            $forumMainLocation,
2200
            $locationService->loadLocation(
2201
                $newFolder->contentInfo->mainLocationId
2202
            )
2203
        );
2204
2205
        $this->assertAliasExists(
2206
            $customRelativeAliasPath,
2207
            $forumMainLocation,
2208
            $urlAliasService
2209
        );
2210
2211
        $urlAliasService->lookup($customRelativeAliasPath);
2212
2213
        $locationService->deleteLocation(
2214
            $locationService->loadLocation(
2215
                $originalFolder->contentInfo->mainLocationId
2216
            )
2217
        );
2218
2219
        $this->assertAliasExists(
2220
            $customRelativeAliasPath,
2221
            $forumMainLocation,
2222
            $urlAliasService
2223
        );
2224
2225
        $urlAliasService->lookup($customRelativeAliasPath);
2226
    }
2227
2228
    /**
2229
     * Test for the copySubtree() method.
2230
     *
2231
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2232
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
2233
     */
2234
    public function testCopySubtree()
2235
    {
2236
        $repository = $this->getRepository();
2237
2238
        $mediaLocationId = $this->generateId('location', 43);
2239
        $demoDesignLocationId = $this->generateId('location', 56);
2240
        /* BEGIN: Use Case */
2241
        // $mediaLocationId is the ID of the "Media" page location in
2242
        // an eZ Publish demo installation
2243
2244
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2245
        // Publish demo installation
2246
2247
        // Load the location service
2248
        $locationService = $repository->getLocationService();
2249
2250
        // Load location to copy
2251
        $locationToCopy = $locationService->loadLocation($mediaLocationId);
2252
2253
        // Load new parent location
2254
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2255
2256
        // Copy location "Media" to "Demo Design"
2257
        $copiedLocation = $locationService->copySubtree(
2258
            $locationToCopy,
2259
            $newParentLocation
2260
        );
2261
        /* END: Use Case */
2262
2263
        $this->assertInstanceOf(
2264
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
2265
            $copiedLocation
2266
        );
2267
2268
        $this->assertPropertiesCorrect(
2269
            [
2270
                'depth' => $newParentLocation->depth + 1,
2271
                'parentLocationId' => $newParentLocation->id,
2272
                'pathString' => $newParentLocation->pathString . $this->parseId('location', $copiedLocation->id) . '/',
2273
            ],
2274
            $copiedLocation
2275
        );
2276
2277
        $this->assertDefaultContentStates($copiedLocation->contentInfo);
2278
    }
2279
2280
    /**
2281
     * Test for the copySubtree() method.
2282
     *
2283
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2284
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
2285
     */
2286
    public function testCopySubtreeWithAliases()
2287
    {
2288
        $repository = $this->getRepository();
2289
        $urlAliasService = $repository->getURLAliasService();
2290
2291
        // $mediaLocationId is the ID of the "Media" page location in
2292
        // an eZ Publish demo installation
2293
2294
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2295
        // Publish demo installation
2296
        $mediaLocationId = $this->generateId('location', 43);
2297
        $demoDesignLocationId = $this->generateId('location', 56);
2298
2299
        $locationService = $repository->getLocationService();
2300
        $locationToCopy = $locationService->loadLocation($mediaLocationId);
2301
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2302
2303
        $expectedSubItemAliases = [
2304
            '/Design/Plain-site/Media/Multimedia',
2305
            '/Design/Plain-site/Media/Images',
2306
            '/Design/Plain-site/Media/Files',
2307
        ];
2308
2309
        $this->assertAliasesBeforeCopy($urlAliasService, $expectedSubItemAliases);
2310
2311
        // Copy location "Media" to "Design"
2312
        $locationService->copySubtree(
2313
            $locationToCopy,
2314
            $newParentLocation
2315
        );
2316
2317
        $this->assertGeneratedAliases($urlAliasService, $expectedSubItemAliases);
2318
    }
2319
2320
    /**
2321
     * Asserts that given Content has default ContentStates.
2322
     *
2323
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
2324
     */
2325
    private function assertDefaultContentStates(ContentInfo $contentInfo)
2326
    {
2327
        $repository = $this->getRepository();
2328
        $objectStateService = $repository->getObjectStateService();
2329
2330
        $objectStateGroups = $objectStateService->loadObjectStateGroups();
2331
2332
        foreach ($objectStateGroups as $objectStateGroup) {
2333
            $contentState = $objectStateService->getContentState($contentInfo, $objectStateGroup);
2334
            foreach ($objectStateService->loadObjectStates($objectStateGroup, Language::ALL) as $objectState) {
2335
                // Only check the first object state which is the default one.
2336
                $this->assertEquals(
2337
                    $objectState,
2338
                    $contentState
2339
                );
2340
                break;
2341
            }
2342
        }
2343
    }
2344
2345
    /**
2346
     * Test for the copySubtree() method.
2347
     *
2348
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2349
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCopySubtree
2350
     */
2351
    public function testCopySubtreeUpdatesSubtreeProperties()
2352
    {
2353
        $repository = $this->getRepository();
2354
        $locationService = $repository->getLocationService();
2355
2356
        $locationToCopy = $locationService->loadLocation($this->generateId('location', 43));
2357
2358
        // Load Subtree properties before copy
2359
        $expected = $this->loadSubtreeProperties($locationToCopy);
2360
2361
        $mediaLocationId = $this->generateId('location', 43);
2362
        $demoDesignLocationId = $this->generateId('location', 56);
2363
        /* BEGIN: Use Case */
2364
        // $mediaLocationId is the ID of the "Media" page location in
2365
        // an eZ Publish demo installation
2366
2367
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2368
        // Publish demo installation
2369
2370
        // Load the location service
2371
        $locationService = $repository->getLocationService();
2372
2373
        // Load location to copy
2374
        $locationToCopy = $locationService->loadLocation($mediaLocationId);
2375
2376
        // Load new parent location
2377
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2378
2379
        // Copy location "Media" to "Demo Design"
2380
        $copiedLocation = $locationService->copySubtree(
2381
            $locationToCopy,
2382
            $newParentLocation
2383
        );
2384
        /* END: Use Case */
2385
2386
        $beforeIds = [];
2387
        foreach ($expected as $properties) {
2388
            $beforeIds[] = $properties['id'];
2389
        }
2390
2391
        $this->refreshSearch($repository);
2392
2393
        // Load Subtree properties after copy
2394
        $actual = $this->loadSubtreeProperties($copiedLocation);
2395
2396
        $this->assertEquals(count($expected), count($actual));
2397
2398
        foreach ($actual as $properties) {
2399
            $this->assertNotContains($properties['id'], $beforeIds);
2400
            $this->assertStringStartsWith(
2401
                $newParentLocation->pathString . $this->parseId('location', $copiedLocation->id) . '/',
2402
                $properties['pathString']
2403
            );
2404
            $this->assertStringEndsWith(
2405
                '/' . $this->parseId('location', $properties['id']) . '/',
2406
                $properties['pathString']
2407
            );
2408
        }
2409
    }
2410
2411
    /**
2412
     * Test for the copySubtree() method.
2413
     *
2414
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2415
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCopySubtree
2416
     */
2417
    public function testCopySubtreeIncrementsChildCountOfNewParent()
2418
    {
2419
        $repository = $this->getRepository();
2420
        $locationService = $repository->getLocationService();
2421
2422
        $childCountBefore = $locationService->getLocationChildCount($locationService->loadLocation(56));
2423
2424
        $mediaLocationId = $this->generateId('location', 43);
2425
        $demoDesignLocationId = $this->generateId('location', 56);
2426
        /* BEGIN: Use Case */
2427
        // $mediaLocationId is the ID of the "Media" page location in
2428
        // an eZ Publish demo installation
2429
2430
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2431
        // Publish demo installation
2432
2433
        // Load the location service
2434
        $locationService = $repository->getLocationService();
2435
2436
        // Load location to copy
2437
        $locationToCopy = $locationService->loadLocation($mediaLocationId);
2438
2439
        // Load new parent location
2440
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2441
2442
        // Copy location "Media" to "Demo Design"
2443
        $copiedLocation = $locationService->copySubtree(
0 ignored issues
show
Unused Code introduced by
$copiedLocation 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...
2444
            $locationToCopy,
2445
            $newParentLocation
2446
        );
2447
        /* END: Use Case */
2448
2449
        $this->refreshSearch($repository);
2450
2451
        $childCountAfter = $locationService->getLocationChildCount($locationService->loadLocation($demoDesignLocationId));
2452
2453
        $this->assertEquals($childCountBefore + 1, $childCountAfter);
2454
    }
2455
2456
    /**
2457
     * Test for the copySubtree() method.
2458
     *
2459
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2460
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCopySubtree
2461
     */
2462
    public function testCopySubtreeThrowsInvalidArgumentException()
2463
    {
2464
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
2465
2466
        $repository = $this->getRepository();
2467
2468
        $communityLocationId = $this->generateId('location', 5);
2469
        /* BEGIN: Use Case */
2470
        // $communityLocationId is the ID of the "Community" page location in
2471
        // an eZ Publish demo installation
2472
2473
        // Load the location service
2474
        $locationService = $repository->getLocationService();
2475
2476
        // Load location to copy
2477
        $locationToCopy = $locationService->loadLocation($communityLocationId);
2478
2479
        // Use a child as new parent
2480
        $childLocations = $locationService->loadLocationChildren($locationToCopy)->locations;
2481
        $newParentLocation = end($childLocations);
2482
2483
        // This call will fail with an "InvalidArgumentException", because the
2484
        // new parent is a child location of the subtree to copy.
2485
        $locationService->copySubtree(
2486
            $locationToCopy,
2487
            $newParentLocation
0 ignored issues
show
Security Bug introduced by
It seems like $newParentLocation defined by end($childLocations) on line 2481 can also be of type false; however, eZ\Publish\API\Repositor...nService::copySubtree() does only seem to accept object<eZ\Publish\API\Re...alues\Content\Location>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
2488
        );
2489
        /* END: Use Case */
2490
    }
2491
2492
    /**
2493
     * Test for the moveSubtree() method.
2494
     *
2495
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2496
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
2497
     */
2498
    public function testMoveSubtree()
2499
    {
2500
        $repository = $this->getRepository();
2501
2502
        $mediaLocationId = $this->generateId('location', 43);
2503
        $demoDesignLocationId = $this->generateId('location', 56);
2504
        /* BEGIN: Use Case */
2505
        // $mediaLocationId is the ID of the "Media" page location in
2506
        // an eZ Publish demo installation
2507
2508
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2509
        // Publish demo installation
2510
2511
        // Load the location service
2512
        $locationService = $repository->getLocationService();
2513
2514
        // Load location to move
2515
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2516
2517
        // Load new parent location
2518
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2519
2520
        // Move location from "Home" to "Demo Design"
2521
        $locationService->moveSubtree(
2522
            $locationToMove,
2523
            $newParentLocation
2524
        );
2525
2526
        // Load moved location
2527
        $movedLocation = $locationService->loadLocation($mediaLocationId);
2528
        /* END: Use Case */
2529
2530
        $this->assertPropertiesCorrect(
2531
            [
2532
                'hidden' => false,
2533
                'invisible' => false,
2534
                'depth' => $newParentLocation->depth + 1,
2535
                'parentLocationId' => $newParentLocation->id,
2536
                'pathString' => $newParentLocation->pathString . $this->parseId('location', $movedLocation->id) . '/',
2537
            ],
2538
            $movedLocation
2539
        );
2540
    }
2541
2542
    /**
2543
     * Test for the moveSubtree() method.
2544
     *
2545
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2546
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2547
     */
2548
    public function testMoveSubtreeHidden()
2549
    {
2550
        $repository = $this->getRepository();
2551
2552
        $mediaLocationId = $this->generateId('location', 43);
2553
        $demoDesignLocationId = $this->generateId('location', 56);
2554
        /* BEGIN: Use Case */
2555
        // $mediaLocationId is the ID of the "Media" page location in
2556
        // an eZ Publish demo installation
2557
2558
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2559
        // Publish demo installation
2560
2561
        // Load the location service
2562
        $locationService = $repository->getLocationService();
2563
2564
        // Load location to move
2565
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2566
2567
        // Load new parent location
2568
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2569
2570
        // Hide the target location before we move
2571
        $newParentLocation = $locationService->hideLocation($newParentLocation);
2572
2573
        // Move location from "Home" to "Demo Design"
2574
        $locationService->moveSubtree(
2575
            $locationToMove,
2576
            $newParentLocation
2577
        );
2578
2579
        // Load moved location
2580
        $movedLocation = $locationService->loadLocation($mediaLocationId);
2581
        /* END: Use Case */
2582
2583
        $this->assertPropertiesCorrect(
2584
            [
2585
                'hidden' => false,
2586
                'invisible' => true,
2587
                'depth' => $newParentLocation->depth + 1,
2588
                'parentLocationId' => $newParentLocation->id,
2589
                'pathString' => $newParentLocation->pathString . $this->parseId('location', $movedLocation->id) . '/',
2590
            ],
2591
            $movedLocation
2592
        );
2593
    }
2594
2595
    /**
2596
     * Test for the moveSubtree() method.
2597
     *
2598
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2599
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2600
     */
2601
    public function testMoveSubtreeUpdatesSubtreeProperties()
2602
    {
2603
        $repository = $this->getRepository();
2604
        $locationService = $repository->getLocationService();
2605
2606
        $locationToMove = $locationService->loadLocation($this->generateId('location', 43));
2607
        $newParentLocation = $locationService->loadLocation($this->generateId('location', 56));
2608
2609
        // Load Subtree properties before move
2610
        $expected = $this->loadSubtreeProperties($locationToMove);
2611
        foreach ($expected as $id => $properties) {
2612
            $expected[$id]['depth'] = $properties['depth'] + 2;
2613
            $expected[$id]['pathString'] = str_replace(
2614
                $locationToMove->pathString,
2615
                $newParentLocation->pathString . $this->parseId('location', $locationToMove->id) . '/',
2616
                $properties['pathString']
2617
            );
2618
        }
2619
2620
        $mediaLocationId = $this->generateId('location', 43);
2621
        $demoDesignLocationId = $this->generateId('location', 56);
2622
        /* BEGIN: Use Case */
2623
        // $mediaLocationId is the ID of the "Media" page location in
2624
        // an eZ Publish demo installation
2625
2626
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2627
        // Publish demo installation
2628
2629
        // Load the location service
2630
        $locationService = $repository->getLocationService();
2631
2632
        // Load location to move
2633
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2634
2635
        // Load new parent location
2636
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2637
2638
        // Move location from "Home" to "Demo Design"
2639
        $locationService->moveSubtree(
2640
            $locationToMove,
2641
            $newParentLocation
2642
        );
2643
2644
        // Load moved location
2645
        $movedLocation = $locationService->loadLocation($mediaLocationId);
2646
        /* END: Use Case */
2647
2648
        $this->refreshSearch($repository);
2649
2650
        // Load Subtree properties after move
2651
        $actual = $this->loadSubtreeProperties($movedLocation);
2652
2653
        $this->assertEquals($expected, $actual);
2654
    }
2655
2656
    /**
2657
     * Test for the moveSubtree() method.
2658
     *
2659
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2660
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtreeUpdatesSubtreeProperties
2661
     */
2662
    public function testMoveSubtreeUpdatesSubtreePropertiesHidden()
2663
    {
2664
        $repository = $this->getRepository();
2665
        $locationService = $repository->getLocationService();
2666
2667
        $locationToMove = $locationService->loadLocation($this->generateId('location', 43));
2668
        $newParentLocation = $locationService->loadLocation($this->generateId('location', 56));
2669
2670
        // Hide the target location before we move
2671
        $newParentLocation = $locationService->hideLocation($newParentLocation);
2672
2673
        // Load Subtree properties before move
2674
        $expected = $this->loadSubtreeProperties($locationToMove);
2675
        foreach ($expected as $id => $properties) {
2676
            $expected[$id]['invisible'] = true;
2677
            $expected[$id]['depth'] = $properties['depth'] + 2;
2678
            $expected[$id]['pathString'] = str_replace(
2679
                $locationToMove->pathString,
2680
                $newParentLocation->pathString . $this->parseId('location', $locationToMove->id) . '/',
2681
                $properties['pathString']
2682
            );
2683
        }
2684
2685
        $mediaLocationId = $this->generateId('location', 43);
2686
        $demoDesignLocationId = $this->generateId('location', 56);
2687
        /* BEGIN: Use Case */
2688
        // $mediaLocationId is the ID of the "Media" page location in
2689
        // an eZ Publish demo installation
2690
2691
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2692
        // Publish demo installation
2693
2694
        // Load the location service
2695
        $locationService = $repository->getLocationService();
2696
2697
        // Load location to move
2698
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2699
2700
        // Load new parent location
2701
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2702
2703
        // Move location from "Home" to "Demo Design"
2704
        $locationService->moveSubtree(
2705
            $locationToMove,
2706
            $newParentLocation
2707
        );
2708
2709
        // Load moved location
2710
        $movedLocation = $locationService->loadLocation($mediaLocationId);
2711
        /* END: Use Case */
2712
2713
        $this->refreshSearch($repository);
2714
2715
        // Load Subtree properties after move
2716
        $actual = $this->loadSubtreeProperties($movedLocation);
2717
2718
        $this->assertEquals($expected, $actual);
2719
    }
2720
2721
    /**
2722
     * Test for the moveSubtree() method.
2723
     *
2724
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2725
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2726
     */
2727 View Code Duplication
    public function testMoveSubtreeIncrementsChildCountOfNewParent()
2728
    {
2729
        $repository = $this->getRepository();
2730
        $locationService = $repository->getLocationService();
2731
2732
        $newParentLocation = $locationService->loadLocation($this->generateId('location', 56));
2733
2734
        // Load expected properties before move
2735
        $expected = $this->loadLocationProperties($newParentLocation);
2736
        $childCountBefore = $locationService->getLocationChildCount($newParentLocation);
2737
2738
        $mediaLocationId = $this->generateId('location', 43);
2739
        $demoDesignLocationId = $this->generateId('location', 56);
2740
        /* BEGIN: Use Case */
2741
        // $mediaLocationId is the ID of the "Media" page location in
2742
        // an eZ Publish demo installation
2743
2744
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2745
        // Publish demo installation
2746
2747
        // Load the location service
2748
        $locationService = $repository->getLocationService();
2749
2750
        // Load location to move
2751
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2752
2753
        // Load new parent location
2754
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2755
2756
        // Move location from "Home" to "Demo Design"
2757
        $locationService->moveSubtree(
2758
            $locationToMove,
2759
            $newParentLocation
2760
        );
2761
2762
        // Load moved location
2763
        $movedLocation = $locationService->loadLocation($mediaLocationId);
0 ignored issues
show
Unused Code introduced by
$movedLocation 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...
2764
2765
        // Reload new parent location
2766
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2767
        /* END: Use Case */
2768
2769
        $this->refreshSearch($repository);
2770
2771
        // Load Subtree properties after move
2772
        $actual = $this->loadLocationProperties($newParentLocation);
2773
        $childCountAfter = $locationService->getLocationChildCount($newParentLocation);
2774
2775
        $this->assertEquals($expected, $actual);
2776
        $this->assertEquals($childCountBefore + 1, $childCountAfter);
2777
    }
2778
2779
    /**
2780
     * Test for the moveSubtree() method.
2781
     *
2782
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2783
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2784
     */
2785 View Code Duplication
    public function testMoveSubtreeDecrementsChildCountOfOldParent()
2786
    {
2787
        $repository = $this->getRepository();
2788
        $locationService = $repository->getLocationService();
2789
2790
        $oldParentLocation = $locationService->loadLocation($this->generateId('location', 1));
2791
2792
        // Load expected properties before move
2793
        $expected = $this->loadLocationProperties($oldParentLocation);
2794
        $childCountBefore = $locationService->getLocationChildCount($oldParentLocation);
2795
2796
        $mediaLocationId = $this->generateId('location', 43);
2797
        $demoDesignLocationId = $this->generateId('location', 56);
2798
        /* BEGIN: Use Case */
2799
        // $mediaLocationId is the ID of the "Media" page location in
2800
        // an eZ Publish demo installation
2801
2802
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2803
        // Publish demo installation
2804
2805
        // Load the location service
2806
        $locationService = $repository->getLocationService();
2807
2808
        // Load location to move
2809
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2810
2811
        // Get the location id of the old parent
2812
        $oldParentLocationId = $locationToMove->parentLocationId;
2813
2814
        // Load new parent location
2815
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2816
2817
        // Move location from "Home" to "Demo Design"
2818
        $locationService->moveSubtree(
2819
            $locationToMove,
2820
            $newParentLocation
2821
        );
2822
2823
        // Reload old parent location
2824
        $oldParentLocation = $locationService->loadLocation($oldParentLocationId);
2825
        /* END: Use Case */
2826
2827
        $this->refreshSearch($repository);
2828
2829
        // Load Subtree properties after move
2830
        $actual = $this->loadLocationProperties($oldParentLocation);
2831
        $childCountAfter = $locationService->getLocationChildCount($oldParentLocation);
2832
2833
        $this->assertEquals($expected, $actual);
2834
        $this->assertEquals($childCountBefore - 1, $childCountAfter);
2835
    }
2836
2837
    /**
2838
     * Test moving invisible (hidden by parent) subtree.
2839
     *
2840
     * @covers \eZ\Publish\API\Repository\LocationService::moveSubtree
2841
     *
2842
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
2843
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
2844
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
2845
     */
2846
    public function testMoveInvisibleSubtree()
2847
    {
2848
        $repository = $this->getRepository();
2849
        $locationService = $repository->getLocationService();
2850
2851
        $rootLocationId = 2;
2852
2853
        $folder = $this->createFolder(['eng-GB' => 'Folder'], $rootLocationId);
2854
        $child = $this->createFolder(['eng-GB' => 'Child'], $folder->contentInfo->mainLocationId);
2855
        $locationService->hideLocation(
2856
            $locationService->loadLocation($folder->contentInfo->mainLocationId)
2857
        );
2858
        // sanity check
2859
        $childLocation = $locationService->loadLocation($child->contentInfo->mainLocationId);
2860
        self::assertFalse($childLocation->hidden);
2861
        self::assertTrue($childLocation->invisible);
2862
        self::assertEquals($folder->contentInfo->mainLocationId, $childLocation->parentLocationId);
2863
2864
        $destination = $this->createFolder(['eng-GB' => 'Destination'], $rootLocationId);
2865
        $destinationLocation = $locationService->loadLocation(
2866
            $destination->contentInfo->mainLocationId
2867
        );
2868
2869
        $locationService->moveSubtree($childLocation, $destinationLocation);
2870
2871
        $childLocation = $locationService->loadLocation($child->contentInfo->mainLocationId);
2872
        // Business logic - Location moved to visible parent becomes visible
2873
        self::assertFalse($childLocation->hidden);
2874
        self::assertFalse($childLocation->invisible);
2875
        self::assertEquals($destinationLocation->id, $childLocation->parentLocationId);
2876
    }
2877
2878
    /**
2879
     * Test for the moveSubtree() method.
2880
     *
2881
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2882
     */
2883
    public function testMoveSubtreeThrowsInvalidArgumentException()
2884
    {
2885
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
2886
2887
        $repository = $this->getRepository();
2888
        $mediaLocationId = $this->generateId('location', 43);
2889
        $multimediaLocationId = $this->generateId('location', 53);
2890
2891
        /* BEGIN: Use Case */
2892
        // $mediaLocationId is the ID of the "Media" page location in
2893
        // an eZ Publish demo installation
2894
2895
        // $multimediaLocationId is the ID of the "Multimedia" page location in an eZ
2896
        // Publish demo installation
2897
2898
        // Load the location service
2899
        $locationService = $repository->getLocationService();
2900
2901
        // Load location to move
2902
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2903
2904
        // Load new parent location
2905
        $newParentLocation = $locationService->loadLocation($multimediaLocationId);
2906
2907
        // Throws an exception because new parent location is placed below location to move
2908
        $locationService->moveSubtree(
2909
            $locationToMove,
2910
            $newParentLocation
2911
        );
2912
        /* END: Use Case */
2913
    }
2914
2915
    /**
2916
     * Test that Legacy ezcontentobject_tree.path_identification_string field is correctly updated
2917
     * after moving subtree.
2918
     *
2919
     * @covers \eZ\Publish\API\Repository\LocationService::moveSubtree
2920
     *
2921
     * @throws \ErrorException
2922
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
2923
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
2924
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
2925
     */
2926
    public function testMoveSubtreeUpdatesPathIdentificationString(): void
2927
    {
2928
        $repository = $this->getRepository();
2929
        $locationService = $repository->getLocationService();
2930
2931
        $topNode = $this->createFolder(['eng-US' => 'top_node'], 2);
2932
2933
        $newParentLocation = $locationService->loadLocation(
2934
            $this
2935
                ->createFolder(['eng-US' => 'Parent'], $topNode->contentInfo->mainLocationId)
2936
                ->contentInfo
2937
                ->mainLocationId
2938
        );
2939
        $location = $locationService->loadLocation(
2940
            $this
2941
                ->createFolder(['eng-US' => 'Move Me'], $topNode->contentInfo->mainLocationId)
2942
                ->contentInfo
2943
                ->mainLocationId
2944
        );
2945
2946
        $locationService->moveSubtree($location, $newParentLocation);
2947
2948
        // path location string is not present on API level, so we need to query database
2949
        $serviceContainer = $this->getSetupFactory()->getServiceContainer();
2950
        /** @var \Doctrine\DBAL\Connection $connection */
2951
        $connection = $serviceContainer->get('ezpublish.persistence.connection');
2952
        $query = $connection->createQueryBuilder();
2953
        $query
2954
            ->select('path_identification_string')
2955
            ->from('ezcontentobject_tree')
2956
            ->where('node_id = :nodeId')
2957
            ->setParameter('nodeId', $location->id);
2958
2959
        self::assertEquals(
2960
            'top_node/parent/move_me',
2961
            $query->execute()->fetchColumn()
2962
        );
2963
    }
2964
2965
    /**
2966
     * Loads properties from all locations in the $location's subtree.
2967
     *
2968
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
2969
     * @param array $properties
2970
     *
2971
     * @return array
2972
     */
2973
    private function loadSubtreeProperties(Location $location, array $properties = [])
2974
    {
2975
        $locationService = $this->getRepository()->getLocationService();
2976
2977
        foreach ($locationService->loadLocationChildren($location)->locations as $childLocation) {
2978
            $properties[] = $this->loadLocationProperties($childLocation);
2979
2980
            $properties = $this->loadSubtreeProperties($childLocation, $properties);
2981
        }
2982
2983
        return $properties;
2984
    }
2985
2986
    /**
2987
     * Loads assertable properties from the given location.
2988
     *
2989
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
2990
     * @param mixed[] $overwrite
2991
     *
2992
     * @return array
2993
     */
2994
    private function loadLocationProperties(Location $location, array $overwrite = [])
2995
    {
2996
        return array_merge(
2997
            [
2998
                'id' => $location->id,
2999
                'depth' => $location->depth,
3000
                'parentLocationId' => $location->parentLocationId,
3001
                'pathString' => $location->pathString,
3002
                'remoteId' => $location->remoteId,
3003
                'hidden' => $location->hidden,
3004
                'invisible' => $location->invisible,
3005
                'priority' => $location->priority,
3006
                'sortField' => $location->sortField,
3007
                'sortOrder' => $location->sortOrder,
3008
            ],
3009
            $overwrite
3010
        );
3011
    }
3012
3013
    /**
3014
     * Assert generated aliases to expected alias return.
3015
     *
3016
     * @param \eZ\Publish\API\Repository\URLAliasService $urlAliasService
3017
     * @param array $expectedAliases
3018
     */
3019
    protected function assertGeneratedAliases($urlAliasService, array $expectedAliases)
3020
    {
3021
        foreach ($expectedAliases as $expectedAlias) {
3022
            $urlAlias = $urlAliasService->lookup($expectedAlias);
3023
            $this->assertPropertiesCorrect(['type' => 0], $urlAlias);
3024
        }
3025
    }
3026
3027
    /**
3028
     * @param \eZ\Publish\API\Repository\URLAliasService $urlAliasService
3029
     * @param array $expectedSubItemAliases
3030
     */
3031
    private function assertAliasesBeforeCopy($urlAliasService, array $expectedSubItemAliases)
3032
    {
3033
        foreach ($expectedSubItemAliases as $aliasUrl) {
3034
            try {
3035
                $urlAliasService->lookup($aliasUrl);
3036
                $this->fail('We didn\'t expect to find alias, but it was found');
3037
            } catch (\Exception $e) {
3038
                $this->assertTrue(true); // OK - alias was not found
3039
            }
3040
        }
3041
    }
3042
3043
    /**
3044
     * Create and publish Content with the given parent Location.
3045
     *
3046
     * @param string $contentName
3047
     * @param int $parentLocationId
3048
     *
3049
     * @return \eZ\Publish\API\Repository\Values\Content\Content published Content
3050
     */
3051 View Code Duplication
    private function publishContentWithParentLocation($contentName, $parentLocationId)
3052
    {
3053
        $repository = $this->getRepository(false);
3054
        $locationService = $repository->getLocationService();
3055
3056
        $contentService = $repository->getContentService();
3057
        $contentTypeService = $repository->getContentTypeService();
3058
3059
        $contentCreateStruct = $contentService->newContentCreateStruct(
3060
            $contentTypeService->loadContentTypeByIdentifier('folder'),
3061
            'eng-US'
3062
        );
3063
        $contentCreateStruct->setField('name', $contentName);
3064
        $contentDraft = $contentService->createContent(
3065
            $contentCreateStruct,
3066
            [
3067
                $locationService->newLocationCreateStruct($parentLocationId),
3068
            ]
3069
        );
3070
3071
        return $contentService->publishVersion($contentDraft->versionInfo);
3072
    }
3073
3074
    /**
3075
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
3076
     */
3077
    private function createForumStruct(string $name): ContentCreateStruct
3078
    {
3079
        $repository = $this->getRepository(false);
3080
3081
        $contentTypeForum = $repository->getContentTypeService()
3082
            ->loadContentTypeByIdentifier('forum');
3083
3084
        $forum = $repository->getContentService()
3085
            ->newContentCreateStruct($contentTypeForum, 'eng-GB');
3086
3087
        $forum->setField('name', $name);
3088
3089
        return $forum;
3090
    }
3091
3092
    private function assertAliasExists(
3093
        string $expectedAliasPath,
3094
        Location $location,
3095
        URLAliasServiceInterface $urlAliasService
3096
    ): void {
3097
        $articleAliasesBeforeDelete = $urlAliasService
3098
            ->listLocationAliases($location);
3099
3100
        $this->assertNotEmpty(
3101
            array_filter(
3102
                $articleAliasesBeforeDelete,
3103
                static function (URLAlias $alias) use ($expectedAliasPath) {
3104
                    return $alias->path === $expectedAliasPath;
3105
                }
3106
            )
3107
        );
3108
    }
3109
}
3110