Completed
Push — 7.4 ( ff0312...dac298 )
by André
204:17 queued 174:28
created

LocationServiceTest::testMoveSubtreeHidden()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

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