Completed
Push — ezp_30973 ( 1b82fd...a5777c )
by
unknown
12:50
created

assertRootLocationStructValues()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 43
rs 9.232
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the LocationServiceTest class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\API\Repository\Tests;
10
11
use Exception;
12
use eZ\Publish\API\Repository\Exceptions\BadStateException;
13
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
14
use eZ\Publish\API\Repository\Values\Content\Content;
15
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
16
use eZ\Publish\API\Repository\Values\Content\Location;
17
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
18
use eZ\Publish\API\Repository\Values\Content\LocationList;
19
use eZ\Publish\API\Repository\Values\Content\LocationUpdateStruct;
20
use eZ\Publish\API\Repository\Values\Content\Query;
21
use eZ\Publish\API\Repository\Values\Content\Search\SearchHit;
22
23
/**
24
 * Test case for operations in the LocationService using in memory storage.
25
 *
26
 * @see eZ\Publish\API\Repository\LocationService
27
 * @group location
28
 */
29
class LocationServiceTest extends BaseTest
30
{
31
    /**
32
     * Test for the newLocationCreateStruct() method.
33
     *
34
     * @return \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct
35
     *
36
     * @see \eZ\Publish\API\Repository\LocationService::newLocationCreateStruct()
37
     */
38 View Code Duplication
    public function testNewLocationCreateStruct()
39
    {
40
        $repository = $this->getRepository();
41
42
        $parentLocationId = $this->generateId('location', 1);
43
        /* BEGIN: Use Case */
44
        // $parentLocationId is the ID of an existing location
45
        $locationService = $repository->getLocationService();
46
47
        $locationCreate = $locationService->newLocationCreateStruct(
48
            $parentLocationId
49
        );
50
        /* END: Use Case */
51
52
        $this->assertInstanceOf(
53
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\LocationCreateStruct',
54
            $locationCreate
55
        );
56
57
        return $locationCreate;
58
    }
59
60
    /**
61
     * Test for the newLocationCreateStruct() method.
62
     *
63
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct $locationCreate
64
     *
65
     * @see \eZ\Publish\API\Repository\LocationService::newLocationCreateStruct()
66
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
67
     */
68
    public function testNewLocationCreateStructValues(LocationCreateStruct $locationCreate)
69
    {
70
        $this->assertPropertiesCorrect(
71
            [
72
                'priority' => 0,
73
                'hidden' => false,
74
                // remoteId should be initialized with a default value
75
                //'remoteId' => null,
76
                'sortField' => Location::SORT_FIELD_NAME,
77
                'sortOrder' => Location::SORT_ORDER_ASC,
78
                'parentLocationId' => $this->generateId('location', 1),
79
            ],
80
            $locationCreate
81
        );
82
    }
83
84
    /**
85
     * Test for the createLocation() method.
86
     *
87
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
88
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
89
     */
90
    public function testCreateLocation()
91
    {
92
        $repository = $this->getRepository();
93
94
        $contentId = $this->generateId('object', 41);
95
        $parentLocationId = $this->generateId('location', 5);
96
        /* BEGIN: Use Case */
97
        // $contentId is the ID of an existing content object
98
        // $parentLocationId is the ID of an existing location
99
        $contentService = $repository->getContentService();
100
        $locationService = $repository->getLocationService();
101
102
        // ContentInfo for "How to use eZ Publish"
103
        $contentInfo = $contentService->loadContentInfo($contentId);
104
105
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
106
        $locationCreate->priority = 23;
107
        $locationCreate->hidden = true;
108
        $locationCreate->remoteId = 'sindelfingen';
109
        $locationCreate->sortField = Location::SORT_FIELD_NODE_ID;
110
        $locationCreate->sortOrder = Location::SORT_ORDER_DESC;
111
112
        $location = $locationService->createLocation(
113
            $contentInfo,
114
            $locationCreate
115
        );
116
        /* END: Use Case */
117
118
        $this->assertInstanceOf(
119
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
120
            $location
121
        );
122
123
        return [
124
            'locationCreate' => $locationCreate,
125
            'createdLocation' => $location,
126
            'contentInfo' => $contentInfo,
127
            'parentLocation' => $locationService->loadLocation($this->generateId('location', 5)),
128
        ];
129
    }
130
131
    /**
132
     * Test for the createLocation() method.
133
     *
134
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
135
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
136
     */
137
    public function testCreateLocationStructValues(array $data)
138
    {
139
        $locationCreate = $data['locationCreate'];
140
        $createdLocation = $data['createdLocation'];
141
        $contentInfo = $data['contentInfo'];
142
143
        $this->assertPropertiesCorrect(
144
            [
145
                'priority' => $locationCreate->priority,
146
                'hidden' => $locationCreate->hidden,
147
                'invisible' => $locationCreate->hidden,
148
                'remoteId' => $locationCreate->remoteId,
149
                'contentInfo' => $contentInfo,
150
                'parentLocationId' => $locationCreate->parentLocationId,
151
                'pathString' => '/1/5/' . $this->parseId('location', $createdLocation->id) . '/',
152
                'depth' => 2,
153
                'sortField' => $locationCreate->sortField,
154
                'sortOrder' => $locationCreate->sortOrder,
155
            ],
156
            $createdLocation
157
        );
158
159
        $this->assertNotNull($createdLocation->id);
160
    }
161
162
    /**
163
     * Test for the createLocation() method.
164
     *
165
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
166
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
167
     */
168
    public function testCreateLocationThrowsInvalidArgumentExceptionContentAlreadyBelowParent()
169
    {
170
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
171
172
        $repository = $this->getRepository();
173
174
        $contentId = $this->generateId('object', 11);
175
        $parentLocationId = $this->generateId('location', 5);
176
        /* BEGIN: Use Case */
177
        // $contentId is the ID of an existing content object
178
        // $parentLocationId is the ID of an existing location which already
179
        // has the content assigned to one of its descendant locations
180
        $contentService = $repository->getContentService();
181
        $locationService = $repository->getLocationService();
182
183
        // ContentInfo for "How to use eZ Publish"
184
        $contentInfo = $contentService->loadContentInfo($contentId);
185
186
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
187
188
        // Throws exception, since content is already located at "/1/2/107/110/"
189
        $locationService->createLocation(
190
            $contentInfo,
191
            $locationCreate
192
        );
193
        /* END: Use Case */
194
    }
195
196
    /**
197
     * Test for the createLocation() method.
198
     *
199
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
200
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
201
     */
202
    public function testCreateLocationThrowsInvalidArgumentExceptionParentIsSubLocationOfContent()
203
    {
204
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
205
206
        $repository = $this->getRepository();
207
208
        $contentId = $this->generateId('object', 4);
209
        $parentLocationId = $this->generateId('location', 12);
210
        /* BEGIN: Use Case */
211
        // $contentId is the ID of an existing content object
212
        // $parentLocationId is the ID of an existing location which is below a
213
        // location that is assigned to the content
214
        $contentService = $repository->getContentService();
215
        $locationService = $repository->getLocationService();
216
217
        // ContentInfo for "How to use eZ Publish"
218
        $contentInfo = $contentService->loadContentInfo($contentId);
219
220
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
221
222
        // Throws exception, since content is already located at "/1/2/"
223
        $locationService->createLocation(
224
            $contentInfo,
225
            $locationCreate
226
        );
227
        /* END: Use Case */
228
    }
229
230
    /**
231
     * Test for the createLocation() method.
232
     *
233
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
234
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
235
     */
236
    public function testCreateLocationThrowsInvalidArgumentExceptionRemoteIdExists()
237
    {
238
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
239
240
        $repository = $this->getRepository();
241
242
        $contentId = $this->generateId('object', 41);
243
        $parentLocationId = $this->generateId('location', 5);
244
        /* BEGIN: Use Case */
245
        // $contentId is the ID of an existing content object
246
        $contentService = $repository->getContentService();
247
        $locationService = $repository->getLocationService();
248
249
        // ContentInfo for "How to use eZ Publish"
250
        $contentInfo = $contentService->loadContentInfo($contentId);
251
252
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
253
        // This remote ID already exists
254
        $locationCreate->remoteId = 'f3e90596361e31d496d4026eb624c983';
255
256
        // Throws exception, since remote ID is already in use
257
        $locationService->createLocation(
258
            $contentInfo,
259
            $locationCreate
260
        );
261
        /* END: Use Case */
262
    }
263
264
    /**
265
     * Test for the createLocation() method.
266
     *
267
     * @covers \eZ\Publish\API\Repository\LocationService::createLocation()
268
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
269
     * @dataProvider dataProviderForOutOfRangeLocationPriority
270
     */
271 View Code Duplication
    public function testCreateLocationThrowsInvalidArgumentExceptionPriorityIsOutOfRange($priority)
272
    {
273
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\InvalidArgumentException::class);
274
275
        $repository = $this->getRepository();
276
277
        $contentId = $this->generateId('object', 41);
278
        $parentLocationId = $this->generateId('location', 5);
279
        /* BEGIN: Use Case */
280
        // $contentId is the ID of an existing content object
281
        // $parentLocationId is the ID of an existing location
282
        $contentService = $repository->getContentService();
283
        $locationService = $repository->getLocationService();
284
285
        // ContentInfo for "How to use eZ Publish"
286
        $contentInfo = $contentService->loadContentInfo($contentId);
287
288
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
289
        $locationCreate->priority = $priority;
290
        $locationCreate->hidden = true;
291
        $locationCreate->remoteId = 'sindelfingen';
292
        $locationCreate->sortField = Location::SORT_FIELD_NODE_ID;
293
        $locationCreate->sortOrder = Location::SORT_ORDER_DESC;
294
295
        // Throws exception, since priority is out of range
296
        $locationService->createLocation(
297
            $contentInfo,
298
            $locationCreate
299
        );
300
        /* END: Use Case */
301
    }
