Completed
Push — EZP-31112-custom-aliases-gone-... ( 9e7d59 )
by
unknown
21:19
created

testSwapLocationCustomAliases()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 42
rs 9.248
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
use eZ\Publish\API\Repository\Values\Content\URLAlias;
23
24
/**
25
 * Test case for operations in the LocationService using in memory storage.
26
 *
27
 * @see eZ\Publish\API\Repository\LocationService
28
 * @group location
29
 */
30
class LocationServiceTest extends BaseTest
31
{
32
    /**
33
     * Test for the newLocationCreateStruct() method.
34
     *
35
     * @return \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct
36
     *
37
     * @see \eZ\Publish\API\Repository\LocationService::newLocationCreateStruct()
38
     */
39
    public function testNewLocationCreateStruct()
40
    {
41
        $repository = $this->getRepository();
42
43
        $parentLocationId = $this->generateId('location', 1);
44
        /* BEGIN: Use Case */
45
        // $parentLocationId is the ID of an existing location
46
        $locationService = $repository->getLocationService();
47
48
        $locationCreate = $locationService->newLocationCreateStruct(
49
            $parentLocationId
50
        );
51
        /* END: Use Case */
52
53
        $this->assertInstanceOf(
54
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\LocationCreateStruct',
55
            $locationCreate
56
        );
57
58
        return $locationCreate;
59
    }
60
61
    /**
62
     * Test for the newLocationCreateStruct() method.
63
     *
64
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct $locationCreate
65
     *
66
     * @see \eZ\Publish\API\Repository\LocationService::newLocationCreateStruct()
67
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
68
     */
69
    public function testNewLocationCreateStructValues(LocationCreateStruct $locationCreate)
70
    {
71
        $this->assertPropertiesCorrect(
72
            [
73
                'priority' => 0,
74
                'hidden' => false,
75
                // remoteId should be initialized with a default value
76
                //'remoteId' => null,
77
                'sortField' => Location::SORT_FIELD_NAME,
78
                'sortOrder' => Location::SORT_ORDER_ASC,
79
                'parentLocationId' => $this->generateId('location', 1),
80
            ],
81
            $locationCreate
82
        );
83
    }
84
85
    /**
86
     * Test for the createLocation() method.
87
     *
88
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
89
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
90
     */
91
    public function testCreateLocation()
92
    {
93
        $repository = $this->getRepository();
94
95
        $contentId = $this->generateId('object', 41);
96
        $parentLocationId = $this->generateId('location', 5);
97
        /* BEGIN: Use Case */
98
        // $contentId is the ID of an existing content object
99
        // $parentLocationId is the ID of an existing location
100
        $contentService = $repository->getContentService();
101
        $locationService = $repository->getLocationService();
102
103
        // ContentInfo for "How to use eZ Publish"
104
        $contentInfo = $contentService->loadContentInfo($contentId);
105
106
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
107
        $locationCreate->priority = 23;
108
        $locationCreate->hidden = true;
109
        $locationCreate->remoteId = 'sindelfingen';
110
        $locationCreate->sortField = Location::SORT_FIELD_NODE_ID;
111
        $locationCreate->sortOrder = Location::SORT_ORDER_DESC;
112
113
        $location = $locationService->createLocation(
114
            $contentInfo,
115
            $locationCreate
116
        );
117
        /* END: Use Case */
118
119
        $this->assertInstanceOf(
120
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
121
            $location
122
        );
123
124
        return [
125
            'locationCreate' => $locationCreate,
126
            'createdLocation' => $location,
127
            'contentInfo' => $contentInfo,
128
            'parentLocation' => $locationService->loadLocation($this->generateId('location', 5)),
129
        ];
130
    }
131
132
    /**
133
     * Test for the createLocation() method.
134
     *
135
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
136
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
137
     */
138
    public function testCreateLocationStructValues(array $data)
139
    {
140
        $locationCreate = $data['locationCreate'];
141
        $createdLocation = $data['createdLocation'];
142
        $contentInfo = $data['contentInfo'];
143
144
        $this->assertPropertiesCorrect(
145
            [
146
                'priority' => $locationCreate->priority,
147
                'hidden' => $locationCreate->hidden,
148
                'invisible' => $locationCreate->hidden,
149
                'remoteId' => $locationCreate->remoteId,
150
                'contentInfo' => $contentInfo,
151
                'parentLocationId' => $locationCreate->parentLocationId,
152
                'pathString' => '/1/5/' . $this->parseId('location', $createdLocation->id) . '/',
153
                'depth' => 2,
154
                'sortField' => $locationCreate->sortField,
155
                'sortOrder' => $locationCreate->sortOrder,
156
            ],
157
            $createdLocation
158
        );
159
160
        $this->assertNotNull($createdLocation->id);
161
    }
162
163
    /**
164
     * Test for the createLocation() method.
165
     *
166
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
167
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
168
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
169
     */
170 View Code Duplication
    public function testCreateLocationThrowsInvalidArgumentExceptionContentAlreadyBelowParent()
171
    {
172
        $repository = $this->getRepository();
173
174
        $contentId = $this->generateId('object', 11);
175
        $parentLocationId = $this->generateId('location', 5);
176
        /* BEGIN: Use Case */
177
        // $contentId is the ID of an existing content object
178
        // $parentLocationId is the ID of an existing location which already
179
        // has the content assigned to one of its descendant locations
180
        $contentService = $repository->getContentService();
181
        $locationService = $repository->getLocationService();
182
183
        // ContentInfo for "How to use eZ Publish"
184
        $contentInfo = $contentService->loadContentInfo($contentId);
185
186
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
187
188
        // Throws exception, since content is already located at "/1/2/107/110/"
189
        $locationService->createLocation(
190
            $contentInfo,
191
            $locationCreate
192
        );
193
        /* END: Use Case */
194
    }
195
196
    /**
197
     * Test for the createLocation() method.
198
     *
199
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
200
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
201
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
202
     */
203 View Code Duplication
    public function testCreateLocationThrowsInvalidArgumentExceptionParentIsSubLocationOfContent()
204
    {
205
        $repository = $this->getRepository();
206
207
        $contentId = $this->generateId('object', 4);
208
        $parentLocationId = $this->generateId('location', 12);
209
        /* BEGIN: Use Case */
210
        // $contentId is the ID of an existing content object
211
        // $parentLocationId is the ID of an existing location which is below a
212
        // location that is assigned to the content
213
        $contentService = $repository->getContentService();
214
        $locationService = $repository->getLocationService();
215
216
        // ContentInfo for "How to use eZ Publish"
217
        $contentInfo = $contentService->loadContentInfo($contentId);
218
219
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
220
221
        // Throws exception, since content is already located at "/1/2/"
222
        $locationService->createLocation(
223
            $contentInfo,
224
            $locationCreate
225
        );
226
        /* END: Use Case */
227
    }
228
229
    /**
230
     * Test for the createLocation() method.
231
     *
232
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
233
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
234
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
235
     */
236 View Code Duplication
    public function testCreateLocationThrowsInvalidArgumentExceptionRemoteIdExists()
237
    {
238
        $repository = $this->getRepository();
239
240
        $contentId = $this->generateId('object', 41);
241
        $parentLocationId = $this->generateId('location', 5);
242
        /* BEGIN: Use Case */
243
        // $contentId is the ID of an existing content object
244
        $contentService = $repository->getContentService();
245
        $locationService = $repository->getLocationService();
246
247
        // ContentInfo for "How to use eZ Publish"
248
        $contentInfo = $contentService->loadContentInfo($contentId);
249
250
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
251
        // This remote ID already exists
252
        $locationCreate->remoteId = 'f3e90596361e31d496d4026eb624c983';
253
254
        // Throws exception, since remote ID is already in use
255
        $locationService->createLocation(
256
            $contentInfo,
257
            $locationCreate
258
        );
259
        /* END: Use Case */
260
    }
261
262
    /**
263
     * Test for the createLocation() method.
264
     *
265
     * @covers \eZ\Publish\API\Repository\LocationService::createLocation()
266
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
267
     * @dataProvider dataProviderForOutOfRangeLocationPriority
268
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
269
     */
270 View Code Duplication
    public function testCreateLocationThrowsInvalidArgumentExceptionPriorityIsOutOfRange($priority)
271
    {
272
        $repository = $this->getRepository();
273
274
        $contentId = $this->generateId('object', 41);
275
        $parentLocationId = $this->generateId('location', 5);
276
        /* BEGIN: Use Case */
277
        // $contentId is the ID of an existing content object
278
        // $parentLocationId is the ID of an existing location
279
        $contentService = $repository->getContentService();
280
        $locationService = $repository->getLocationService();
281
282
        // ContentInfo for "How to use eZ Publish"
283
        $contentInfo = $contentService->loadContentInfo($contentId);
284
285
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
286
        $locationCreate->priority = $priority;
287
        $locationCreate->hidden = true;
288
        $locationCreate->remoteId = 'sindelfingen';
289
        $locationCreate->sortField = Location::SORT_FIELD_NODE_ID;
290
        $locationCreate->sortOrder = Location::SORT_ORDER_DESC;
291
292
        // Throws exception, since priority is out of range
293
        $locationService->createLocation(
294
            $contentInfo,
295
            $locationCreate
296
        );
297
        /* END: Use Case */
298
    }
299
300
    public function dataProviderForOutOfRangeLocationPriority()
301
    {
302
        return [[-2147483649], [2147483648]];
303
    }
304
305
    /**
306
     * Test for the createLocation() method.
307
     *
308
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
309
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
310
     */
311
    public function testCreateLocationInTransactionWithRollback()
312
    {
313
        $repository = $this->getRepository();
314
315
        $contentId = $this->generateId('object', 41);
316
        $parentLocationId = $this->generateId('location', 5);
317
        /* BEGIN: Use Case */
318
        // $contentId is the ID of an existing content object
319
        // $parentLocationId is the ID of an existing location
320
        $contentService = $repository->getContentService();
321
        $locationService = $repository->getLocationService();
322
323
        $repository->beginTransaction();
324
325
        try {
326
            // ContentInfo for "How to use eZ Publish"
327
            $contentInfo = $contentService->loadContentInfo($contentId);
328
329
            $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
330
            $locationCreate->remoteId = 'sindelfingen';
331
332
            $createdLocationId = $locationService->createLocation(
333
                $contentInfo,
334
                $locationCreate
335
            )->id;
336
        } catch (Exception $e) {
337
            // Cleanup hanging transaction on error
338
            $repository->rollback();
339
            throw $e;
340
        }
341
342
        $repository->rollback();
343
344
        try {
345
            // Throws exception since creation of location was rolled back
346
            $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...
347
        } catch (NotFoundException $e) {
348
            return;
349
        }
350
        /* END: Use Case */
351
352
        $this->fail('Objects still exists after rollback.');
353
    }
354
355
    /**
356
     * Test for the loadLocation() method.
357
     *
358
     * @return \eZ\Publish\API\Repository\Values\Content\Location
359
     *
360
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocation
361
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
362
     */
363
    public function testLoadLocation()
364
    {
365
        $repository = $this->getRepository();
366
367
        $locationId = $this->generateId('location', 5);
368
        /* BEGIN: Use Case */
369
        // $locationId is the ID of an existing location
370
        $locationService = $repository->getLocationService();
371
372
        $location = $locationService->loadLocation($locationId);
373
        /* END: Use Case */
374
375
        $this->assertInstanceOf(
376
            Location::class,
377
            $location
378
        );
379
        self::assertEquals(5, $location->id);
380
381
        return $location;
382
    }
383
384
    /**
385
     * Test for the loadLocation() method.
386
     *
387
     * @see \eZ\Publish\API\Repository\LocationService::loadLocation()
388
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
389
     */
390
    public function testLoadLocationRootStructValues()
391
    {
392
        $repository = $this->getRepository();
393
        $locationService = $repository->getLocationService();
394
        $location = $locationService->loadLocation($this->generateId('location', 1));
395
396
        $this->assertRootLocationStructValues($location);
397
    }
398
399
    public function testLoadLocationRootStructValuesWithPrioritizedLanguages(): void
400
    {
401
        $repository = $this->getRepository();
402
403
        $rootLocation = $repository
404
            ->getLocationService()
405
            ->loadLocation(
406
                $this->generateId('location', 1),
407
                [
408
                    'eng-GB',
409
                    'ger-DE',
410
                ]
411
            );
412
413
        $this->assertRootLocationStructValues($rootLocation);
414
    }
415
416
    private function assertRootLocationStructValues(Location $location): void
417
    {
418
        $legacyDateTime = new \DateTime();
419
        $legacyDateTime->setTimestamp(1030968000);
420
421
        $this->assertInstanceOf(Location::class, $location);
422
        $this->assertPropertiesCorrect(
423
            [
424
                'id' => $this->generateId('location', 1),
425
                'status' => 1,
426
                'priority' => 0,
427
                'hidden' => false,
428
                'invisible' => false,
429
                'remoteId' => '629709ba256fe317c3ddcee35453a96a',
430
                'parentLocationId' => $this->generateId('location', 1),
431
                'pathString' => '/1/',
432
                'depth' => 0,
433
                'sortField' => 1,
434
                'sortOrder' => 1,
435
            ],
436
            $location
437
        );
438
439
        $this->assertInstanceOf(ContentInfo::class, $location->contentInfo);
440
        $this->assertPropertiesCorrect(
441
            [
442
                'id' => $this->generateId('content', 0),
443
                'name' => 'Top Level Nodes',
444
                'sectionId' => 1,
445
                'mainLocationId' => 1,
446
                'contentTypeId' => 1,
447
                'currentVersionNo' => 1,
448
                'published' => 1,
449
                'ownerId' => 14,
450
                'modificationDate' => $legacyDateTime,
451
                'publishedDate' => $legacyDateTime,
452
                'alwaysAvailable' => 1,
453
                'remoteId' => null,
454
                'mainLanguageCode' => 'eng-GB',
455
            ],
456
            $location->contentInfo
457
        );
458
    }
459
460
    /**
461
     * Test for the loadLocation() method.
462
     *
463
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
464
     *
465
     * @see \eZ\Publish\API\Repository\LocationService::loadLocation()
466
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
467
     */
468
    public function testLoadLocationStructValues(Location $location)
469
    {
470
        $this->assertPropertiesCorrect(
471
            [
472
                'id' => $this->generateId('location', 5),
473
                'priority' => 0,
474
                'hidden' => false,
475
                'invisible' => false,
476
                'remoteId' => '3f6d92f8044aed134f32153517850f5a',
477
                'parentLocationId' => $this->generateId('location', 1),
478
                'pathString' => '/1/5/',
479
                'depth' => 1,
480
                'sortField' => 1,
481
                'sortOrder' => 1,
482
            ],
483
            $location
484
        );
485
486
        $this->assertInstanceOf(
487
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo',
488
            $location->contentInfo
489
        );
490
        $this->assertEquals($this->generateId('object', 4), $location->contentInfo->id);
491
492
        // Check lazy loaded proxy on ->content
493
        $this->assertInstanceOf(
494
            Content::class,
495
            $content = $location->getContent()
496
        );
497
        $this->assertEquals(4, $content->contentInfo->id);
498
    }
499
500
    public function testLoadLocationPrioritizedLanguagesFallback()
501
    {
502
        $repository = $this->getRepository();
503
504
        // Add a language
505
        $this->createLanguage('nor-NO', 'Norsk');
506
507
        $locationService = $repository->getLocationService();
508
        $contentService = $repository->getContentService();
509
        $location = $locationService->loadLocation(5);
510
511
        // Translate "Users"
512
        $draft = $contentService->createContentDraft($location->contentInfo);
513
        $struct = $contentService->newContentUpdateStruct();
514
        $struct->setField('name', 'Brukere', 'nor-NO');
515
        $draft = $contentService->updateContent($draft->getVersionInfo(), $struct);
516
        $contentService->publishVersion($draft->getVersionInfo());
517
518
        // Load with priority language (fallback will be the old one)
519
        $location = $locationService->loadLocation(5, ['nor-NO']);
520
521
        $this->assertInstanceOf(
522
            Location::class,
523
            $location
524
        );
525
        self::assertEquals(5, $location->id);
526
        $this->assertInstanceOf(
527
            Content::class,
528
            $content = $location->getContent()
529
        );
530
        $this->assertEquals(4, $content->contentInfo->id);
531
532
        $this->assertEquals($content->getVersionInfo()->getName(), 'Brukere');
533
        $this->assertEquals($content->getVersionInfo()->getName('eng-US'), 'Users');
534
    }
535
536
    /**
537
     * Test that accessing lazy-loaded Content without a translation in the specific
538
     * not available language throws NotFoundException.
539
     */
540
    public function testLoadLocationThrowsNotFoundExceptionForNotAvailableContent(): void
541
    {
542
        $repository = $this->getRepository();
543
544
        $locationService = $repository->getLocationService();
545
546
        $this->createLanguage('pol-PL', 'Polski');
547
548
        $this->expectException(NotFoundException::class);
549
550
        // Note: relying on existing database fixtures to make test case more readable
551
        $locationService->loadLocation(60, ['pol-PL']);
552
    }
553
554
    /**
555
     * Test for the loadLocation() method.
556
     *
557
     * @see \eZ\Publish\API\Repository\LocationService::loadLocation()
558
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
559
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
560
     */
561
    public function testLoadLocationThrowsNotFoundException()
562
    {
563
        $repository = $this->getRepository();
564
565
        $nonExistentLocationId = $this->generateId('location', 2342);
566
        /* BEGIN: Use Case */
567
        $locationService = $repository->getLocationService();
568
569
        // Throws exception, if Location with $nonExistentLocationId does not
570
        // exist
571
        $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...
572
        /* END: Use Case */
573
    }
574
575
    /**
576
     * Test for the loadLocationList() method.
577
     *
578
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
579
     */
580 View Code Duplication
    public function testLoadLocationList(): void
581
    {
582
        $repository = $this->getRepository();
583
584
        // 5 is the ID of an existing location, 442 is a non-existing id
585
        $locationService = $repository->getLocationService();
586
        $locations = $locationService->loadLocationList([5, 442]);
587
588
        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...
589
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLocationList(array(5, 442)) on line 586 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...
590
        self::assertEquals([5], array_keys($locations));
591
        self::assertInstanceOf(Location::class, $locations[5]);
592
        self::assertEquals(5, $locations[5]->id);
593
    }
594
595
    /**
596
     * Test for the loadLocationList() method.
597
     *
598
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
599
     * @depends testLoadLocationList
600
     */
601
    public function testLoadLocationListPrioritizedLanguagesFallback(): void
602
    {
603
        $repository = $this->getRepository();
604
605
        $this->createLanguage('pol-PL', 'Polski');
606
607
        // 5 is the ID of an existing location, 442 is a non-existing id
608
        $locationService = $repository->getLocationService();
609
        $locations = $locationService->loadLocationList([5, 442], ['pol-PL'], false);
610
611
        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...
612
        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 609 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...
613
    }
614
615
    /**
616
     * Test for the loadLocationList() method.
617
     *
618
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
619
     * @depends testLoadLocationListPrioritizedLanguagesFallback
620
     */
621
    public function testLoadLocationListPrioritizedLanguagesFallbackAndAlwaysAvailable(): void
622
    {
623
        $repository = $this->getRepository();
624
625
        $this->createLanguage('pol-PL', 'Polski');
626
627
        // 5 is the ID of an existing location, 442 is a non-existing id
628
        $locationService = $repository->getLocationService();
629
        $locations = $locationService->loadLocationList([5, 442], ['pol-PL'], true);
630
631
        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...
632
        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 629 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...
633
        self::assertEquals([5], array_keys($locations));
634
        self::assertInstanceOf(Location::class, $locations[5]);
635
        self::assertEquals(5, $locations[5]->id);
636
    }
637
638
    /**
639
     * Test for the loadLocationList() method.
640
     *
641
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
642
     */
643 View Code Duplication
    public function testLoadLocationListWithRootLocationId()
644
    {
645
        $repository = $this->getRepository();
646
647
        // 1 is the ID of an root location
648
        $locationService = $repository->getLocationService();
649
        $locations = $locationService->loadLocationList([1]);
650
651
        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...
652
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLocationList(array(1)) on line 649 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...
653
        self::assertEquals([1], array_keys($locations));
654
        self::assertInstanceOf(Location::class, $locations[1]);
655
        self::assertEquals(1, $locations[1]->id);
656
    }
657
658
    /**
659
     * Test for the loadLocationList() method.
660
     *
661
     * Ensures the list is returned in the same order as passed IDs array.
662
     *
663
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
664
     */
665
    public function testLoadLocationListInCorrectOrder()
666
    {
667
        $repository = $this->getRepository();
668
        $locationService = $repository->getLocationService();
669
670
        $cachedLocationId = 2;
671
        $locationIdsToLoad = [43, $cachedLocationId, 5];
672
673
        // Call loadLocation to cache it in memory as it might possibly affect list order
674
        $locationService->loadLocation($cachedLocationId);
675
676
        $locations = $locationService->loadLocationList($locationIdsToLoad);
677
        $locationIds = array_column($locations, 'id');
678
679
        self::assertEquals($locationIdsToLoad, $locationIds);
680
    }
681
682
    /**
683
     * Test for the loadLocationByRemoteId() method.
684
     *
685
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationByRemoteId()
686
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
687
     */
688 View Code Duplication
    public function testLoadLocationByRemoteId()
689
    {
690
        $repository = $this->getRepository();
691
692
        /* BEGIN: Use Case */
693
        $locationService = $repository->getLocationService();
694
695
        $location = $locationService->loadLocationByRemoteId(
696
            '3f6d92f8044aed134f32153517850f5a'
697
        );
698
        /* END: Use Case */
699
700
        $this->assertEquals(
701
            $locationService->loadLocation($this->generateId('location', 5)),
702
            $location
703
        );
704
    }
705
706
    /**
707
     * Test for the loadLocationByRemoteId() method.
708
     *
709
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationByRemoteId()
710
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
711
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
712
     */
713
    public function testLoadLocationByRemoteIdThrowsNotFoundException()
714
    {
715
        $repository = $this->getRepository();
716
717
        /* BEGIN: Use Case */
718
        $locationService = $repository->getLocationService();
719
720
        // Throws exception, since Location with remote ID does not exist
721
        $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...
722
            'not-exists'
723
        );
724
        /* END: Use Case */
725
    }
