Completed
Push — master ( 260ec9...add83c )
by
unknown
18:59
created

LocationServiceTest::testMoveSubtree()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 43
rs 9.232
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the LocationServiceTest class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\API\Repository\Tests;
10
11
use Exception;
12
use eZ\Publish\API\Repository\Exceptions\BadStateException;
13
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
14
use eZ\Publish\API\Repository\Values\Content\Content;
15
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
16
use eZ\Publish\API\Repository\Values\Content\Location;
17
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
18
use eZ\Publish\API\Repository\Values\Content\LocationList;
19
use eZ\Publish\API\Repository\Values\Content\LocationUpdateStruct;
20
use eZ\Publish\API\Repository\Values\Content\Query;
21
use eZ\Publish\API\Repository\Values\Content\Search\SearchHit;
22
23
/**
24
 * Test case for operations in the LocationService using in memory storage.
25
 *
26
 * @see eZ\Publish\API\Repository\LocationService
27
 * @group location
28
 */
29
class LocationServiceTest extends BaseTest
30
{
31
    /**
32
     * Test for the newLocationCreateStruct() method.
33
     *
34
     * @return \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct
35
     *
36
     * @see \eZ\Publish\API\Repository\LocationService::newLocationCreateStruct()
37
     */
38
    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
            array(
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 array(
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
            array(
145
                'priority' => $locationCreate->priority,
146
                'hidden' => $locationCreate->hidden,
147
                'invisible' => $locationCreate->hidden,
148
                'remoteId' => $locationCreate->remoteId,
149
                'contentInfo' => $contentInfo,
150
                'parentLocationId' => $locationCreate->parentLocationId,
151
                'pathString' => '/1/5/' . $this->parseId('location', $createdLocation->id) . '/',
152
                'depth' => 2,
153
                'sortField' => $locationCreate->sortField,
154
                'sortOrder' => $locationCreate->sortOrder,
155
            ),
156
            $createdLocation
157
        );
158
159
        $this->assertNotNull($createdLocation->id);
160
    }
161
162
    /**
163
     * Test for the createLocation() method.
164
     *
165
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
166
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
167
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
168
     */
169 View Code Duplication
    public function testCreateLocationThrowsInvalidArgumentExceptionContentAlreadyBelowParent()
170
    {
171
        $repository = $this->getRepository();
172
173
        $contentId = $this->generateId('object', 11);
174
        $parentLocationId = $this->generateId('location', 5);
175
        /* BEGIN: Use Case */
176
        // $contentId is the ID of an existing content object
177
        // $parentLocationId is the ID of an existing location which already
178
        // has the content assigned to one of its descendant locations
179
        $contentService = $repository->getContentService();
180
        $locationService = $repository->getLocationService();
181
182
        // ContentInfo for "How to use eZ Publish"
183
        $contentInfo = $contentService->loadContentInfo($contentId);
184
185
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
186
187
        // Throws exception, since content is already located at "/1/2/107/110/"
188
        $locationService->createLocation(
189
            $contentInfo,
190
            $locationCreate
191
        );
192
        /* END: Use Case */
193
    }
194
195
    /**
196
     * Test for the createLocation() method.
197
     *
198
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
199
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
200
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
201
     */
202 View Code Duplication
    public function testCreateLocationThrowsInvalidArgumentExceptionParentIsSubLocationOfContent()
203
    {
204
        $repository = $this->getRepository();
205
206
        $contentId = $this->generateId('object', 4);
207
        $parentLocationId = $this->generateId('location', 12);
208
        /* BEGIN: Use Case */
209
        // $contentId is the ID of an existing content object
210
        // $parentLocationId is the ID of an existing location which is below a
211
        // location that is assigned to the content
212
        $contentService = $repository->getContentService();
213
        $locationService = $repository->getLocationService();
214
215
        // ContentInfo for "How to use eZ Publish"
216
        $contentInfo = $contentService->loadContentInfo($contentId);
217
218
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
219
220
        // Throws exception, since content is already located at "/1/2/"
221
        $locationService->createLocation(
222
            $contentInfo,
223
            $locationCreate
224
        );
225
        /* END: Use Case */
226
    }
227
228
    /**
229
     * Test for the createLocation() method.
230
     *
231
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
232
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
233
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
234
     */
235 View Code Duplication
    public function testCreateLocationThrowsInvalidArgumentExceptionRemoteIdExists()
236
    {
237
        $repository = $this->getRepository();
238
239
        $contentId = $this->generateId('object', 41);
240
        $parentLocationId = $this->generateId('location', 5);
241
        /* BEGIN: Use Case */
242
        // $contentId is the ID of an existing content object
243
        $contentService = $repository->getContentService();
244
        $locationService = $repository->getLocationService();
245
246
        // ContentInfo for "How to use eZ Publish"
247
        $contentInfo = $contentService->loadContentInfo($contentId);
248
249
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
250
        // This remote ID already exists
251
        $locationCreate->remoteId = 'f3e90596361e31d496d4026eb624c983';
252
253
        // Throws exception, since remote ID is already in use
254
        $locationService->createLocation(
255
            $contentInfo,
256
            $locationCreate
257
        );
258
        /* END: Use Case */
259
    }
260
261
    /**
262
     * Test for the createLocation() method.
263
     *
264
     * @covers \eZ\Publish\API\Repository\LocationService::createLocation()
265
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
266
     * @dataProvider dataProviderForOutOfRangeLocationPriority
267
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
268
     */
269 View Code Duplication
    public function testCreateLocationThrowsInvalidArgumentExceptionPriorityIsOutOfRange($priority)
270
    {
271
        $repository = $this->getRepository();
272
273
        $contentId = $this->generateId('object', 41);
274
        $parentLocationId = $this->generateId('location', 5);
275
        /* BEGIN: Use Case */
276
        // $contentId is the ID of an existing content object
277
        // $parentLocationId is the ID of an existing location
278
        $contentService = $repository->getContentService();
279
        $locationService = $repository->getLocationService();
280
281
        // ContentInfo for "How to use eZ Publish"
282
        $contentInfo = $contentService->loadContentInfo($contentId);
283
284
        $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
285
        $locationCreate->priority = $priority;
286
        $locationCreate->hidden = true;
287
        $locationCreate->remoteId = 'sindelfingen';
288
        $locationCreate->sortField = Location::SORT_FIELD_NODE_ID;
289
        $locationCreate->sortOrder = Location::SORT_ORDER_DESC;
290
291
        // Throws exception, since priority is out of range
292
        $locationService->createLocation(
293
            $contentInfo,
294
            $locationCreate
295
        );
296
        /* END: Use Case */
297
    }
298
299
    public function dataProviderForOutOfRangeLocationPriority()
300
    {
301
        return [[-2147483649], [2147483648]];
302
    }
303
304
    /**
305
     * Test for the createLocation() method.
306
     *
307
     * @see \eZ\Publish\API\Repository\LocationService::createLocation()
308
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
309
     */
310
    public function testCreateLocationInTransactionWithRollback()
311
    {
312
        $repository = $this->getRepository();
313
314
        $contentId = $this->generateId('object', 41);
315
        $parentLocationId = $this->generateId('location', 5);
316
        /* BEGIN: Use Case */
317
        // $contentId is the ID of an existing content object
318
        // $parentLocationId is the ID of an existing location
319
        $contentService = $repository->getContentService();
320
        $locationService = $repository->getLocationService();
321
322
        $repository->beginTransaction();
323
324
        try {
325
            // ContentInfo for "How to use eZ Publish"
326
            $contentInfo = $contentService->loadContentInfo($contentId);
327
328
            $locationCreate = $locationService->newLocationCreateStruct($parentLocationId);
329
            $locationCreate->remoteId = 'sindelfingen';
330
331
            $createdLocationId = $locationService->createLocation(
332
                $contentInfo,
333
                $locationCreate
334
            )->id;
335
        } catch (Exception $e) {
336
            // Cleanup hanging transaction on error
337
            $repository->rollback();
338
            throw $e;
339
        }
340
341
        $repository->rollback();
342
343
        try {
344
            // Throws exception since creation of location was rolled back
345
            $location = $locationService->loadLocation($createdLocationId);
0 ignored issues
show
Unused Code introduced by
$location is not used, you could remove the assignment.

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

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

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

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

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

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

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

Loading history...
567
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLocationList(array(5, 442)) on line 564 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...
568
        self::assertEquals([5], array_keys($locations));
569
        self::assertInstanceOf(Location::class, $locations[5]);
570
        self::assertEquals(5, $locations[5]->id);
571
    }
572
573
    /**
574
     * Test for the loadLocationList() method.
575
     *
576
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
577
     * @depends testLoadLocationList
578
     */
579
    public function testLoadLocationListPrioritizedLanguagesFallback(): void
580
    {
581
        $repository = $this->getRepository();
582
583
        $this->createLanguage('pol-PL', 'Polski');
584
585
        // 5 is the ID of an existing location, 442 is a non-existing id
586
        $locationService = $repository->getLocationService();
587
        $locations = $locationService->loadLocationList([5, 442], ['pol-PL'], false);
588
589
        self::assertInternalType('iterable', $locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

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

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

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

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

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

Loading history...
610
        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 607 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...
611
        self::assertEquals([5], array_keys($locations));
612
        self::assertInstanceOf(Location::class, $locations[5]);
613
        self::assertEquals(5, $locations[5]->id);
614
    }
615
616
    /**
617
     * Test for the loadLocationList() method.
618
     *
619
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationList
620
     */
621 View Code Duplication
    public function testLoadLocationListWithRootLocationId()
622
    {
623
        $repository = $this->getRepository();
624
625
        // 1 is the ID of an root location
626
        $locationService = $repository->getLocationService();
627
        $locations = $locationService->loadLocationList([1]);
628
629
        self::assertInternalType('iterable', $locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

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

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

Loading history...
630
        self::assertCount(1, $locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by $locationService->loadLocationList(array(1)) on line 627 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...
631
        self::assertEquals([1], array_keys($locations));
632
        self::assertInstanceOf(Location::class, $locations[1]);
633
        self::assertEquals(1, $locations[1]->id);
634
    }
635
636
    /**
637
     * Test for the loadLocationByRemoteId() method.
638
     *
639
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationByRemoteId()
640
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
641
     */
642 View Code Duplication
    public function testLoadLocationByRemoteId()
643
    {
644
        $repository = $this->getRepository();
645
646
        /* BEGIN: Use Case */
647
        $locationService = $repository->getLocationService();
648
649
        $location = $locationService->loadLocationByRemoteId(
650
            '3f6d92f8044aed134f32153517850f5a'
651
        );
652
        /* END: Use Case */
653
654
        $this->assertEquals(
655
            $locationService->loadLocation($this->generateId('location', 5)),
656
            $location
657
        );
658
    }
659
660
    /**
661
     * Test for the loadLocationByRemoteId() method.
662
     *
663
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationByRemoteId()
664
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
665
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
666
     */
667
    public function testLoadLocationByRemoteIdThrowsNotFoundException()
668
    {
669
        $repository = $this->getRepository();
670
671
        /* BEGIN: Use Case */
672
        $locationService = $repository->getLocationService();
673
674
        // Throws exception, since Location with remote ID does not exist
675
        $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...
676
            'not-exists'
677
        );
678
        /* END: Use Case */
679
    }
680
681
    /**
682
     * Test for the loadLocations() method.
683
     *
684
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
685
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
686
     */
687
    public function testLoadLocations()
688
    {
689
        $repository = $this->getRepository();
690
691
        $contentId = $this->generateId('object', 4);
692
        /* BEGIN: Use Case */
693
        // $contentId contains the ID of an existing content object
694
        $contentService = $repository->getContentService();
695
        $locationService = $repository->getLocationService();
696
697
        $contentInfo = $contentService->loadContentInfo($contentId);
698
699
        $locations = $locationService->loadLocations($contentInfo);
700
        /* END: Use Case */
701
702
        $this->assertInternalType('array', $locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

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

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

Loading history...
703
        self::assertNotEmpty($locations);
704
705
        foreach ($locations as $location) {
706
            self::assertInstanceOf(Location::class, $location);
707
            self::assertEquals($contentInfo->id, $location->getContentInfo()->id);
708
        }
709
710
        return $locations;
711
    }
712
713
    /**
714
     * Test for the loadLocations() method.
715
     *
716
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
717
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
718
     */
719
    public function testLoadLocationsContent(array $locations)
720
    {
721
        $repository = $this->getRepository();
722
        $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...
723
724
        $this->assertEquals(1, count($locations));
725
        foreach ($locations as $loadedLocation) {
726
            $this->assertInstanceOf(
727
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
728
                $loadedLocation
729
            );
730
        }
731
732
        usort(
733
            $locations,
734
            function ($a, $b) {
735
                strcmp($a->id, $b->id);
736
            }
737
        );
738
739
        $this->assertEquals(
740
            array($this->generateId('location', 5)),
741
            array_map(
742
                function (Location $location) {
743
                    return $location->id;
744
                },
745
                $locations
746
            )
747
        );
748
    }
749
750
    /**
751
     * Test for the loadLocations() method.
752
     *
753
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
754
     *
755
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations($contentInfo, $rootLocation)
756
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
757
     */
758
    public function testLoadLocationsLimitedSubtree()
759
    {
760
        $repository = $this->getRepository();
761
762
        $originalLocationId = $this->generateId('location', 54);
763
        $originalParentLocationId = $this->generateId('location', 48);
764
        $newParentLocationId = $this->generateId('location', 43);
765
        /* BEGIN: Use Case */
766
        // $originalLocationId is the ID of an existing location
767
        // $originalParentLocationId is the ID of the parent location of
768
        //     $originalLocationId
769
        // $newParentLocationId is the ID of an existing location outside the tree
770
        // of $originalLocationId and $originalParentLocationId
771
        $locationService = $repository->getLocationService();
772
773
        // Location at "/1/48/54"
774
        $originalLocation = $locationService->loadLocation($originalLocationId);
775
776
        // Create location under "/1/43/"
777
        $locationCreate = $locationService->newLocationCreateStruct($newParentLocationId);
778
        $locationService->createLocation(
779
            $originalLocation->contentInfo,
780
            $locationCreate
781
        );
782
783
        $findRootLocation = $locationService->loadLocation($originalParentLocationId);
784
785
        // Returns an array with only $originalLocation
786
        $locations = $locationService->loadLocations(
787
            $originalLocation->contentInfo,
788
            $findRootLocation
789
        );
790
        /* END: Use Case */
791
792
        $this->assertInternalType('array', $locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

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

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

Loading history...
793
794
        return $locations;
795
    }
796
797
    /**
798
     * Test for the loadLocations() method.
799
     *
800
     * @param \eZ\Publish\API\Repository\Values\Content\Location[] $locations
801
     *
802
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
803
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationsLimitedSubtree
804
     */
805
    public function testLoadLocationsLimitedSubtreeContent(array $locations)
806
    {
807
        $this->assertEquals(1, count($locations));
808
809
        $this->assertEquals(
810
            $this->generateId('location', 54),
811
            reset($locations)->id
812
        );
813
    }
814
815
    /**
816
     * Test for the loadLocations() method.
817
     *
818
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations()
819
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
820
     * @expectedException \eZ\Publish\API\Repository\Exceptions\BadStateException
821
     */
822 View Code Duplication
    public function testLoadLocationsThrowsBadStateException()
823
    {
824
        $repository = $this->getRepository();
825
826
        /* BEGIN: Use Case */
827
        $contentTypeService = $repository->getContentTypeService();
828
        $contentService = $repository->getContentService();
829
        $locationService = $repository->getLocationService();
830
831
        // Create new content, which is not published
832
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
833
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
834
        $contentCreate->setField('name', 'New Folder');
835
        $content = $contentService->createContent($contentCreate);
836
837
        // Throws Exception, since $content has no published version, yet
838
        $locationService->loadLocations(
839
            $content->contentInfo
840
        );
841
        /* END: Use Case */
842
    }
843
844
    /**
845
     * Test for the loadLocations() method.
846
     *
847
     * @see \eZ\Publish\API\Repository\LocationService::loadLocations($contentInfo, $rootLocation)
848
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocations
849
     * @expectedException \eZ\Publish\API\Repository\Exceptions\BadStateException
850
     */
851
    public function testLoadLocationsThrowsBadStateExceptionLimitedSubtree()
852
    {
853
        $repository = $this->getRepository();
854
855
        $someLocationId = $this->generateId('location', 2);
856
        /* BEGIN: Use Case */
857
        // $someLocationId is the ID of an existing location
858
        $contentTypeService = $repository->getContentTypeService();
859
        $contentService = $repository->getContentService();
860
        $locationService = $repository->getLocationService();
861
862
        // Create new content, which is not published
863
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
864
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
865
        $contentCreate->setField('name', 'New Folder');
866
        $content = $contentService->createContent($contentCreate);
867
868
        $findRootLocation = $locationService->loadLocation($someLocationId);
869
870
        // Throws Exception, since $content has no published version, yet
871
        $locationService->loadLocations(
872
            $content->contentInfo,
873
            $findRootLocation
874
        );
875
        /* END: Use Case */
876
    }
877
878
    /**
879
     * Test for the loadLocationChildren() method.
880
     *
881
     * @covers \eZ\Publish\API\Repository\LocationService::loadLocationChildren
882
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
883
     */
884
    public function testLoadLocationChildren()
885
    {
886
        $repository = $this->getRepository();
887
888
        $locationId = $this->generateId('location', 5);
889
        /* BEGIN: Use Case */
890
        // $locationId is the ID of an existing location
891
        $locationService = $repository->getLocationService();
892
893
        $location = $locationService->loadLocation($locationId);
894
895
        $childLocations = $locationService->loadLocationChildren($location);
896
        /* END: Use Case */
897
898
        $this->assertInstanceOf(LocationList::class, $childLocations);
899
        $this->assertInternalType('array', $childLocations->locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

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

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

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

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

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

Loading history...
902
903
        foreach ($childLocations->locations as $childLocation) {
904
            $this->assertInstanceOf(Location::class, $childLocation);
905
            $this->assertEquals($location->id, $childLocation->parentLocationId);
906
        }
907
908
        return $childLocations;
909
    }
910
911
    /**
912
     * Test loading parent Locations for draft Content.
913
     *
914
     * @covers \eZ\Publish\API\Repository\LocationService::loadParentLocationsForDraftContent
915
     */
916
    public function testLoadParentLocationsForDraftContent()
917
    {
918
        $repository = $this->getRepository();
919
        $locationService = $repository->getLocationService();
920
        $contentService = $repository->getContentService();
921
        $contentTypeService = $repository->getContentTypeService();
922
923
        // prepare locations
924
        $locationCreateStructs = [
925
            $locationService->newLocationCreateStruct(2),
926
            $locationService->newLocationCreateStruct(5),
927
        ];
928
929
        // Create new content
930
        $folderType = $contentTypeService->loadContentTypeByIdentifier('folder');
931
        $contentCreate = $contentService->newContentCreateStruct($folderType, 'eng-US');
932
        $contentCreate->setField('name', 'New Folder');
933
        $contentDraft = $contentService->createContent($contentCreate, $locationCreateStructs);
934
935
        // Test loading parent Locations
936
        $locations = $locationService->loadParentLocationsForDraftContent($contentDraft->versionInfo);
937
938
        self::assertCount(2, $locations);
939
        foreach ($locations as $location) {
940
            // test it is one of the given parent locations
941
            self::assertTrue($location->id === 2 || $location->id === 5);
942
        }
943
944
        return $contentDraft;
945
    }
946
947
    /**
948
     * Test that trying to load parent Locations throws Exception if Content is not a draft.
949
     *
950
     * @depends testLoadParentLocationsForDraftContent
951
     *
952
     * @param \eZ\Publish\API\Repository\Values\Content\Content $contentDraft
953
     */
954
    public function testLoadParentLocationsForDraftContentThrowsBadStateException(Content $contentDraft)
955
    {
956
        $this->expectException(BadStateException::class);
957
        $this->expectExceptionMessageRegExp('/has been already published/');
958
959
        $repository = $this->getRepository(false);
960
        $locationService = $repository->getLocationService();
961
        $contentService = $repository->getContentService();
962
963
        $content = $contentService->publishVersion($contentDraft->versionInfo);
964
965
        $locationService->loadParentLocationsForDraftContent($content->versionInfo);
966
    }
967
968
    /**
969
     * Test for the getLocationChildCount() method.
970
     *
971
     * @see \eZ\Publish\API\Repository\LocationService::getLocationChildCount()
972
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
973
     */
974
    public function testGetLocationChildCount()
975
    {
976
        // $locationId is the ID of an existing location
977
        $locationService = $this->getRepository()->getLocationService();
978
979
        $this->assertSame(
980
            5,
981
            $locationService->getLocationChildCount(
982
                $locationService->loadLocation($this->generateId('location', 5))
983
            )
984
        );
985
    }
986
987
    /**
988
     * Test for the loadLocationChildren() method.
989
     *
990
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren()
991
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
992
     */
993
    public function testLoadLocationChildrenData(LocationList $locations)
994
    {
995
        $this->assertEquals(5, count($locations->locations));
996
        $this->assertEquals(5, $locations->totalCount);
997
998
        foreach ($locations->locations as $location) {
999
            $this->assertInstanceOf(
1000
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1001
                $location
1002
            );
1003
        }
1004
1005
        $this->assertEquals(
1006
            array(
1007
                $this->generateId('location', 12),
1008
                $this->generateId('location', 13),
1009
                $this->generateId('location', 14),
1010
                $this->generateId('location', 44),
1011
                $this->generateId('location', 61),
1012
            ),
1013
            array_map(
1014
                function (Location $location) {
1015
                    return $location->id;
1016
                },
1017
                $locations->locations
1018
            )
1019
        );
1020
    }
1021
1022
    /**
1023
     * Test for the loadLocationChildren() method.
1024
     *
1025
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
1026
     *
1027
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset)
1028
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
1029
     */
1030 View Code Duplication
    public function testLoadLocationChildrenWithOffset()
1031
    {
1032
        $repository = $this->getRepository();
1033
1034
        $locationId = $this->generateId('location', 5);
1035
        /* BEGIN: Use Case */
1036
        // $locationId is the ID of an existing location
1037
        $locationService = $repository->getLocationService();
1038
1039
        $location = $locationService->loadLocation($locationId);
1040
1041
        $childLocations = $locationService->loadLocationChildren($location, 2);
1042
        /* END: Use Case */
1043
1044
        $this->assertInstanceOf('\\eZ\\Publish\\API\\Repository\\Values\\Content\\LocationList', $childLocations);
1045
        $this->assertInternalType('array', $childLocations->locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

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

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

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

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

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

Loading history...
1047
1048
        return $childLocations;
1049
    }
1050
1051
    /**
1052
     * Test for the loadLocationChildren() method.
1053
     *
1054
     * @param \eZ\Publish\API\Repository\Values\Content\LocationList $locations
1055
     *
1056
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset)
1057
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildrenWithOffset
1058
     */
1059 View Code Duplication
    public function testLoadLocationChildrenDataWithOffset(LocationList $locations)
1060
    {
1061
        $this->assertEquals(3, count($locations->locations));
1062
        $this->assertEquals(5, $locations->totalCount);
1063
1064
        foreach ($locations->locations as $location) {
1065
            $this->assertInstanceOf(
1066
                '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location',
1067
                $location
1068
            );
1069
        }
1070
1071
        $this->assertEquals(
1072
            array(
1073
                $this->generateId('location', 14),
1074
                $this->generateId('location', 44),
1075
                $this->generateId('location', 61),
1076
            ),
1077
            array_map(
1078
                function (Location $location) {
1079
                    return $location->id;
1080
                },
1081
                $locations->locations
1082
            )
1083
        );
1084
    }
1085
1086
    /**
1087
     * Test for the loadLocationChildren() method.
1088
     *
1089
     * @return \eZ\Publish\API\Repository\Values\Content\Location[]
1090
     *
1091
     * @see \eZ\Publish\API\Repository\LocationService::loadLocationChildren($location, $offset, $limit)
1092
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
1093
     */
1094 View Code Duplication
    public function testLoadLocationChildrenWithOffsetAndLimit()
1095
    {
1096
        $repository = $this->getRepository();
1097
1098
        $locationId = $this->generateId('location', 5);
1099
        /* BEGIN: Use Case */
1100
        // $locationId is the ID of an existing location
1101
        $locationService = $repository->getLocationService();
1102
1103
        $location = $locationService->loadLocation($locationId);
1104
1105
        $childLocations = $locationService->loadLocationChildren($location, 2, 2);
1106
        /* END: Use Case */
1107
1108
        $this->assertInstanceOf('\\eZ\\Publish\\API\\Repository\\Values\\Content\\LocationList', $childLocations);
1109
        $this->assertInternalType('array', $childLocations->locations);
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit\Framework\Assert::assertInternalType() has been deprecated with message: https://github.com/sebastianbergmann/phpunit/issues/3369

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

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

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

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

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

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