302
303
    public function dataProviderForOutOfRangeLocationPriority()
304
    {
305
        return [[-2147483649], [2147483648]];
306
    }
307
308
    /**
309
     * Test for the createLocation() method.
310
     *
311
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
312
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
313
     */
314
    public function testCreateLocationInTransactionWithRollback()
315
    {
316
        $repository = $this->getRepository();
317
318
        $contentId = $this->generateId('object', 41);
319
        $parentLocationId = $this->generateId('location', 5);
320
        /* BEGIN: Use Case */
321
        // $contentId is the ID of an existing content object
322
        // $parentLocationId is the ID of an existing location
323
        $contentService = $repository->getContentService();
324
        $locationService = $repository->getLocationService();
325
326
        $repository->beginTransaction();
327
328
        try {
329
            // ContentInfo for "How to use eZ Publish"
330
            $contentInfo = $contentService->loadContentInfo($contentId);
331
332
            $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
333
            $locationCreate->remoteId = 'sindelfingen';
334
335
            $createdLocationId = $locationService->createLocation(
336
                $contentInfo,
337
                $locationCreate
338
            )->id;
339
        } catch (Exception $e) {
340
            // Cleanup hanging transaction on error
341
            $repository->rollback();
342
            throw $e;
343
        }
344
345
        $repository->rollback();
346
347
        try {
348
            // Throws exception since creation of location was rolled back
349
            $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...
350
        } catch (NotFoundException $e) {
351
            return;
352
        }
353
        /* END: Use Case */
354
355
        $this->fail('Objects still exists after rollback.');
356
    }