726
727
    /**
728
     * Test for the loadLocations() method.
729
     *
730
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
731
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
732
     */
733
    public function testLoadLocations()
734
    {
735
        $repository = $this->getRepository();
736
737
        $contentId = $this->generateId('object', 4);
738
        /* BEGIN: Use Case */
739
        // $contentId contains the ID of an existing content object
740
        $contentService = $repository->getContentService();
741
        $locationService = $repository->getLocationService();
742
743
        $contentInfo = $contentService->loadContentInfo($contentId);
744
745
        $locations = $locationService->loadLocations($contentInfo);
746
        /* END: Use Case */
747
748
        $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...
749
        self::assertNotEmpty($locations);
750
751
        foreach ($locations as $location) {
752
            self::assertInstanceOf(Location::class, $location);
753
            self::assertEquals($contentInfo->id, $location->getContentInfo()->id);
754
        }
755
756
        return $locations;
757
    }
758
759
    /**
760
     * Test for the loadLocations() method.
761
     *
762
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
763
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
764
     */
765
    public function testLoadLocationsContent(array $locations)
766
    {
767
        $repository = $this->getRepository();
768
        $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...
769
770
        $this->assertEquals(1, count($locations));
771
        foreach ($locations as $loadedLocation) {
772
            $this->assertInstanceOf(
773
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
774
                $loadedLocation
775
            );
776
        }
777
778
        usort(
779
            $locations,
780
            function ($a, $b) {
781
                strcmp($a->id, $b->id);
782
            }
783
        );
784
785
        $this->assertEquals(
786
            [$this->generateId('location', 5)],
787
            array_map(
788
                function (Location $location) {
789
                    return $location->id;
790
                },
791
                $locations
792
            )
793
        );
794
    }
795
796
    /**
797
     * Test for the loadLocations() method.
798
     *
799
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
800
     *
801
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations($contentInfo, $rootLocation)
802
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
803
     */
804
    public function testLoadLocationsLimitedSubtree()
805
    {
806
        $repository = $this->getRepository();
807
808
        $originalLocationId = $this->generateId('location', 54);
809
        $originalParentLocationId = $this->generateId('location', 48);
810
        $newParentLocationId = $this->generateId('location', 43);
811
        /* BEGIN: Use Case */
812
        // $originalLocationId is the ID of an existing location
813
        // $originalParentLocationId is the ID of the parent location of
814
        //     $originalLocationId
815
        // $newParentLocationId is the ID of an existing location outside the tree
816
        // of $originalLocationId and $originalParentLocationId
817
        $locationService = $repository->getLocationService();
818
819
        // Location at "/1/48/54"
820
        $originalLocation = $locationService->loadLocation($originalLocationId);
821
822
        // Create location under "/1/43/"
823
        $locationCreate = $locationService->newLocationCreateStruct($newParentLocationId);
824
        $locationService->createLocation(
825
            $originalLocation->contentInfo,
826
            $locationCreate
827
        );
828
829
        $findRootLocation = $locationService->loadLocation($originalParentLocationId);
830
831
        // Returns an array with only $originalLocation
832
        $locations = $locationService->loadLocations(
833
            $originalLocation->contentInfo,
834
            $findRootLocation
835
        );
836
        /* END: Use Case */
837
838
        $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...
839
840
        return $locations;
841
    }
