Completed
Push — master ( 330859...27ce39 )
by Łukasz
15:32
created

LocationServiceTest   F

Complexity

Total Complexity 112

Size/Duplication

Total Lines 2890
Duplicated Lines 10.28 %

Coupling/Cohesion

Components 1
Dependencies 29

Importance

Changes 0
Metric Value
dl 297
loc 2890
rs 0.8
c 0
b 0
f 0
wmc 112
lcom 1
cbo 29

79 Methods

Rating   Name   Duplication   Size   Complexity  
A testNewLocationCreateStruct() 0 21 1
A testNewLocationCreateStructValues() 0 15 1
A testCreateLocation() 0 40 1
A testCreateLocationStructValues() 0 24 1
A testCreateLocationThrowsInvalidArgumentExceptionPriorityIsOutOfRange() 31 31 1
A dataProviderForOutOfRangeLocationPriority() 0 4 1
A testCreateLocationInTransactionWithRollback() 0 43 3
A testLoadLocation() 0 20 1
A testLoadLocationRootStructValues() 0 48 1
A testLoadLocationStructValues() 0 31 1
A testLoadLocationPrioritizedLanguagesFallback() 0 35 1
A testLoadLocationThrowsNotFoundExceptionForNotAvailableContent() 0 13 1
A testLoadLocationThrowsNotFoundException() 0 15 1
A testLoadLocationList() 14 14 1
A testLoadLocationListPrioritizedLanguagesFallback() 0 13 1
A testLoadLocationListPrioritizedLanguagesFallbackAndAlwaysAvailable() 0 16 1
A testLoadLocationListWithRootLocationId() 14 14 1
A testLoadLocationByRemoteId() 0 17 1
A testLoadLocations() 0 25 2
A testLoadLocationsContent() 0 30 2
A testLoadLocationsLimitedSubtree() 0 38 1
A testLoadLocationsLimitedSubtreeContent() 0 9 1
A testLoadLocationsThrowsBadStateException() 23 23 1
A testLoadLocationsThrowsBadStateExceptionLimitedSubtree() 0 28 1
A testLoadLocationChildren() 0 26 2
A testLoadParentLocationsForDraftContent() 0 30 3
A testLoadParentLocationsForDraftContentThrowsBadStateException() 0 13 1
A testGetLocationChildCount() 0 12 1
A testLoadLocationChildrenData() 0 28 2
A testLoadLocationChildrenDataWithOffset() 26 26 2
A testLoadLocationChildrenDataWithOffsetAndLimit() 25 25 2
A testNewLocationUpdateStruct() 25 25 1
A testUpdateLocation() 0 31 1
A testUpdateLocationStructValues() 0 23 1
A testUpdateLocationWithSameRemoteId() 0 28 1
A testUpdateLocationThrowsInvalidArgumentException() 0 22 1
A testUpdateLocationThrowsInvalidArgumentExceptionPriorityIsOutOfRange() 0 22 1
A testUpdateLocationTwice() 0 23 1
A testSwapLocation() 0 52 1
A testSwapLocationForMainAndSecondaryLocation() 0 54 1
A testLoadLocationChildrenWithOffset() 0 20 1
A testLoadLocationChildrenWithOffsetAndLimit() 0 20 1
A testLoadLocationByRemoteIdThrowsNotFoundException() 15 15 1
A assertContentHasExpectedLocations() 0 32 1
A testSwapLocationDoesNotCorruptSearchResults() 0 39 1
A testSwapLocationForSecondaryLocations() 0 42 1
A testSwapLocationUpdatesMainLocation() 0 31 1
A testBookmarksAreSwappedAfterSwapLocation() 0 29 1
A testHideLocation() 0 36 2
A assertSubtreeProperties() 0 20 4
A testUnhideLocation() 0 37 2
B testUnhideLocationNotUnhidesHiddenSubtree() 0 58 3
B testDeleteLocation() 0 42 6
A testDeleteLocationDecrementsChildCountOnParent() 0 38 1
A testDeleteContentObjectLastLocation() 0 38 1
A testDeleteLocationDeletesRelatedBookmarks() 0 26 2
A testCopySubtree() 0 45 1
A testCopySubtreeWithAliases() 0 33 1
A assertDefaultContentStates() 0 19 3
B testCopySubtreeUpdatesSubtreeProperties() 0 59 3
A testCopySubtreeIncrementsChildCountOfNewParent() 0 38 1
A testCopySubtreeThrowsInvalidArgumentException() 0 29 1
A testMoveSubtree() 0 43 1
A testMoveSubtreeHidden() 0 46 1
A testMoveSubtreeUpdatesSubtreeProperties() 0 54 2
B testMoveSubtreeUpdatesSubtreePropertiesHidden() 0 58 2
A testMoveSubtreeIncrementsChildCountOfNewParent() 51 51 1
A testMoveSubtreeDecrementsChildCountOfOldParent() 51 51 1
A testMoveInvisibleSubtree() 0 31 1
A testMoveSubtreeThrowsInvalidArgumentException() 0 31 1
A testCreateLocationThrowsInvalidArgumentExceptionContentAlreadyBelowParent() 0 27 1
A testCreateLocationThrowsInvalidArgumentExceptionParentIsSubLocationOfContent() 0 27 1
A testCreateLocationThrowsInvalidArgumentExceptionRemoteIdExists() 0 27 1
A testMoveSubtreeUpdatesPathIdentificationString() 0 38 1
A loadSubtreeProperties() 0 12 2
A loadLocationProperties() 0 18 1
A assertGeneratedAliases() 0 7 2
A assertAliasesBeforeCopy() 0 11 3
A publishContentWithParentLocation() 22 22 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like LocationServiceTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use LocationServiceTest, and based on these observations, apply Extract Interface, too.

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

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

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

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

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

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