Completed
Push — EZP-31112-custom-aliases-gone-... ( b328b9...058804 )
by
unknown
22:36
created

testSwapLocationForContentWithCustomUrlAliases()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 33
rs 9.392
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the LocationServiceTest class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\API\Repository\Tests;
10
11
use Exception;
12
use eZ\Publish\API\Repository\Exceptions\BadStateException;
13
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
14
use eZ\Publish\API\Repository\Values\Content\Content;
15
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
16
use eZ\Publish\API\Repository\Values\Content\Location;
17
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
18
use eZ\Publish\API\Repository\Values\Content\LocationList;
19
use eZ\Publish\API\Repository\Values\Content\LocationUpdateStruct;
20
use eZ\Publish\API\Repository\Values\Content\Query;
21
use eZ\Publish\API\Repository\Values\Content\Search\SearchHit;
22
23
/**
24
 * Test case for operations in the LocationService using in memory storage.
25
 *
26
 * @see eZ\Publish\API\Repository\LocationService
27
 * @group location
28
 */
29
class LocationServiceTest extends BaseTest
30
{
31
    /**
32
     * Test for the newLocationCreateStruct() method.
33
     *
34
     * @return \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct
35
     *
36
     * @see \eZ\Publish\API\Repository\LocationService::newLocationCreateStruct()
37
     */
38
    public function testNewLocationCreateStruct()
39
    {
40
        $repository = $this->getRepository();
41
42
        $parentLocationId = $this->generateId('location', 1);
43
        /* BEGIN: Use Case */
44
        // $parentLocationId is the ID of an existing location
45
        $locationService = $repository->getLocationService();
46
47
        $locationCreate = $locationService->newLocationCreateStruct(
48
            $parentLocationId
49
        );
50
        /* END: Use Case */
51
52
        $this->assertInstanceOf(
53
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\LocationCreateStruct',
54
            $locationCreate
55
        );
56
57
        return $locationCreate;
58
    }
59
60
    /**
61
     * Test for the newLocationCreateStruct() method.
62
     *
63
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct $locationCreate
64
     *
65
     * @see \eZ\Publish\API\Repository\LocationService::newLocationCreateStruct()
66
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
67
     */
68
    public function testNewLocationCreateStructValues(LocationCreateStruct $locationCreate)
69
    {
70
        $this->assertPropertiesCorrect(
71
            [
72
                'priority' => 0,
73
                'hidden' => false,
74
                // remoteId should be initialized with a default value
75
                //'remoteId' => null,
76
                'sortField' => Location::SORT_FIELD_NAME,
77
                'sortOrder' => Location::SORT_ORDER_ASC,
78
                'parentLocationId' => $this->generateId('location', 1),
79
            ],
80
            $locationCreate
81
        );
82
    }
83
84
    /**
85
     * Test for the createLocation() method.
86
     *
87
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
88
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
89
     */
90
    public function testCreateLocation()
91
    {
92
        $repository = $this->getRepository();
93
94
        $contentId = $this->generateId('object', 41);
95
        $parentLocationId = $this->generateId('location', 5);
96
        /* BEGIN: Use Case */
97
        // $contentId is the ID of an existing content object
98
        // $parentLocationId is the ID of an existing location
99
        $contentService = $repository->getContentService();
100
        $locationService = $repository->getLocationService();
101
102
        // ContentInfo for "How to use eZ Publish"
103
        $contentInfo = $contentService->loadContentInfo($contentId);
104
105
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
106
        $locationCreate->priority = 23;
107
        $locationCreate->hidden = true;
108
        $locationCreate->remoteId = 'sindelfingen';
109
        $locationCreate->sortField = Location::SORT_FIELD_NODE_ID;
110
        $locationCreate->sortOrder = Location::SORT_ORDER_DESC;
111
112
        $location = $locationService->createLocation(
113
            $contentInfo,
114
            $locationCreate
115
        );
116
        /* END: Use Case */
117
118
        $this->assertInstanceOf(
119
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
120
            $location
121
        );
122
123
        return [
124
            'locationCreate' => $locationCreate,
125
            'createdLocation' => $location,
126
            'contentInfo' => $contentInfo,
127
            'parentLocation' => $locationService->loadLocation($this->generateId('location', 5)),
128
        ];
129
    }
130
131
    /**
132
     * Test for the createLocation() method.
133
     *
134
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
135
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
136
     */
137
    public function testCreateLocationStructValues(array $data)
138
    {
139
        $locationCreate = $data['locationCreate'];
140
        $createdLocation = $data['createdLocation'];
141
        $contentInfo = $data['contentInfo'];
142
143
        $this->assertPropertiesCorrect(
144
            [
145
                'priority' => $locationCreate->priority,
146
                'hidden' => $locationCreate->hidden,
147
                'invisible' => $locationCreate->hidden,
148
                'remoteId' => $locationCreate->remoteId,
149
                'contentInfo' => $contentInfo,
150
                'parentLocationId' => $locationCreate->parentLocationId,
151
                'pathString' => '/1/5/' . $this->parseId('location', $createdLocation->id) . '/',
152
                'depth' => 2,
153
                'sortField' => $locationCreate->sortField,
154
                'sortOrder' => $locationCreate->sortOrder,
155
            ],
156
            $createdLocation
157
        );
158
159
        $this->assertNotNull($createdLocation->id);
160
    }
161
162
    /**
163
     * Test for the createLocation() method.
164
     *
165
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
166
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
167
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
168
     */
169 View Code Duplication
    public function testCreateLocationThrowsInvalidArgumentExceptionContentAlreadyBelowParent()
170
    {
171
        $repository = $this->getRepository();
172
173
        $contentId = $this->generateId('object', 11);
174
        $parentLocationId = $this->generateId('location', 5);
175
        /* BEGIN: Use Case */
176
        // $contentId is the ID of an existing content object
177
        // $parentLocationId is the ID of an existing location which already
178
        // has the content assigned to one of its descendant locations
179
        $contentService = $repository->getContentService();
180
        $locationService = $repository->getLocationService();
181
182
        // ContentInfo for "How to use eZ Publish"
183
        $contentInfo = $contentService->loadContentInfo($contentId);
184
185
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
186
187
        // Throws exception, since content is already located at "/1/2/107/110/"
188
        $locationService->createLocation(
189
            $contentInfo,
190
            $locationCreate
191
        );
192
        /* END: Use Case */
193
    }
194
195
    /**
196
     * Test for the createLocation() method.
197
     *
198
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
199
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
200
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
201
     */
202 View Code Duplication
    public function testCreateLocationThrowsInvalidArgumentExceptionParentIsSubLocationOfContent()
203
    {
204
        $repository = $this->getRepository();
205
206
        $contentId = $this->generateId('object', 4);
207
        $parentLocationId = $this->generateId('location', 12);
208
        /* BEGIN: Use Case */
209
        // $contentId is the ID of an existing content object
210
        // $parentLocationId is the ID of an existing location which is below a
211
        // location that is assigned to the content
212
        $contentService = $repository->getContentService();
213
        $locationService = $repository->getLocationService();
214
215
        // ContentInfo for "How to use eZ Publish"
216
        $contentInfo = $contentService->loadContentInfo($contentId);
217
218
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
219
220
        // Throws exception, since content is already located at "/1/2/"
221
        $locationService->createLocation(
222
            $contentInfo,
223
            $locationCreate
224
        );
225
        /* END: Use Case */
226
    }
227
228
    /**
229
     * Test for the createLocation() method.
230
     *
231
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
232
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
233
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
234
     */
235 View Code Duplication
    public function testCreateLocationThrowsInvalidArgumentExceptionRemoteIdExists()
236
    {
237
        $repository = $this->getRepository();
238
239
        $contentId = $this->generateId('object', 41);
240
        $parentLocationId = $this->generateId('location', 5);
241
        /* BEGIN: Use Case */
242
        // $contentId is the ID of an existing content object
243
        $contentService = $repository->getContentService();
244
        $locationService = $repository->getLocationService();
245
246
        // ContentInfo for "How to use eZ Publish"
247
        $contentInfo = $contentService->loadContentInfo($contentId);
248
249
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
250
        // This remote ID already exists
251
        $locationCreate->remoteId = 'f3e90596361e31d496d4026eb624c983';
252
253
        // Throws exception, since remote ID is already in use
254
        $locationService->createLocation(
255
            $contentInfo,
256
            $locationCreate
257
        );
258
        /* END: Use Case */
259
    }
260
261
    /**
262
     * Test for the createLocation() method.
263
     *
264
     * @covers \eZ\Publish\API\Repository\LocationService::createLocation()
265
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
266
     * @dataProvider dataProviderForOutOfRangeLocationPriority
267
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
268
     */
269 View Code Duplication
    public function testCreateLocationThrowsInvalidArgumentExceptionPriorityIsOutOfRange($priority)
270
    {
271
        $repository = $this->getRepository();
272
273
        $contentId = $this->generateId('object', 41);
274
        $parentLocationId = $this->generateId('location', 5);
275
        /* BEGIN: Use Case */
276
        // $contentId is the ID of an existing content object
277
        // $parentLocationId is the ID of an existing location
278
        $contentService = $repository->getContentService();
279
        $locationService = $repository->getLocationService();
280
281
        // ContentInfo for "How to use eZ Publish"
282
        $contentInfo = $contentService->loadContentInfo($contentId);
283
284
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
285
        $locationCreate->priority = $priority;
286
        $locationCreate->hidden = true;
287
        $locationCreate->remoteId = 'sindelfingen';
288
        $locationCreate->sortField = Location::SORT_FIELD_NODE_ID;
289
        $locationCreate->sortOrder = Location::SORT_ORDER_DESC;
290
291
        // Throws exception, since priority is out of range
292
        $locationService->createLocation(
293
            $contentInfo,
294
            $locationCreate
295
        );
296
        /* END: Use Case */
297
    }
298
299
    public function dataProviderForOutOfRangeLocationPriority()
300
    {
301
        return [[-2147483649], [2147483648]];
302
    }
303
304
    /**
305
     * Test for the createLocation() method.
306
     *
307
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
308
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
309
     */
310
    public function testCreateLocationInTransactionWithRollback()
311
    {
312
        $repository = $this->getRepository();
313
314
        $contentId = $this->generateId('object', 41);
315
        $parentLocationId = $this->generateId('location', 5);
316
        /* BEGIN: Use Case */
317
        // $contentId is the ID of an existing content object
318
        // $parentLocationId is the ID of an existing location
319
        $contentService = $repository->getContentService();
320
        $locationService = $repository->getLocationService();
321
322
        $repository->beginTransaction();
323
324
        try {
325
            // ContentInfo for "How to use eZ Publish"
326
            $contentInfo = $contentService->loadContentInfo($contentId);
327
328
            $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
329
            $locationCreate->remoteId = 'sindelfingen';
330
331
            $createdLocationId = $locationService->createLocation(
332
                $contentInfo,
333
                $locationCreate
334
            )->id;
335
        } catch (Exception $e) {
336
            // Cleanup hanging transaction on error
337
            $repository->rollback();
338
            throw $e;
339
        }
340
341
        $repository->rollback();
342
343
        try {
344
            // Throws exception since creation of location was rolled back
345
            $location = $locationService->loadLocation($createdLocationId);
0 ignored issues
show
Unused Code introduced by
$location is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
346
        } catch (NotFoundException $e) {
347
            return;
348
        }
349
        /* END: Use Case */
350
351
        $this->fail('Objects still exists after rollback.');
352
    }
353
354
    /**
355
     * Test for the loadLocation() method.
356
     *
357
     * @return \eZ\Publish\API\Repository\Values\Content\Location
358
     *
359
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocation
360
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
361
     */
362
    public function testLoadLocation()
363
    {
364
        $repository = $this->getRepository();
365
366
        $locationId = $this->generateId('location', 5);
367
        /* BEGIN: Use Case */
368
        // $locationId is the ID of an existing location
369
        $locationService = $repository->getLocationService();
370
371
        $location = $locationService->loadLocation($locationId);
372
        /* END: Use Case */
373
374
        $this->assertInstanceOf(
375
            Location::class,
376
            $location
377
        );
378
        self::assertEquals(5, $location->id);
379
380
        return $location;
381
    }
382
383
    /**
384
     * Test for the loadLocation() method.
385
     *
386
     * @see \eZ\Publish\API\Repository\LocationService::loadLocation()
387
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
388
     */
389
    public function testLoadLocationRootStructValues()
390
    {
391
        $repository = $this->getRepository();
392
        $locationService = $repository->getLocationService();
393
        $location = $locationService->loadLocation($this->generateId('location', 1));
394
395
        $this->assertRootLocationStructValues($location);
396
    }
397
398
    public function testLoadLocationRootStructValuesWithPrioritizedLanguages(): void
399
    {
400
        $repository = $this->getRepository();
401
402
        $rootLocation = $repository
403
            ->getLocationService()
404
            ->loadLocation(
405
                $this->generateId('location', 1),
406
                [
407
                    'eng-GB',
408
                    'ger-DE',
409
                ]
410
            );
411
412
        $this->assertRootLocationStructValues($rootLocation);
413
    }
414
415
    private function assertRootLocationStructValues(Location $location): void
416
    {
417
        $legacyDateTime = new \DateTime();
418
        $legacyDateTime->setTimestamp(1030968000);
419
420
        $this->assertInstanceOf(Location::class, $location);
421
        $this->assertPropertiesCorrect(
422
            [
423
                'id' => $this->generateId('location', 1),
424
                'status' => 1,
425
                'priority' => 0,
426
                'hidden' => false,
427
                'invisible' => false,
428
                'remoteId' => '629709ba256fe317c3ddcee35453a96a',
429
                'parentLocationId' => $this->generateId('location', 1),
430
                'pathString' => '/1/',
431
                'depth' => 0,
432
                'sortField' => 1,
433
                'sortOrder' => 1,
434
            ],
435
            $location
436
        );
437
438
        $this->assertInstanceOf(ContentInfo::class, $location->contentInfo);
439
        $this->assertPropertiesCorrect(
440
            [
441
                'id' => $this->generateId('content', 0),
442
                'name' => 'Top Level Nodes',
443
                'sectionId' => 1,
444
                'mainLocationId' => 1,
445
                'contentTypeId' => 1,
446
                'currentVersionNo' => 1,
447
                'published' => 1,
448
                'ownerId' => 14,
449
                'modificationDate' => $legacyDateTime,
450
                'publishedDate' => $legacyDateTime,
451
                'alwaysAvailable' => 1,
452
                'remoteId' => null,
453
                'mainLanguageCode' => 'eng-GB',
454
            ],
455
            $location->contentInfo
456
        );
457
    }
458
459
    /**
460
     * Test for the loadLocation() method.
461
     *
462
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
463
     *
464
     * @see \eZ\Publish\API\Repository\LocationService::loadLocation()
465
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
466
     */
467
    public function testLoadLocationStructValues(Location $location)
468
    {
469
        $this->assertPropertiesCorrect(
470
            [
471
                'id' => $this->generateId('location', 5),
472
                'priority' => 0,
473
                'hidden' => false,
474
                'invisible' => false,
475
                'remoteId' => '3f6d92f8044aed134f32153517850f5a',
476
                'parentLocationId' => $this->generateId('location', 1),
477
                'pathString' => '/1/5/',
478
                'depth' => 1,
479
                'sortField' => 1,
480
                'sortOrder' => 1,
481
            ],
482
            $location
483
        );
484
485
        $this->assertInstanceOf(
486
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo',
487
            $location->contentInfo
488
        );
489
        $this->assertEquals($this->generateId('object', 4), $location->contentInfo->id);
490
491
        // Check lazy loaded proxy on ->content
492
        $this->assertInstanceOf(
493
            Content::class,
494
            $content = $location->getContent()
495
        );
496
        $this->assertEquals(4, $content->contentInfo->id);
497
    }
498
499
    public function testLoadLocationPrioritizedLanguagesFallback()
500
    {
501
        $repository = $this->getRepository();
502
503
        // Add a language
504
        $this->createLanguage('nor-NO', 'Norsk');
505
506
        $locationService = $repository->getLocationService();
507
        $contentService = $repository->getContentService();
508
        $location = $locationService->loadLocation(5);
509
510
        // Translate "Users"
511
        $draft = $contentService->createContentDraft($location->contentInfo);
512
        $struct = $contentService->newContentUpdateStruct();
513
        $struct->setField('name', 'Brukere', 'nor-NO');
514
        $draft = $contentService->updateContent($draft->getVersionInfo(), $struct);
515
        $contentService->publishVersion($draft->getVersionInfo());
516
517
        // Load with priority language (fallback will be the old one)
518
        $location = $locationService->loadLocation(5, ['nor-NO']);
519
520
        $this->assertInstanceOf(
521
            Location::class,
522
            $location
523
        );
524
        self::assertEquals(5, $location->id);
525
        $this->assertInstanceOf(
526
            Content::class,
527
            $content = $location->getContent()
528
        );
529
        $this->assertEquals(4, $content->contentInfo->id);
530
531
        $this->assertEquals($content->getVersionInfo()->getName(), 'Brukere');
532
        $this->assertEquals($content->getVersionInfo()->getName('eng-US'), 'Users');
533
    }
534
535
    /**
536
     * Test that accessing lazy-loaded Content without a translation in the specific
537
     * not available language throws NotFoundException.
538
     */
539
    public function testLoadLocationThrowsNotFoundExceptionForNotAvailableContent(): void
540
    {
541
        $repository = $this->getRepository();
542
543
        $locationService = $repository->getLocationService();
544
545
        $this->createLanguage('pol-PL', 'Polski');
546
547
        $this->expectException(NotFoundException::class);
548
549
        // Note: relying on existing database fixtures to make test case more readable
550
        $locationService->loadLocation(60, ['pol-PL']);
551
    }
552
553
    /**
554
     * Test for the loadLocation() method.
555
     *
556
     * @see \eZ\Publish\API\Repository\LocationService::loadLocation()
557
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
558
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
559
     */
560
    public function testLoadLocationThrowsNotFoundException()
561
    {
562
        $repository = $this->getRepository();
563
564
        $nonExistentLocationId = $this->generateId('location', 2342);
565
        /* BEGIN: Use Case */
566
        $locationService = $repository->getLocationService();
567
568
        // Throws exception, if Location with $nonExistentLocationId does not
569
        // exist
570
        $location = $locationService->loadLocation($nonExistentLocationId);
0 ignored issues
show
Unused Code introduced by
$location is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
571
        /* END: Use Case */
572
    }
573
574
    /**
575
     * Test for the loadLocationList() method.
576
     *
577
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
578
     */
579 View Code Duplication
    public function testLoadLocationList(): void
580
    {
581
        $repository = $this->getRepository();
582
583
        // 5 is the ID of an existing location, 442 is a non-existing id
584
        $locationService = $repository->getLocationService();
585
        $locations = $locationService->loadLocationList([5, 442]);
586
587
        self::assertInternalType('iterable', $locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

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

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

Loading history...
588
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLocationList(array(5, 442)) on line 585 can also be of type array<integer,object<eZ\...lues\Content\Location>>; however, PHPUnit\Framework\Assert::assertCount() does only seem to accept object<Countable>|object...nit\Framework\iterable>, maybe add an additional type check?

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

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

    return array();
}

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

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

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

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

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

Loading history...
611
        self::assertCount(0, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLo...array('pol-PL'), false) on line 608 can also be of type array<integer,object<eZ\...lues\Content\Location>>; however, PHPUnit\Framework\Assert::assertCount() does only seem to accept object<Countable>|object...nit\Framework\iterable>, maybe add an additional type check?

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

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

    return array();
}

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

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

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

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

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

Loading history...
631
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLo... array('pol-PL'), true) on line 628 can also be of type array<integer,object<eZ\...lues\Content\Location>>; however, PHPUnit\Framework\Assert::assertCount() does only seem to accept object<Countable>|object...nit\Framework\iterable>, maybe add an additional type check?

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

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

    return array();
}

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

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

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

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

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

Loading history...
651
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLocationList(array(1)) on line 648 can also be of type array<integer,object<eZ\...lues\Content\Location>>; however, PHPUnit\Framework\Assert::assertCount() does only seem to accept object<Countable>|object...nit\Framework\iterable>, maybe add an additional type check?

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

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

    return array();
}

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

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

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