Completed
Push — 6.13 ( 87c7b3...c7cf3a )
by André
18:47
created

testRecoverWithLocationCreateStructParameterIncrementsChildCountOnNewParent()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 3
nop 0
dl 0
loc 39
rs 9.296
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the TrashServiceTest 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 eZ\Publish\API\Repository\Repository;
12
use eZ\Publish\API\Repository\URLAliasService;
13
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
14
use eZ\Publish\API\Repository\Values\Content\Location as APILocation;
15
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
16
use eZ\Publish\API\Repository\Values\Content\Query;
17
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
18
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
19
use eZ\Publish\API\Repository\Values\Content\TrashItem as APITrashItem;
20
use eZ\Publish\Core\Repository\Values\Content\TrashItem;
21
use eZ\Publish\Core\Repository\Values\Content\Location;
22
23
/**
24
 * Test case for operations in the TrashService using in memory storage.
25
 *
26
 * @see eZ\Publish\API\Repository\TrashService
27
 * @group integration
28
 * @group trash
29
 */
30
class TrashServiceTest extends BaseTrashServiceTest
31
{
32
    /**
33
     * Test for the trash() method.
34
     *
35
     * @see \eZ\Publish\API\Repository\TrashService::trash()
36
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationByRemoteId
37
     */
38
    public function testTrash()
39
    {
40
        /* BEGIN: Use Case */
41
        $trashItem = $this->createTrashItem();
42
        /* END: Use Case */
43
44
        $this->assertInstanceOf(
45
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\TrashItem',
46
            $trashItem
47
        );
48
    }
49
50
    /**
51
     * Test for the trash() method.
52
     *
53
     * @see \eZ\Publish\API\Repository\TrashService::trash()
54
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
55
     */
56
    public function testTrashSetsExpectedTrashItemProperties()
57
    {
58
        $repository = $this->getRepository();
59
60
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
61
62
        // Load the location that will be trashed
63
        $location = $repository->getLocationService()
64
            ->loadLocationByRemoteId($mediaRemoteId);
65
66
        $expected = array(
67
            'id' => $location->id,
68
            'depth' => $location->depth,
69
            'hidden' => $location->hidden,
70
            'invisible' => $location->invisible,
71
            'parentLocationId' => $location->parentLocationId,
72
            'pathString' => $location->pathString,
73
            'priority' => $location->priority,
74
            'remoteId' => $location->remoteId,
75
            'sortField' => $location->sortField,
76
            'sortOrder' => $location->sortOrder,
77
        );
78
79
        $trashItem = $this->createTrashItem();
80
81
        $this->assertPropertiesCorrect($expected, $trashItem);
82
    }
83
84
    /**
85
     * Test for the trash() method.
86
     *
87
     * @see \eZ\Publish\API\Repository\TrashService::trash()
88
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
89
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
90
     */
91
    public function testTrashRemovesLocationFromMainStorage()
92
    {
93
        $repository = $this->getRepository();
94
95
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
96
97
        /* BEGIN: Use Case */
98
        $this->createTrashItem();
99
100
        // Load the location service
101
        $locationService = $repository->getLocationService();
102
103
        // This call will fail with a "NotFoundException", because the media
104
        // location was marked as trashed in the main storage
105
        $locationService->loadLocationByRemoteId($mediaRemoteId);
106
        /* END: Use Case */
107
    }
108
109
    /**
110
     * Test for the trash() method.
111
     *
112
     * @see \eZ\Publish\API\Repository\TrashService::trash()
113
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
114
     */
115
    public function testTrashRemovesChildLocationsFromMainStorage()
116
    {
117
        $repository = $this->getRepository();
118
119
        /* BEGIN: Use Case */
120
        $remoteIds = $this->createRemoteIdList();
121
122
        $this->createTrashItem();
123
124
        // All invocations to loadLocationByRemoteId() to one of the above
125
        // collected remoteIds will return in an "NotFoundException"
126
        /* END: Use Case */
127
128
        $locationService = $repository->getLocationService();
129
        foreach ($remoteIds as $remoteId) {
130
            try {
131
                $locationService->loadLocationByRemoteId($remoteId);
132
                $this->fail("Location '{$remoteId}' should exist.'");
133
            } catch (NotFoundException $e) {
134
                // echo $e->getFile(), ' +', $e->getLine(), PHP_EOL;
135
            }
136
        }
137
138
        $this->assertGreaterThan(
139
            0,
140
            count($remoteIds),
141
            "There should be at least one 'Community' child location."
142
        );
143
    }
144
145
    /**
146
     * Test for the trash() method.
147
     *
148
     * @see \eZ\Publish\API\Repository\TrashService::trash()
149
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
150
     */
151 View Code Duplication
    public function testTrashDecrementsChildCountOnParentLocation()
152
    {
153
        $repository = $this->getRepository();
154
        $locationService = $repository->getLocationService();
155
156
        $baseLocationId = $this->generateId('location', 1);
157
158
        $location = $locationService->loadLocation($baseLocationId);
159
160
        $childCount = $locationService->getLocationChildCount($location);
161
162
        $this->createTrashItem();
163
164
        $this->refreshSearch($repository);
165
166
        $this->assertEquals(
167
            $childCount - 1,
168
            $locationService->getLocationChildCount($location)
169
        );
170
    }
171
172
    /**
173
     * Test sending a location to trash updates Content mainLocation.
174
     *
175
     * @covers \eZ\Publish\API\Repository\TrashService::trash
176
     */
177
    public function testTrashUpdatesMainLocation()
178
    {
179
        $repository = $this->getRepository();
180
        $contentService = $repository->getContentService();
181
        $locationService = $repository->getLocationService();
182
        $trashService = $repository->getTrashService();
183
184
        $contentInfo = $contentService->loadContentInfo(42);
185
186
        // Create additional location that will become new main location
187
        $location = $locationService->createLocation(
188
            $contentInfo,
189
            new LocationCreateStruct(['parentLocationId' => 2])
190
        );
191
192
        $trashService->trash(
193
            $locationService->loadLocation($contentInfo->mainLocationId)
194
        );
195
196
        self::assertEquals(
197
            $location->id,
198
            $contentService->loadContentInfo(42)->mainLocationId
199
        );
200
    }
201
202
    /**
203
     * Test sending a location to trash.
204
     *
205
     * @covers \eZ\Publish\API\Repository\TrashService::trash
206
     */
207 View Code Duplication
    public function testTrashReturnsNull()
208
    {
209
        $repository = $this->getRepository();
210
        $contentService = $repository->getContentService();
211
        $locationService = $repository->getLocationService();
212
        $trashService = $repository->getTrashService();
213
214
        // Create additional location to trash
215
        $location = $locationService->createLocation(
216
            $contentService->loadContentInfo(42),
217
            new LocationCreateStruct(['parentLocationId' => 2])
218
        );
219
220
        $trashItem = $trashService->trash($location);
221
222
        self::assertNull($trashItem);
223
    }
224
225
    /**
226
     * Test for the loadTrashItem() method.
227
     *
228
     * @covers \eZ\Publish\API\Repository\TrashService::loadTrashItem
229
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
230
     */
231
    public function testLoadTrashItem()
232
    {
233
        $repository = $this->getRepository();
234
        $trashService = $repository->getTrashService();
235
236
        /* BEGIN: Use Case */
237
        $trashItem = $this->createTrashItem();
238
239
        // Reload the trash item
240
        $trashItemReloaded = $trashService->loadTrashItem($trashItem->id);
241
        /* END: Use Case */
242
243
        $this->assertInstanceOf(
244
            APITrashItem::class,
245
            $trashItemReloaded
246
        );
247
248
        $this->assertEquals(
249
            $trashItem->pathString,
250
            $trashItemReloaded->pathString
251
        );
252
253
        $this->assertEquals(
254
            $trashItem,
255
            $trashItemReloaded
256
        );
257
    }
258
259
    /**
260
     * Test for the loadTrashItem() method.
261
     *
262
     * @see \eZ\Publish\API\Repository\TrashService::loadTrashItem()
263
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
264
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testLoadTrashItem
265
     */
266
    public function testLoadTrashItemThrowsNotFoundException()
267
    {
268
        $repository = $this->getRepository();
269
270
        $nonExistingTrashId = $this->generateId('trash', 2342);
271
        /* BEGIN: Use Case */
272
        $trashService = $repository->getTrashService();
273
274
        // This call will fail with a "NotFoundException", because no trash item
275
        // with the ID 1342 should exist in an eZ Publish demo installation
276
        $trashService->loadTrashItem($nonExistingTrashId);
277
        /* END: Use Case */
278
    }
279
280
    /**
281
     * Test for the recover() method.
282
     *
283
     * @covers \eZ\Publish\API\Repository\TrashService::recover
284
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
285
     */
286
    public function testRecover()
287
    {
288
        $repository = $this->getRepository();
289
        $trashService = $repository->getTrashService();
290
        $locationService = $repository->getLocationService();
291
292
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
293
294
        /* BEGIN: Use Case */
295
        $trashItem = $this->createTrashItem();
296
297
        // Recover the trashed item
298
        $location = $trashService->recover($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 295 can be null; however, eZ\Publish\API\Repository\TrashService::recover() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
299
300
        // Load the recovered location
301
        $locationReloaded = $locationService->loadLocationByRemoteId(
302
            $mediaRemoteId
303
        );
304
        /* END: Use Case */
305
306
        $this->assertInstanceOf(
307
            APILocation::class,
308
            $location
309
        );
310
311
        $this->assertEquals(
312
            $location,
313
            $locationReloaded
314
        );
315
316
        try {
317
            $trashService->loadTrashItem($trashItem->id);
318
            $this->fail('Trash item was not removed after being recovered.');
319
        } catch (NotFoundException $e) {
320
            // All well
321
        }
322
    }
323
324
    /**
325
     * Test recovering a non existing trash item results in a NotFoundException.
326
     *
327
     * @covers \eZ\Publish\API\Repository\TrashService::recover
328
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
329
     */
330
    public function testRecoverThrowsNotFoundExceptionForNonExistingTrashItem()
331
    {
332
        $repository = $this->getRepository();
333
        $trashService = $repository->getTrashService();
334
335
        $trashService->recover(
336
            $this->getTrashItemDouble(
337
                12364,
338
                12345,
339
                12363
340
            )
341
        );
342
    }
343
344
    /**
345
     * Test for the trash() method.
346
     *
347
     * @see \eZ\Publish\API\Repository\TrashService::recover()
348
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
349
     *
350
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
351
     */
352
    public function testNotFoundAliasAfterRemoveIt()
353
    {
354
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
355
356
        $repository = $this->getRepository();
357
        $trashService = $repository->getTrashService();
358
        $urlAliasService = $repository->getURLAliasService();
359
        $locationService = $repository->getLocationService();
360
361
        // Double ->lookup() call because there where issue that one call was not enough to spot bug
362
        $urlAliasService->lookup('/Media');
363
        $urlAliasService->lookup('/Media');
364
365
        $mediaLocation = $locationService->loadLocationByRemoteId($mediaRemoteId);
366
        $trashService->trash($mediaLocation);
367
368
        $urlAliasService->lookup('/Media');
369
    }
370
371
    /**
372
     * Test for the recover() method.
373
     *
374
     * @see \eZ\Publish\API\Repository\TrashService::recover()
375
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
376
     */
377
    public function testAliasesForRemovedItems()
378
    {
379
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
380
381
        $repository = $this->getRepository();
382
        $trashService = $repository->getTrashService();
383
        $urlAliasService = $repository->getURLAliasService();
384
        $locationService = $repository->getLocationService();
385
386
        // Double ->lookup() call because there where issue that one call was not enough to spot bug
387
        $urlAliasService->lookup('/Media');
388
        $trashedLocationAlias = $urlAliasService->lookup('/Media');
389
390
        $mediaLocation = $locationService->loadLocationByRemoteId($mediaRemoteId);
391
        $trashItem = $trashService->trash($mediaLocation);
392
        $this->assertAliasNotExists($urlAliasService, '/Media');
393
394
        $this->createNewContentInPlaceTrashedOne($repository, $mediaLocation->parentLocationId);
395
396
        $createdLocationAlias = $urlAliasService->lookup('/Media');
397
398
        $this->assertNotEquals(
399
            $trashedLocationAlias->destination,
400
            $createdLocationAlias->destination,
401
            'Destination for /media url should changed'
402
        );
403
404
        $recoveredLocation = $trashService->recover($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $trashService->trash($mediaLocation) on line 391 can be null; however, eZ\Publish\API\Repository\TrashService::recover() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
405
        $recoveredLocationAlias = $urlAliasService->lookup('/Media2');
406
        $recoveredLocationAliasReverse = $urlAliasService->reverseLookup($recoveredLocation);
407
408
        $this->assertEquals($recoveredLocationAlias->destination, $recoveredLocationAliasReverse->destination);
409
410
        $this->assertNotEquals($recoveredLocationAliasReverse->destination, $trashedLocationAlias->destination);
411
        $this->assertNotEquals($recoveredLocationAliasReverse->destination, $createdLocationAlias->destination);
412
    }
413
414
    /**
415
     * Test for the recover() method.
416
     *
417
     * @see \eZ\Publish\API\Repository\TrashService::recover()
418
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testRecover
419
     */
420
    public function testRecoverDoesNotRestoreChildLocations()
421
    {
422
        $repository = $this->getRepository();
423
        $trashService = $repository->getTrashService();
424
        $locationService = $repository->getLocationService();
425
426
        $remoteIds = $this->createRemoteIdList();
427
428
        // Unset remote ID of actually restored location
429
        unset($remoteIds[array_search('3f6d92f8044aed134f32153517850f5a', $remoteIds)]);
430
431
        $trashItem = $this->createTrashItem();
432
433
        $trashService->recover($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 431 can be null; however, eZ\Publish\API\Repository\TrashService::recover() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
434
435
        $this->assertGreaterThan(
436
            0,
437
            count($remoteIds),
438
            "There should be at least one 'Community' child location."
439
        );
440
441
        // None of the child locations will be available again
442
        foreach ($remoteIds as $remoteId) {
443
            try {
444
                $locationService->loadLocationByRemoteId($remoteId);
445
                $this->fail(
446
                    sprintf(
447
                        'Location with remote ID "%s" unexpectedly restored.',
448
                        $remoteId
449
                    )
450
                );
451
            } catch (NotFoundException $e) {
452
                // All well
453
            }
454
        }
455
456
        try {
457
            $trashService->loadTrashItem($trashItem->id);
458
            $this->fail('Trash item was not removed after being recovered.');
459
        } catch (NotFoundException $e) {
460
            // All well
461
        }
462
    }
463
464
    /**
465
     * Test for the recover() method.
466
     *
467
     * @see \eZ\Publish\API\Repository\TrashService::recover($trashItem, $newParentLocation)
468
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testRecover
469
     *
470
     * @todo Fix naming
471
     */
472
    public function testRecoverWithLocationCreateStructParameter()
473
    {
474
        $repository = $this->getRepository();
475
        $trashService = $repository->getTrashService();
476
        $locationService = $repository->getLocationService();
477
478
        $homeLocationId = $this->generateId('location', 2);
479
        /* BEGIN: Use Case */
480
        // $homeLocationId is the ID of the "Home" location in an eZ Publish
481
        // demo installation
482
483
        $trashItem = $this->createTrashItem();
484
485
        // Get the new parent location
486
        $newParentLocation = $locationService->loadLocation($homeLocationId);
487
488
        // Recover location with new location
489
        $location = $trashService->recover($trashItem, $newParentLocation);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 483 can be null; however, eZ\Publish\API\Repository\TrashService::recover() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
490
        /* END: Use Case */
491
492
        $this->assertPropertiesCorrect(
493
            array(
494
                'remoteId' => $trashItem->remoteId,
495
                'parentLocationId' => $homeLocationId,
496
                // Not the full sub tree is restored
497
                'depth' => $newParentLocation->depth + 1,
498
                'hidden' => false,
499
                'invisible' => $trashItem->invisible,
500
                'pathString' => $newParentLocation->pathString . $this->parseId('location', $location->id) . '/',
501
                'priority' => 0,
502
                'sortField' => APILocation::SORT_FIELD_NAME,
503
                'sortOrder' => APILocation::SORT_ORDER_ASC,
504
            ),
505
            $location
506
        );
507
508
        try {
509
            $trashService->loadTrashItem($trashItem->id);
510
            $this->fail('Trash item was not removed after being recovered.');
511
        } catch (NotFoundException $e) {
512
            // All well
513
        }
514
    }
515
516
    /**
517
     * Test for the recover() method.
518
     *
519
     * @see \eZ\Publish\API\Repository\TrashService::recover($trashItem)
520
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testRecover
521
     */
522
    public function testRecoverIncrementsChildCountOnOriginalParent()
523
    {
524
        $repository = $this->getRepository();
525
        $trashService = $repository->getTrashService();
526
        $locationService = $repository->getLocationService();
527
528
        $location = $locationService->loadLocation($this->generateId('location', 1));
529
530
        $trashItem = $this->createTrashItem();
531
532
        $this->refreshSearch($repository);
533
534
        /* BEGIN: Use Case */
535
        $childCount = $locationService->getLocationChildCount($location);
536
537
        // Recover location with new location
538
        $trashService->recover($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 530 can be null; however, eZ\Publish\API\Repository\TrashService::recover() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
539
        /* END: Use Case */
540
541
        $this->refreshSearch($repository);
542
543
        $this->assertEquals(
544
            $childCount + 1,
545
            $locationService->getLocationChildCount($location)
546
        );
547
548
        try {
549
            $trashService->loadTrashItem($trashItem->id);
550
            $this->fail('Trash item was not removed after being recovered.');
551
        } catch (NotFoundException $e) {
552
            // All well
553
        }
554
    }
555
556
    /**
557
     * Test for the recover() method.
558
     *
559
     * @see \eZ\Publish\API\Repository\TrashService::recover($trashItem, $newParentLocation)
560
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testRecoverWithLocationCreateStructParameter
561
     */
562
    public function testRecoverWithLocationCreateStructParameterIncrementsChildCountOnNewParent()
563
    {
564
        $repository = $this->getRepository();
565
        $trashService = $repository->getTrashService();
566
        $locationService = $repository->getLocationService();
567
568
        $homeLocationId = $this->generateId('location', 2);
569
570
        $location = $locationService->loadLocation($homeLocationId);
571
572
        $childCount = $locationService->getLocationChildCount($location);
573
574
        /* BEGIN: Use Case */
575
        // $homeLocationId is the ID of the "Home" location in an eZ Publish
576
        // demo installation
577
578
        $trashItem = $this->createTrashItem();
579
580
        // Get the new parent location
581
        $newParentLocation = $locationService->loadLocation($homeLocationId);
582
583
        // Recover location with new location
584
        $trashService->recover($trashItem, $newParentLocation);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 578 can be null; however, eZ\Publish\API\Repository\TrashService::recover() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
585
        /* END: Use Case */
586
587
        $this->refreshSearch($repository);
588
589
        $this->assertEquals(
590
            $childCount + 1,
591
            $locationService->getLocationChildCount($location)
592
        );
593
594
        try {
595
            $trashService->loadTrashItem($trashItem->id);
596
            $this->fail('Trash item was not removed after being recovered.');
597
        } catch (NotFoundException $e) {
598
            // All well
599
        }
600
    }
601
602
    /**
603
     * Test recovering a location from trash to non existing location.
604
     *
605
     * @covers \eZ\Publish\API\Repository\TrashService::recover
606
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
607
     */
608 View Code Duplication
    public function testRecoverToNonExistingLocation()
609
    {
610
        $repository = $this->getRepository();
611
        $trashService = $repository->getTrashService();
612
        $locationService = $repository->getLocationService();
613
614
        $location = $locationService->loadLocation(44);
615
        $trashItem = $trashService->trash($location);
616
617
        $newParentLocation = new Location(
618
            array(
619
                'id' => 123456,
620
                'parentLocationId' => 123455,
621
            )
622
        );
623
        $trashService->recover($trashItem, $newParentLocation);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $trashService->trash($location) on line 615 can be null; however, eZ\Publish\API\Repository\TrashService::recover() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
624
    }
625
626
    /**
627
     * Test for the findTrashItems() method.
628
     *
629
     * @see \eZ\Publish\API\Repository\TrashService::findTrashItems()
630
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
631
     */
632 View Code Duplication
    public function testFindTrashItems()
633
    {
634
        $repository = $this->getRepository();
635
        $trashService = $repository->getTrashService();
636
637
        /* BEGIN: Use Case */
638
        $this->createTrashItem();
639
640
        // Create a search query for all trashed items
641
        $query = new Query();
642
        $query->filter = new Criterion\LogicalAnd(
643
            array(
644
                new Criterion\Field('title', Criterion\Operator::LIKE, '*'),
645
            )
646
        );
647
648
        // Load all trashed locations
649
        $searchResult = $trashService->findTrashItems($query);
650
        /* END: Use Case */
651
652
        $this->assertInstanceOf(
653
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\SearchResult',
654
            $searchResult
655
        );
656
657
        // 4 trashed locations from the sub tree
658
        $this->assertEquals(4, $searchResult->count);
659
    }
660
661
    /**
662
     * Test for the findTrashItems() method.
663
     *
664
     * @see \eZ\Publish\API\Repository\TrashService::findTrashItems()
665
     * @depends \eZ\Publish\API\Repository\Tests\TrashServiceTest::testFindTrashItems
666
     */
667
    public function testFindTrashItemsLimitedAccess()
668
    {
669
        $repository = $this->getRepository();
670
        $trashService = $repository->getTrashService();
671
672
        /* BEGIN: Use Case */
673
        $this->createTrashItem();
674
675
        // Create a search query for all trashed items
676
        $query = new Query();
677
        $query->filter = new Criterion\LogicalAnd(
678
            array(
679
                new Criterion\Field('title', Criterion\Operator::LIKE, '*'),
680
            )
681
        );
682
683
        // Create a user in the Editor user group.
684
        $user = $this->createUserVersion1();
685
686
        // Set the Editor user as current user, these users have no access to Trash by default.
687
        $repository->getPermissionResolver()->setCurrentUserReference($user);
688
689
        // Load all trashed locations
690
        $searchResult = $trashService->findTrashItems($query);
691
        /* END: Use Case */
692
693
        $this->assertInstanceOf(
694
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\SearchResult',
695
            $searchResult
696
        );
697
698
        // 0 trashed locations found, though 4 exist
699
        $this->assertEquals(0, $searchResult->count);
700
    }
701
702
    /**
703
     * Test for the emptyTrash() method.
704
     *
705
     * @see \eZ\Publish\API\Repository\TrashService::emptyTrash()
706
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testFindTrashItems
707
     */
708 View Code Duplication
    public function testEmptyTrash()
709
    {
710
        $repository = $this->getRepository();
711
        $trashService = $repository->getTrashService();
712
713
        /* BEGIN: Use Case */
714
        $this->createTrashItem();
715
716
        // Empty the trash
717
        $trashService->emptyTrash();
718
719
        // Create a search query for all trashed items
720
        $query = new Query();
721
        $query->filter = new Criterion\LogicalAnd(
722
            array(
723
                new Criterion\Field('title', Criterion\Operator::LIKE, '*'),
724
            )
725
        );
726
727
        // Load all trashed locations, search result should be empty
728
        $searchResult = $trashService->findTrashItems($query);
729
        /* END: Use Case */
730
731
        $this->assertEquals(0, $searchResult->count);
732
    }
733
734
    /**
735
     * Test for the deleteTrashItem() method.
736
     *
737
     * @see \eZ\Publish\API\Repository\TrashService::deleteTrashItem()
738
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testFindTrashItems
739
     */
740
    public function testDeleteTrashItem()
741
    {
742
        $repository = $this->getRepository();
743
        $trashService = $repository->getTrashService();
744
        $locationService = $repository->getLocationService();
745
746
        $demoDesignLocationId = $this->generateId('location', 56);
747
        /* BEGIN: Use Case */
748
        // $demoDesignLocationId is the ID of the "Demo Design" location in an eZ
749
        // Publish demo installation
750
751
        $trashItem = $this->createTrashItem();
752
753
        // Trash one more location
754
        $trashService->trash(
755
            $locationService->loadLocation($demoDesignLocationId)
756
        );
757
758
        // Empty the trash
759
        $trashService->deleteTrashItem($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 751 can be null; however, eZ\Publish\API\Repositor...vice::deleteTrashItem() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
760
761
        // Create a search query for all trashed items
762
        $query = new Query();
763
        $query->filter = new Criterion\LogicalAnd(
764
            array(
765
                new Criterion\Field('title', Criterion\Operator::LIKE, '*'),
766
            )
767
        );
768
769
        // Load all trashed locations, should only contain the Demo Design location
770
        $searchResult = $trashService->findTrashItems($query);
771
        /* END: Use Case */
772
773
        $foundIds = array_map(
774
            function ($trashItem) {
775
                return $trashItem->id;
776
            },
777
            $searchResult->items
778
        );
779
780
        $this->assertEquals(4, $searchResult->count);
781
        $this->assertTrue(
782
            in_array($demoDesignLocationId, $foundIds)
783
        );
784
    }
785
786
    /**
787
     * Test deleting a non existing trash item.
788
     *
789
     * @covers \eZ\Publish\API\Repository\TrashService::deleteTrashItem
790
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
791
     */
792
    public function testDeleteThrowsNotFoundExceptionForNonExistingTrashItem()
793
    {
794
        $repository = $this->getRepository();
795
        $trashService = $repository->getTrashService();
796
797
        $trashService->deleteTrashItem($this->getTrashItemDouble(
798
            12364,
799
            12345,
800
            12363
801
        ));
802
    }
803
804
    /**
805
     * Returns an array with the remoteIds of all child locations of the
806
     * <b>Community</b> location. It is stored in a local variable named
807
     * <b>$remoteIds</b>.
808
     *
809
     * @return string[]
810
     */
811
    private function createRemoteIdList()
812
    {
813
        $repository = $this->getRepository();
814
815
        /* BEGIN: Inline */
816
        // remoteId of the "Community" location in an eZ Publish demo installation
817
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
818
819
        // Load the location service
820
        $locationService = $repository->getLocationService();
821
822
        $remoteIds = array();
823
        $children = $locationService->loadLocationChildren($locationService->loadLocationByRemoteId($mediaRemoteId));
824
        foreach ($children->locations as $child) {
825
            $remoteIds[] = $child->remoteId;
826
            foreach ($locationService->loadLocationChildren($child)->locations as $grandChild) {
827
                $remoteIds[] = $grandChild->remoteId;
828
            }
829
        }
830
        /* END: Inline */
831
832
        return $remoteIds;
833
    }
834
835
    /**
836
     * @param Repository $repository
837
     * @param int $parentLocationId
838
     *
839
     * @return \eZ\Publish\API\Repository\Values\Content\Content
840
     */
841 View Code Duplication
    protected function createNewContentInPlaceTrashedOne(Repository $repository, $parentLocationId)
842
    {
843
        $contentService = $repository->getContentService();
844
        $locationService = $repository->getLocationService();
845
        $contentTypeService = $repository->getContentTypeService();
846
847
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
848
        $newContent = $contentService->newContentCreateStruct($contentType, 'eng-US');
849
        $newContent->setField('name', 'Media');
850
851
        $location = $locationService->newLocationCreateStruct($parentLocationId);
852
853
        $draftContent = $contentService->createContent($newContent, [$location]);
854
855
        return $contentService->publishVersion($draftContent->versionInfo);
856
    }
857
858
    /**
859
     * @param URLAliasService $urlAliasService
860
     * @param string $urlPath Url alias path
861
     *
862
     * @return \eZ\Publish\API\Repository\Values\Content\URLAlias
863
     */
864
    private function assertAliasExists(URLAliasService $urlAliasService, $urlPath)
865
    {
866
        $urlAlias = $urlAliasService->lookup($urlPath);
867
868
        $this->assertInstanceOf('\eZ\Publish\API\Repository\Values\Content\URLAlias', $urlAlias);
869
870
        return $urlAlias;
871
    }
872
873
    /**
874
     * @param URLAliasService $urlAliasService
875
     * @param string $urlPath Url alias path
876
     */
877
    private function assertAliasNotExists(URLAliasService $urlAliasService, $urlPath)
0 ignored issues
show
Unused Code introduced by
The parameter $urlAliasService is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
878
    {
879
        try {
880
            $this->getRepository()->getURLAliasService()->lookup($urlPath);
881
            $this->fail(sprintf('Alias [%s] should not exists', $urlPath));
882
        } catch (\eZ\Publish\API\Repository\Exceptions\NotFoundException $e) {
883
            $this->assertTrue(true);
884
        }
885
    }
886
887
    /**
888
     * Get Test Double for TrashItem for exception testing and similar.
889
     */
890
    private function getTrashItemDouble(int $trashId, int $contentId = 44, int $parentLocationId = 2): TrashItem
891
    {
892
        return new TrashItem([
893
            'id' => $trashId,
894
            'parentLocationId' => $parentLocationId,
895
            'contentInfo' => new ContentInfo(['id' => $contentId]),
896
        ]);
897
    }
898
}
899