Completed
Push — EZP-30760-fix-broken-link-afte... ( b1354b...dbc3fe )
by
unknown
21:31
created

LocationServiceTest::createSampleArticleStruct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

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

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

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

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

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

Loading history...
634
        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 631 can also be of type array<integer,object<eZ\...lues\Content\Location>>; however, PHPUnit\Framework\Assert::assertCount() does only seem to accept object<Countable>|object...nit\Framework\iterable>, maybe add an additional type check?

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

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

    return array();
}

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

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

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

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

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

Loading history...
654
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLocationList(array(1)) on line 651 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...
655
        self::assertEquals([1], array_keys($locations));
656
        self::assertInstanceOf(Location::class, $locations[1]);
657
        self::assertEquals(1, $locations[1]->id);
658
    }
659
660
    /**
661
     * Test for the loadLocationList() method.
662
     *
663
     * Ensures the list is returned in the same order as passed IDs array.
664
     *
665
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
666
     */
667
    public function testLoadLocationListInCorrectOrder()
668
    {
669
        $repository = $this->getRepository();
670
        $locationService = $repository->getLocationService();
671
672
        $cachedLocationId = 2;
673
        $locationIdsToLoad = [43, $cachedLocationId, 5];
674
675
        // Call loadLocation to cache it in memory as it might possibly affect list order
676
        $locationService->loadLocation($cachedLocationId);
677
678
        $locations = $locationService->loadLocationList($locationIdsToLoad);
679
        $locationIds = array_column($locations, 'id');
680
681
        self::assertEquals($locationIdsToLoad, $locationIds);
682
    }
683
684
    /**
685
     * Test for the loadLocationByRemoteId() method.
686
     *
687
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationByRemoteId()
688
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
689
     */
690 View Code Duplication
    public function testLoadLocationByRemoteId()
691
    {
692
        $repository = $this->getRepository();
693
694
        /* BEGIN: Use Case */
695
        $locationService = $repository->getLocationService();
696
697
        $location = $locationService->loadLocationByRemoteId(
698
            '3f6d92f8044aed134f32153517850f5a'
699
        );
700
        /* END: Use Case */
701
702
        $this->assertEquals(
703
            $locationService->loadLocation($this->generateId('location', 5)),
704
            $location
705
        );
706
    }
707
708
    /**
709
     * Test for the loadLocationByRemoteId() method.
710
     *
711
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationByRemoteId()
712
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
713
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
714
     */
715
    public function testLoadLocationByRemoteIdThrowsNotFoundException()
716
    {
717
        $repository = $this->getRepository();
718
719
        /* BEGIN: Use Case */
720
        $locationService = $repository->getLocationService();
721
722
        // Throws exception, since Location with remote ID does not exist
723
        $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...
724
            'not-exists'
725
        );
726
        /* END: Use Case */
727
    }
728
729
    /**
730
     * Test for the loadLocations() method.
731
     *
732
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
733
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
734
     */
735
    public function testLoadLocations()