357
358
    /**
359
     * Test for the loadLocation() method.
360
     *
361
     * @return \eZ\Publish\API\Repository\Values\Content\Location
362
     *
363
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocation
364
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
365
     */
366
    public function testLoadLocation()
367
    {
368
        $repository = $this->getRepository();
369
370
        $locationId = $this->generateId('location', 5);
371
        /* BEGIN: Use Case */
372
        // $locationId is the ID of an existing location
373
        $locationService = $repository->getLocationService();
374
375
        $location = $locationService->loadLocation($locationId);
376
        /* END: Use Case */
377
378
        $this->assertInstanceOf(
379
            Location::class,
380
            $location
381
        );
382
        self::assertEquals(5, $location->id);
383
384
        return $location;
385
    }
386
387
    /**
388
     * Test for the loadLocation() method.
389
     *
390
     * @see \eZ\Publish\API\Repository\LocationService::loadLocation()
391
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
392
     */
393
    public function testLoadLocationRootStructValues()
394
    {
395
        $repository = $this->getRepository();
396
        $locationService = $repository->getLocationService();
397
        $location = $locationService->loadLocation($this->generateId('location', 1));
398
399
        $this->assertRootLocationStructValues($location);
400
    }
401
402
    public function testLoadLocationRootStructValuesWithPrioritizedLanguages(): void