842
843
    /**
844
     * Test for the loadLocations() method.
845
     *
846
     * @param \eZ\Publish\API\Repository\Values\Content\Location[] $locations
847
     *
848
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
849
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationsLimitedSubtree
850
     */
851
    public function testLoadLocationsLimitedSubtreeContent(array $locations)
852
    {
853
        $this->assertEquals(1, count($locations));
854
855
        $this->assertEquals(
856
            $this->generateId('location', 54),
857
            reset($locations)->id
858
        );
859
    }
860
861
    /**
862
     * Test for the loadLocations() method.
863
     *
864
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
865
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
866
     * @expectedException \eZ\Publish\API\Repository\Exceptions\BadStateException
867
     */
868
    public function testLoadLocationsThrowsBadStateException()
869
    {
870
        $repository = $this->getRepository();
871
872
        /* BEGIN: Use Case */
873
        $contentTypeService = $repository->getContentTypeService();
874
        $contentService = $repository->getContentService();
875
        $locationService = $repository->getLocationService();
876
877
        // Create new content, which is not published
878
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
879
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
880
        $contentCreate->setField('name', 'New Folder');
881
        $content = $contentService->createContent($contentCreate);
882
883
        // Throws Exception, since $content has no published version, yet
884
        $locationService->loadLocations(
885
            $content->contentInfo
886
        );
887
        /* END: Use Case */
888
    }
889
890
    /**
891
     * Test for the loadLocations() method.
892
     *
893
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations($contentInfo, $rootLocation)
894
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
895
     * @expectedException \eZ\Publish\API\Repository\Exceptions\BadStateException
896
     */
897
    public function testLoadLocationsThrowsBadStateExceptionLimitedSubtree()
898
    {
899
        $repository = $this->getRepository();
900
901
        $someLocationId = $this->generateId('location', 2);
902
        /* BEGIN: Use Case */
903
        // $someLocationId is the ID of an existing location
904
        $contentTypeService = $repository->getContentTypeService();
905
        $contentService = $repository->getContentService();
906
        $locationService = $repository->getLocationService();
907
908
        // Create new content, which is not published
909
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
910
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
911
        $contentCreate->setField('name', 'New Folder');
912
        $content = $contentService->createContent($contentCreate);
913
914
        $findRootLocation = $locationService->loadLocation($someLocationId);
915
916
        // Throws Exception, since $content has no published version, yet
917
        $locationService->loadLocations(
918
            $content->contentInfo,
919
            $findRootLocation
920
        );
921
        /* END: Use Case */
922
    }
923
924
    /**
925
     * Test for the loadLocationChildren() method.
926
     *
927
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationChildren
928
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
929
     */
930
    public function testLoadLocationChildren()
931
    {
932
        $repository = $this->getRepository();
933
934
        $locationId = $this->generateId('location', 5);
935
        /* BEGIN: Use Case */
936
        // $locationId is the ID of an existing location
937
        $locationService = $repository->getLocationService();
938
939
        $location = $locationService->loadLocation($locationId);
940
941
        $childLocations = $locationService->loadLocationChildren($location);
942
        /* END: Use Case */
943
944
        $this->assertInstanceOf(LocationList::class, $childLocations);
945
        $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...
946
        $this->assertNotEmpty($childLocations->locations);
947
        $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...
948
949
        foreach ($childLocations->locations as $childLocation) {
950
            $this->assertInstanceOf(Location::class, $childLocation);
951
            $this->assertEquals($location->id, $childLocation->parentLocationId);
952
        }
953
954
        return $childLocations;
955
    }
956
957
    /**
958
     * Test loading parent Locations for draft Content.
959
     *
960
     * @covers \eZ\Publish\API\Repository\LocationService::loadParentLocationsForDraftContent
961
     */
962
    public function testLoadParentLocationsForDraftContent()
963
    {
964
        $repository = $this->getRepository();
965
        $locationService = $repository->getLocationService();
966
        $contentService = $repository->getContentService();
967
        $contentTypeService = $repository->getContentTypeService();
968
969
        // prepare locations
970
        $locationCreateStructs = [
971
            $locationService->newLocationCreateStruct(2),
972
            $locationService->newLocationCreateStruct(5),
973
        ];
974
975
        // Create new content
976
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
977
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
978
        $contentCreate->setField('name', 'New Folder');
979
        $contentDraft = $contentService->createContent($contentCreate, $locationCreateStructs);
980
981
        // Test loading parent Locations
982
        $locations = $locationService->loadParentLocationsForDraftContent($contentDraft->versionInfo);
983
984
        self::assertCount(2, $locations);
985
        foreach ($locations as $location) {
986
            // test it is one of the given parent locations
987
            self::assertTrue($location->id === 2 || $location->id === 5);
988
        }
989
990
        return $contentDraft;
991
    }
992
993
    /**
994
     * Test that trying to load parent Locations throws Exception if Content is not a draft.
995
     *
996
     * @depends testLoadParentLocationsForDraftContent
997
     *
998
     * @param \eZ\Publish\API\Repository\Values\Content\Content $contentDraft
999
     */
1000
    public function testLoadParentLocationsForDraftContentThrowsBadStateException(Content $contentDraft)
1001
    {
1002
        $this->expectException(BadStateException::class);
1003
        $this->expectExceptionMessageRegExp('/has been already published/');
1004
1005
        $repository = $this->getRepository(false);
1006
        $locationService = $repository->getLocationService();
1007
        $contentService = $repository->getContentService();
1008
1009
        $content = $contentService->publishVersion($contentDraft->versionInfo);
1010
1011
        $locationService->loadParentLocationsForDraftContent($content->versionInfo);
1012
    }
1013
1014
    /**
1015
     * Test for the getLocationChildCount() method.
1016
     *
1017
     * @see \eZ\Publish\API\Repository\LocationService::getLocationChildCount()
1018
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1019
     */
1020
    public function testGetLocationChildCount()
1021
    {
1022
        // $locationId is the ID of an existing location
1023
        $locationService = $this->getRepository()->getLocationService();
1024
1025
        $this->assertSame(
1026
            5,
1027
            $locationService->getLocationChildCount(
1028
                $locationService->loadLocation($this->generateId('location', 5))
1029
            )
1030
        );
1031
    }
1032
1033
    /**
1034
     * Test for the loadLocationChildren() method.
1035
     *
1036
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren()
1037
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
1038
     */
1039
    public function testLoadLocationChildrenData(LocationList $locations)
1040
    {
1041
        $this->assertEquals(5, count($locations->locations));
1042
        $this->assertEquals(5, $locations->totalCount);
1043
1044
        foreach ($locations->locations as $location) {
1045
            $this->assertInstanceOf(
1046
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1047
                $location
1048
            );
1049
        }
1050
1051
        $this->assertEquals(
1052
            [
1053
                $this->generateId('location', 12),
1054
                $this->generateId('location', 13),
1055
                $this->generateId('location', 14),
1056
                $this->generateId('location', 44),
1057
                $this->generateId('location', 61),
1058
            ],
1059
            array_map(
1060
                function (Location $location) {
1061
                    return $location->id;
1062
                },
1063
                $locations->locations
1064
            )
1065
        );
1066
    }
1067
1068
    /**
1069
     * Test for the loadLocationChildren() method.
1070
     *
1071
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
1072
     *
1073
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset)
1074
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
1075
     */
1076 View Code Duplication
    public function testLoadLocationChildrenWithOffset()
1077
    {
1078
        $repository = $this->getRepository();
1079
1080
        $locationId = $this->generateId('location', 5);
1081
        /* BEGIN: Use Case */
1082
        // $locationId is the ID of an existing location
1083
        $locationService = $repository->getLocationService();
1084
1085
        $location = $locationService->loadLocation($locationId);
1086
1087
        $childLocations = $locationService->loadLocationChildren($location, 2);
1088
        /* END: Use Case */
1089
1090
        $this->assertInstanceOf('\\eZ\\Publish\\API\\Repository\\Values\\Content\\LocationList', $childLocations);
1091
        $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...
1092
        $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...
1093
1094
        return $childLocations;
1095
    }
1096
1097
    /**
1098
     * Test for the loadLocationChildren() method.
1099
     *
1100
     * @param \eZ\Publish\API\Repository\Values\Content\LocationList $locations
1101
     *
1102
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset)
1103
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildrenWithOffset
1104
     */
1105 View Code Duplication
    public function testLoadLocationChildrenDataWithOffset(LocationList $locations)
1106
    {
1107
        $this->assertEquals(3, count($locations->locations));
1108
        $this->assertEquals(5, $locations->totalCount);
1109
1110
        foreach ($locations->locations as $location) {
1111
            $this->assertInstanceOf(
1112
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1113
                $location
1114
            );
1115
        }
1116
1117
        $this->assertEquals(
1118
            [
1119
                $this->generateId('location', 14),
1120
                $this->generateId('location', 44),
1121
                $this->generateId('location', 61),
1122
            ],
1123
            array_map(
1124
                function (Location $location) {
1125
                    return $location->id;
1126
                },
1127
                $locations->locations
1128
            )
1129
        );
1130
    }
1131
1132
    /**
1133
     * Test for the loadLocationChildren() method.
1134
     *
1135
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
1136
     *
1137
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset, $limit)
1138
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
1139
     */
1140 View Code Duplication
    public function testLoadLocationChildrenWithOffsetAndLimit()
1141
    {
1142
        $repository = $this->getRepository();
1143
1144
        $locationId = $this->generateId('location', 5);
1145
        /* BEGIN: Use Case */
1146
        // $locationId is the ID of an existing location
1147
        $locationService = $repository->getLocationService();
1148
1149
        $location = $locationService->loadLocation($locationId);
1150
1151
        $childLocations = $locationService->loadLocationChildren($location, 2, 2);
1152
        /* END: Use Case */
1153
1154
        $this->assertInstanceOf('\\eZ\\Publish\\API\\Repository\\Values\\Content\\LocationList', $childLocations);
1155
        $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...
1156
        $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...
1157
1158
        return $childLocations;
1159
    }
1160
1161
    /**
1162
     * Test for the loadLocationChildren() method.
1163
     *
1164
     * @param \eZ\Publish\API\Repository\Values\Content\Location[] $locations
1165
     *
1166
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset, $limit)
1167
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildrenWithOffsetAndLimit
1168
     */
1169 View Code Duplication
    public function testLoadLocationChildrenDataWithOffsetAndLimit(LocationList $locations)
1170
    {
1171
        $this->assertEquals(2, count($locations->locations));
1172
        $this->assertEquals(5, $locations->totalCount);
1173
1174
        foreach ($locations->locations as $location) {
1175
            $this->assertInstanceOf(
1176
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1177
                $location
1178
            );
1179
        }
1180
1181
        $this->assertEquals(
1182
            [
1183
                $this->generateId('location', 14),
1184
                $this->generateId('location', 44),
1185
            ],
1186
            array_map(
1187
                function (Location $location) {
1188
                    return $location->id;
1189
                },
1190
                $locations->locations
1191
            )
1192
        );
1193
    }
1194
1195
    /**
1196
     * Test for the newLocationUpdateStruct() method.
1197
     *
1198
     * @covers \eZ\Publish\API\Repository\LocationService::newLocationUpdateStruct
1199
     */
1200 View Code Duplication
    public function testNewLocationUpdateStruct()
1201
    {
1202
        $repository = $this->getRepository();
1203
1204
        /* BEGIN: Use Case */
1205
        $locationService = $repository->getLocationService();
1206
1207
        $updateStruct = $locationService->newLocationUpdateStruct();
1208
        /* END: Use Case */
1209
1210
        $this->assertInstanceOf(
1211
            LocationUpdateStruct::class,
1212
            $updateStruct
1213
        );
1214
1215
        $this->assertPropertiesCorrect(
1216
            [
1217
                'priority' => null,
1218
                'remoteId' => null,
1219
                'sortField' => null,
1220
                'sortOrder' => null,
1221
            ],
1222
            $updateStruct
1223
        );
1224
    }
1225
1226
    /**
1227
     * Test for the updateLocation() method.
1228
     *
1229
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1230
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1231
     */
1232
    public function testUpdateLocation()
1233
    {
1234
        $repository = $this->getRepository();
1235
1236
        $originalLocationId = $this->generateId('location', 5);
1237
        /* BEGIN: Use Case */
1238
        // $originalLocationId is the ID of an existing location
1239
        $locationService = $repository->getLocationService();
1240
1241
        $originalLocation = $locationService->loadLocation($originalLocationId);
1242
1243
        $updateStruct = $locationService->newLocationUpdateStruct();
1244
        $updateStruct->priority = 3;
1245
        $updateStruct->remoteId = 'c7adcbf1e96bc29bca28c2d809d0c7ef69272651';
1246
        $updateStruct->sortField = Location::SORT_FIELD_PRIORITY;
1247
        $updateStruct->sortOrder = Location::SORT_ORDER_DESC;
1248
1249
        $updatedLocation = $locationService->updateLocation($originalLocation, $updateStruct);
1250
        /* END: Use Case */
1251
1252
        $this->assertInstanceOf(
1253
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1254
            $updatedLocation
1255
        );
1256
1257
        return [
1258
            'originalLocation' => $originalLocation,
1259
            'updateStruct' => $updateStruct,
1260
            'updatedLocation' => $updatedLocation,
1261
        ];
1262
    }