736
    {
737
        $repository = $this->getRepository();
738
739
        $contentId = $this->generateId('object', 4);
740
        /* BEGIN: Use Case */
741
        // $contentId contains the ID of an existing content object
742
        $contentService = $repository->getContentService();
743
        $locationService = $repository->getLocationService();
744
745
        $contentInfo = $contentService->loadContentInfo($contentId);
746
747
        $locations = $locationService->loadLocations($contentInfo);
748
        /* END: Use Case */
749
750
        $this->assertInternalType('array', $locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

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

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

Loading history...
751
        self::assertNotEmpty($locations);
752
753
        foreach ($locations as $location) {
754
            self::assertInstanceOf(Location::class, $location);
755
            self::assertEquals($contentInfo->id, $location->getContentInfo()->id);
756
        }
757
758
        return $locations;
759
    }
760
761
    /**
762
     * Test for the loadLocations() method.
763
     *
764
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
765
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
766
     */
767
    public function testLoadLocationsContent(array $locations)
768
    {
769
        $repository = $this->getRepository();
770
        $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...
771
772
        $this->assertEquals(1, count($locations));
773
        foreach ($locations as $loadedLocation) {
774
            $this->assertInstanceOf(
775
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
776
                $loadedLocation
777
            );
778
        }
779
780
        usort(
781
            $locations,
782
            function ($a, $b) {
783
                strcmp($a->id, $b->id);
784
            }
785
        );
786
787
        $this->assertEquals(
788
            [$this->generateId('location', 5)],
789
            array_map(
790
                function (Location $location) {
791
                    return $location->id;
792
                },
793
                $locations
794
            )
795
        );
796
    }
797
798
    /**
799
     * Test for the loadLocations() method.
800
     *
801
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
802
     *
803
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations($contentInfo, $rootLocation)
804
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
805
     */
806
    public function testLoadLocationsLimitedSubtree()
807
    {
808
        $repository = $this->getRepository();
809
810
        $originalLocationId = $this->generateId('location', 54);
811
        $originalParentLocationId = $this->generateId('location', 48);
812
        $newParentLocationId = $this->generateId('location', 43);
813
        /* BEGIN: Use Case */
814
        // $originalLocationId is the ID of an existing location
815
        // $originalParentLocationId is the ID of the parent location of
816
        //     $originalLocationId
817
        // $newParentLocationId is the ID of an existing location outside the tree
818
        // of $originalLocationId and $originalParentLocationId
819
        $locationService = $repository->getLocationService();
820
821
        // Location at "/1/48/54"
822
        $originalLocation = $locationService->loadLocation($originalLocationId);
823
824
        // Create location under "/1/43/"
825
        $locationCreate = $locationService->newLocationCreateStruct($newParentLocationId);
826
        $locationService->createLocation(
827
            $originalLocation->contentInfo,
828
            $locationCreate
829
        );
830
831
        $findRootLocation = $locationService->loadLocation($originalParentLocationId);
832
833
        // Returns an array with only $originalLocation
834
        $locations = $locationService->loadLocations(
835
            $originalLocation->contentInfo,
836
            $findRootLocation
837
        );
838
        /* END: Use Case */
839
840
        $this->assertInternalType('array', $locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Loading history...
1095
1096
        return $childLocations;
1097
    }
1098
1099
    /**
1100
     * Test for the loadLocationChildren() method.
1101
     *
1102
     * @param \eZ\Publish\API\Repository\Values\Content\LocationList $locations
1103
     *
1104
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset)
1105
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildrenWithOffset
1106
     */
1107 View Code Duplication
    public function testLoadLocationChildrenDataWithOffset(LocationList $locations)
1108
    {
1109
        $this->assertEquals(3, count($locations->locations));
1110
        $this->assertEquals(5, $locations->totalCount);
1111
1112
        foreach ($locations->locations as $location) {
1113
            $this->assertInstanceOf(
1114
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1115
                $location
1116
            );
1117
        }
1118
1119
        $this->assertEquals(
1120
            [
1121
                $this->generateId('location', 14),
1122
                $this->generateId('location', 44),
1123
                $this->generateId('location', 61),
1124
            ],
1125
            array_map(
1126
                function (Location $location) {
1127
                    return $location->id;
1128
                },
1129
                $locations->locations
1130
            )
1131
        );
1132
    }
1133
1134
    /**
1135
     * Test for the loadLocationChildren() method.
1136
     *
1137
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
1138
     *
1139
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset, $limit)
1140
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
1141
     */
1142 View Code Duplication
    public function testLoadLocationChildrenWithOffsetAndLimit()
1143
    {
1144
        $repository = $this->getRepository();
1145
1146
        $locationId = $this->generateId('location', 5);
1147
        /* BEGIN: Use Case */
1148
        // $locationId is the ID of an existing location
1149
        $locationService = $repository->getLocationService();
1150
1151
        $location = $locationService->loadLocation($locationId);
1152
1153
        $childLocations = $locationService->loadLocationChildren($location, 2, 2);
1154
        /* END: Use Case */
1155
1156
        $this->assertInstanceOf('\\eZ\\Publish\\API\\Repository\\Values\\Content\\LocationList', $childLocations);
1157
        $this->assertInternalType('array', $childLocations->locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

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

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

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

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

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

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

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

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

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

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

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

Loading history...
3087
3088
        return $articleCreateStruct;
3089
    }
3090
3091
    /**
3092
     * @param string $expectedAliasPath
3093
     * @param \eZ\Publish\API\Repository\Values\Content\Location $location
3094
     * @param \eZ\Publish\API\Repository\URLAliasService $urlAliasService
3095
     */
3096
    private function assertIsAliasExists(
3097
        string $expectedAliasPath,
3098
        Location $location,
3099
        URLAliasServiceInterface $urlAliasService
3100
    ): void {
3101
        $articleAliasesBeforeDelete = $urlAliasService
3102
            ->listLocationAliases($location);
3103
3104
        foreach ($articleAliasesBeforeDelete as $alias) {
3105
            if ($alias->path === $expectedAliasPath) {
3106
                $this->assertTrue(true);
3107
                return;
3108
            }
3109
        }
3110
    }
3111
}
3112