403
    {
404
        $repository = $this->getRepository();
405
406
        $rootLocation = $repository
407
            ->getLocationService()
408
            ->loadLocation(
409
                $this->generateId('location', 1),
410
                [
411
                    'eng-GB',
412
                    'ger-DE',
413
                ]
414
            );
415
416
        $this->assertRootLocationStructValues($rootLocation);
417
    }
418
419
    private function assertRootLocationStructValues(Location $location): void
420
    {
421
        $legacyDateTime = new \DateTime();
422
        $legacyDateTime->setTimestamp(1030968000);
423
424
        $this->assertInstanceOf(Location::class, $location);
425
        $this->assertPropertiesCorrect(
426
            [
427
                'id' => $this->generateId('location', 1),
428
                'status' => 1,
429
                'priority' => 0,
430
                'hidden' => false,
431
                'invisible' => false,
432
                'remoteId' => '629709ba256fe317c3ddcee35453a96a',
433
                'parentLocationId' => $this->generateId('location', 1),
434
                'pathString' => '/1/',
435
                'depth' => 0,
436
                'sortField' => 1,
437
                'sortOrder' => 1,
438
            ],
439
            $location
440
        );
441
442
        $this->assertInstanceOf(ContentInfo::class, $location->contentInfo);
443
        $this->assertPropertiesCorrect(
444
            [
445
                'id' => $this->generateId('content', 0),
446
                'name' => 'Top Level Nodes',
447
                'sectionId' => 1,
448
                'mainLocationId' => 1,
449
                'contentTypeId' => 1,
450
                'currentVersionNo' => 1,
451
                'published' => 1,
452
                'ownerId' => 14,
453
                'modificationDate' => $legacyDateTime,
454
                'publishedDate' => $legacyDateTime,
455
                'alwaysAvailable' => 1,
456
                'remoteId' => null,
457
                'mainLanguageCode' => 'eng-GB',
458
            ],
459
            $location->contentInfo
460
        );
461
    }
462
463
    /**
464
     * Test for the loadLocation() method.
465
     *
466
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
467
     *
468
     * @see \eZ\Publish\API\Repository\LocationService::loadLocation()
469
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
470
     */
471
    public function testLoadLocationStructValues(Location $location)
472
    {
473
        $this->assertPropertiesCorrect(
474
            [
475
                'id' => $this->generateId('location', 5),
476
                'priority' => 0,
477
                'hidden' => false,
478
                'invisible' => false,
479
                'remoteId' => '3f6d92f8044aed134f32153517850f5a',
480
                'parentLocationId' => $this->generateId('location', 1),
481
                'pathString' => '/1/5/',
482
                'depth' => 1,
483
                'sortField' => 1,
484
                'sortOrder' => 1,
485
            ],
486
            $location
487
        );
488
489
        $this->assertInstanceOf(
490
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo',
491
            $location->contentInfo
492
        );
493
        $this->assertEquals($this->generateId('object', 4), $location->contentInfo->id);
494
495
        // Check lazy loaded proxy on ->content
496
        $this->assertInstanceOf(
497
            Content::class,
498
            $content = $location->getContent()
499
        );
500
        $this->assertEquals(4, $content->contentInfo->id);
501
    }