1263
1264
    /**
1265
     * Test for the updateLocation() method.
1266
     *
1267
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1268
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testUpdateLocation
1269
     */
1270
    public function testUpdateLocationStructValues(array $data)
1271
    {
1272
        $originalLocation = $data['originalLocation'];
1273
        $updateStruct = $data['updateStruct'];
1274
        $updatedLocation = $data['updatedLocation'];
1275
1276
        $this->assertPropertiesCorrect(
1277
            [
1278
                'id' => $originalLocation->id,
1279
                'priority' => $updateStruct->priority,
1280
                'hidden' => $originalLocation->hidden,
1281
                'invisible' => $originalLocation->invisible,
1282
                'remoteId' => $updateStruct->remoteId,
1283
                'contentInfo' => $originalLocation->contentInfo,
1284
                'parentLocationId' => $originalLocation->parentLocationId,
1285
                'pathString' => $originalLocation->pathString,
1286
                'depth' => $originalLocation->depth,
1287
                'sortField' => $updateStruct->sortField,
1288
                'sortOrder' => $updateStruct->sortOrder,
1289
            ],
1290
            $updatedLocation
1291
        );
1292
    }
1293
1294
    /**
1295
     * Test for the updateLocation() method.
1296
     *
1297
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1298
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1299
     */
1300
    public function testUpdateLocationWithSameRemoteId()
1301
    {
1302
        $repository = $this->getRepository();
1303
1304
        $locationId = $this->generateId('location', 5);
1305
        /* BEGIN: Use Case */
1306
        // $locationId and remote ID is the IDs of the same, existing location
1307
        $locationService = $repository->getLocationService();
1308
1309
        $originalLocation = $locationService->loadLocation($locationId);
1310
1311
        $updateStruct = $locationService->newLocationUpdateStruct();
1312
1313
        // Remote ID of an existing location with the same locationId
1314
        $updateStruct->remoteId = $originalLocation->remoteId;
1315
1316
        // Sets one of the properties to be able to confirm location gets updated, here: priority
1317
        $updateStruct->priority = 2;
1318
1319
        $location = $locationService->updateLocation($originalLocation, $updateStruct);
1320
1321
        // Checks that the location was updated
1322
        $this->assertEquals(2, $location->priority);
1323
1324
        // Checks that remoteId remains the same
1325
        $this->assertEquals($originalLocation->remoteId, $location->remoteId);
1326
        /* END: Use Case */
1327
    }
1328
1329
    /**
1330
     * Test for the updateLocation() method.
1331
     *
1332
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1333
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1334
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1335
     */
1336 View Code Duplication
    public function testUpdateLocationThrowsInvalidArgumentException()
1337
    {
1338
        $repository = $this->getRepository();
1339
1340
        $locationId = $this->generateId('location', 5);
1341
        /* BEGIN: Use Case */
1342
        // $locationId and remoteId is the IDs of an existing, but not the same, location
1343
        $locationService = $repository->getLocationService();
1344
1345
        $originalLocation = $locationService->loadLocation($locationId);
1346
1347
        $updateStruct = $locationService->newLocationUpdateStruct();
1348
1349
        // Remote ID of an existing location with a different locationId
1350
        $updateStruct->remoteId = 'f3e90596361e31d496d4026eb624c983';
1351
1352
        // Throws exception, since remote ID is already taken
1353
        $locationService->updateLocation($originalLocation, $updateStruct);
1354
        /* END: Use Case */
1355
    }
1356
1357
    /**
1358
     * Test for the updateLocation() method.
1359
     *
1360
     * @covers \eZ\Publish\API\Repository\LocationService::updateLocation()
1361
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1362
     * @dataProvider dataProviderForOutOfRangeLocationPriority
1363
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1364
     */
1365 View Code Duplication
    public function testUpdateLocationThrowsInvalidArgumentExceptionPriorityIsOutOfRange($priority)
1366
    {
1367
        $repository = $this->getRepository();
1368
1369
        $locationId = $this->generateId('location', 5);
1370
        /* BEGIN: Use Case */
1371
        // $locationId and remoteId is the IDs of an existing, but not the same, location
1372
        $locationService = $repository->getLocationService();
1373
1374
        $originalLocation = $locationService->loadLocation($locationId);
1375
1376
        $updateStruct = $locationService->newLocationUpdateStruct();
1377
1378
        // Priority value is out of range
1379
        $updateStruct->priority = $priority;
1380
1381
        // Throws exception, since remote ID is already taken
1382
        $locationService->updateLocation($originalLocation, $updateStruct);
1383
        /* END: Use Case */
1384
    }
1385
1386
    /**
1387
     * Test for the updateLocation() method.
1388
     * Ref EZP-23302: Update Location fails if no change is performed with the update.
1389
     *
1390
     * @see \eZ\Publish\API\Repository\LocationService::updateLocation()
1391
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1392
     */
1393
    public function testUpdateLocationTwice()
1394
    {
1395
        $repository = $this->getRepository();
1396
1397
        $locationId = $this->generateId('location', 5);
1398
        /* BEGIN: Use Case */
1399
        $locationService = $repository->getLocationService();
1400
        $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...
1401
1402
        $originalLocation = $locationService->loadLocation($locationId);
1403
1404
        $updateStruct = $locationService->newLocationUpdateStruct();
1405
        $updateStruct->priority = 42;
1406
1407
        $updatedLocation = $locationService->updateLocation($originalLocation, $updateStruct);
1408
1409
        // Repeated update with the same, unchanged struct
1410
        $secondUpdatedLocation = $locationService->updateLocation($updatedLocation, $updateStruct);
1411
        /* END: Use Case */
1412
1413
        $this->assertEquals($updatedLocation->priority, 42);
1414
        $this->assertEquals($secondUpdatedLocation->priority, 42);
1415
    }
1416
1417
    /**
1418
     * Test for the swapLocation() method.
1419
     *
1420
     * @see \eZ\Publish\API\Repository\LocationService::swapLocation()
1421
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1422
     */
1423
    public function testSwapLocation()
1424
    {
1425
        $repository = $this->getRepository();
1426
        $locationService = $repository->getLocationService();
1427
1428
        $mediaLocationId = $this->generateId('location', 43);
1429
        $demoDesignLocationId = $this->generateId('location', 56);
1430
1431
        $mediaContentInfo = $locationService->loadLocation($mediaLocationId)->getContentInfo();
1432
        $demoDesignContentInfo = $locationService->loadLocation($demoDesignLocationId)->getContentInfo();
1433
1434
        /* BEGIN: Use Case */
1435
        // $mediaLocationId is the ID of the "Media" page location in
1436
        // an eZ Publish demo installation
1437
1438
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
1439
        // Publish demo installation
1440
1441
        // Load the location service
1442
        $locationService = $repository->getLocationService();
1443
1444
        $mediaLocation = $locationService->loadLocation($mediaLocationId);
1445
        $demoDesignLocation = $locationService->loadLocation($demoDesignLocationId);
1446
1447
        // Swaps the content referred to by the locations
1448
        $locationService->swapLocation($mediaLocation, $demoDesignLocation);
1449
        /* END: Use Case */
1450
1451
        // Reload Locations, IDs swapped
1452
        $demoDesignLocation = $locationService->loadLocation($mediaLocationId);
1453
        $mediaLocation = $locationService->loadLocation($demoDesignLocationId);
1454
1455
        // Assert Location's Content is updated
1456
        $this->assertEquals(
1457
            $mediaContentInfo->id,
1458
            $mediaLocation->getContentInfo()->id
1459
        );
1460
        $this->assertEquals(
1461
            $demoDesignContentInfo->id,
1462
            $demoDesignLocation->getContentInfo()->id
1463
        );
1464
1465
        // Assert URL aliases are updated
1466
        $this->assertEquals(
1467
            $mediaLocation->id,
1468
            $repository->getURLAliasService()->lookup('/Design/Media')->destination
1469
        );
1470
        $this->assertEquals(
1471
            $demoDesignLocation->id,
1472
            $repository->getURLAliasService()->lookup('/eZ-Publish-Demo-Design-without-demo-content')->destination
1473
        );
1474
    }
1475
1476
    /**
1477
     * Test for the swapLocation() method with custom aliases.
1478
     *
1479
     * @see \eZ\Publish\API\Repository\LocationService::swapLocation()
1480
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1481
     *
1482
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1483
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1484
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1485
     */
1486
    public function testSwapLocationCustomAliases()
1487
    {
1488
        $repository = $this->getRepository();
1489
        $locationService = $repository->getLocationService();
1490
        $urlAliasService = $repository->getURLAliasService();
1491
        $this->createLanguage('pol-Pl', 'Polski');
1492
1493
        $folder1 = $this->createFolder(['eng-GB' => 'Folder1', 'pol-Pl' => 'Folder1'], 2);
1494
        $folder2 = $this->createFolder(['eng-GB' => 'Folder2'], 2);
1495
        $location1 = $locationService->loadLocation($folder1->contentInfo->mainLocationId);
1496
        $location2 = $locationService->loadLocation($folder2->contentInfo->mainLocationId);
1497
1498
        $urlAliasService->createUrlAlias($location1, '/custom-location1', 'eng-GB', false, true);
1499
        $urlAliasService->createUrlAlias($location1, '/custom-location1', 'pol-Pl', false, true);
1500
        $urlAliasService->createUrlAlias($location2, '/custom-location2', 'eng-GB', false, true);
1501
        $location1UrlAliases = $urlAliasService->listLocationAliases($location1);
1502
        $location2UrlAliases = $urlAliasService->listLocationAliases($location2);
1503
1504
        $locationService->swapLocation($location1, $location2);
1505
        $location1 = $locationService->loadLocation($location1->contentInfo->mainLocationId);
1506
        $location2 = $locationService->loadLocation($location2->contentInfo->mainLocationId);
1507
        $location1UrlAliasesAfterSwap = $urlAliasService->listLocationAliases($location1);
1508
        $location2UrlAliasesAfterSwap = $urlAliasService->listLocationAliases($location2);
1509
1510
        $urlAlias = new URLAlias([
1511
            'id' => $location1UrlAliases[0]->id,
1512
            'type' => $location1UrlAliases[0]->type,
1513
            'destination' => $location1UrlAliases[0]->destination,
1514
            'path' => $location1UrlAliases[0]->path,
1515
            'languageCodes' => ['eng-GB'],
1516
            'alwaysAvailable' => $location1UrlAliases[0]->alwaysAvailable,
1517
            'isHistory' => $location1UrlAliases[0]->isHistory,
1518
            'isCustom' => $location1UrlAliases[0]->isCustom,
1519
            'forward' => $location1UrlAliases[0]->forward,
1520
        ]);
1521
1522
        self::assertEquals($folder1->id, $location2->contentInfo->id);
1523
        self::assertEquals($folder2->id, $location1->contentInfo->id);
1524
        self::assertNotEquals($location1UrlAliases, $location1UrlAliasesAfterSwap);
1525
        self::assertEquals($location2UrlAliases, $location2UrlAliasesAfterSwap);
1526
        self::assertEquals([$urlAlias], $location1UrlAliasesAfterSwap);
1527
    }
1528
1529
    /**
1530
     * Test swapping secondary Location with main Location.
1531
     *
1532
     * @covers \eZ\Publish\API\Repository\LocationService::swapLocation
1533
     *
1534
     * @see https://jira.ez.no/browse/EZP-28663
1535
     *
1536
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1537
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1538
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1539
     *
1540
     * @return int[]
1541
     */
1542
    public function testSwapLocationForMainAndSecondaryLocation(): array
