Completed
Push — 7.5 ( 93f2e7...ee9dfe )
by Łukasz
19:41
created

assertRootLocationStructValues()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

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

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
588
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLocationList(array(5, 442)) on line 585 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...
589
        self::assertEquals([5], array_keys($locations));
590
        self::assertInstanceOf(Location::class, $locations[5]);
591
        self::assertEquals(5, $locations[5]->id);
592
    }
593
594
    /**
595
     * Test for the loadLocationList() method.
596
     *
597
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
598
     * @depends testLoadLocationList
599
     */
600
    public function testLoadLocationListPrioritizedLanguagesFallback(): void
601
    {
602
        $repository = $this->getRepository();
603
604
        $this->createLanguage('pol-PL', 'Polski');
605
606
        // 5 is the ID of an existing location, 442 is a non-existing id
607
        $locationService = $repository->getLocationService();
608
        $locations = $locationService->loadLocationList([5, 442], ['pol-PL'], false);
609
610
        self::assertInternalType('iterable', $locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
611
        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 608 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...
612
    }
613
614
    /**
615
     * Test for the loadLocationList() method.
616
     *
617
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
618
     * @depends testLoadLocationListPrioritizedLanguagesFallback
619
     */
620
    public function testLoadLocationListPrioritizedLanguagesFallbackAndAlwaysAvailable(): void
621
    {
622
        $repository = $this->getRepository();
623
624
        $this->createLanguage('pol-PL', 'Polski');
625
626
        // 5 is the ID of an existing location, 442 is a non-existing id
627
        $locationService = $repository->getLocationService();
628
        $locations = $locationService->loadLocationList([5, 442], ['pol-PL'], true);
629
630
        self::assertInternalType('iterable', $locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
631
        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 628 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...
632
        self::assertEquals([5], array_keys($locations));
633
        self::assertInstanceOf(Location::class, $locations[5]);
634
        self::assertEquals(5, $locations[5]->id);
635
    }
636
637
    /**
638
     * Test for the loadLocationList() method.
639
     *
640
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
641
     */
642 View Code Duplication
    public function testLoadLocationListWithRootLocationId()
643
    {
644
        $repository = $this->getRepository();
645
646
        // 1 is the ID of an root location
647
        $locationService = $repository->getLocationService();
648
        $locations = $locationService->loadLocationList([1]);
649
650
        self::assertInternalType('iterable', $locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
651
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLocationList(array(1)) on line 648 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...
652
        self::assertEquals([1], array_keys($locations));
653
        self::assertInstanceOf(Location::class, $locations[1]);
654
        self::assertEquals(1, $locations[1]->id);
655
    }
656
657
    /**
658
     * Test for the loadLocationByRemoteId() method.
659
     *
660
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationByRemoteId()
661
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
662
     */
663 View Code Duplication
    public function testLoadLocationByRemoteId()
664
    {
665
        $repository = $this->getRepository();
666
667
        /* BEGIN: Use Case */
668
        $locationService = $repository->getLocationService();
669
670
        $location = $locationService->loadLocationByRemoteId(
671
            '3f6d92f8044aed134f32153517850f5a'
672
        );
673
        /* END: Use Case */
674
675
        $this->assertEquals(
676
            $locationService->loadLocation($this->generateId('location', 5)),
677
            $location
678
        );
679
    }
680
681
    /**
682
     * Test for the loadLocationByRemoteId() method.
683
     *
684
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationByRemoteId()
685
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
686
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
687
     */
688
    public function testLoadLocationByRemoteIdThrowsNotFoundException()
689
    {
690
        $repository = $this->getRepository();
691
692
        /* BEGIN: Use Case */
693
        $locationService = $repository->getLocationService();
694
695
        // Throws exception, since Location with remote ID does not exist
696
        $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...
697
            'not-exists'
698
        );
699
        /* END: Use Case */
700
    }
701
702
    /**
703
     * Test for the loadLocations() method.
704
     *
705
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
706
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
707
     */
708
    public function testLoadLocations()
709
    {
710
        $repository = $this->getRepository();
711
712
        $contentId = $this->generateId('object', 4);
713
        /* BEGIN: Use Case */
714
        // $contentId contains the ID of an existing content object
715
        $contentService = $repository->getContentService();
716
        $locationService = $repository->getLocationService();
717
718
        $contentInfo = $contentService->loadContentInfo($contentId);
719
720
        $locations = $locationService->loadLocations($contentInfo);
721
        /* END: Use Case */
722
723
        $this->assertInternalType('array', $locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
724
        self::assertNotEmpty($locations);
725
726
        foreach ($locations as $location) {
727
            self::assertInstanceOf(Location::class, $location);
728
            self::assertEquals($contentInfo->id, $location->getContentInfo()->id);
729
        }
730
731
        return $locations;
732
    }
733
734
    /**
735
     * Test for the loadLocations() method.
736
     *
737
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
738
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
739
     */
740
    public function testLoadLocationsContent(array $locations)
741
    {
742
        $repository = $this->getRepository();
743
        $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...
744
745
        $this->assertEquals(1, count($locations));
746
        foreach ($locations as $loadedLocation) {
747
            $this->assertInstanceOf(
748
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
749
                $loadedLocation
750
            );
751
        }
752
753
        usort(
754
            $locations,
755
            function ($a, $b) {
756
                strcmp($a->id, $b->id);
757
            }
758
        );
759
760
        $this->assertEquals(
761
            [$this->generateId('location', 5)],
762
            array_map(
763
                function (Location $location) {
764
                    return $location->id;
765
                },
766
                $locations
767
            )
768
        );
769
    }
770
771
    /**
772
     * Test for the loadLocations() method.
773
     *
774
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
775
     *
776
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations($contentInfo, $rootLocation)
777
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
778
     */
779
    public function testLoadLocationsLimitedSubtree()
780
    {
781
        $repository = $this->getRepository();
782
783
        $originalLocationId = $this->generateId('location', 54);
784
        $originalParentLocationId = $this->generateId('location', 48);
785
        $newParentLocationId = $this->generateId('location', 43);
786
        /* BEGIN: Use Case */
787
        // $originalLocationId is the ID of an existing location
788
        // $originalParentLocationId is the ID of the parent location of
789
        //     $originalLocationId
790
        // $newParentLocationId is the ID of an existing location outside the tree
791
        // of $originalLocationId and $originalParentLocationId
792
        $locationService = $repository->getLocationService();
793
794
        // Location at "/1/48/54"
795
        $originalLocation = $locationService->loadLocation($originalLocationId);
796
797
        // Create location under "/1/43/"
798
        $locationCreate = $locationService->newLocationCreateStruct($newParentLocationId);
799
        $locationService->createLocation(
800
            $originalLocation->contentInfo,
801
            $locationCreate
802
        );
803
804
        $findRootLocation = $locationService->loadLocation($originalParentLocationId);
805
806
        // Returns an array with only $originalLocation
807
        $locations = $locationService->loadLocations(
808
            $originalLocation->contentInfo,
809
            $findRootLocation
810
        );
811
        /* END: Use Case */
812
813
        $this->assertInternalType('array', $locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
814
815
        return $locations;
816
    }
817
818
    /**
819
     * Test for the loadLocations() method.
820
     *
821
     * @param \eZ\Publish\API\Repository\Values\Content\Location[] $locations
822
     *
823
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
824
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationsLimitedSubtree
825
     */
826
    public function testLoadLocationsLimitedSubtreeContent(array $locations)
827
    {
828
        $this->assertEquals(1, count($locations));
829
830
        $this->assertEquals(
831
            $this->generateId('location', 54),
832
            reset($locations)->id
833
        );
834
    }
835
836
    /**
837
     * Test for the loadLocations() method.
838
     *
839
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
840
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
841
     * @expectedException \eZ\Publish\API\Repository\Exceptions\BadStateException
842
     */
843 View Code Duplication
    public function testLoadLocationsThrowsBadStateException()
844
    {
845
        $repository = $this->getRepository();
846
847
        /* BEGIN: Use Case */
848
        $contentTypeService = $repository->getContentTypeService();
849
        $contentService = $repository->getContentService();
850
        $locationService = $repository->getLocationService();
851
852
        // Create new content, which is not published
853
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
854
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
855
        $contentCreate->setField('name', 'New Folder');
856
        $content = $contentService->createContent($contentCreate);
857
858
        // Throws Exception, since $content has no published version, yet
859
        $locationService->loadLocations(
860
            $content->contentInfo
861
        );
862
        /* END: Use Case */
863
    }
864
865
    /**
866
     * Test for the loadLocations() method.
867
     *
868
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations($contentInfo, $rootLocation)
869
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
870
     * @expectedException \eZ\Publish\API\Repository\Exceptions\BadStateException
871
     */
872
    public function testLoadLocationsThrowsBadStateExceptionLimitedSubtree()
873
    {
874
        $repository = $this->getRepository();
875
876
        $someLocationId = $this->generateId('location', 2);
877
        /* BEGIN: Use Case */
878
        // $someLocationId is the ID of an existing location
879
        $contentTypeService = $repository->getContentTypeService();
880
        $contentService = $repository->getContentService();
881
        $locationService = $repository->getLocationService();
882
883
        // Create new content, which is not published
884
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
885
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
886
        $contentCreate->setField('name', 'New Folder');
887
        $content = $contentService->createContent($contentCreate);
888
889
        $findRootLocation = $locationService->loadLocation($someLocationId);
890
891
        // Throws Exception, since $content has no published version, yet
892
        $locationService->loadLocations(
893
            $content->contentInfo,
894
            $findRootLocation
895
        );
896
        /* END: Use Case */
897
    }
898
899
    /**
900
     * Test for the loadLocationChildren() method.
901
     *
902
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationChildren
903
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
904
     */
905
    public function testLoadLocationChildren()
906
    {
907
        $repository = $this->getRepository();
908
909
        $locationId = $this->generateId('location', 5);
910
        /* BEGIN: Use Case */
911
        // $locationId is the ID of an existing location
912
        $locationService = $repository->getLocationService();
913
914
        $location = $locationService->loadLocation($locationId);
915
916
        $childLocations = $locationService->loadLocationChildren($location);
917
        /* END: Use Case */
918
919
        $this->assertInstanceOf(LocationList::class, $childLocations);
920
        $this->assertInternalType('array', $childLocations->locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
921
        $this->assertNotEmpty($childLocations->locations);
922
        $this->assertInternalType('int', $childLocations->totalCount);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
923
924
        foreach ($childLocations->locations as $childLocation) {
925
            $this->assertInstanceOf(Location::class, $childLocation);
926
            $this->assertEquals($location->id, $childLocation->parentLocationId);
927
        }
928
929
        return $childLocations;
930
    }
931
932
    /**
933
     * Test loading parent Locations for draft Content.
934
     *
935
     * @covers \eZ\Publish\API\Repository\LocationService::loadParentLocationsForDraftContent
936
     */
937
    public function testLoadParentLocationsForDraftContent()
938
    {
939
        $repository = $this->getRepository();
940
        $locationService = $repository->getLocationService();
941
        $contentService = $repository->getContentService();
942
        $contentTypeService = $repository->getContentTypeService();
943
944
        // prepare locations
945
        $locationCreateStructs = [
946
            $locationService->newLocationCreateStruct(2),
947
            $locationService->newLocationCreateStruct(5),
948
        ];
949
950
        // Create new content
951
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
952
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
953
        $contentCreate->setField('name', 'New Folder');
954
        $contentDraft = $contentService->createContent($contentCreate, $locationCreateStructs);
955
956
        // Test loading parent Locations
957
        $locations = $locationService->loadParentLocationsForDraftContent($contentDraft->versionInfo);
958
959
        self::assertCount(2, $locations);
960
        foreach ($locations as $location) {
961
            // test it is one of the given parent locations
962
            self::assertTrue($location->id === 2 || $location->id === 5);
963
        }
964
965
        return $contentDraft;
966
    }
967
968
    /**
969
     * Test that trying to load parent Locations throws Exception if Content is not a draft.
970
     *
971
     * @depends testLoadParentLocationsForDraftContent
972
     *
973
     * @param \eZ\Publish\API\Repository\Values\Content\Content $contentDraft
974
     */
975
    public function testLoadParentLocationsForDraftContentThrowsBadStateException(Content $contentDraft)
976
    {
977
        $this->expectException(BadStateException::class);
978
        $this->expectExceptionMessageRegExp('/has been already published/');
979
980
        $repository = $this->getRepository(false);
981
        $locationService = $repository->getLocationService();
982
        $contentService = $repository->getContentService();
983
984
        $content = $contentService->publishVersion($contentDraft->versionInfo);
985
986
        $locationService->loadParentLocationsForDraftContent($content->versionInfo);
987
    }
988
989
    /**
990
     * Test for the getLocationChildCount() method.
991
     *
992
     * @see \eZ\Publish\API\Repository\LocationService::getLocationChildCount()
993
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
994
     */
995
    public function testGetLocationChildCount()
996
    {
997
        // $locationId is the ID of an existing location
998
        $locationService = $this->getRepository()->getLocationService();
999
1000
        $this->assertSame(
1001
            5,
1002
            $locationService->getLocationChildCount(
1003
                $locationService->loadLocation($this->generateId('location', 5))
1004
            )
1005
        );
1006
    }
1007
1008
    /**
1009
     * Test for the loadLocationChildren() method.
1010
     *
1011
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren()
1012
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
1013
     */
1014
    public function testLoadLocationChildrenData(LocationList $locations)
1015
    {
1016
        $this->assertEquals(5, count($locations->locations));
1017
        $this->assertEquals(5, $locations->totalCount);
1018
1019
        foreach ($locations->locations as $location) {
1020
            $this->assertInstanceOf(
1021
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1022
                $location
1023
            );
1024
        }
1025
1026
        $this->assertEquals(
1027
            [
1028
                $this->generateId('location', 12),
1029
                $this->generateId('location', 13),
1030
                $this->generateId('location', 14),
1031
                $this->generateId('location', 44),
1032
                $this->generateId('location', 61),
1033
            ],
1034
            array_map(
1035
                function (Location $location) {
1036
                    return $location->id;
1037
                },
1038
                $locations->locations
1039
            )
1040
        );
1041
    }
1042
1043
    /**
1044
     * Test for the loadLocationChildren() method.
1045
     *
1046
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
1047
     *
1048
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset)
1049
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
1050
     */
1051 View Code Duplication
    public function testLoadLocationChildrenWithOffset()
1052
    {
1053
        $repository = $this->getRepository();
1054
1055
        $locationId = $this->generateId('location', 5);
1056
        /* BEGIN: Use Case */
1057
        // $locationId is the ID of an existing location
1058
        $locationService = $repository->getLocationService();
1059
1060
        $location = $locationService->loadLocation($locationId);
1061
1062
        $childLocations = $locationService->loadLocationChildren($location, 2);
1063
        /* END: Use Case */
1064
1065
        $this->assertInstanceOf('\\eZ\\Publish\\API\\Repository\\Values\\Content\\LocationList', $childLocations);
1066
        $this->assertInternalType('array', $childLocations->locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1067
        $this->assertInternalType('int', $childLocations->totalCount);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1068
1069
        return $childLocations;
1070
    }
1071
1072
    /**
1073
     * Test for the loadLocationChildren() method.
1074
     *
1075
     * @param \eZ\Publish\API\Repository\Values\Content\LocationList $locations
1076
     *
1077
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset)
1078
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildrenWithOffset
1079
     */
1080 View Code Duplication
    public function testLoadLocationChildrenDataWithOffset(LocationList $locations)
1081
    {
1082
        $this->assertEquals(3, count($locations->locations));
1083
        $this->assertEquals(5, $locations->totalCount);
1084
1085
        foreach ($locations->locations as $location) {
1086
            $this->assertInstanceOf(
1087
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1088
                $location
1089
            );
1090
        }
1091
1092
        $this->assertEquals(
1093
            [
1094
                $this->generateId('location', 14),
1095
                $this->generateId('location', 44),
1096
                $this->generateId('location', 61),
1097
            ],
1098
            array_map(
1099
                function (Location $location) {
1100
                    return $location->id;
1101
                },
1102
                $locations->locations
1103
            )
1104
        );
1105
    }
1106
1107
    /**
1108
     * Test for the loadLocationChildren() method.
1109
     *
1110
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
1111
     *
1112
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset, $limit)
1113
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
1114
     */
1115 View Code Duplication
    public function testLoadLocationChildrenWithOffsetAndLimit()
1116
    {
1117
        $repository = $this->getRepository();
1118
1119
        $locationId = $this->generateId('location', 5);
1120
        /* BEGIN: Use Case */
1121
        // $locationId is the ID of an existing location
1122
        $locationService = $repository->getLocationService();
1123
1124
        $location = $locationService->loadLocation($locationId);
1125
1126
        $childLocations = $locationService->loadLocationChildren($location, 2, 2);
1127
        /* END: Use Case */
1128
1129
        $this->assertInstanceOf('\\eZ\\Publish\\API\\Repository\\Values\\Content\\LocationList', $childLocations);
1130
        $this->assertInternalType('array', $childLocations->locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1131
        $this->assertInternalType('int', $childLocations->totalCount);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1132
1133
        return $childLocations;
1134
    }
1135
1136
    /**
1137
     * Test for the loadLocationChildren() method.
1138
     *
1139
     * @param \eZ\Publish\API\Repository\Values\Content\Location[] $locations
1140
     *
1141
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset, $limit)
1142
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildrenWithOffsetAndLimit
1143
     */
1144 View Code Duplication
    public function testLoadLocationChildrenDataWithOffsetAndLimit(LocationList $locations)
1145
    {
1146
        $this->assertEquals(2, count($locations->locations));
1147
        $this->assertEquals(5, $locations->totalCount);
1148
1149
        foreach ($locations->locations as $location) {
1150
            $this->assertInstanceOf(
1151
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1152
                $location
1153
            );
1154
        }
1155
1156
        $this->assertEquals(
1157
            [
1158
                $this->generateId('location', 14),
1159
                $this->generateId('location', 44),
1160
            ],
1161
            array_map(
1162
                function (Location $location) {
1163
                    return $location->id;
1164
                },
1165
                $locations->locations
1166
            )
1167
        );
1168
    }
1169
1170
    /**
1171
     * Test for the newLocationUpdateStruct() method.
1172
     *
1173
     * @covers \eZ\Publish\API\Repository\LocationService::newLocationUpdateStruct
1174
     */
1175 View Code Duplication
    public function testNewLocationUpdateStruct()
1176
    {
1177
        $repository = $this->getRepository();
1178
1179
        /* BEGIN: Use Case */
1180
        $locationService = $repository->getLocationService();
1181
1182
        $updateStruct = $locationService->newLocationUpdateStruct();
1183
        /* END: Use Case */
1184
1185
        $this->assertInstanceOf(
1186
            LocationUpdateStruct::class,
1187
            $updateStruct
1188
        );
1189
1190
        $this->assertPropertiesCorrect(
1191
            [
1192
                'priority' => null,
1193
                'remoteId' => null,
1194
                'sortField' => null,
1195
                'sortOrder' => null,
1196
            ],
1197
            $updateStruct
1198
        );
1199
    }
1200
1201
    /**
1202
     * Test for the updateLocation() method.
1203
     *
1204
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1205
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1206
     */
1207
    public function testUpdateLocation()
1208
    {
1209
        $repository = $this->getRepository();
1210
1211
        $originalLocationId = $this->generateId('location', 5);
1212
        /* BEGIN: Use Case */
1213
        // $originalLocationId is the ID of an existing location
1214
        $locationService = $repository->getLocationService();
1215
1216
        $originalLocation = $locationService->loadLocation($originalLocationId);
1217
1218
        $updateStruct = $locationService->newLocationUpdateStruct();
1219
        $updateStruct->priority = 3;
1220
        $updateStruct->remoteId = 'c7adcbf1e96bc29bca28c2d809d0c7ef69272651';
1221
        $updateStruct->sortField = Location::SORT_FIELD_PRIORITY;
1222
        $updateStruct->sortOrder = Location::SORT_ORDER_DESC;
1223
1224
        $updatedLocation = $locationService->updateLocation($originalLocation, $updateStruct);
1225
        /* END: Use Case */
1226
1227
        $this->assertInstanceOf(
1228
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1229
            $updatedLocation
1230
        );
1231
1232
        return [
1233
            'originalLocation' => $originalLocation,
1234
            'updateStruct' => $updateStruct,
1235
            'updatedLocation' => $updatedLocation,
1236
        ];
1237
    }
1238
1239
    /**
1240
     * Test for the updateLocation() method.
1241
     *
1242
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1243
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testUpdateLocation
1244
     */
1245
    public function testUpdateLocationStructValues(array $data)
1246
    {
1247
        $originalLocation = $data['originalLocation'];
1248
        $updateStruct = $data['updateStruct'];
1249
        $updatedLocation = $data['updatedLocation'];
1250
1251
        $this->assertPropertiesCorrect(
1252
            [
1253
                'id' => $originalLocation->id,
1254
                'priority' => $updateStruct->priority,
1255
                'hidden' => $originalLocation->hidden,
1256
                'invisible' => $originalLocation->invisible,
1257
                'remoteId' => $updateStruct->remoteId,
1258
                'contentInfo' => $originalLocation->contentInfo,
1259
                'parentLocationId' => $originalLocation->parentLocationId,
1260
                'pathString' => $originalLocation->pathString,
1261
                'depth' => $originalLocation->depth,
1262
                'sortField' => $updateStruct->sortField,
1263
                'sortOrder' => $updateStruct->sortOrder,
1264
            ],
1265
            $updatedLocation
1266
        );
1267
    }
1268
1269
    /**
1270
     * Test for the updateLocation() method.
1271
     *
1272
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1273
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1274
     */
1275
    public function testUpdateLocationWithSameRemoteId()
1276
    {
1277
        $repository = $this->getRepository();
1278
1279
        $locationId = $this->generateId('location', 5);
1280
        /* BEGIN: Use Case */
1281
        // $locationId and remote ID is the IDs of the same, existing location
1282
        $locationService = $repository->getLocationService();
1283
1284
        $originalLocation = $locationService->loadLocation($locationId);
1285
1286
        $updateStruct = $locationService->newLocationUpdateStruct();
1287
1288
        // Remote ID of an existing location with the same locationId
1289
        $updateStruct->remoteId = $originalLocation->remoteId;
1290
1291
        // Sets one of the properties to be able to confirm location gets updated, here: priority
1292
        $updateStruct->priority = 2;
1293
1294
        $location = $locationService->updateLocation($originalLocation, $updateStruct);
1295
1296
        // Checks that the location was updated
1297
        $this->assertEquals(2, $location->priority);
1298
1299
        // Checks that remoteId remains the same
1300
        $this->assertEquals($originalLocation->remoteId, $location->remoteId);
1301
        /* END: Use Case */
1302
    }
1303
1304
    /**
1305
     * Test for the updateLocation() method.
1306
     *
1307
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1308
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1309
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1310
     */
1311 View Code Duplication
    public function testUpdateLocationThrowsInvalidArgumentException()
1312
    {
1313
        $repository = $this->getRepository();
1314
1315
        $locationId = $this->generateId('location', 5);
1316
        /* BEGIN: Use Case */
1317
        // $locationId and remoteId is the IDs of an existing, but not the same, location
1318
        $locationService = $repository->getLocationService();
1319
1320
        $originalLocation = $locationService->loadLocation($locationId);
1321
1322
        $updateStruct = $locationService->newLocationUpdateStruct();
1323
1324
        // Remote ID of an existing location with a different locationId
1325
        $updateStruct->remoteId = 'f3e90596361e31d496d4026eb624c983';
1326
1327
        // Throws exception, since remote ID is already taken
1328
        $locationService->updateLocation($originalLocation, $updateStruct);
1329
        /* END: Use Case */
1330
    }
1331
1332
    /**
1333
     * Test for the updateLocation() method.
1334
     *
1335
     * @covers \eZ\Publish\API\Repository\LocationService::updateLocation()
1336
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1337
     * @dataProvider dataProviderForOutOfRangeLocationPriority
1338
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1339
     */
1340 View Code Duplication
    public function testUpdateLocationThrowsInvalidArgumentExceptionPriorityIsOutOfRange($priority)
1341
    {
1342
        $repository = $this->getRepository();
1343
1344
        $locationId = $this->generateId('location', 5);
1345
        /* BEGIN: Use Case */
1346
        // $locationId and remoteId is the IDs of an existing, but not the same, location
1347
        $locationService = $repository->getLocationService();
1348
1349
        $originalLocation = $locationService->loadLocation($locationId);
1350
1351
        $updateStruct = $locationService->newLocationUpdateStruct();
1352
1353
        // Priority value is out of range
1354
        $updateStruct->priority = $priority;
1355
1356
        // Throws exception, since remote ID is already taken
1357
        $locationService->updateLocation($originalLocation, $updateStruct);
1358
        /* END: Use Case */
1359
    }
1360
1361
    /**
1362
     * Test for the updateLocation() method.
1363
     * Ref EZP-23302: Update Location fails if no change is performed with the update.
1364
     *
1365
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1366
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1367
     */
1368
    public function testUpdateLocationTwice()
1369
    {
1370
        $repository = $this->getRepository();
1371
1372
        $locationId = $this->generateId('location', 5);
1373
        /* BEGIN: Use Case */
1374
        $locationService = $repository->getLocationService();
1375
        $repository->setCurrentUser($repository->getUserService()->loadUser(14));
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...itory::setCurrentUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::setCurrentUserReference() instead. Sets the current user to the given $user.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1376
1377
        $originalLocation = $locationService->loadLocation($locationId);
1378
1379
        $updateStruct = $locationService->newLocationUpdateStruct();
1380
        $updateStruct->priority = 42;
1381
1382
        $updatedLocation = $locationService->updateLocation($originalLocation, $updateStruct);
1383
1384
        // Repeated update with the same, unchanged struct
1385
        $secondUpdatedLocation = $locationService->updateLocation($updatedLocation, $updateStruct);
1386
        /* END: Use Case */
1387
1388
        $this->assertEquals($updatedLocation->priority, 42);
1389
        $this->assertEquals($secondUpdatedLocation->priority, 42);
1390
    }
1391
1392
    /**
1393
     * Test for the swapLocation() method.
1394
     *
1395
     * @see \eZ\Publish\API\Repository\LocationService::swapLocation()
1396
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1397
     */
1398
    public function testSwapLocation()
1399
    {
1400
        $repository = $this->getRepository();
1401
        $locationService = $repository->getLocationService();
1402
1403
        $mediaLocationId = $this->generateId('location', 43);
1404
        $demoDesignLocationId = $this->generateId('location', 56);
1405
1406
        $mediaContentInfo = $locationService->loadLocation($mediaLocationId)->getContentInfo();
1407
        $demoDesignContentInfo = $locationService->loadLocation($demoDesignLocationId)->getContentInfo();
1408
1409
        /* BEGIN: Use Case */
1410
        // $mediaLocationId is the ID of the "Media" page location in
1411
        // an eZ Publish demo installation
1412
1413
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
1414
        // Publish demo installation
1415
1416
        // Load the location service
1417
        $locationService = $repository->getLocationService();
1418
1419
        $mediaLocation = $locationService->loadLocation($mediaLocationId);
1420
        $demoDesignLocation = $locationService->loadLocation($demoDesignLocationId);
1421
1422
        // Swaps the content referred to by the locations
1423
        $locationService->swapLocation($mediaLocation, $demoDesignLocation);
1424
        /* END: Use Case */
1425
1426
        // Reload Locations, IDs swapped
1427
        $demoDesignLocation = $locationService->loadLocation($mediaLocationId);
1428
        $mediaLocation = $locationService->loadLocation($demoDesignLocationId);
1429
1430
        // Assert Location's Content is updated
1431
        $this->assertEquals(
1432
            $mediaContentInfo->id,
1433
            $mediaLocation->getContentInfo()->id
1434
        );
1435
        $this->assertEquals(
1436
            $demoDesignContentInfo->id,
1437
            $demoDesignLocation->getContentInfo()->id
1438
        );
1439
1440
        // Assert URL aliases are updated
1441
        $this->assertEquals(
1442
            $mediaLocation->id,
1443
            $repository->getURLAliasService()->lookup('/Design/Media')->destination
1444
        );
1445
        $this->assertEquals(
1446
            $demoDesignLocation->id,
1447
            $repository->getURLAliasService()->lookup('/eZ-Publish-Demo-Design-without-demo-content')->destination
1448
        );
1449
    }
1450
1451
    /**
1452
     * Test swapping secondary Location with main Location.
1453
     *
1454
     * @covers \eZ\Publish\API\Repository\LocationService::swapLocation
1455
     *
1456
     * @see https://jira.ez.no/browse/EZP-28663
1457
     *
1458
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1459
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1460
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1461
     *
1462
     * @return int[]
1463
     */
1464
    public function testSwapLocationForMainAndSecondaryLocation(): array
1465
    {
1466
        $repository = $this->getRepository();
1467
        $locationService = $repository->getLocationService();
1468
        $contentService = $repository->getContentService();
1469
1470
        $folder1 = $this->createFolder(['eng-GB' => 'Folder1'], 2);
1471
        $folder2 = $this->createFolder(['eng-GB' => 'Folder2'], 2);
1472
        $folder3 = $this->createFolder(['eng-GB' => 'Folder3'], 2);
1473
1474
        $primaryLocation = $locationService->loadLocation($folder1->contentInfo->mainLocationId);
1475
        $parentLocation = $locationService->loadLocation($folder2->contentInfo->mainLocationId);
1476
        $secondaryLocation = $locationService->createLocation(
1477
            $folder1->contentInfo,
1478
            $locationService->newLocationCreateStruct($parentLocation->id)
1479
        );
1480
1481
        $targetLocation = $locationService->loadLocation($folder3->contentInfo->mainLocationId);
1482
1483
        // perform sanity checks
1484
        $this->assertContentHasExpectedLocations([$primaryLocation, $secondaryLocation], $folder1);
1485
1486
        // begin use case
1487
        $locationService->swapLocation($secondaryLocation, $targetLocation);
1488
1489
        // test results
1490
        $primaryLocation = $locationService->loadLocation($primaryLocation->id);
1491
        $secondaryLocation = $locationService->loadLocation($secondaryLocation->id);
1492
        $targetLocation = $locationService->loadLocation($targetLocation->id);
1493
1494
        self::assertEquals($folder1->id, $primaryLocation->contentInfo->id);
1495
        self::assertEquals($folder1->id, $targetLocation->contentInfo->id);
1496
        self::assertEquals($folder3->id, $secondaryLocation->contentInfo->id);
1497
1498
        $this->assertContentHasExpectedLocations([$primaryLocation, $targetLocation], $folder1);
1499
1500
        self::assertEquals(
1501
            $folder1,
1502
            $contentService->loadContent($folder1->id)
1503
        );
1504
1505
        self::assertEquals(
1506
            $folder2,
1507
            $contentService->loadContent($folder2->id)
1508
        );
1509
1510
        // only in case of Folder 3, main location id changed due to swap
1511
        self::assertEquals(
1512
            $secondaryLocation->id,
1513
            $contentService->loadContent($folder3->id)->contentInfo->mainLocationId
1514
        );
1515
1516
        return [$folder1, $folder2, $folder3];
1517
    }
1518
1519
    /**
1520
     * Compare Ids of expected and loaded Locations for the given Content.
1521
     *
1522
     * @param \eZ\Publish\API\Repository\Values\Content\Location[] $expectedLocations
1523
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
1524
     *
1525
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
1526
     */
1527
    private function assertContentHasExpectedLocations(array $expectedLocations, Content $content)
1528
    {
1529
        $repository = $this->getRepository(false);
1530
        $locationService = $repository->getLocationService();
1531
1532
        $expectedLocationIds = array_map(
1533
            function (Location $location) {
1534
                return (int)$location->id;
1535
            },
1536
            $expectedLocations
1537
        );
1538
1539
        $actualLocationsIds = array_map(
1540
            function (Location $location) {
1541
                return $location->id;
1542
            },
1543
            $locationService->loadLocations($content->contentInfo)
1544
        );
1545
        self::assertCount(count($expectedLocations), $actualLocationsIds);
1546
1547
        // perform unordered equality assertion
1548
        self::assertEquals(
1549
            $expectedLocationIds,
1550
            $actualLocationsIds,
1551
            sprintf(
1552
                'Content %d contains Locations %s, but expected: %s',
1553
                $content->id,
1554
                implode(', ', $actualLocationsIds),
1555
                implode(', ', $expectedLocationIds)
1556
            ),
1557
            0.0,
1558
            10,
1559
            true
1560
        );
1561
    }
1562
1563
    /**
1564
     * @depends testSwapLocationForMainAndSecondaryLocation
1565
     *
1566
     * @param \eZ\Publish\API\Repository\Values\Content\Content[] $contentItems Content items created by testSwapLocationForSecondaryLocation
1567
     *
1568
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1569
     */
1570
    public function testSwapLocationDoesNotCorruptSearchResults(array $contentItems)
1571
    {
1572
        $repository = $this->getRepository(false);
1573
        $searchService = $repository->getSearchService();
1574
1575
        $this->refreshSearch($repository);
1576
1577
        $contentIds = array_map(
1578
            function (Content $content) {
1579
                return $content->id;
1580
            },
1581
            $contentItems
1582
        );
1583
1584
        $query = new Query();
1585
        $query->filter = new Query\Criterion\ContentId($contentIds);
1586
1587
        $searchResult = $searchService->findContent($query);
1588
1589
        self::assertEquals(count($contentItems), $searchResult->totalCount);
1590
        self::assertEquals(
1591
            $searchResult->totalCount,
1592
            count($searchResult->searchHits),
1593
            'Total count of search result hits does not match the actual number of found results'
1594
        );
1595
        $foundContentIds = array_map(
1596
            function (SearchHit $searchHit) {
1597
                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...
1598
            },
1599
            $searchResult->searchHits
1600
        );
1601
        sort($contentIds);
1602
        sort($foundContentIds);
1603
        self::assertSame(
1604
            $contentIds,
1605
            $foundContentIds,
1606
            'Got different than expected Content item Ids'
1607
        );
1608
    }
1609
1610
    /**
1611
     * Test swapping two secondary (non-main) Locations.
1612
     *
1613
     * @covers \eZ\Publish\API\Repository\LocationService::swapLocation
1614
     *
1615
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1616
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1617
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1618
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1619
     */
1620
    public function testSwapLocationForSecondaryLocations()
1621
    {
1622
        $repository = $this->getRepository();
1623
        $locationService = $repository->getLocationService();
1624
        $contentService = $repository->getContentService();
1625
1626
        $folder1 = $this->createFolder(['eng-GB' => 'Folder1'], 2);
1627
        $folder2 = $this->createFolder(['eng-GB' => 'Folder2'], 2);
1628
        $parentFolder1 = $this->createFolder(['eng-GB' => 'Parent1'], 2);
1629
        $parentFolder2 = $this->createFolder(['eng-GB' => 'Parent2'], 2);
1630
1631
        $parentLocation1 = $locationService->loadLocation($parentFolder1->contentInfo->mainLocationId);
1632
        $parentLocation2 = $locationService->loadLocation($parentFolder2->contentInfo->mainLocationId);
1633
        $secondaryLocation1 = $locationService->createLocation(
1634
            $folder1->contentInfo,
1635
            $locationService->newLocationCreateStruct($parentLocation1->id)
1636
        );
1637
        $secondaryLocation2 = $locationService->createLocation(
1638
            $folder2->contentInfo,
1639
            $locationService->newLocationCreateStruct($parentLocation2->id)
1640
        );
1641
1642
        // begin use case
1643
        $locationService->swapLocation($secondaryLocation1, $secondaryLocation2);
1644
1645
        // test results
1646
        $secondaryLocation1 = $locationService->loadLocation($secondaryLocation1->id);
1647
        $secondaryLocation2 = $locationService->loadLocation($secondaryLocation2->id);
1648
1649
        self::assertEquals($folder2->id, $secondaryLocation1->contentInfo->id);
1650
        self::assertEquals($folder1->id, $secondaryLocation2->contentInfo->id);
1651
1652
        self::assertEquals(
1653
            $folder1,
1654
            $contentService->loadContent($folder1->id)
1655
        );
1656
1657
        self::assertEquals(
1658
            $folder2,
1659
            $contentService->loadContent($folder2->id)
1660
        );
1661
    }
1662
1663
    /**
1664
     * Test swapping Main Location of a Content with another one updates Content item Main Location.
1665
     *
1666
     * @covers \eZ\Publish\API\Repository\LocationService::swapLocation
1667
     */
1668
    public function testSwapLocationUpdatesMainLocation()
1669
    {
1670
        $repository = $this->getRepository();
1671
        $locationService = $repository->getLocationService();
1672
        $contentService = $repository->getContentService();
1673
1674
        $mainLocationParentId = 60;
1675
        $secondaryLocationId = 43;
1676
1677
        $publishedContent = $this->publishContentWithParentLocation(
1678
            'Content for Swap Location Test', $mainLocationParentId
1679
        );
1680
1681
        // sanity check
1682
        $mainLocation = $locationService->loadLocation($publishedContent->contentInfo->mainLocationId);
1683
        self::assertEquals($mainLocationParentId, $mainLocation->parentLocationId);
1684
1685
        // load another pre-existing location
1686
        $secondaryLocation = $locationService->loadLocation($secondaryLocationId);
1687
1688
        // swap the Main Location with a secondary one
1689
        $locationService->swapLocation($mainLocation, $secondaryLocation);
1690
1691
        // check if Main Location has been updated
1692
        $mainLocation = $locationService->loadLocation($secondaryLocation->id);
1693
        self::assertEquals($publishedContent->contentInfo->id, $mainLocation->contentInfo->id);
1694
        self::assertEquals($mainLocation->id, $mainLocation->contentInfo->mainLocationId);
1695
1696
        $reloadedContent = $contentService->loadContentByContentInfo($publishedContent->contentInfo);
1697
        self::assertEquals($mainLocation->id, $reloadedContent->contentInfo->mainLocationId);
1698
    }
1699
1700
    /**
1701
     * Test if location swap affects related bookmarks.
1702
     *
1703
     * @covers \eZ\Publish\API\Repository\LocationService::swapLocation
1704
     */
1705
    public function testBookmarksAreSwappedAfterSwapLocation()
1706
    {
1707
        $repository = $this->getRepository();
1708
1709
        $mediaLocationId = $this->generateId('location', 43);
1710
        $demoDesignLocationId = $this->generateId('location', 56);
1711
1712
        /* BEGIN: Use Case */
1713
        $locationService = $repository->getLocationService();
1714
        $bookmarkService = $repository->getBookmarkService();
1715
1716
        $mediaLocation = $locationService->loadLocation($mediaLocationId);
1717
        $demoDesignLocation = $locationService->loadLocation($demoDesignLocationId);
1718
1719
        // Bookmark locations
1720
        $bookmarkService->createBookmark($mediaLocation);
1721
        $bookmarkService->createBookmark($demoDesignLocation);
1722
1723
        $beforeSwap = $bookmarkService->loadBookmarks();
1724
1725
        // Swaps the content referred to by the locations
1726
        $locationService->swapLocation($mediaLocation, $demoDesignLocation);
1727
1728
        $afterSwap = $bookmarkService->loadBookmarks();
1729
        /* END: Use Case */
1730
1731
        $this->assertEquals($beforeSwap->items[0]->id, $afterSwap->items[1]->id);
1732
        $this->assertEquals($beforeSwap->items[1]->id, $afterSwap->items[0]->id);
1733
    }
1734
1735
    /**
1736
     * Test for the hideLocation() method.
1737
     *
1738
     * @see \eZ\Publish\API\Repository\LocationService::hideLocation()
1739
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1740
     */
1741
    public function testHideLocation()
1742
    {
1743
        $repository = $this->getRepository();
1744
1745
        $locationId = $this->generateId('location', 5);
1746
        /* BEGIN: Use Case */
1747
        // $locationId is the ID of an existing location
1748
        $locationService = $repository->getLocationService();
1749
1750
        $visibleLocation = $locationService->loadLocation($locationId);
1751
1752
        $hiddenLocation = $locationService->hideLocation($visibleLocation);
1753
        /* END: Use Case */
1754
1755
        $this->assertInstanceOf(
1756
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1757
            $hiddenLocation
1758
        );
1759
1760
        $this->assertTrue(
1761
            $hiddenLocation->hidden,
1762
            sprintf(
1763
                'Location with ID "%s" not hidden.',
1764
                $hiddenLocation->id
1765
            )
1766
        );
1767
1768
        $this->refreshSearch($repository);
1769
1770
        foreach ($locationService->loadLocationChildren($hiddenLocation)->locations as $child) {
1771
            $this->assertSubtreeProperties(
1772
                ['invisible' => true],
1773
                $child
1774
            );
1775
        }
1776
    }
1777
1778
    /**
1779
     * Assert that $expectedValues are set in the subtree starting at $location.
1780
     *
1781
     * @param array $expectedValues
1782
     * @param Location $location
1783
     */
1784
    protected function assertSubtreeProperties(array $expectedValues, Location $location, $stopId = null)
1785
    {
1786
        $repository = $this->getRepository();
1787
        $locationService = $repository->getLocationService();
1788
1789
        if ($location->id === $stopId) {
1790
            return;
1791
        }
1792
1793
        foreach ($expectedValues as $propertyName => $propertyValue) {
1794
            $this->assertEquals(
1795
                $propertyValue,
1796
                $location->$propertyName
1797
            );
1798
1799
            foreach ($locationService->loadLocationChildren($location)->locations as $child) {
1800
                $this->assertSubtreeProperties($expectedValues, $child);
1801
            }
1802
        }
1803
    }
1804
1805
    /**
1806
     * Test for the unhideLocation() method.
1807
     *
1808
     * @see \eZ\Publish\API\Repository\LocationService::unhideLocation()
1809
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testHideLocation
1810
     */
1811
    public function testUnhideLocation()
1812
    {
1813
        $repository = $this->getRepository();
1814
1815
        $locationId = $this->generateId('location', 5);
1816
        /* BEGIN: Use Case */
1817
        // $locationId is the ID of an existing location
1818
        $locationService = $repository->getLocationService();
1819
1820
        $visibleLocation = $locationService->loadLocation($locationId);
1821
        $hiddenLocation = $locationService->hideLocation($visibleLocation);
1822
1823
        $unHiddenLocation = $locationService->unhideLocation($hiddenLocation);
1824
        /* END: Use Case */
1825
1826
        $this->assertInstanceOf(
1827
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1828
            $unHiddenLocation
1829
        );
1830
1831
        $this->assertFalse(
1832
            $unHiddenLocation->hidden,
1833
            sprintf(
1834
                'Location with ID "%s" not unhidden.',
1835
                $unHiddenLocation->id
1836
            )
1837
        );
1838
1839
        $this->refreshSearch($repository);
1840
1841
        foreach ($locationService->loadLocationChildren($unHiddenLocation)->locations as $child) {
1842
            $this->assertSubtreeProperties(
1843
                ['invisible' => false],
1844
                $child
1845
            );
1846
        }
1847
    }
1848
1849
    /**
1850
     * Test for the unhideLocation() method.
1851
     *
1852
     * @see \eZ\Publish\API\Repository\LocationService::unhideLocation()
1853
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testUnhideLocation
1854
     */
1855
    public function testUnhideLocationNotUnhidesHiddenSubtree()
1856
    {
1857
        $repository = $this->getRepository();
1858
1859
        $higherLocationId = $this->generateId('location', 5);
1860
        $lowerLocationId = $this->generateId('location', 13);
1861
        /* BEGIN: Use Case */
1862
        // $higherLocationId is the ID of a location
1863
        // $lowerLocationId is the ID of a location below $higherLocationId
1864
        $locationService = $repository->getLocationService();
1865
1866
        $higherLocation = $locationService->loadLocation($higherLocationId);
1867
        $hiddenHigherLocation = $locationService->hideLocation($higherLocation);
1868
1869
        $lowerLocation = $locationService->loadLocation($lowerLocationId);
1870
        $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...
1871
1872
        $unHiddenHigherLocation = $locationService->unhideLocation($hiddenHigherLocation);
1873
        /* END: Use Case */
1874
1875
        $this->assertInstanceOf(
1876
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1877
            $unHiddenHigherLocation
1878
        );
1879
1880
        $this->assertFalse(
1881
            $unHiddenHigherLocation->hidden,
1882
            sprintf(
1883
                'Location with ID "%s" not unhidden.',
1884
                $unHiddenHigherLocation->id
1885
            )
1886
        );
1887
1888
        $this->refreshSearch($repository);
1889
1890
        foreach ($locationService->loadLocationChildren($unHiddenHigherLocation)->locations as $child) {
1891
            $this->assertSubtreeProperties(
1892
                ['invisible' => false],
1893
                $child,
1894
                $this->generateId('location', 13)
1895
            );
1896
        }
1897
1898
        $stillHiddenLocation = $locationService->loadLocation($this->generateId('location', 13));
1899
        $this->assertTrue(
1900
            $stillHiddenLocation->hidden,
1901
            sprintf(
1902
                'Hidden sub-location with ID %s accidentally unhidden.',
1903
                $stillHiddenLocation->id
1904
            )
1905
        );
1906
        foreach ($locationService->loadLocationChildren($stillHiddenLocation)->locations as $child) {
1907
            $this->assertSubtreeProperties(
1908
                ['invisible' => true],
1909
                $child
1910
            );
1911
        }
1912
    }
1913
1914
    /**
1915
     * Test for the deleteLocation() method.
1916
     *
1917
     * @see \eZ\Publish\API\Repository\LocationService::deleteLocation()
1918
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1919
     */
1920
    public function testDeleteLocation()
1921
    {
1922
        $repository = $this->getRepository();
1923
1924
        $mediaLocationId = $this->generateId('location', 43);
1925
        /* BEGIN: Use Case */
1926
        // $mediaLocationId is the ID of the location of the
1927
        // "Media" location in an eZ Publish demo installation
1928
        $locationService = $repository->getLocationService();
1929
1930
        $location = $locationService->loadLocation($mediaLocationId);
1931
1932
        $locationService->deleteLocation($location);
1933
        /* END: Use Case */
1934
1935
        try {
1936
            $locationService->loadLocation($mediaLocationId);
1937
            $this->fail("Location $mediaLocationId not deleted.");
1938
        } catch (NotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1939
        }
1940
1941
        // The following IDs are IDs of child locations of $mediaLocationId location
1942
        // ( Media/Images, Media/Files, Media/Multimedia respectively )
1943
        foreach ([51, 52, 53] as $childLocationId) {
1944
            try {
1945
                $locationService->loadLocation($this->generateId('location', $childLocationId));
1946
                $this->fail("Location $childLocationId not deleted.");
1947
            } catch (NotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1948
            }
1949
        }
1950
1951
        // The following IDs are IDs of content below $mediaLocationId location
1952
        // ( Media/Images, Media/Files, Media/Multimedia respectively )
1953
        $contentService = $this->getRepository()->getContentService();
1954
        foreach ([49, 50, 51] as $childContentId) {
1955
            try {
1956
                $contentService->loadContentInfo($this->generateId('object', $childContentId));
1957
                $this->fail("Content $childContentId not deleted.");
1958
            } catch (NotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1959
            }
1960
        }
1961
    }
1962
1963
    /**
1964
     * Test for the deleteLocation() method.
1965
     *
1966
     * @see \eZ\Publish\API\Repository\LocationService::deleteLocation()
1967
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testDeleteLocation
1968
     */
1969
    public function testDeleteLocationDecrementsChildCountOnParent()
1970
    {
1971
        $repository = $this->getRepository();
1972
1973
        $mediaLocationId = $this->generateId('location', 43);
1974
        /* BEGIN: Use Case */
1975
        // $mediaLocationId is the ID of the location of the
1976
        // "Media" location in an eZ Publish demo installation
1977
1978
        $locationService = $repository->getLocationService();
1979
1980
        // Load the current the user group location
1981
        $location = $locationService->loadLocation($mediaLocationId);
1982
1983
        // Load the parent location
1984
        $parentLocation = $locationService->loadLocation(
1985
            $location->parentLocationId
1986
        );
1987
1988
        // Get child count
1989
        $childCountBefore = $locationService->getLocationChildCount($parentLocation);
1990
1991
        // Delete the user group location
1992
        $locationService->deleteLocation($location);
1993
1994
        $this->refreshSearch($repository);
1995
1996
        // Reload parent location
1997
        $parentLocation = $locationService->loadLocation(
1998
            $location->parentLocationId
1999
        );
2000
2001
        // This will be $childCountBefore - 1
2002
        $childCountAfter = $locationService->getLocationChildCount($parentLocation);
2003
        /* END: Use Case */
2004
2005
        $this->assertEquals($childCountBefore - 1, $childCountAfter);
2006
    }
2007
2008
    /**
2009
     * Test for the deleteLocation() method.
2010
     *
2011
     * Related issue: EZP-21904
2012
     *
2013
     * @see \eZ\Publish\API\Repository\LocationService::deleteLocation()
2014
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
2015
     */
2016
    public function testDeleteContentObjectLastLocation()
2017
    {
2018
        $repository = $this->getRepository();
2019
2020
        /* BEGIN: Use case */
2021
        $contentService = $repository->getContentService();
2022
        $locationService = $repository->getLocationService();
2023
        $contentTypeService = $repository->getContentTypeService();
2024
        $urlAliasService = $repository->getURLAliasService();
2025
2026
        // prepare Content object
2027
        $createStruct = $contentService->newContentCreateStruct(
2028
            $contentTypeService->loadContentTypeByIdentifier('folder'),
2029
            'eng-GB'
2030
        );
2031
        $createStruct->setField('name', 'Test folder');
2032
2033
        // creata Content object
2034
        $content = $contentService->publishVersion(
2035
            $contentService->createContent(
2036
                $createStruct,
2037
                [$locationService->newLocationCreateStruct(2)]
2038
            )->versionInfo
2039
        );
2040
2041
        // delete location
2042
        $locationService->deleteLocation(
2043
            $locationService->loadLocation(
2044
                $urlAliasService->lookup('/Test-folder')->destination
2045
            )
2046
        );
2047
2048
        // this should throw a not found exception
2049
        $contentService->loadContent($content->versionInfo->contentInfo->id);
2050
        /* END: Use case*/
2051
    }
2052
2053
    /**
2054
     * Test for the deleteLocation() method.
2055
     *
2056
     * @covers  \eZ\Publish\API\Repository\LocationService::deleteLocation()
2057
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testDeleteLocation
2058
     */
2059
    public function testDeleteLocationDeletesRelatedBookmarks()
2060
    {
2061
        $repository = $this->getRepository();
2062
2063
        $parentLocationId = $this->generateId('location', 43);
2064
        $childLocationId = $this->generateId('location', 53);
2065
2066
        /* BEGIN: Use Case */
2067
        $locationService = $repository->getLocationService();
2068
        $bookmarkService = $repository->getBookmarkService();
2069
2070
        // Load location
2071
        $childLocation = $locationService->loadLocation($childLocationId);
2072
        // Add location to bookmarks
2073
        $bookmarkService->createBookmark($childLocation);
2074
        // Load parent location
2075
        $parentLocation = $locationService->loadLocation($parentLocationId);
2076
        // Delete parent location
2077
        $locationService->deleteLocation($parentLocation);
2078
        /* END: Use Case */
2079
2080
        // Location isn't bookmarked anymore
2081
        foreach ($bookmarkService->loadBookmarks(0, 9999) as $bookmarkedLocation) {
2082
            $this->assertNotEquals($childLocation->id, $bookmarkedLocation->id);
2083
        }
2084
    }
2085
2086
    /**
2087
     * Test for the copySubtree() method.
2088
     *
2089
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2090
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
2091
     */
2092
    public function testCopySubtree()
2093
    {
2094
        $repository = $this->getRepository();
2095
2096
        $mediaLocationId = $this->generateId('location', 43);
2097
        $demoDesignLocationId = $this->generateId('location', 56);
2098
        /* BEGIN: Use Case */
2099
        // $mediaLocationId is the ID of the "Media" page location in
2100
        // an eZ Publish demo installation
2101
2102
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2103
        // Publish demo installation
2104
2105
        // Load the location service
2106
        $locationService = $repository->getLocationService();
2107
2108
        // Load location to copy
2109
        $locationToCopy = $locationService->loadLocation($mediaLocationId);
2110
2111
        // Load new parent location
2112
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2113
2114
        // Copy location "Media" to "Demo Design"
2115
        $copiedLocation = $locationService->copySubtree(
2116
            $locationToCopy,
2117
            $newParentLocation
2118
        );
2119
        /* END: Use Case */
2120
2121
        $this->assertInstanceOf(
2122
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
2123
            $copiedLocation
2124
        );
2125
2126
        $this->assertPropertiesCorrect(
2127
            [
2128
                'depth' => $newParentLocation->depth + 1,
2129
                'parentLocationId' => $newParentLocation->id,
2130
                'pathString' => $newParentLocation->pathString . $this->parseId('location', $copiedLocation->id) . '/',
2131
            ],
2132
            $copiedLocation
2133
        );
2134
2135
        $this->assertDefaultContentStates($copiedLocation->contentInfo);
2136
    }
2137
2138
    /**
2139
     * Test for the copySubtree() method.
2140
     *
2141
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2142
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
2143
     */
2144
    public function testCopySubtreeWithAliases()
2145
    {
2146
        $repository = $this->getRepository();
2147
        $urlAliasService = $repository->getURLAliasService();
2148
2149
        // $mediaLocationId is the ID of the "Media" page location in
2150
        // an eZ Publish demo installation
2151
2152
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2153
        // Publish demo installation
2154
        $mediaLocationId = $this->generateId('location', 43);
2155
        $demoDesignLocationId = $this->generateId('location', 56);
2156
2157
        $locationService = $repository->getLocationService();
2158
        $locationToCopy = $locationService->loadLocation($mediaLocationId);
2159
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2160
2161
        $expectedSubItemAliases = [
2162
            '/Design/Plain-site/Media/Multimedia',
2163
            '/Design/Plain-site/Media/Images',
2164
            '/Design/Plain-site/Media/Files',
2165
        ];
2166
2167
        $this->assertAliasesBeforeCopy($urlAliasService, $expectedSubItemAliases);
2168
2169
        // Copy location "Media" to "Design"
2170
        $locationService->copySubtree(
2171
            $locationToCopy,
2172
            $newParentLocation
2173
        );
2174
2175
        $this->assertGeneratedAliases($urlAliasService, $expectedSubItemAliases);
2176
    }
2177
2178
    /**
2179
     * Asserts that given Content has default ContentStates.
2180
     *
2181
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
2182
     */
2183
    private function assertDefaultContentStates(ContentInfo $contentInfo)
2184
    {
2185
        $repository = $this->getRepository();
2186
        $objectStateService = $repository->getObjectStateService();
2187
2188
        $objectStateGroups = $objectStateService->loadObjectStateGroups();
2189
2190
        foreach ($objectStateGroups as $objectStateGroup) {
2191
            $contentState = $objectStateService->getContentState($contentInfo, $objectStateGroup);
2192
            foreach ($objectStateService->loadObjectStates($objectStateGroup) as $objectState) {
2193
                // Only check the first object state which is the default one.
2194
                $this->assertEquals(
2195
                    $objectState,
2196
                    $contentState
2197
                );
2198
                break;
2199
            }
2200
        }
2201
    }
2202
2203
    /**
2204
     * Test for the copySubtree() method.
2205
     *
2206
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2207
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCopySubtree
2208
     */
2209
    public function testCopySubtreeUpdatesSubtreeProperties()
2210
    {
2211
        $repository = $this->getRepository();
2212
        $locationService = $repository->getLocationService();
2213
2214
        $locationToCopy = $locationService->loadLocation($this->generateId('location', 43));
2215
2216
        // Load Subtree properties before copy
2217
        $expected = $this->loadSubtreeProperties($locationToCopy);
2218
2219
        $mediaLocationId = $this->generateId('location', 43);
2220
        $demoDesignLocationId = $this->generateId('location', 56);
2221
        /* BEGIN: Use Case */
2222
        // $mediaLocationId is the ID of the "Media" page location in
2223
        // an eZ Publish demo installation
2224
2225
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2226
        // Publish demo installation
2227
2228
        // Load the location service
2229
        $locationService = $repository->getLocationService();
2230
2231
        // Load location to copy
2232
        $locationToCopy = $locationService->loadLocation($mediaLocationId);
2233
2234
        // Load new parent location
2235
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2236
2237
        // Copy location "Media" to "Demo Design"
2238
        $copiedLocation = $locationService->copySubtree(
2239
            $locationToCopy,
2240
            $newParentLocation
2241
        );
2242
        /* END: Use Case */
2243
2244
        $beforeIds = [];
2245
        foreach ($expected as $properties) {
2246
            $beforeIds[] = $properties['id'];
2247
        }
2248
2249
        $this->refreshSearch($repository);
2250
2251
        // Load Subtree properties after copy
2252
        $actual = $this->loadSubtreeProperties($copiedLocation);
2253
2254
        $this->assertEquals(count($expected), count($actual));
2255
2256
        foreach ($actual as $properties) {
2257
            $this->assertNotContains($properties['id'], $beforeIds);
2258
            $this->assertStringStartsWith(
2259
                $newParentLocation->pathString . $this->parseId('location', $copiedLocation->id) . '/',
2260
                $properties['pathString']
2261
            );
2262
            $this->assertStringEndsWith(
2263
                '/' . $this->parseId('location', $properties['id']) . '/',
2264
                $properties['pathString']
2265
            );
2266
        }
2267
    }
2268
2269
    /**
2270
     * Test for the copySubtree() method.
2271
     *
2272
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2273
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCopySubtree
2274
     */
2275
    public function testCopySubtreeIncrementsChildCountOfNewParent()
2276
    {
2277
        $repository = $this->getRepository();
2278
        $locationService = $repository->getLocationService();
2279
2280
        $childCountBefore = $locationService->getLocationChildCount($locationService->loadLocation(56));
2281
2282
        $mediaLocationId = $this->generateId('location', 43);
2283
        $demoDesignLocationId = $this->generateId('location', 56);
2284
        /* BEGIN: Use Case */
2285
        // $mediaLocationId is the ID of the "Media" page location in
2286
        // an eZ Publish demo installation
2287
2288
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2289
        // Publish demo installation
2290
2291
        // Load the location service
2292
        $locationService = $repository->getLocationService();
2293
2294
        // Load location to copy
2295
        $locationToCopy = $locationService->loadLocation($mediaLocationId);
2296
2297
        // Load new parent location
2298
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2299
2300
        // Copy location "Media" to "Demo Design"
2301
        $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...
2302
            $locationToCopy,
2303
            $newParentLocation
2304
        );
2305
        /* END: Use Case */
2306
2307
        $this->refreshSearch($repository);
2308
2309
        $childCountAfter = $locationService->getLocationChildCount($locationService->loadLocation($demoDesignLocationId));
2310
2311
        $this->assertEquals($childCountBefore + 1, $childCountAfter);
2312
    }
2313
2314
    /**
2315
     * Test for the copySubtree() method.
2316
     *
2317
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2318
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
2319
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCopySubtree
2320
     */
2321 View Code Duplication
    public function testCopySubtreeThrowsInvalidArgumentException()
2322
    {
2323
        $repository = $this->getRepository();
2324
2325
        $communityLocationId = $this->generateId('location', 5);
2326
        /* BEGIN: Use Case */
2327
        // $communityLocationId is the ID of the "Community" page location in
2328
        // an eZ Publish demo installation
2329
2330
        // Load the location service
2331
        $locationService = $repository->getLocationService();
2332
2333
        // Load location to copy
2334
        $locationToCopy = $locationService->loadLocation($communityLocationId);
2335
2336
        // Use a child as new parent
2337
        $childLocations = $locationService->loadLocationChildren($locationToCopy)->locations;
2338
        $newParentLocation = end($childLocations);
2339
2340
        // This call will fail with an "InvalidArgumentException", because the
2341
        // new parent is a child location of the subtree to copy.
2342
        $locationService->copySubtree(
2343
            $locationToCopy,
2344
            $newParentLocation
0 ignored issues
show
Security Bug introduced by
It seems like $newParentLocation defined by end($childLocations) on line 2338 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...
2345
        );
2346
        /* END: Use Case */
2347
    }
2348
2349
    /**
2350
     * Test for the moveSubtree() method.
2351
     *
2352
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2353
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
2354
     */
2355
    public function testMoveSubtree()
2356
    {
2357
        $repository = $this->getRepository();
2358
2359
        $mediaLocationId = $this->generateId('location', 43);
2360
        $demoDesignLocationId = $this->generateId('location', 56);
2361
        /* BEGIN: Use Case */
2362
        // $mediaLocationId is the ID of the "Media" page location in
2363
        // an eZ Publish demo installation
2364
2365
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2366
        // Publish demo installation
2367
2368
        // Load the location service
2369
        $locationService = $repository->getLocationService();
2370
2371
        // Load location to move
2372
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2373
2374
        // Load new parent location
2375
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2376
2377
        // Move location from "Home" to "Demo Design"
2378
        $locationService->moveSubtree(
2379
            $locationToMove,
2380
            $newParentLocation
2381
        );
2382
2383
        // Load moved location
2384
        $movedLocation = $locationService->loadLocation($mediaLocationId);
2385
        /* END: Use Case */
2386
2387
        $this->assertPropertiesCorrect(
2388
            [
2389
                'hidden' => false,
2390
                'invisible' => false,
2391
                'depth' => $newParentLocation->depth + 1,
2392
                'parentLocationId' => $newParentLocation->id,
2393
                'pathString' => $newParentLocation->pathString . $this->parseId('location', $movedLocation->id) . '/',
2394
            ],
2395
            $movedLocation
2396
        );
2397
    }
2398
2399
    /**
2400
     * Test for the moveSubtree() method.
2401
     *
2402
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2403
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2404
     */
2405
    public function testMoveSubtreeHidden()
2406
    {
2407
        $repository = $this->getRepository();
2408
2409
        $mediaLocationId = $this->generateId('location', 43);
2410
        $demoDesignLocationId = $this->generateId('location', 56);
2411
        /* BEGIN: Use Case */
2412
        // $mediaLocationId is the ID of the "Media" page location in
2413
        // an eZ Publish demo installation
2414
2415
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2416
        // Publish demo installation
2417
2418
        // Load the location service
2419
        $locationService = $repository->getLocationService();
2420
2421
        // Load location to move
2422
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2423
2424
        // Load new parent location
2425
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2426
2427
        // Hide the target location before we move
2428
        $newParentLocation = $locationService->hideLocation($newParentLocation);
2429
2430
        // Move location from "Home" to "Demo Design"
2431
        $locationService->moveSubtree(
2432
            $locationToMove,
2433
            $newParentLocation
2434
        );
2435
2436
        // Load moved location
2437
        $movedLocation = $locationService->loadLocation($mediaLocationId);
2438
        /* END: Use Case */
2439
2440
        $this->assertPropertiesCorrect(
2441
            [
2442
                'hidden' => false,
2443
                'invisible' => true,
2444
                'depth' => $newParentLocation->depth + 1,
2445
                'parentLocationId' => $newParentLocation->id,
2446
                'pathString' => $newParentLocation->pathString . $this->parseId('location', $movedLocation->id) . '/',
2447
            ],
2448
            $movedLocation
2449
        );
2450
    }
2451
2452
    /**
2453
     * Test for the moveSubtree() method.
2454
     *
2455
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2456
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2457
     */
2458
    public function testMoveSubtreeUpdatesSubtreeProperties()
2459
    {
2460
        $repository = $this->getRepository();
2461
        $locationService = $repository->getLocationService();
2462
2463
        $locationToMove = $locationService->loadLocation($this->generateId('location', 43));
2464
        $newParentLocation = $locationService->loadLocation($this->generateId('location', 56));
2465
2466
        // Load Subtree properties before move
2467
        $expected = $this->loadSubtreeProperties($locationToMove);
2468
        foreach ($expected as $id => $properties) {
2469
            $expected[$id]['depth'] = $properties['depth'] + 2;
2470
            $expected[$id]['pathString'] = str_replace(
2471
                $locationToMove->pathString,
2472
                $newParentLocation->pathString . $this->parseId('location', $locationToMove->id) . '/',
2473
                $properties['pathString']
2474
            );
2475
        }
2476
2477
        $mediaLocationId = $this->generateId('location', 43);
2478
        $demoDesignLocationId = $this->generateId('location', 56);
2479
        /* BEGIN: Use Case */
2480
        // $mediaLocationId is the ID of the "Media" page location in
2481
        // an eZ Publish demo installation
2482
2483
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2484
        // Publish demo installation
2485
2486
        // Load the location service
2487
        $locationService = $repository->getLocationService();
2488
2489
        // Load location to move
2490
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2491
2492
        // Load new parent location
2493
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2494
2495
        // Move location from "Home" to "Demo Design"
2496
        $locationService->moveSubtree(
2497
            $locationToMove,
2498
            $newParentLocation
2499
        );
2500
2501
        // Load moved location
2502
        $movedLocation = $locationService->loadLocation($mediaLocationId);
2503
        /* END: Use Case */
2504
2505
        $this->refreshSearch($repository);
2506
2507
        // Load Subtree properties after move
2508
        $actual = $this->loadSubtreeProperties($movedLocation);
2509
2510
        $this->assertEquals($expected, $actual);
2511
    }
2512
2513
    /**
2514
     * Test for the moveSubtree() method.
2515
     *
2516
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2517
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtreeUpdatesSubtreeProperties
2518
     */
2519
    public function testMoveSubtreeUpdatesSubtreePropertiesHidden()
2520
    {
2521
        $repository = $this->getRepository();
2522
        $locationService = $repository->getLocationService();
2523
2524
        $locationToMove = $locationService->loadLocation($this->generateId('location', 43));
2525
        $newParentLocation = $locationService->loadLocation($this->generateId('location', 56));
2526
2527
        // Hide the target location before we move
2528
        $newParentLocation = $locationService->hideLocation($newParentLocation);
2529
2530
        // Load Subtree properties before move
2531
        $expected = $this->loadSubtreeProperties($locationToMove);
2532
        foreach ($expected as $id => $properties) {
2533
            $expected[$id]['invisible'] = true;
2534
            $expected[$id]['depth'] = $properties['depth'] + 2;
2535
            $expected[$id]['pathString'] = str_replace(
2536
                $locationToMove->pathString,
2537
                $newParentLocation->pathString . $this->parseId('location', $locationToMove->id) . '/',
2538
                $properties['pathString']
2539
            );
2540
        }
2541
2542
        $mediaLocationId = $this->generateId('location', 43);
2543
        $demoDesignLocationId = $this->generateId('location', 56);
2544
        /* BEGIN: Use Case */
2545
        // $mediaLocationId is the ID of the "Media" page location in
2546
        // an eZ Publish demo installation
2547
2548
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2549
        // Publish demo installation
2550
2551
        // Load the location service
2552
        $locationService = $repository->getLocationService();
2553
2554
        // Load location to move
2555
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2556
2557
        // Load new parent location
2558
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2559
2560
        // Move location from "Home" to "Demo Design"
2561
        $locationService->moveSubtree(
2562
            $locationToMove,
2563
            $newParentLocation
2564
        );
2565
2566
        // Load moved location
2567
        $movedLocation = $locationService->loadLocation($mediaLocationId);
2568
        /* END: Use Case */
2569
2570
        $this->refreshSearch($repository);
2571
2572
        // Load Subtree properties after move
2573
        $actual = $this->loadSubtreeProperties($movedLocation);
2574
2575
        $this->assertEquals($expected, $actual);
2576
    }
2577
2578
    /**
2579
     * Test for the moveSubtree() method.
2580
     *
2581
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2582
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2583
     */
2584 View Code Duplication
    public function testMoveSubtreeIncrementsChildCountOfNewParent()
2585
    {
2586
        $repository = $this->getRepository();
2587
        $locationService = $repository->getLocationService();
2588
2589
        $newParentLocation = $locationService->loadLocation($this->generateId('location', 56));
2590
2591
        // Load expected properties before move
2592
        $expected = $this->loadLocationProperties($newParentLocation);
2593
        $childCountBefore = $locationService->getLocationChildCount($newParentLocation);
2594
2595
        $mediaLocationId = $this->generateId('location', 43);
2596
        $demoDesignLocationId = $this->generateId('location', 56);
2597
        /* BEGIN: Use Case */
2598
        // $mediaLocationId is the ID of the "Media" page location in
2599
        // an eZ Publish demo installation
2600
2601
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2602
        // Publish demo installation
2603
2604
        // Load the location service
2605
        $locationService = $repository->getLocationService();
2606
2607
        // Load location to move
2608
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2609
2610
        // Load new parent location
2611
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2612
2613
        // Move location from "Home" to "Demo Design"
2614
        $locationService->moveSubtree(
2615
            $locationToMove,
2616
            $newParentLocation
2617
        );
2618
2619
        // Load moved location
2620
        $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...
2621
2622
        // Reload new parent location
2623
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2624
        /* END: Use Case */
2625
2626
        $this->refreshSearch($repository);
2627
2628
        // Load Subtree properties after move
2629
        $actual = $this->loadLocationProperties($newParentLocation);
2630
        $childCountAfter = $locationService->getLocationChildCount($newParentLocation);
2631
2632
        $this->assertEquals($expected, $actual);
2633
        $this->assertEquals($childCountBefore + 1, $childCountAfter);
2634
    }
2635
2636
    /**
2637
     * Test for the moveSubtree() method.
2638
     *
2639
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2640
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2641
     */
2642 View Code Duplication
    public function testMoveSubtreeDecrementsChildCountOfOldParent()
2643
    {
2644
        $repository = $this->getRepository();
2645
        $locationService = $repository->getLocationService();
2646
2647
        $oldParentLocation = $locationService->loadLocation($this->generateId('location', 1));
2648
2649
        // Load expected properties before move
2650
        $expected = $this->loadLocationProperties($oldParentLocation);
2651
        $childCountBefore = $locationService->getLocationChildCount($oldParentLocation);
2652
2653
        $mediaLocationId = $this->generateId('location', 43);
2654
        $demoDesignLocationId = $this->generateId('location', 56);
2655
        /* BEGIN: Use Case */
2656
        // $mediaLocationId is the ID of the "Media" page location in
2657
        // an eZ Publish demo installation
2658
2659
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2660
        // Publish demo installation
2661
2662
        // Load the location service
2663
        $locationService = $repository->getLocationService();
2664
2665
        // Load location to move
2666
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2667
2668
        // Get the location id of the old parent
2669
        $oldParentLocationId = $locationToMove->parentLocationId;
2670
2671
        // Load new parent location
2672
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2673
2674
        // Move location from "Home" to "Demo Design"
2675
        $locationService->moveSubtree(
2676
            $locationToMove,
2677
            $newParentLocation
2678
        );
2679
2680
        // Reload old parent location
2681
        $oldParentLocation = $locationService->loadLocation($oldParentLocationId);
2682
        /* END: Use Case */
2683
2684
        $this->refreshSearch($repository);
2685
2686
        // Load Subtree properties after move
2687
        $actual = $this->loadLocationProperties($oldParentLocation);
2688
        $childCountAfter = $locationService->getLocationChildCount($oldParentLocation);
2689
2690
        $this->assertEquals($expected, $actual);
2691
        $this->assertEquals($childCountBefore - 1, $childCountAfter);
2692
    }
2693
2694
    /**
2695
     * Test moving invisible (hidden by parent) subtree.
2696
     *
2697
     * @covers \eZ\Publish\API\Repository\LocationService::moveSubtree
2698
     *
2699
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
2700
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
2701
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
2702
     */
2703
    public function testMoveInvisibleSubtree()
2704
    {
2705
        $repository = $this->getRepository();
2706
        $locationService = $repository->getLocationService();
2707
2708
        $rootLocationId = 2;
2709
2710
        $folder = $this->createFolder(['eng-GB' => 'Folder'], $rootLocationId);
2711
        $child = $this->createFolder(['eng-GB' => 'Child'], $folder->contentInfo->mainLocationId);
2712
        $locationService->hideLocation(
2713
            $locationService->loadLocation($folder->contentInfo->mainLocationId)
2714
        );
2715
        // sanity check
2716
        $childLocation = $locationService->loadLocation($child->contentInfo->mainLocationId);
2717
        self::assertFalse($childLocation->hidden);
2718
        self::assertTrue($childLocation->invisible);
2719
        self::assertEquals($folder->contentInfo->mainLocationId, $childLocation->parentLocationId);
2720
2721
        $destination = $this->createFolder(['eng-GB' => 'Destination'], $rootLocationId);
2722
        $destinationLocation = $locationService->loadLocation(
2723
            $destination->contentInfo->mainLocationId
2724
        );
2725
2726
        $locationService->moveSubtree($childLocation, $destinationLocation);
2727
2728
        $childLocation = $locationService->loadLocation($child->contentInfo->mainLocationId);
2729
        // Business logic - Location moved to visible parent becomes visible
2730
        self::assertFalse($childLocation->hidden);
2731
        self::assertFalse($childLocation->invisible);
2732
        self::assertEquals($destinationLocation->id, $childLocation->parentLocationId);
2733
    }
2734
2735
    /**
2736
     * Test for the moveSubtree() method.
2737
     *
2738
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2739
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
2740
     */
2741 View Code Duplication
    public function testMoveSubtreeThrowsInvalidArgumentException()
2742
    {
2743
        $repository = $this->getRepository();
2744
        $mediaLocationId = $this->generateId('location', 43);
2745
        $multimediaLocationId = $this->generateId('location', 53);
2746
2747
        /* BEGIN: Use Case */
2748
        // $mediaLocationId is the ID of the "Media" page location in
2749
        // an eZ Publish demo installation
2750
2751
        // $multimediaLocationId is the ID of the "Multimedia" page location in an eZ
2752
        // Publish demo installation
2753
2754
        // Load the location service
2755
        $locationService = $repository->getLocationService();
2756
2757
        // Load location to move
2758
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2759
2760
        // Load new parent location
2761
        $newParentLocation = $locationService->loadLocation($multimediaLocationId);
2762
2763
        // Throws an exception because new parent location is placed below location to move
2764
        $locationService->moveSubtree(
2765
            $locationToMove,
2766
            $newParentLocation
2767
        );
2768
        /* END: Use Case */
2769
    }
2770
2771
    /**
2772
     * Test that Legacy ezcontentobject_tree.path_identification_string field is correctly updated
2773
     * after moving subtree.
2774
     *
2775
     * @covers \eZ\Publish\API\Repository\LocationService::moveSubtree
2776
     *
2777
     * @throws \ErrorException
2778
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
2779
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
2780
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
2781
     */
2782
    public function testMoveSubtreeUpdatesPathIdentificationString(): void
2783
    {
2784
        $repository = $this->getRepository();
2785
        $locationService = $repository->getLocationService();
2786
2787
        $topNode = $this->createFolder(['eng-US' => 'top_node'], 2);
2788
2789
        $newParentLocation = $locationService->loadLocation(
2790
            $this
2791
                ->createFolder(['eng-US' => 'Parent'], $topNode->contentInfo->mainLocationId)
2792
                ->contentInfo
2793
                ->mainLocationId
2794
        );
2795
        $location = $locationService->loadLocation(
2796
            $this
2797
                ->createFolder(['eng-US' => 'Move Me'], $topNode->contentInfo->mainLocationId)
2798
                ->contentInfo
2799
                ->mainLocationId
2800
        );
2801
2802
        $locationService->moveSubtree($location, $newParentLocation);
2803
2804
        // path location string is not present on API level, so we need to query database
2805
        $serviceContainer = $this->getSetupFactory()->getServiceContainer();
2806
        /** @var \Doctrine\DBAL\Connection $connection */
2807
        $connection = $serviceContainer->get('ezpublish.persistence.connection');
2808
        $query = $connection->createQueryBuilder();
2809
        $query
2810
            ->select('path_identification_string')
2811
            ->from('ezcontentobject_tree')
2812
            ->where('node_id = :nodeId')
2813
            ->setParameter('nodeId', $location->id);
2814
2815
        self::assertEquals(
2816
            'top_node/parent/move_me',
2817
            $query->execute()->fetchColumn()
2818
        );
2819
    }
2820
2821
    /**
2822
     * Loads properties from all locations in the $location's subtree.
2823
     *
2824
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
2825
     * @param array $properties
2826
     *
2827
     * @return array
2828
     */
2829
    private function loadSubtreeProperties(Location $location, array $properties = [])
2830
    {
2831
        $locationService = $this->getRepository()->getLocationService();
2832
2833
        foreach ($locationService->loadLocationChildren($location)->locations as $childLocation) {
2834
            $properties[] = $this->loadLocationProperties($childLocation);
2835
2836
            $properties = $this->loadSubtreeProperties($childLocation, $properties);
2837
        }
2838
2839
        return $properties;
2840
    }
2841
2842
    /**
2843
     * Loads assertable properties from the given location.
2844
     *
2845
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
2846
     * @param mixed[] $overwrite
2847
     *
2848
     * @return array
2849
     */
2850 View Code Duplication
    private function loadLocationProperties(Location $location, array $overwrite = [])
2851
    {
2852
        return array_merge(
2853
            [
2854
                'id' => $location->id,
2855
                'depth' => $location->depth,
2856
                'parentLocationId' => $location->parentLocationId,
2857
                'pathString' => $location->pathString,
2858
                'remoteId' => $location->remoteId,
2859
                'hidden' => $location->hidden,
2860
                'invisible' => $location->invisible,
2861
                'priority' => $location->priority,
2862
                'sortField' => $location->sortField,
2863
                'sortOrder' => $location->sortOrder,
2864
            ],
2865
            $overwrite
2866
        );
2867
    }
2868
2869
    /**
2870
     * Assert generated aliases to expected alias return.
2871
     *
2872
     * @param \eZ\Publish\API\Repository\URLAliasService $urlAliasService
2873
     * @param array $expectedAliases
2874
     */
2875
    protected function assertGeneratedAliases($urlAliasService, array $expectedAliases)
2876
    {
2877
        foreach ($expectedAliases as $expectedAlias) {
2878
            $urlAlias = $urlAliasService->lookup($expectedAlias);
2879
            $this->assertPropertiesCorrect(['type' => 0], $urlAlias);
2880
        }
2881
    }
2882
2883
    /**
2884
     * @param \eZ\Publish\API\Repository\URLAliasService $urlAliasService
2885
     * @param array $expectedSubItemAliases
2886
     */
2887
    private function assertAliasesBeforeCopy($urlAliasService, array $expectedSubItemAliases)
2888
    {
2889
        foreach ($expectedSubItemAliases as $aliasUrl) {
2890
            try {
2891
                $urlAliasService->lookup($aliasUrl);
2892
                $this->fail('We didn\'t expect to find alias, but it was found');
2893
            } catch (\Exception $e) {
2894
                $this->assertTrue(true); // OK - alias was not found
2895
            }
2896
        }
2897
    }
2898
2899
    /**
2900
     * Create and publish Content with the given parent Location.
2901
     *
2902
     * @param string $contentName
2903
     * @param int $parentLocationId
2904
     *
2905
     * @return \eZ\Publish\API\Repository\Values\Content\Content published Content
2906
     */
2907 View Code Duplication
    private function publishContentWithParentLocation($contentName, $parentLocationId)
2908
    {
2909
        $repository = $this->getRepository(false);
2910
        $locationService = $repository->getLocationService();
2911
2912
        $contentService = $repository->getContentService();
2913
        $contentTypeService = $repository->getContentTypeService();
2914
2915
        $contentCreateStruct = $contentService->newContentCreateStruct(
2916
            $contentTypeService->loadContentTypeByIdentifier('folder'),
2917
            'eng-US'
2918
        );
2919
        $contentCreateStruct->setField('name', $contentName);
2920
        $contentDraft = $contentService->createContent(
2921
            $contentCreateStruct,
2922
            [
2923
                $locationService->newLocationCreateStruct($parentLocationId),
2924
            ]
2925
        );
2926
2927
        return $contentService->publishVersion($contentDraft->versionInfo);
2928
    }
2929
}
2930