502
503
    public function testLoadLocationPrioritizedLanguagesFallback()
504
    {
505
        $repository = $this->getRepository();
506
507
        // Add a language
508
        $this->createLanguage('nor-NO', 'Norsk');
509
510
        $locationService = $repository->getLocationService();
511
        $contentService = $repository->getContentService();
512
        $location = $locationService->loadLocation(5);
513
514
        // Translate "Users"
515
        $draft = $contentService->createContentDraft($location->contentInfo);
516
        $struct = $contentService->newContentUpdateStruct();
517
        $struct->setField('name', 'Brukere', 'nor-NO');
518
        $draft = $contentService->updateContent($draft->getVersionInfo(), $struct);
519
        $contentService->publishVersion($draft->getVersionInfo());
520
521
        // Load with priority language (fallback will be the old one)
522
        $location = $locationService->loadLocation(5, ['nor-NO']);
523
524
        $this->assertInstanceOf(
525
            Location::class,
526
            $location
527
        );
528
        self::assertEquals(5, $location->id);
529
        $this->assertInstanceOf(
530
            Content::class,
531
            $content = $location->getContent()
532
        );
533
        $this->assertEquals(4, $content->contentInfo->id);
534
535
        $this->assertEquals($content->getVersionInfo()->getName(), 'Brukere');
536
        $this->assertEquals($content->getVersionInfo()->getName('eng-US'), 'Users');
537
    }
538
539
    /**
540
     * Test that accessing lazy-loaded Content without a translation in the specific
541
     * not available language throws NotFoundException.
542
     */
543
    public function testLoadLocationThrowsNotFoundExceptionForNotAvailableContent(): void
544
    {
545
        $repository = $this->getRepository();
546
547
        $locationService = $repository->getLocationService();
548
549
        $this->createLanguage('pol-PL', 'Polski');
550
551
        $this->expectException(NotFoundException::class);
552
553
        // Note: relying on existing database fixtures to make test case more readable
554
        $locationService->loadLocation(60, ['pol-PL']);
555
    }
556
557
    /**
558
     * Test for the loadLocation() method.
559
     *
560
     * @see \eZ\Publish\API\Repository\LocationService::loadLocation()
561
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
562
     */
563 View Code Duplication
    public function testLoadLocationThrowsNotFoundException()
564
    {
565
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
566
567
        $repository = $this->getRepository();
568
569
        $nonExistentLocationId = $this->generateId('location', 2342);
570
        /* BEGIN: Use Case */
571
        $locationService = $repository->getLocationService();
572
573
        // Throws exception, if Location with $nonExistentLocationId does not
574
        // exist
575
        $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...
576
        /* END: Use Case */
577
    }
578
579
    /**
580
     * Test for the loadLocationList() method.
581
     *
582
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
583
     */
584 View Code Duplication
    public function testLoadLocationList(): void
585
    {
586
        $repository = $this->getRepository();
587
588
        // 5 is the ID of an existing location, 442 is a non-existing id
589
        $locationService = $repository->getLocationService();
590
        $locations = $locationService->loadLocationList([5, 442]);
591
592
        self::assertIsIterable($locations);
593
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLocationList(array(5, 442)) on line 590 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...
594
        self::assertEquals([5], array_keys($locations));
595
        self::assertInstanceOf(Location::class, $locations[5]);
596
        self::assertEquals(5, $locations[5]->id);
597
    }
598
599
    /**
600
     * Test for the loadLocationList() method.
601
     *
602
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
603
     * @depends testLoadLocationList
604
     */
605
    public function testLoadLocationListPrioritizedLanguagesFallback(): void