1543
    {
1544
        $repository = $this->getRepository();
1545
        $locationService = $repository->getLocationService();
1546
        $contentService = $repository->getContentService();
1547
1548
        $folder1 = $this->createFolder(['eng-GB' => 'Folder1'], 2);
1549
        $folder2 = $this->createFolder(['eng-GB' => 'Folder2'], 2);
1550
        $folder3 = $this->createFolder(['eng-GB' => 'Folder3'], 2);
1551
1552
        $primaryLocation = $locationService->loadLocation($folder1->contentInfo->mainLocationId);
1553
        $parentLocation = $locationService->loadLocation($folder2->contentInfo->mainLocationId);
1554
        $secondaryLocation = $locationService->createLocation(
1555
            $folder1->contentInfo,
1556
            $locationService->newLocationCreateStruct($parentLocation->id)
1557
        );
1558
1559
        $targetLocation = $locationService->loadLocation($folder3->contentInfo->mainLocationId);
1560
1561
        // perform sanity checks
1562
        $this->assertContentHasExpectedLocations([$primaryLocation, $secondaryLocation], $folder1);
1563
1564
        // begin use case
1565
        $locationService->swapLocation($secondaryLocation, $targetLocation);
1566
1567
        // test results
1568
        $primaryLocation = $locationService->loadLocation($primaryLocation->id);
1569
        $secondaryLocation = $locationService->loadLocation($secondaryLocation->id);
1570
        $targetLocation = $locationService->loadLocation($targetLocation->id);
1571
1572
        self::assertEquals($folder1->id, $primaryLocation->contentInfo->id);
1573
        self::assertEquals($folder1->id, $targetLocation->contentInfo->id);
1574
        self::assertEquals($folder3->id, $secondaryLocation->contentInfo->id);
1575
1576
        $this->assertContentHasExpectedLocations([$primaryLocation, $targetLocation], $folder1);
1577
1578
        self::assertEquals(
1579
            $folder1,
1580
            $contentService->loadContent($folder1->id)
1581
        );
1582
1583
        self::assertEquals(
1584
            $folder2,
1585
            $contentService->loadContent($folder2->id)
1586
        );
1587
1588
        // only in case of Folder 3, main location id changed due to swap
1589
        self::assertEquals(
1590
            $secondaryLocation->id,
1591
            $contentService->loadContent($folder3->id)->contentInfo->mainLocationId
1592
        );
1593
1594
        return [$folder1, $folder2, $folder3];
1595
    }
1596
1597
    /**
1598
     * Compare Ids of expected and loaded Locations for the given Content.
1599
     *
1600
     * @param \eZ\Publish\API\Repository\Values\Content\Location[] $expectedLocations
1601
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
1602
     *
1603
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
1604
     */
1605
    private function assertContentHasExpectedLocations(array $expectedLocations, Content $content)
1606
    {
1607
        $repository = $this->getRepository(false);
1608
        $locationService = $repository->getLocationService();
1609
1610
        $expectedLocationIds = array_map(
1611
            function (Location $location) {
1612
                return (int)$location->id;
1613
            },
1614
            $expectedLocations
1615
        );
1616
1617
        $actualLocationsIds = array_map(
1618
            function (Location $location) {
1619
                return $location->id;
1620
            },
1621
            $locationService->loadLocations($content->contentInfo)
1622
        );
1623
        self::assertCount(count($expectedLocations), $actualLocationsIds);
1624
1625
        // perform unordered equality assertion
1626
        self::assertEquals(
1627
            $expectedLocationIds,
1628
            $actualLocationsIds,
1629
            sprintf(
1630
                'Content %d contains Locations %s, but expected: %s',
1631
                $content->id,
1632
                implode(', ', $actualLocationsIds),
1633
                implode(', ', $expectedLocationIds)
1634
            ),
1635
            0.0,
1636
            10,
1637
            true
1638
        );
1639
    }
1640
1641
    /**
1642
     * @depends testSwapLocationForMainAndSecondaryLocation
1643
     *
1644
     * @param \eZ\Publish\API\Repository\Values\Content\Content[] $contentItems Content items created by testSwapLocationForSecondaryLocation
1645
     *
1646
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1647
     */
1648
    public function testSwapLocationDoesNotCorruptSearchResults(array $contentItems)
1649
    {
1650
        $repository = $this->getRepository(false);
1651
        $searchService = $repository->getSearchService();
1652
1653
        $this->refreshSearch($repository);
1654
1655
        $contentIds = array_map(
1656
            function (Content $content) {
1657
                return $content->id;
1658
            },
1659
            $contentItems
1660
        );
1661
1662
        $query = new Query();
1663
        $query->filter = new Query\Criterion\ContentId($contentIds);
1664
1665
        $searchResult = $searchService->findContent($query);
1666
1667
        self::assertEquals(count($contentItems), $searchResult->totalCount);
1668
        self::assertEquals(
1669
            $searchResult->totalCount,
1670
            count($searchResult->searchHits),
1671
            'Total count of search result hits does not match the actual number of found results'
1672
        );
1673
        $foundContentIds = array_map(
1674
            function (SearchHit $searchHit) {
1675
                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...
1676
            },
1677
            $searchResult->searchHits
1678
        );
1679
        sort($contentIds);
1680
        sort($foundContentIds);
1681
        self::assertSame(
1682
            $contentIds,
1683
            $foundContentIds,
1684
            'Got different than expected Content item Ids'
1685
        );
1686
    }
1687
1688
    /**
1689
     * Test swapping two secondary (non-main) Locations.
1690
     *
1691
     * @covers \eZ\Publish\API\Repository\LocationService::swapLocation
1692
     *
1693
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
1694
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
1695
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
1696
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
1697
     */
1698
    public function testSwapLocationForSecondaryLocations()
1699
    {
1700
        $repository = $this->getRepository();
1701
        $locationService = $repository->getLocationService();
1702
        $contentService = $repository->getContentService();
1703
1704
        $folder1 = $this->createFolder(['eng-GB' => 'Folder1'], 2);
1705
        $folder2 = $this->createFolder(['eng-GB' => 'Folder2'], 2);
1706
        $parentFolder1 = $this->createFolder(['eng-GB' => 'Parent1'], 2);
1707
        $parentFolder2 = $this->createFolder(['eng-GB' => 'Parent2'], 2);
1708
1709
        $parentLocation1 = $locationService->loadLocation($parentFolder1->contentInfo->mainLocationId);
1710
        $parentLocation2 = $locationService->loadLocation($parentFolder2->contentInfo->mainLocationId);
1711
        $secondaryLocation1 = $locationService->createLocation(
1712
            $folder1->contentInfo,
1713
            $locationService->newLocationCreateStruct($parentLocation1->id)
1714
        );
1715
        $secondaryLocation2 = $locationService->createLocation(
1716
            $folder2->contentInfo,
1717
            $locationService->newLocationCreateStruct($parentLocation2->id)
1718
        );
1719
1720
        // begin use case
1721
        $locationService->swapLocation($secondaryLocation1, $secondaryLocation2);
1722
1723
        // test results
1724
        $secondaryLocation1 = $locationService->loadLocation($secondaryLocation1->id);
1725
        $secondaryLocation2 = $locationService->loadLocation($secondaryLocation2->id);
1726
1727
        self::assertEquals($folder2->id, $secondaryLocation1->contentInfo->id);
1728
        self::assertEquals($folder1->id, $secondaryLocation2->contentInfo->id);
1729
1730
        self::assertEquals(
1731
            $folder1,
1732
            $contentService->loadContent($folder1->id)
1733
        );
1734
1735
        self::assertEquals(
1736
            $folder2,
1737
            $contentService->loadContent($folder2->id)
1738
        );
1739
    }
1740
1741
    /**
1742
     * Test swapping Main Location of a Content with another one updates Content item Main Location.
1743
     *
1744
     * @covers \eZ\Publish\API\Repository\LocationService::swapLocation
1745
     */
1746
    public function testSwapLocationUpdatesMainLocation()
1747
    {
1748
        $repository = $this->getRepository();
1749
        $locationService = $repository->getLocationService();
1750
        $contentService = $repository->getContentService();
1751
1752
        $mainLocationParentId = 60;
1753
        $secondaryLocationId = 43;
1754
1755
        $publishedContent = $this->publishContentWithParentLocation(
1756
            'Content for Swap Location Test', $mainLocationParentId
1757
        );
1758
1759
        // sanity check
1760
        $mainLocation = $locationService->loadLocation($publishedContent->contentInfo->mainLocationId);
1761
        self::assertEquals($mainLocationParentId, $mainLocation->parentLocationId);
1762
1763
        // load another pre-existing location
1764
        $secondaryLocation = $locationService->loadLocation($secondaryLocationId);
1765
1766
        // swap the Main Location with a secondary one
1767
        $locationService->swapLocation($mainLocation, $secondaryLocation);
1768
1769
        // check if Main Location has been updated
1770
        $mainLocation = $locationService->loadLocation($secondaryLocation->id);
1771
        self::assertEquals($publishedContent->contentInfo->id, $mainLocation->contentInfo->id);
1772
        self::assertEquals($mainLocation->id, $mainLocation->contentInfo->mainLocationId);
1773
1774
        $reloadedContent = $contentService->loadContentByContentInfo($publishedContent->contentInfo);
1775
        self::assertEquals($mainLocation->id, $reloadedContent->contentInfo->mainLocationId);
1776
    }
1777
1778
    /**
1779
     * Test if location swap affects related bookmarks.
1780
     *
1781
     * @covers \eZ\Publish\API\Repository\LocationService::swapLocation
1782
     */
1783
    public function testBookmarksAreSwappedAfterSwapLocation()
1784
    {
1785
        $repository = $this->getRepository();
1786
1787
        $mediaLocationId = $this->generateId('location', 43);
1788
        $demoDesignLocationId = $this->generateId('location', 56);
1789
1790
        /* BEGIN: Use Case */
1791
        $locationService = $repository->getLocationService();
1792
        $bookmarkService = $repository->getBookmarkService();
1793
1794
        $mediaLocation = $locationService->loadLocation($mediaLocationId);
1795
        $demoDesignLocation = $locationService->loadLocation($demoDesignLocationId);
1796
1797
        // Bookmark locations
1798
        $bookmarkService->createBookmark($mediaLocation);
1799
        $bookmarkService->createBookmark($demoDesignLocation);
1800
1801
        $beforeSwap = $bookmarkService->loadBookmarks();
1802
1803
        // Swaps the content referred to by the locations
1804
        $locationService->swapLocation($mediaLocation, $demoDesignLocation);
1805
1806
        $afterSwap = $bookmarkService->loadBookmarks();
1807
        /* END: Use Case */
1808
1809
        $this->assertEquals($beforeSwap->items[0]->id, $afterSwap->items[1]->id);
1810
        $this->assertEquals($beforeSwap->items[1]->id, $afterSwap->items[0]->id);
1811
    }
1812
1813
    /**
1814
     * Test for the hideLocation() method.
1815
     *
1816
     * @see \eZ\Publish\API\Repository\LocationService::hideLocation()
1817
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1818
     */
1819
    public function testHideLocation()
1820
    {
1821
        $repository = $this->getRepository();
1822
1823
        $locationId = $this->generateId('location', 5);
1824
        /* BEGIN: Use Case */
1825
        // $locationId is the ID of an existing location
1826
        $locationService = $repository->getLocationService();
1827
1828
        $visibleLocation = $locationService->loadLocation($locationId);
1829
1830
        $hiddenLocation = $locationService->hideLocation($visibleLocation);
1831
        /* END: Use Case */
1832
1833
        $this->assertInstanceOf(
1834
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1835
            $hiddenLocation
1836
        );
1837
1838
        $this->assertTrue(
1839
            $hiddenLocation->hidden,
1840
            sprintf(
1841
                'Location with ID "%s" not hidden.',
1842
                $hiddenLocation->id
1843
            )
1844
        );
1845
1846
        $this->refreshSearch($repository);
1847
1848
        foreach ($locationService->loadLocationChildren($hiddenLocation)->locations as $child) {
1849
            $this->assertSubtreeProperties(
1850
                ['invisible' => true],
1851
                $child
1852
            );
1853
        }
1854
    }
1855
1856
    /**
1857
     * Assert that $expectedValues are set in the subtree starting at $location.
1858
     *
1859
     * @param array $expectedValues
1860
     * @param Location $location
1861
     */
1862
    protected function assertSubtreeProperties(array $expectedValues, Location $location, $stopId = null)
1863
    {
1864
        $repository = $this->getRepository();
1865
        $locationService = $repository->getLocationService();
1866
1867
        if ($location->id === $stopId) {
1868
            return;
1869
        }
1870
1871
        foreach ($expectedValues as $propertyName => $propertyValue) {
1872
            $this->assertEquals(
1873
                $propertyValue,
1874
                $location->$propertyName
1875
            );
1876
1877
            foreach ($locationService->loadLocationChildren($location)->locations as $child) {
1878
                $this->assertSubtreeProperties($expectedValues, $child);
1879
            }
1880
        }
1881
    }
1882
1883
    /**
1884
     * Test for the unhideLocation() method.
1885
     *
1886
     * @see \eZ\Publish\API\Repository\LocationService::unhideLocation()
1887
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testHideLocation
1888
     */
1889
    public function testUnhideLocation()
1890
    {
1891
        $repository = $this->getRepository();
1892
1893
        $locationId = $this->generateId('location', 5);
1894
        /* BEGIN: Use Case */
1895
        // $locationId is the ID of an existing location
1896
        $locationService = $repository->getLocationService();
1897
1898
        $visibleLocation = $locationService->loadLocation($locationId);
1899
        $hiddenLocation = $locationService->hideLocation($visibleLocation);
1900
1901
        $unHiddenLocation = $locationService->unhideLocation($hiddenLocation);
1902
        /* END: Use Case */
1903
1904
        $this->assertInstanceOf(
1905
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1906
            $unHiddenLocation
1907
        );
1908
1909
        $this->assertFalse(
1910
            $unHiddenLocation->hidden,
1911
            sprintf(
1912
                'Location with ID "%s" not unhidden.',
1913
                $unHiddenLocation->id
1914
            )
1915
        );
1916
1917
        $this->refreshSearch($repository);
1918
1919
        foreach ($locationService->loadLocationChildren($unHiddenLocation)->locations as $child) {
1920
            $this->assertSubtreeProperties(
1921
                ['invisible' => false],
1922
                $child
1923
            );
1924
        }
1925
    }
1926
1927
    /**
1928
     * Test for the unhideLocation() method.
1929
     *
1930
     * @see \eZ\Publish\API\Repository\LocationService::unhideLocation()
1931
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testUnhideLocation
1932
     */
1933
    public function testUnhideLocationNotUnhidesHiddenSubtree()
1934
    {
1935
        $repository = $this->getRepository();
1936
1937
        $higherLocationId = $this->generateId('location', 5);
1938
        $lowerLocationId = $this->generateId('location', 13);
1939
        /* BEGIN: Use Case */
1940
        // $higherLocationId is the ID of a location
1941
        // $lowerLocationId is the ID of a location below $higherLocationId
1942
        $locationService = $repository->getLocationService();
1943
1944
        $higherLocation = $locationService->loadLocation($higherLocationId);
1945
        $hiddenHigherLocation = $locationService->hideLocation($higherLocation);
1946
1947
        $lowerLocation = $locationService->loadLocation($lowerLocationId);
1948
        $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...
1949
1950
        $unHiddenHigherLocation = $locationService->unhideLocation($hiddenHigherLocation);
1951
        /* END: Use Case */
1952
1953
        $this->assertInstanceOf(
1954
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1955
            $unHiddenHigherLocation
1956
        );
1957
1958
        $this->assertFalse(
1959
            $unHiddenHigherLocation->hidden,
1960
            sprintf(
1961
                'Location with ID "%s" not unhidden.',
1962
                $unHiddenHigherLocation->id
1963
            )
1964
        );
1965
1966
        $this->refreshSearch($repository);
1967
1968
        foreach ($locationService->loadLocationChildren($unHiddenHigherLocation)->locations as $child) {
1969
            $this->assertSubtreeProperties(
1970
                ['invisible' => false],
1971
                $child,
1972
                $this->generateId('location', 13)
1973
            );
1974
        }
1975
1976
        $stillHiddenLocation = $locationService->loadLocation($this->generateId('location', 13));
1977
        $this->assertTrue(
1978
            $stillHiddenLocation->hidden,
1979
            sprintf(
1980
                'Hidden sub-location with ID %s accidentally unhidden.',
1981
                $stillHiddenLocation->id
1982
            )
1983
        );
1984
        foreach ($locationService->loadLocationChildren($stillHiddenLocation)->locations as $child) {
1985
            $this->assertSubtreeProperties(
1986
                ['invisible' => true],
1987
                $child
1988
            );
1989
        }
1990
    }
1991
1992
    /**
1993
     * Test for the deleteLocation() method.
1994
     *
1995
     * @see \eZ\Publish\API\Repository\LocationService::deleteLocation()
1996
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
1997
     */
1998
    public function testDeleteLocation()
1999
    {
2000
        $repository = $this->getRepository();
2001
2002
        $mediaLocationId = $this->generateId('location', 43);
2003
        /* BEGIN: Use Case */
2004
        // $mediaLocationId is the ID of the location of the
2005
        // "Media" location in an eZ Publish demo installation
2006
        $locationService = $repository->getLocationService();
2007
2008
        $location = $locationService->loadLocation($mediaLocationId);
2009
2010
        $locationService->deleteLocation($location);
2011
        /* END: Use Case */
2012
2013
        try {
2014
            $locationService->loadLocation($mediaLocationId);
2015
            $this->fail("Location $mediaLocationId not deleted.");
2016
        } catch (NotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
2017
        }
2018
2019
        // The following IDs are IDs of child locations of $mediaLocationId location
2020
        // ( Media/Images, Media/Files, Media/Multimedia respectively )
2021
        foreach ([51, 52, 53] as $childLocationId) {
2022
            try {
2023
                $locationService->loadLocation($this->generateId('location', $childLocationId));
2024
                $this->fail("Location $childLocationId not deleted.");
2025
            } catch (NotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
2026
            }
2027
        }
2028
2029
        // The following IDs are IDs of content below $mediaLocationId location
2030
        // ( Media/Images, Media/Files, Media/Multimedia respectively )
2031
        $contentService = $this->getRepository()->getContentService();
2032
        foreach ([49, 50, 51] as $childContentId) {
2033
            try {
2034
                $contentService->loadContentInfo($this->generateId('object', $childContentId));
2035
                $this->fail("Content $childContentId not deleted.");
2036
            } catch (NotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
2037
            }
2038
        }
2039
    }
2040
2041
    /**
2042
     * Test for the deleteLocation() method.
2043
     *
2044
     * @see \eZ\Publish\API\Repository\LocationService::deleteLocation()
2045
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testDeleteLocation
2046
     */
2047
    public function testDeleteLocationDecrementsChildCountOnParent()
2048
    {
2049
        $repository = $this->getRepository();
2050
2051
        $mediaLocationId = $this->generateId('location', 43);
2052
        /* BEGIN: Use Case */
2053
        // $mediaLocationId is the ID of the location of the
2054
        // "Media" location in an eZ Publish demo installation
2055
2056
        $locationService = $repository->getLocationService();
2057
2058
        // Load the current the user group location
2059
        $location = $locationService->loadLocation($mediaLocationId);
2060
2061
        // Load the parent location
2062
        $parentLocation = $locationService->loadLocation(
2063
            $location->parentLocationId
2064
        );
2065
2066
        // Get child count
2067
        $childCountBefore = $locationService->getLocationChildCount($parentLocation);
2068
2069
        // Delete the user group location
2070
        $locationService->deleteLocation($location);
2071
2072
        $this->refreshSearch($repository);
2073
2074
        // Reload parent location
2075
        $parentLocation = $locationService->loadLocation(
2076
            $location->parentLocationId
2077
        );
2078
2079
        // This will be $childCountBefore - 1
2080
        $childCountAfter = $locationService->getLocationChildCount($parentLocation);
2081
        /* END: Use Case */
2082
2083
        $this->assertEquals($childCountBefore - 1, $childCountAfter);
2084
    }
2085
2086
    /**
2087
     * Test for the deleteLocation() method.
2088
     *
2089
     * Related issue: EZP-21904
2090
     *
2091
     * @see \eZ\Publish\API\Repository\LocationService::deleteLocation()
2092
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
2093
     */
2094
    public function testDeleteContentObjectLastLocation()
2095
    {
2096
        $repository = $this->getRepository();
2097
2098
        /* BEGIN: Use case */
2099
        $contentService = $repository->getContentService();
2100
        $locationService = $repository->getLocationService();
2101
        $contentTypeService = $repository->getContentTypeService();
2102
        $urlAliasService = $repository->getURLAliasService();
2103
2104
        // prepare Content object
2105
        $createStruct = $contentService->newContentCreateStruct(
2106
            $contentTypeService->loadContentTypeByIdentifier('folder'),
2107
            'eng-GB'
2108
        );
2109
        $createStruct->setField('name', 'Test folder');
2110
2111
        // creata Content object
2112
        $content = $contentService->publishVersion(
2113
            $contentService->createContent(
2114
                $createStruct,
2115
                [$locationService->newLocationCreateStruct(2)]
2116
            )->versionInfo
2117
        );
2118
2119
        // delete location
2120
        $locationService->deleteLocation(
2121
            $locationService->loadLocation(
2122
                $urlAliasService->lookup('/Test-folder')->destination
2123
            )
2124
        );
2125
2126
        // this should throw a not found exception
2127
        $contentService->loadContent($content->versionInfo->contentInfo->id);
2128
        /* END: Use case*/
2129
    }
2130
2131
    /**
2132
     * Test for the deleteLocation() method.
2133
     *
2134
     * @covers  \eZ\Publish\API\Repository\LocationService::deleteLocation()
2135
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testDeleteLocation
2136
     */
2137
    public function testDeleteLocationDeletesRelatedBookmarks()
2138
    {
2139
        $repository = $this->getRepository();
2140
2141
        $parentLocationId = $this->generateId('location', 43);
2142
        $childLocationId = $this->generateId('location', 53);
2143
2144
        /* BEGIN: Use Case */
2145
        $locationService = $repository->getLocationService();
2146
        $bookmarkService = $repository->getBookmarkService();
2147
2148
        // Load location
2149
        $childLocation = $locationService->loadLocation($childLocationId);
2150
        // Add location to bookmarks
2151
        $bookmarkService->createBookmark($childLocation);
2152
        // Load parent location
2153
        $parentLocation = $locationService->loadLocation($parentLocationId);
2154
        // Delete parent location
2155
        $locationService->deleteLocation($parentLocation);
2156
        /* END: Use Case */
2157
2158
        // Location isn't bookmarked anymore
2159
        foreach ($bookmarkService->loadBookmarks(0, 9999) as $bookmarkedLocation) {
2160
            $this->assertNotEquals($childLocation->id, $bookmarkedLocation->id);
2161
        }
2162
    }
2163
2164
    /**
2165
     * Test for the copySubtree() method.
2166
     *
2167
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2168
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
2169
     */
2170
    public function testCopySubtree()
2171
    {
2172
        $repository = $this->getRepository();
2173
2174
        $mediaLocationId = $this->generateId('location', 43);
2175
        $demoDesignLocationId = $this->generateId('location', 56);
2176
        /* BEGIN: Use Case */
2177
        // $mediaLocationId is the ID of the "Media" page location in
2178
        // an eZ Publish demo installation
2179
2180
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2181
        // Publish demo installation
2182
2183
        // Load the location service
2184
        $locationService = $repository->getLocationService();
2185
2186
        // Load location to copy
2187
        $locationToCopy = $locationService->loadLocation($mediaLocationId);
2188
2189
        // Load new parent location
2190
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2191
2192
        // Copy location "Media" to "Demo Design"
2193
        $copiedLocation = $locationService->copySubtree(
2194
            $locationToCopy,
2195
            $newParentLocation
2196
        );
2197
        /* END: Use Case */
2198
2199
        $this->assertInstanceOf(
2200
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
2201
            $copiedLocation
2202
        );
2203
2204
        $this->assertPropertiesCorrect(
2205
            [
2206
                'depth' => $newParentLocation->depth + 1,
2207
                'parentLocationId' => $newParentLocation->id,
2208
                'pathString' => $newParentLocation->pathString . $this->parseId('location', $copiedLocation->id) . '/',
2209
            ],
2210
            $copiedLocation
2211
        );
2212
2213
        $this->assertDefaultContentStates($copiedLocation->contentInfo);
2214
    }
2215
2216
    /**
2217
     * Test for the copySubtree() method.
2218
     *
2219
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2220
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
2221
     */
2222
    public function testCopySubtreeWithAliases()
2223
    {
2224
        $repository = $this->getRepository();
2225
        $urlAliasService = $repository->getURLAliasService();
2226
2227
        // $mediaLocationId is the ID of the "Media" page location in
2228
        // an eZ Publish demo installation
2229
2230
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2231
        // Publish demo installation
2232
        $mediaLocationId = $this->generateId('location', 43);
2233
        $demoDesignLocationId = $this->generateId('location', 56);
2234
2235
        $locationService = $repository->getLocationService();
2236
        $locationToCopy = $locationService->loadLocation($mediaLocationId);
2237
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2238
2239
        $expectedSubItemAliases = [
2240
            '/Design/Plain-site/Media/Multimedia',
2241
            '/Design/Plain-site/Media/Images',
2242
            '/Design/Plain-site/Media/Files',
2243
        ];
2244
2245
        $this->assertAliasesBeforeCopy($urlAliasService, $expectedSubItemAliases);
2246
2247
        // Copy location "Media" to "Design"
2248
        $locationService->copySubtree(
2249
            $locationToCopy,
2250
            $newParentLocation
2251
        );
2252
2253
        $this->assertGeneratedAliases($urlAliasService, $expectedSubItemAliases);
2254
    }
2255
2256
    /**
2257
     * Asserts that given Content has default ContentStates.
2258
     *
2259
     * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo
2260
     */
2261
    private function assertDefaultContentStates(ContentInfo $contentInfo)
2262
    {
2263
        $repository = $this->getRepository();
2264
        $objectStateService = $repository->getObjectStateService();
2265
2266
        $objectStateGroups = $objectStateService->loadObjectStateGroups();
2267
2268
        foreach ($objectStateGroups as $objectStateGroup) {
2269
            $contentState = $objectStateService->getContentState($contentInfo, $objectStateGroup);
2270
            foreach ($objectStateService->loadObjectStates($objectStateGroup) as $objectState) {
2271
                // Only check the first object state which is the default one.
2272
                $this->assertEquals(
2273
                    $objectState,
2274
                    $contentState
2275
                );
2276
                break;
2277
            }
2278
        }
2279
    }