606
    {
607
        $repository = $this->getRepository();
608
609
        $this->createLanguage('pol-PL', 'Polski');
610
611
        // 5 is the ID of an existing location, 442 is a non-existing id
612
        $locationService = $repository->getLocationService();
613
        $locations = $locationService->loadLocationList([5, 442], ['pol-PL'], false);
614
615
        self::assertIsIterable($locations);
616
        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 613 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...
617
    }
618
619
    /**
620
     * Test for the loadLocationList() method.
621
     *
622
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
623
     * @depends testLoadLocationListPrioritizedLanguagesFallback
624
     */
625
    public function testLoadLocationListPrioritizedLanguagesFallbackAndAlwaysAvailable(): void
626
    {
627
        $repository = $this->getRepository();
628
629
        $this->createLanguage('pol-PL', 'Polski');
630
631
        // 5 is the ID of an existing location, 442 is a non-existing id
632
        $locationService = $repository->getLocationService();
633
        $locations = $locationService->loadLocationList([5, 442], ['pol-PL'], true);
634
635
        self::assertIsIterable($locations);
636
        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 633 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...
637
        self::assertEquals([5], array_keys($locations));
638
        self::assertInstanceOf(Location::class, $locations[5]);
639
        self::assertEquals(5, $locations[5]->id);
640
    }
641
642
    /**
643
     * Test for the loadLocationList() method.
644
     *
645
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
646
     */
647 View Code Duplication
    public function testLoadLocationListWithRootLocationId()
648
    {
649
        $repository = $this->getRepository();
650
651
        // 1 is the ID of an root location
652
        $locationService = $repository->getLocationService();
653
        $locations = $locationService->loadLocationList([1]);
654
655
        self::assertIsIterable($locations);
656
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLocationList(array(1)) on line 653 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...
657
        self::assertEquals([1], array_keys($locations));
658
        self::assertInstanceOf(Location::class, $locations[1]);
659
        self::assertEquals(1, $locations[1]->id);
660
    }
661
662
    /**
663
     * Test for the loadLocationByRemoteId() method.
664
     *
665
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationByRemoteId()
666
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
667
     */
668 View Code Duplication
    public function testLoadLocationByRemoteId()
669
    {
670
        $repository = $this->getRepository();
671
672
        /* BEGIN: Use Case */
673
        $locationService = $repository->getLocationService();
674
675
        $location = $locationService->loadLocationByRemoteId(
676
            '3f6d92f8044aed134f32153517850f5a'
677
        );
678
        /* END: Use Case */
679
680
        $this->assertEquals(
681
            $locationService->loadLocation($this->generateId('location', 5)),
682
            $location
683
        );
684
    }
685
686
    /**
687
     * Test for the loadLocationByRemoteId() method.
688
     *
689
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationByRemoteId()
690
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
691
     */
692 View Code Duplication
    public function testLoadLocationByRemoteIdThrowsNotFoundException()
693
    {
694
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\NotFoundException::class);
695
696
        $repository = $this->getRepository();
697
698
        /* BEGIN: Use Case */
699
        $locationService = $repository->getLocationService();
700
701
        // Throws exception, since Location with remote ID does not exist
702
        $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...
703
            'not-exists'
704
        );
705
        /* END: Use Case */
706
    }
707
708
    /**
709
     * Test for the loadLocations() method.
710
     *
711
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
712
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
713
     */
714
    public function testLoadLocations()
715
    {
716
        $repository = $this->getRepository();
717
718
        $contentId = $this->generateId('object', 4);
719
        /* BEGIN: Use Case */
720
        // $contentId contains the ID of an existing content object
721
        $contentService = $repository->getContentService();
722
        $locationService = $repository->getLocationService();
723
724
        $contentInfo = $contentService->loadContentInfo($contentId);
725
726
        $locations = $locationService->loadLocations($contentInfo);
727
        /* END: Use Case */
728
729
        $this->assertIsArray($locations);
730
        self::assertNotEmpty($locations);
731
732
        foreach ($locations as $location) {
733
            self::assertInstanceOf(Location::class, $location);
734
            self::assertEquals($contentInfo->id, $location->getContentInfo()->id);
735
        }
736
737
        return $locations;
738
    }