2280
2281
    /**
2282
     * Test for the copySubtree() method.
2283
     *
2284
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2285
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCopySubtree
2286
     */
2287
    public function testCopySubtreeUpdatesSubtreeProperties()
2288
    {
2289
        $repository = $this->getRepository();
2290
        $locationService = $repository->getLocationService();
2291
2292
        $locationToCopy = $locationService->loadLocation($this->generateId('location', 43));
2293
2294
        // Load Subtree properties before copy
2295
        $expected = $this->loadSubtreeProperties($locationToCopy);
2296
2297
        $mediaLocationId = $this->generateId('location', 43);
2298
        $demoDesignLocationId = $this->generateId('location', 56);
2299
        /* BEGIN: Use Case */
2300
        // $mediaLocationId is the ID of the "Media" page location in
2301
        // an eZ Publish demo installation
2302
2303
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2304
        // Publish demo installation
2305
2306
        // Load the location service
2307
        $locationService = $repository->getLocationService();
2308
2309
        // Load location to copy
2310
        $locationToCopy = $locationService->loadLocation($mediaLocationId);
2311
2312
        // Load new parent location
2313
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2314
2315
        // Copy location "Media" to "Demo Design"
2316
        $copiedLocation = $locationService->copySubtree(
2317
            $locationToCopy,
2318
            $newParentLocation
2319
        );
2320
        /* END: Use Case */
2321
2322
        $beforeIds = [];
2323
        foreach ($expected as $properties) {
2324
            $beforeIds[] = $properties['id'];
2325
        }
2326
2327
        $this->refreshSearch($repository);
2328
2329
        // Load Subtree properties after copy
2330
        $actual = $this->loadSubtreeProperties($copiedLocation);
2331
2332
        $this->assertEquals(count($expected), count($actual));
2333
2334
        foreach ($actual as $properties) {
2335
            $this->assertNotContains($properties['id'], $beforeIds);
2336
            $this->assertStringStartsWith(
2337
                $newParentLocation->pathString . $this->parseId('location', $copiedLocation->id) . '/',
2338
                $properties['pathString']
2339
            );
2340
            $this->assertStringEndsWith(
2341
                '/' . $this->parseId('location', $properties['id']) . '/',
2342
                $properties['pathString']
2343
            );
2344
        }
2345
    }
2346
2347
    /**
2348
     * Test for the copySubtree() method.
2349
     *
2350
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2351
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCopySubtree
2352
     */
2353
    public function testCopySubtreeIncrementsChildCountOfNewParent()
2354
    {
2355
        $repository = $this->getRepository();
2356
        $locationService = $repository->getLocationService();
2357
2358
        $childCountBefore = $locationService->getLocationChildCount($locationService->loadLocation(56));
2359
2360
        $mediaLocationId = $this->generateId('location', 43);
2361
        $demoDesignLocationId = $this->generateId('location', 56);
2362
        /* BEGIN: Use Case */
2363
        // $mediaLocationId is the ID of the "Media" page location in
2364
        // an eZ Publish demo installation
2365
2366
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2367
        // Publish demo installation
2368
2369
        // Load the location service
2370
        $locationService = $repository->getLocationService();
2371
2372
        // Load location to copy
2373
        $locationToCopy = $locationService->loadLocation($mediaLocationId);
2374
2375
        // Load new parent location
2376
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2377
2378
        // Copy location "Media" to "Demo Design"
2379
        $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...
2380
            $locationToCopy,
2381
            $newParentLocation
2382
        );
2383
        /* END: Use Case */
2384
2385
        $this->refreshSearch($repository);
2386
2387
        $childCountAfter = $locationService->getLocationChildCount($locationService->loadLocation($demoDesignLocationId));
2388
2389
        $this->assertEquals($childCountBefore + 1, $childCountAfter);
2390
    }
2391
2392
    /**
2393
     * Test for the copySubtree() method.
2394
     *
2395
     * @see \eZ\Publish\API\Repository\LocationService::copySubtree()
2396
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
2397
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCopySubtree
2398
     */
2399 View Code Duplication
    public function testCopySubtreeThrowsInvalidArgumentException()
2400
    {
2401
        $repository = $this->getRepository();
2402
2403
        $communityLocationId = $this->generateId('location', 5);
2404
        /* BEGIN: Use Case */
2405
        // $communityLocationId is the ID of the "Community" page location in
2406
        // an eZ Publish demo installation
2407
2408
        // Load the location service
2409
        $locationService = $repository->getLocationService();
2410
2411
        // Load location to copy
2412
        $locationToCopy = $locationService->loadLocation($communityLocationId);
2413
2414
        // Use a child as new parent
2415
        $childLocations = $locationService->loadLocationChildren($locationToCopy)->locations;
2416
        $newParentLocation = end($childLocations);
2417
2418
        // This call will fail with an "InvalidArgumentException", because the
2419
        // new parent is a child location of the subtree to copy.
2420
        $locationService->copySubtree(
2421
            $locationToCopy,
2422
            $newParentLocation
0 ignored issues
show
Security Bug introduced by
It seems like $newParentLocation defined by end($childLocations) on line 2416 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...
2423
        );
2424
        /* END: Use Case */
2425
    }
2426
2427
    /**
2428
     * Test for the moveSubtree() method.
2429
     *
2430
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2431
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
2432
     */
2433
    public function testMoveSubtree()
2434
    {
2435
        $repository = $this->getRepository();
2436
2437
        $mediaLocationId = $this->generateId('location', 43);
2438
        $demoDesignLocationId = $this->generateId('location', 56);
2439
        /* BEGIN: Use Case */
2440
        // $mediaLocationId is the ID of the "Media" page location in
2441
        // an eZ Publish demo installation
2442
2443
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2444
        // Publish demo installation
2445
2446
        // Load the location service
2447
        $locationService = $repository->getLocationService();
2448
2449
        // Load location to move
2450
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2451
2452
        // Load new parent location
2453
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2454
2455
        // Move location from "Home" to "Demo Design"
2456
        $locationService->moveSubtree(
2457
            $locationToMove,
2458
            $newParentLocation
2459
        );
2460
2461
        // Load moved location
2462
        $movedLocation = $locationService->loadLocation($mediaLocationId);
2463
        /* END: Use Case */
2464
2465
        $this->assertPropertiesCorrect(
2466
            [
2467
                'hidden' => false,
2468
                'invisible' => false,
2469
                'depth' => $newParentLocation->depth + 1,
2470
                'parentLocationId' => $newParentLocation->id,
2471
                'pathString' => $newParentLocation->pathString . $this->parseId('location', $movedLocation->id) . '/',
2472
            ],
2473
            $movedLocation
2474
        );
2475
    }
2476
2477
    /**
2478
     * Test for the moveSubtree() method.
2479
     *
2480
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2481
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2482
     */
2483
    public function testMoveSubtreeHidden()
2484
    {
2485
        $repository = $this->getRepository();
2486
2487
        $mediaLocationId = $this->generateId('location', 43);
2488
        $demoDesignLocationId = $this->generateId('location', 56);
2489
        /* BEGIN: Use Case */
2490
        // $mediaLocationId is the ID of the "Media" page location in
2491
        // an eZ Publish demo installation
2492
2493
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2494
        // Publish demo installation
2495
2496
        // Load the location service
2497
        $locationService = $repository->getLocationService();
2498
2499
        // Load location to move
2500
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2501
2502
        // Load new parent location
2503
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2504
2505
        // Hide the target location before we move
2506
        $newParentLocation = $locationService->hideLocation($newParentLocation);
2507
2508
        // Move location from "Home" to "Demo Design"
2509
        $locationService->moveSubtree(
2510
            $locationToMove,
2511
            $newParentLocation
2512
        );
2513
2514
        // Load moved location
2515
        $movedLocation = $locationService->loadLocation($mediaLocationId);
2516
        /* END: Use Case */
2517
2518
        $this->assertPropertiesCorrect(
2519
            [
2520
                'hidden' => false,
2521
                'invisible' => true,
2522
                'depth' => $newParentLocation->depth + 1,
2523
                'parentLocationId' => $newParentLocation->id,
2524
                'pathString' => $newParentLocation->pathString . $this->parseId('location', $movedLocation->id) . '/',
2525
            ],
2526
            $movedLocation
2527
        );
2528
    }
2529
2530
    /**
2531
     * Test for the moveSubtree() method.
2532
     *
2533
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2534
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2535
     */
2536
    public function testMoveSubtreeUpdatesSubtreeProperties()
2537
    {
2538
        $repository = $this->getRepository();
2539
        $locationService = $repository->getLocationService();
2540
2541
        $locationToMove = $locationService->loadLocation($this->generateId('location', 43));
2542
        $newParentLocation = $locationService->loadLocation($this->generateId('location', 56));
2543
2544
        // Load Subtree properties before move
2545
        $expected = $this->loadSubtreeProperties($locationToMove);
2546
        foreach ($expected as $id => $properties) {
2547
            $expected[$id]['depth'] = $properties['depth'] + 2;
2548
            $expected[$id]['pathString'] = str_replace(
2549
                $locationToMove->pathString,
2550
                $newParentLocation->pathString . $this->parseId('location', $locationToMove->id) . '/',
2551
                $properties['pathString']
2552
            );
2553
        }
2554
2555
        $mediaLocationId = $this->generateId('location', 43);
2556
        $demoDesignLocationId = $this->generateId('location', 56);
2557
        /* BEGIN: Use Case */
2558
        // $mediaLocationId is the ID of the "Media" page location in
2559
        // an eZ Publish demo installation
2560
2561
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2562
        // Publish demo installation
2563
2564
        // Load the location service
2565
        $locationService = $repository->getLocationService();
2566
2567
        // Load location to move
2568
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2569
2570
        // Load new parent location
2571
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2572
2573
        // Move location from "Home" to "Demo Design"
2574
        $locationService->moveSubtree(
2575
            $locationToMove,
2576
            $newParentLocation
2577
        );
2578
2579
        // Load moved location
2580
        $movedLocation = $locationService->loadLocation($mediaLocationId);
2581
        /* END: Use Case */
2582
2583
        $this->refreshSearch($repository);
2584
2585
        // Load Subtree properties after move
2586
        $actual = $this->loadSubtreeProperties($movedLocation);
2587
2588
        $this->assertEquals($expected, $actual);
2589
    }
2590
2591
    /**
2592
     * Test for the moveSubtree() method.
2593
     *
2594
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2595
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtreeUpdatesSubtreeProperties
2596
     */
2597
    public function testMoveSubtreeUpdatesSubtreePropertiesHidden()
2598
    {
2599
        $repository = $this->getRepository();
2600
        $locationService = $repository->getLocationService();
2601
2602
        $locationToMove = $locationService->loadLocation($this->generateId('location', 43));
2603
        $newParentLocation = $locationService->loadLocation($this->generateId('location', 56));
2604
2605
        // Hide the target location before we move
2606
        $newParentLocation = $locationService->hideLocation($newParentLocation);
2607
2608
        // Load Subtree properties before move
2609
        $expected = $this->loadSubtreeProperties($locationToMove);
2610
        foreach ($expected as $id => $properties) {
2611
            $expected[$id]['invisible'] = true;
2612
            $expected[$id]['depth'] = $properties['depth'] + 2;
2613
            $expected[$id]['pathString'] = str_replace(
2614
                $locationToMove->pathString,
2615
                $newParentLocation->pathString . $this->parseId('location', $locationToMove->id) . '/',
2616
                $properties['pathString']
2617
            );
2618
        }
2619
2620
        $mediaLocationId = $this->generateId('location', 43);
2621
        $demoDesignLocationId = $this->generateId('location', 56);
2622
        /* BEGIN: Use Case */
2623
        // $mediaLocationId is the ID of the "Media" page location in
2624
        // an eZ Publish demo installation
2625
2626
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2627
        // Publish demo installation
2628
2629
        // Load the location service
2630
        $locationService = $repository->getLocationService();
2631
2632
        // Load location to move
2633
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2634
2635
        // Load new parent location
2636
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2637
2638
        // Move location from "Home" to "Demo Design"
2639
        $locationService->moveSubtree(
2640
            $locationToMove,
2641
            $newParentLocation
2642
        );
2643
2644
        // Load moved location
2645
        $movedLocation = $locationService->loadLocation($mediaLocationId);
2646
        /* END: Use Case */
2647
2648
        $this->refreshSearch($repository);
2649
2650
        // Load Subtree properties after move
2651
        $actual = $this->loadSubtreeProperties($movedLocation);
2652
2653
        $this->assertEquals($expected, $actual);
2654
    }
2655
2656
    /**
2657
     * Test for the moveSubtree() method.
2658
     *
2659
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2660
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2661
     */
2662 View Code Duplication
    public function testMoveSubtreeIncrementsChildCountOfNewParent()
2663
    {
2664
        $repository = $this->getRepository();
2665
        $locationService = $repository->getLocationService();
2666
2667
        $newParentLocation = $locationService->loadLocation($this->generateId('location', 56));
2668
2669
        // Load expected properties before move
2670
        $expected = $this->loadLocationProperties($newParentLocation);
2671
        $childCountBefore = $locationService->getLocationChildCount($newParentLocation);
2672
2673
        $mediaLocationId = $this->generateId('location', 43);
2674
        $demoDesignLocationId = $this->generateId('location', 56);
2675
        /* BEGIN: Use Case */
2676
        // $mediaLocationId is the ID of the "Media" page location in
2677
        // an eZ Publish demo installation
2678
2679
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2680
        // Publish demo installation
2681
2682
        // Load the location service
2683
        $locationService = $repository->getLocationService();
2684
2685
        // Load location to move
2686
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2687
2688
        // Load new parent location
2689
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2690
2691
        // Move location from "Home" to "Demo Design"
2692
        $locationService->moveSubtree(
2693
            $locationToMove,
2694
            $newParentLocation
2695
        );
2696
2697
        // Load moved location
2698
        $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...
2699
2700
        // Reload new parent location
2701
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2702
        /* END: Use Case */
2703
2704
        $this->refreshSearch($repository);
2705
2706
        // Load Subtree properties after move
2707
        $actual = $this->loadLocationProperties($newParentLocation);
2708
        $childCountAfter = $locationService->getLocationChildCount($newParentLocation);
2709
2710
        $this->assertEquals($expected, $actual);
2711
        $this->assertEquals($childCountBefore + 1, $childCountAfter);
2712
    }
2713
2714
    /**
2715
     * Test for the moveSubtree() method.
2716
     *
2717
     * @see \eZ\Publish\API\Repository\LocationService::moveSubtree()
2718
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2719
     */
2720 View Code Duplication
    public function testMoveSubtreeDecrementsChildCountOfOldParent()
2721
    {
2722
        $repository = $this->getRepository();
2723
        $locationService = $repository->getLocationService();
2724
2725
        $oldParentLocation = $locationService->loadLocation($this->generateId('location', 1));
2726
2727
        // Load expected properties before move
2728
        $expected = $this->loadLocationProperties($oldParentLocation);
2729
        $childCountBefore = $locationService->getLocationChildCount($oldParentLocation);
2730
2731
        $mediaLocationId = $this->generateId('location', 43);
2732
        $demoDesignLocationId = $this->generateId('location', 56);
2733
        /* BEGIN: Use Case */
2734
        // $mediaLocationId is the ID of the "Media" page location in
2735
        // an eZ Publish demo installation
2736
2737
        // $demoDesignLocationId is the ID of the "Demo Design" page location in an eZ
2738
        // Publish demo installation
2739
2740
        // Load the location service
2741
        $locationService = $repository->getLocationService();
2742
2743
        // Load location to move
2744
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2745
2746
        // Get the location id of the old parent
2747
        $oldParentLocationId = $locationToMove->parentLocationId;
2748
2749
        // Load new parent location
2750
        $newParentLocation = $locationService->loadLocation($demoDesignLocationId);
2751
2752
        // Move location from "Home" to "Demo Design"
2753
        $locationService->moveSubtree(
2754
            $locationToMove,
2755
            $newParentLocation
2756
        );
2757
2758
        // Reload old parent location
2759
        $oldParentLocation = $locationService->loadLocation($oldParentLocationId);
2760
        /* END: Use Case */
2761
2762
        $this->refreshSearch($repository);
2763
2764
        // Load Subtree properties after move
2765
        $actual = $this->loadLocationProperties($oldParentLocation);
2766
        $childCountAfter = $locationService->getLocationChildCount($oldParentLocation);
2767
2768
        $this->assertEquals($expected, $actual);
2769
        $this->assertEquals($childCountBefore - 1, $childCountAfter);
2770
    }
2771
2772
    /**
2773
     * Test moving invisible (hidden by parent) subtree.
2774
     *
2775
     * @covers \eZ\Publish\API\Repository\LocationService::moveSubtree
2776
     *
2777
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
2778
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
2779
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
2780
     */
2781
    public function testMoveInvisibleSubtree()
2782
    {
2783
        $repository = $this->getRepository();
2784
        $locationService = $repository->getLocationService();
2785
2786
        $rootLocationId = 2;
2787
2788
        $folder = $this->createFolder(['eng-GB' => 'Folder'], $rootLocationId);
2789
        $child = $this->createFolder(['eng-GB' => 'Child'], $folder->contentInfo->mainLocationId);
2790
        $locationService->hideLocation(
2791
            $locationService->loadLocation($folder->contentInfo->mainLocationId)
2792
        );
2793
        // sanity check
2794
        $childLocation = $locationService->loadLocation($child->contentInfo->mainLocationId);
2795
        self::assertFalse($childLocation->hidden);
2796
        self::assertTrue($childLocation->invisible);
2797
        self::assertEquals($folder->contentInfo->mainLocationId, $childLocation->parentLocationId);
2798
2799
        $destination = $this->createFolder(['eng-GB' => 'Destination'], $rootLocationId);
2800
        $destinationLocation = $locationService->loadLocation(
2801
            $destination->contentInfo->mainLocationId
2802
        );
2803
2804
        $locationService->moveSubtree($childLocation, $destinationLocation);
2805
2806
        $childLocation = $locationService->loadLocation($child->contentInfo->mainLocationId);
2807
        // Business logic - Location moved to visible parent becomes visible
2808
        self::assertFalse($childLocation->hidden);
2809
        self::assertFalse($childLocation->invisible);
2810
        self::assertEquals($destinationLocation->id, $childLocation->parentLocationId);
2811
    }
2812
2813
    /**
2814
     * Test for the moveSubtree() method.
2815
     *
2816
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testMoveSubtree
2817
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
2818
     */
2819 View Code Duplication
    public function testMoveSubtreeThrowsInvalidArgumentException()
2820
    {
2821
        $repository = $this->getRepository();
2822
        $mediaLocationId = $this->generateId('location', 43);
2823
        $multimediaLocationId = $this->generateId('location', 53);
2824
2825
        /* BEGIN: Use Case */
2826
        // $mediaLocationId is the ID of the "Media" page location in
2827
        // an eZ Publish demo installation
2828
2829
        // $multimediaLocationId is the ID of the "Multimedia" page location in an eZ
2830
        // Publish demo installation
2831
2832
        // Load the location service
2833
        $locationService = $repository->getLocationService();
2834
2835
        // Load location to move
2836
        $locationToMove = $locationService->loadLocation($mediaLocationId);
2837
2838
        // Load new parent location
2839
        $newParentLocation = $locationService->loadLocation($multimediaLocationId);
2840
2841
        // Throws an exception because new parent location is placed below location to move
2842
        $locationService->moveSubtree(
2843
            $locationToMove,
2844
            $newParentLocation
2845
        );
2846
        /* END: Use Case */
2847
    }
2848
2849
    /**
2850
     * Test that Legacy ezcontentobject_tree.path_identification_string field is correctly updated
2851
     * after moving subtree.
2852
     *
2853
     * @covers \eZ\Publish\API\Repository\LocationService::moveSubtree
2854
     *
2855
     * @throws \ErrorException
2856
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
2857
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
2858
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
2859
     */
2860
    public function testMoveSubtreeUpdatesPathIdentificationString(): void
2861
    {
2862
        $repository = $this->getRepository();
2863
        $locationService = $repository->getLocationService();
2864
2865
        $topNode = $this->createFolder(['eng-US' => 'top_node'], 2);
2866
2867
        $newParentLocation = $locationService->loadLocation(
2868
            $this
2869
                ->createFolder(['eng-US' => 'Parent'], $topNode->contentInfo->mainLocationId)
2870
                ->contentInfo
2871
                ->mainLocationId
2872
        );
2873
        $location = $locationService->loadLocation(
2874
            $this
2875
                ->createFolder(['eng-US' => 'Move Me'], $topNode->contentInfo->mainLocationId)
2876
                ->contentInfo
2877
                ->mainLocationId
2878
        );
2879
2880
        $locationService->moveSubtree($location, $newParentLocation);
2881
2882
        // path location string is not present on API level, so we need to query database
2883
        $serviceContainer = $this->getSetupFactory()->getServiceContainer();
2884
        /** @var \Doctrine\DBAL\Connection $connection */
2885
        $connection = $serviceContainer->get('ezpublish.persistence.connection');
2886
        $query = $connection->createQueryBuilder();
2887
        $query
2888
            ->select('path_identification_string')
2889
            ->from('ezcontentobject_tree')
2890
            ->where('node_id = :nodeId')
2891
            ->setParameter('nodeId', $location->id);
2892
2893
        self::assertEquals(
2894
            'top_node/parent/move_me',
2895
            $query->execute()->fetchColumn()
2896
        );
2897
    }
2898
2899
    /**
2900
     * Loads properties from all locations in the $location's subtree.
2901
     *
2902
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
2903
     * @param array $properties
2904
     *
2905
     * @return array
2906
     */
2907
    private function loadSubtreeProperties(Location $location, array $properties = [])
2908
    {
2909
        $locationService = $this->getRepository()->getLocationService();
2910
2911
        foreach ($locationService->loadLocationChildren($location)->locations as $childLocation) {
2912
            $properties[] = $this->loadLocationProperties($childLocation);
2913
2914
            $properties = $this->loadSubtreeProperties($childLocation, $properties);
2915
        }
2916
2917
        return $properties;
2918
    }
2919
2920
    /**
2921
     * Loads assertable properties from the given location.
2922
     *
2923
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
2924
     * @param mixed[] $overwrite
2925
     *
2926
     * @return array
2927
     */
2928 View Code Duplication
    private function loadLocationProperties(Location $location, array $overwrite = [])
2929
    {
2930
        return array_merge(
2931
            [
2932
                'id' => $location->id,
2933
                'depth' => $location->depth,
2934
                'parentLocationId' => $location->parentLocationId,
2935
                'pathString' => $location->pathString,
2936
                'remoteId' => $location->remoteId,
2937
                'hidden' => $location->hidden,
2938
                'invisible' => $location->invisible,
2939
                'priority' => $location->priority,
2940
                'sortField' => $location->sortField,
2941
                'sortOrder' => $location->sortOrder,
2942
            ],
2943
            $overwrite
2944
        );
2945
    }
2946
2947
    /**
2948
     * Assert generated aliases to expected alias return.
2949
     *
2950
     * @param \eZ\Publish\API\Repository\URLAliasService $urlAliasService
2951
     * @param array $expectedAliases
2952
     */
2953
    protected function assertGeneratedAliases($urlAliasService, array $expectedAliases)
2954
    {
2955
        foreach ($expectedAliases as $expectedAlias) {
2956
            $urlAlias = $urlAliasService->lookup($expectedAlias);
2957
            $this->assertPropertiesCorrect(['type' => 0], $urlAlias);
2958
        }
2959
    }
2960
2961
    /**
2962
     * @param \eZ\Publish\API\Repository\URLAliasService $urlAliasService
2963
     * @param array $expectedSubItemAliases
2964
     */
2965
    private function assertAliasesBeforeCopy($urlAliasService, array $expectedSubItemAliases)
2966
    {
2967
        foreach ($expectedSubItemAliases as $aliasUrl) {
2968
            try {
2969
                $urlAliasService->lookup($aliasUrl);
2970
                $this->fail('We didn\'t expect to find alias, but it was found');
2971
            } catch (\Exception $e) {
2972
                $this->assertTrue(true); // OK - alias was not found
2973
            }
2974
        }
2975
    }
2976
2977
    /**
2978
     * Create and publish Content with the given parent Location.
2979
     *
2980
     * @param string $contentName
2981
     * @param int $parentLocationId
2982
     *
2983
     * @return \eZ\Publish\API\Repository\Values\Content\Content published Content
2984
     */
2985 View Code Duplication
    private function publishContentWithParentLocation($contentName, $parentLocationId)
2986
    {
2987
        $repository = $this->getRepository(false);
2988
        $locationService = $repository->getLocationService();
2989
2990
        $contentService = $repository->getContentService();
2991
        $contentTypeService = $repository->getContentTypeService();
2992
2993
        $contentCreateStruct = $contentService->newContentCreateStruct(
2994
            $contentTypeService->loadContentTypeByIdentifier('folder'),
2995
            'eng-US'
2996
        );
2997
        $contentCreateStruct->setField('name', $contentName);
2998
        $contentDraft = $contentService->createContent(
2999
            $contentCreateStruct,
3000
            [
3001
                $locationService->newLocationCreateStruct($parentLocationId),
3002
            ]
3003
        );
3004
3005
        return $contentService->publishVersion($contentDraft->versionInfo);
3006
    }
3007
}
3008