739
740
    /**
741
     * Test for the loadLocations() method.
742
     *
743
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
744
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
745
     */
746
    public function testLoadLocationsContent(array $locations)
747
    {
748
        $repository = $this->getRepository();
749
        $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...
750
751
        $this->assertCount(1, $locations);
752
        foreach ($locations as $loadedLocation) {
753
            $this->assertInstanceOf(
754
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
755
                $loadedLocation
756
            );
757
        }
758
759
        usort(
760
            $locations,
761
            function ($a, $b) {
762
                strcmp($a->id, $b->id);
763
            }
764
        );
765
766
        $this->assertEquals(
767
            [$this->generateId('location', 5)],
768
            array_map(
769
                function (Location $location) {
770
                    return $location->id;
771
                },
772
                $locations
773
            )
774
        );
775
    }
776
777
    /**
778
     * Test for the loadLocations() method.
779
     *
780
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
781
     *
782
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations($contentInfo, $rootLocation)
783
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
784
     */
785
    public function testLoadLocationsLimitedSubtree()
786
    {
787
        $repository = $this->getRepository();
788
789
        $originalLocationId = $this->generateId('location', 54);
790
        $originalParentLocationId = $this->generateId('location', 48);
791
        $newParentLocationId = $this->generateId('location', 43);
792
        /* BEGIN: Use Case */
793
        // $originalLocationId is the ID of an existing location
794
        // $originalParentLocationId is the ID of the parent location of
795
        //     $originalLocationId
796
        // $newParentLocationId is the ID of an existing location outside the tree
797
        // of $originalLocationId and $originalParentLocationId
798
        $locationService = $repository->getLocationService();
799
800
        // Location at "/1/48/54"
801
        $originalLocation = $locationService->loadLocation($originalLocationId);
802
803
        // Create location under "/1/43/"
804
        $locationCreate = $locationService->newLocationCreateStruct($newParentLocationId);
805
        $locationService->createLocation(
806
            $originalLocation->contentInfo,
807
            $locationCreate
808
        );
809
810
        $findRootLocation = $locationService->loadLocation($originalParentLocationId);
811
812
        // Returns an array with only $originalLocation
813
        $locations = $locationService->loadLocations(
814
            $originalLocation->contentInfo,
815
            $findRootLocation
816
        );
817
        /* END: Use Case */
818
819
        $this->assertIsArray($locations);
820
821
        return $locations;
822
    }
823
824
    /**
825
     * Test for the loadLocations() method.
826
     *
827
     * @param \eZ\Publish\API\Repository\Values\Content\Location[] $locations
828
     *
829
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
830
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationsLimitedSubtree
831
     */
832
    public function testLoadLocationsLimitedSubtreeContent(array $locations)
833
    {
834
        $this->assertCount(1, $locations);
835
836
        $this->assertEquals(
837
            $this->generateId('location', 54),
838
            reset($locations)->id
839
        );
840
    }
841
842
    /**
843
     * Test for the loadLocations() method.
844
     *
845
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
846
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
847
     */
848 View Code Duplication
    public function testLoadLocationsThrowsBadStateException()
849
    {
850
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\BadStateException::class);
851
852
        $repository = $this->getRepository();
853
854
        /* BEGIN: Use Case */
855
        $contentTypeService = $repository->getContentTypeService();
856
        $contentService = $repository->getContentService();
857
        $locationService = $repository->getLocationService();
858
859
        // Create new content, which is not published
860
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
861
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
862
        $contentCreate->setField('name', 'New Folder');
863
        $content = $contentService->createContent($contentCreate);
864
865
        // Throws Exception, since $content has no published version, yet
866
        $locationService->loadLocations(
867
            $content->contentInfo
868
        );
869
        /* END: Use Case */
870
    }
871
872
    /**
873
     * Test for the loadLocations() method.
874
     *
875
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations($contentInfo, $rootLocation)
876
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
877
     */
878
    public function testLoadLocationsThrowsBadStateExceptionLimitedSubtree()
879
    {
880
        $this->expectException(\eZ\Publish\API\Repository\Exceptions\BadStateException::class);
881
882
        $repository = $this->getRepository();
883
884
        $someLocationId = $this->generateId('location', 2);
885
        /* BEGIN: Use Case */
886
        // $someLocationId is the ID of an existing location
887
        $contentTypeService = $repository->getContentTypeService();
888
        $contentService = $repository->getContentService();
889
        $locationService = $repository->getLocationService();
890
891
        // Create new content, which is not published
892
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
893
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
894
        $contentCreate->setField('name', 'New Folder');
895
        $content = $contentService->createContent($contentCreate);
896
897
        $findRootLocation = $locationService->loadLocation($someLocationId);
898
899
        // Throws Exception, since $content has no published version, yet
900
        $locationService->loadLocations(
901
            $content->contentInfo,
902
            $findRootLocation
903
        );
904
        /* END: Use Case */
905
    }
906
907
    /**
908
     * Test for the loadLocationChildren() method.
909
     *
910
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationChildren
911
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
912
     */
913
    public function testLoadLocationChildren()
914
    {
915
        $repository = $this->getRepository();
916
917
        $locationId = $this->generateId('location', 5);
918
        /* BEGIN: Use Case */
919
        // $locationId is the ID of an existing location
920
        $locationService = $repository->getLocationService();
921
922
        $location = $locationService->loadLocation($locationId);
923
924
        $childLocations = $locationService->loadLocationChildren($location);
925
        /* END: Use Case */
926
927
        $this->assertInstanceOf(LocationList::class, $childLocations);
928
        $this->assertIsArray($childLocations->locations);
929
        $this->assertNotEmpty($childLocations->locations);
930
        $this->assertIsInt($childLocations->totalCount);
931
932
        foreach ($childLocations->locations as $childLocation) {
933
            $this->assertInstanceOf(Location::class, $childLocation);
934
            $this->assertEquals($location->id, $childLocation->parentLocationId);
935
        }
936
937
        return $childLocations;
938
    }
939
940
    /**
941
     * Test loading parent Locations for draft Content.
942
     *
943
     * @covers \eZ\Publish\API\Repository\LocationService::loadParentLocationsForDraftContent
944
     */
945
    public function testLoadParentLocationsForDraftContent()
946
    {
947
        $repository = $this->getRepository();
948
        $locationService = $repository->getLocationService();
949
        $contentService = $repository->getContentService();
950
        $contentTypeService = $repository->getContentTypeService();
951
952
        // prepare locations
953
        $locationCreateStructs = [
954
            $locationService->newLocationCreateStruct(2),
955
            $locationService->newLocationCreateStruct(5),
956
        ];
957
958
        // Create new content
959
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
960
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
961
        $contentCreate->setField('name', 'New Folder');
962
        $contentDraft = $contentService->createContent($contentCreate, $locationCreateStructs);
963
964
        // Test loading parent Locations
965
        $locations = $locationService->loadParentLocationsForDraftContent($contentDraft->versionInfo);
966
967
        self::assertCount(2, $locations);
968
        foreach ($locations as $location) {
969
            // test it is one of the given parent locations
970
            self::assertTrue($location->id === 2 || $location->id === 5);
971
        }
972
973
        return $contentDraft;
974
    }
975
976
    /**
977
     * Test that trying to load parent Locations throws Exception if Content is not a draft.
978
     *
979
     * @depends testLoadParentLocationsForDraftContent
980
     *
981
     * @param \eZ\Publish\API\Repository\Values\Content\Content $contentDraft
982
     */
983
    public function testLoadParentLocationsForDraftContentThrowsBadStateException(Content $contentDraft)
984
    {
985
        $this->expectException(BadStateException::class);
986
        $this->expectExceptionMessageRegExp('/has been already published/');
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\TestCa...xceptionMessageRegExp() has been deprecated with message: Use expectExceptionMessageMatches() instead

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