Completed
Push — spi_log_cache_hits ( 876d84...ef4861 )
by André
39:52
created

TrashServiceTest::assertAliasNotExists()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 3
nop 2
dl 0
loc 9
rs 9.9666
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\Content;
14
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
15
use eZ\Publish\API\Repository\Values\Content\Location as APILocation;
16
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
17
use eZ\Publish\API\Repository\Values\Content\Query;
18
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
19
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
20
use eZ\Publish\API\Repository\Values\Content\Trash\SearchResult;
21
use eZ\Publish\API\Repository\Values\Content\TrashItem as APITrashItem;
22
use eZ\Publish\Core\Repository\Values\Content\TrashItem;
23
use eZ\Publish\Core\Repository\Values\Content\Location;
24
use DateTime;
25
26
/**
27
 * Test case for operations in the TrashService using in memory storage.
28
 *
29
 * @see eZ\Publish\API\Repository\TrashService
30
 * @group integration
31
 * @group trash
32
 */
33
class TrashServiceTest extends BaseTrashServiceTest
34
{
35
    /**
36
     * Test for the trash() method.
37
     *
38
     * @see \eZ\Publish\API\Repository\TrashService::trash()
39
     * @depends eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationByRemoteId
40
     */
41
    public function testTrash()
42
    {
43
        /* BEGIN: Use Case */
44
        $trashItem = $this->createTrashItem();
45
        /* END: Use Case */
46
47
        $this->assertInstanceOf(
48
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\TrashItem',
49
            $trashItem
50
        );
51
    }
52
53
    /**
54
     * Test for the trash() method.
55
     *
56
     * @see \eZ\Publish\API\Repository\TrashService::trash()
57
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
58
     */
59
    public function testTrashSetsExpectedTrashItemProperties()
60
    {
61
        $repository = $this->getRepository();
62
63
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
64
65
        // Load the location that will be trashed
66
        $location = $repository->getLocationService()
67
            ->loadLocationByRemoteId($mediaRemoteId);
68
69
        $expected = array(
70
            'id' => $location->id,
71
            'depth' => $location->depth,
72
            'hidden' => $location->hidden,
73
            'invisible' => $location->invisible,
74
            'parentLocationId' => $location->parentLocationId,
75
            'pathString' => $location->pathString,
76
            'priority' => $location->priority,
77
            'remoteId' => $location->remoteId,
78
            'sortField' => $location->sortField,
79
            'sortOrder' => $location->sortOrder,
80
        );
81
82
        $trashItem = $this->createTrashItem();
83
84
        $this->assertPropertiesCorrect($expected, $trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 82 can be null; however, eZ\Publish\API\Repositor...sertPropertiesCorrect() 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...
85
    }
86
87
    /**
88
     * Test for the trash() method.
89
     *
90
     * @see \eZ\Publish\API\Repository\TrashService::trash()
91
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
92
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
93
     */
94
    public function testTrashRemovesLocationFromMainStorage()
95
    {
96
        $repository = $this->getRepository();
97
98
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
99
100
        /* BEGIN: Use Case */
101
        $this->createTrashItem();
102
103
        // Load the location service
104
        $locationService = $repository->getLocationService();
105
106
        // This call will fail with a "NotFoundException", because the media
107
        // location was marked as trashed in the main storage
108
        $locationService->loadLocationByRemoteId($mediaRemoteId);
109
        /* END: Use Case */
110
    }
111
112
    /**
113
     * Test for the trash() method.
114
     *
115
     * @see \eZ\Publish\API\Repository\TrashService::trash()
116
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
117
     */
118
    public function testTrashRemovesChildLocationsFromMainStorage()
119
    {
120
        $repository = $this->getRepository();
121
122
        /* BEGIN: Use Case */
123
        $remoteIds = $this->createRemoteIdList();
124
125
        $this->createTrashItem();
126
127
        // All invocations to loadLocationByRemoteId() to one of the above
128
        // collected remoteIds will return in an "NotFoundException"
129
        /* END: Use Case */
130
131
        $locationService = $repository->getLocationService();
132
        foreach ($remoteIds as $remoteId) {
133
            try {
134
                $locationService->loadLocationByRemoteId($remoteId);
135
                $this->fail("Location '{$remoteId}' should exist.'");
136
            } catch (NotFoundException $e) {
137
                // echo $e->getFile(), ' +', $e->getLine(), PHP_EOL;
138
            }
139
        }
140
141
        $this->assertGreaterThan(
142
            0,
143
            count($remoteIds),
144
            "There should be at least one 'Community' child location."
145
        );
146
    }
147
148
    /**
149
     * Test for the trash() method.
150
     *
151
     * @see \eZ\Publish\API\Repository\TrashService::trash()
152
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
153
     */
154 View Code Duplication
    public function testTrashDecrementsChildCountOnParentLocation()
155
    {
156
        $repository = $this->getRepository();
157
        $locationService = $repository->getLocationService();
158
159
        $baseLocationId = $this->generateId('location', 1);
160
161
        $location = $locationService->loadLocation($baseLocationId);
162
163
        $childCount = $locationService->getLocationChildCount($location);
164
165
        $this->createTrashItem();
166
167
        $this->refreshSearch($repository);
168
169
        $this->assertEquals(
170
            $childCount - 1,
171
            $locationService->getLocationChildCount($location)
172
        );
173
    }
174
175
    /**
176
     * Test sending a location to trash updates Content mainLocation.
177
     *
178
     * @covers \eZ\Publish\API\Repository\TrashService::trash
179
     */
180
    public function testTrashUpdatesMainLocation()
181
    {
182
        $repository = $this->getRepository();
183
        $contentService = $repository->getContentService();
184
        $locationService = $repository->getLocationService();
185
        $trashService = $repository->getTrashService();
186
187
        $contentInfo = $contentService->loadContentInfo(42);
188
189
        // Create additional location that will become new main location
190
        $location = $locationService->createLocation(
191
            $contentInfo,
192
            new LocationCreateStruct(['parentLocationId' => 2])
193
        );
194
195
        $trashService->trash(
196
            $locationService->loadLocation($contentInfo->mainLocationId)
197
        );
198
199
        self::assertEquals(
200
            $location->id,
201
            $contentService->loadContentInfo(42)->mainLocationId
202
        );
203
    }
204
205
    /**
206
     * Test sending a location to trash.
207
     *
208
     * @covers \eZ\Publish\API\Repository\TrashService::trash
209
     */
210 View Code Duplication
    public function testTrashReturnsNull()
211
    {
212
        $repository = $this->getRepository();
213
        $contentService = $repository->getContentService();
214
        $locationService = $repository->getLocationService();
215
        $trashService = $repository->getTrashService();
216
217
        // Create additional location to trash
218
        $location = $locationService->createLocation(
219
            $contentService->loadContentInfo(42),
220
            new LocationCreateStruct(['parentLocationId' => 2])
221
        );
222
223
        $trashItem = $trashService->trash($location);
224
225
        self::assertNull($trashItem);
226
    }
227
228
    /**
229
     * Test for the loadTrashItem() method.
230
     *
231
     * @covers \eZ\Publish\API\Repository\TrashService::loadTrashItem
232
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
233
     */
234
    public function testLoadTrashItem()
235
    {
236
        $repository = $this->getRepository();
237
        $trashService = $repository->getTrashService();
238
239
        /* BEGIN: Use Case */
240
        $trashItem = $this->createTrashItem();
241
242
        // Reload the trash item
243
        $trashItemReloaded = $trashService->loadTrashItem($trashItem->id);
244
        /* END: Use Case */
245
246
        $this->assertInstanceOf(
247
            APITrashItem::class,
248
            $trashItemReloaded
249
        );
250
251
        $this->assertEquals(
252
            $trashItem->pathString,
253
            $trashItemReloaded->pathString
254
        );
255
256
        $this->assertEquals(
257
            $trashItem,
258
            $trashItemReloaded
259
        );
260
261
        $this->assertInstanceOf(
262
            DateTime::class,
263
            $trashItemReloaded->trashed
264
        );
265
266
        $this->assertEquals(
267
            $trashItem->trashed->getTimestamp(),
268
            $trashItemReloaded->trashed->getTimestamp()
269
        );
270
271
        $this->assertGreaterThan(
272
            0,
273
            $trashItemReloaded->trashed->getTimestamp()
274
        );
275
276
        $this->assertInstanceOf(
277
            Content::class,
278
            $content = $trashItemReloaded->getContent()
279
        );
280
        $this->assertEquals($trashItem->contentId, $content->contentInfo->id);
281
    }
282
283
    /**
284
     * Test for the loadTrashItem() method.
285
     *
286
     * @see \eZ\Publish\API\Repository\TrashService::loadTrashItem()
287
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
288
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testLoadTrashItem
289
     */
290
    public function testLoadTrashItemThrowsNotFoundException()
291
    {
292
        $repository = $this->getRepository();
293
294
        $nonExistingTrashId = $this->generateId('trash', 2342);
295
        /* BEGIN: Use Case */
296
        $trashService = $repository->getTrashService();
297
298
        // This call will fail with a "NotFoundException", because no trash item
299
        // with the ID 1342 should exist in an eZ Publish demo installation
300
        $trashService->loadTrashItem($nonExistingTrashId);
301
        /* END: Use Case */
302
    }
303
304
    /**
305
     * Test for the recover() method.
306
     *
307
     * @covers \eZ\Publish\API\Repository\TrashService::recover
308
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
309
     */
310
    public function testRecover()
311
    {
312
        $repository = $this->getRepository();
313
        $trashService = $repository->getTrashService();
314
        $locationService = $repository->getLocationService();
315
316
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
317
318
        /* BEGIN: Use Case */
319
        $trashItem = $this->createTrashItem();
320
321
        // Recover the trashed item
322
        $location = $trashService->recover($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 319 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...
323
324
        // Load the recovered location
325
        $locationReloaded = $locationService->loadLocationByRemoteId(
326
            $mediaRemoteId
327
        );
328
        /* END: Use Case */
329
330
        $this->assertInstanceOf(
331
            APILocation::class,
332
            $location
333
        );
334
335
        $this->assertEquals(
336
            $location,
337
            $locationReloaded
338
        );
339
340
        try {
341
            $trashService->loadTrashItem($trashItem->id);
342
            $this->fail('Trash item was not removed after being recovered.');
343
        } catch (NotFoundException $e) {
344
            // All well
345
        }
346
    }
347
348
    /**
349
     * Test recovering a non existing trash item results in a NotFoundException.
350
     *
351
     * @covers \eZ\Publish\API\Repository\TrashService::recover
352
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
353
     */
354
    public function testRecoverThrowsNotFoundExceptionForNonExistingTrashItem()
355
    {
356
        $repository = $this->getRepository();
357
        $trashService = $repository->getTrashService();
358
359
        $trashService->recover(
360
            $this->getTrashItemDouble(
361
                12364,
362
                12345,
363
                12363
364
            )
365
        );
366
    }
367
368
    /**
369
     * Test for the trash() method.
370
     *
371
     * @see \eZ\Publish\API\Repository\TrashService::recover()
372
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
373
     *
374
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
375
     */
376
    public function testNotFoundAliasAfterRemoveIt()
377
    {
378
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
379
380
        $repository = $this->getRepository();
381
        $trashService = $repository->getTrashService();
382
        $urlAliasService = $repository->getURLAliasService();
383
        $locationService = $repository->getLocationService();
384
385
        // Double ->lookup() call because there where issue that one call was not enough to spot bug
386
        $urlAliasService->lookup('/Media');
387
        $urlAliasService->lookup('/Media');
388
389
        $mediaLocation = $locationService->loadLocationByRemoteId($mediaRemoteId);
390
        $trashService->trash($mediaLocation);
391
392
        $urlAliasService->lookup('/Media');
393
    }
394
395
    /**
396
     * Test for the recover() method.
397
     *
398
     * @see \eZ\Publish\API\Repository\TrashService::recover()
399
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
400
     */
401
    public function testAliasesForRemovedItems()
402
    {
403
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
404
405
        $repository = $this->getRepository();
406
        $trashService = $repository->getTrashService();
407
        $urlAliasService = $repository->getURLAliasService();
408
        $locationService = $repository->getLocationService();
409
410
        // Double ->lookup() call because there where issue that one call was not enough to spot bug
411
        $urlAliasService->lookup('/Media');
412
        $trashedLocationAlias = $urlAliasService->lookup('/Media');
413
414
        $mediaLocation = $locationService->loadLocationByRemoteId($mediaRemoteId);
415
        $trashItem = $trashService->trash($mediaLocation);
416
        $this->assertAliasNotExists($urlAliasService, '/Media');
417
418
        $this->createNewContentInPlaceTrashedOne($repository, $mediaLocation->parentLocationId);
419
420
        $createdLocationAlias = $urlAliasService->lookup('/Media');
421
422
        $this->assertNotEquals(
423
            $trashedLocationAlias->destination,
424
            $createdLocationAlias->destination,
425
            'Destination for /media url should changed'
426
        );
427
428
        $recoveredLocation = $trashService->recover($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $trashService->trash($mediaLocation) on line 415 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...
429
        $recoveredLocationAlias = $urlAliasService->lookup('/Media2');
430
        $recoveredLocationAliasReverse = $urlAliasService->reverseLookup($recoveredLocation);
431
432
        $this->assertEquals($recoveredLocationAlias->destination, $recoveredLocationAliasReverse->destination);
433
434
        $this->assertNotEquals($recoveredLocationAliasReverse->destination, $trashedLocationAlias->destination);
435
        $this->assertNotEquals($recoveredLocationAliasReverse->destination, $createdLocationAlias->destination);
436
    }
437
438
    /**
439
     * Test for the recover() method.
440
     *
441
     * @see \eZ\Publish\API\Repository\TrashService::recover()
442
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testRecover
443
     */
444
    public function testRecoverDoesNotRestoreChildLocations()
445
    {
446
        $repository = $this->getRepository();
447
        $trashService = $repository->getTrashService();
448
        $locationService = $repository->getLocationService();
449
450
        $remoteIds = $this->createRemoteIdList();
451
452
        // Unset remote ID of actually restored location
453
        unset($remoteIds[array_search('3f6d92f8044aed134f32153517850f5a', $remoteIds)]);
454
455
        $trashItem = $this->createTrashItem();
456
457
        $trashService->recover($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 455 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...
458
459
        $this->assertGreaterThan(
460
            0,
461
            count($remoteIds),
462
            "There should be at least one 'Community' child location."
463
        );
464
465
        // None of the child locations will be available again
466
        foreach ($remoteIds as $remoteId) {
467
            try {
468
                $locationService->loadLocationByRemoteId($remoteId);
469
                $this->fail(
470
                    sprintf(
471
                        'Location with remote ID "%s" unexpectedly restored.',
472
                        $remoteId
473
                    )
474
                );
475
            } catch (NotFoundException $e) {
476
                // All well
477
            }
478
        }
479
480
        try {
481
            $trashService->loadTrashItem($trashItem->id);
482
            $this->fail('Trash item was not removed after being recovered.');
483
        } catch (NotFoundException $e) {
484
            // All well
485
        }
486
    }
487
488
    /**
489
     * Test for the recover() method.
490
     *
491
     * @see \eZ\Publish\API\Repository\TrashService::recover($trashItem, $newParentLocation)
492
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testRecover
493
     *
494
     * @todo Fix naming
495
     */
496
    public function testRecoverWithLocationCreateStructParameter()
497
    {
498
        $repository = $this->getRepository();
499
        $trashService = $repository->getTrashService();
500
        $locationService = $repository->getLocationService();
501
502
        $homeLocationId = $this->generateId('location', 2);
503
        /* BEGIN: Use Case */
504
        // $homeLocationId is the ID of the "Home" location in an eZ Publish
505
        // demo installation
506
507
        $trashItem = $this->createTrashItem();
508
509
        // Get the new parent location
510
        $newParentLocation = $locationService->loadLocation($homeLocationId);
511
512
        // Recover location with new location
513
        $location = $trashService->recover($trashItem, $newParentLocation);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 507 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...
514
        /* END: Use Case */
515
516
        $this->assertPropertiesCorrect(
517
            array(
518
                'remoteId' => $trashItem->remoteId,
519
                'parentLocationId' => $homeLocationId,
520
                // Not the full sub tree is restored
521
                'depth' => $newParentLocation->depth + 1,
522
                'hidden' => false,
523
                'invisible' => $trashItem->invisible,
524
                'pathString' => $newParentLocation->pathString . $this->parseId('location', $location->id) . '/',
525
                'priority' => 0,
526
                'sortField' => APILocation::SORT_FIELD_NAME,
527
                'sortOrder' => APILocation::SORT_ORDER_ASC,
528
            ),
529
            $location
530
        );
531
532
        try {
533
            $trashService->loadTrashItem($trashItem->id);
534
            $this->fail('Trash item was not removed after being recovered.');
535
        } catch (NotFoundException $e) {
536
            // All well
537
        }
538
    }
539
540
    /**
541
     * Test for the recover() method.
542
     *
543
     * @see \eZ\Publish\API\Repository\TrashService::recover($trashItem)
544
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testRecover
545
     */
546
    public function testRecoverIncrementsChildCountOnOriginalParent()
547
    {
548
        $repository = $this->getRepository();
549
        $trashService = $repository->getTrashService();
550
        $locationService = $repository->getLocationService();
551
552
        $location = $locationService->loadLocation($this->generateId('location', 1));
553
554
        $trashItem = $this->createTrashItem();
555
556
        $this->refreshSearch($repository);
557
558
        /* BEGIN: Use Case */
559
        $childCount = $locationService->getLocationChildCount($location);
560
561
        // Recover location with new location
562
        $trashService->recover($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 554 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...
563
        /* END: Use Case */
564
565
        $this->refreshSearch($repository);
566
567
        $this->assertEquals(
568
            $childCount + 1,
569
            $locationService->getLocationChildCount($location)
570
        );
571
572
        try {
573
            $trashService->loadTrashItem($trashItem->id);
574
            $this->fail('Trash item was not removed after being recovered.');
575
        } catch (NotFoundException $e) {
576
            // All well
577
        }
578
    }
579
580
    /**
581
     * Test for the recover() method.
582
     *
583
     * @see \eZ\Publish\API\Repository\TrashService::recover($trashItem, $newParentLocation)
584
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testRecoverWithLocationCreateStructParameter
585
     */
586
    public function testRecoverWithLocationCreateStructParameterIncrementsChildCountOnNewParent()
587
    {
588
        $repository = $this->getRepository();
589
        $trashService = $repository->getTrashService();
590
        $locationService = $repository->getLocationService();
591
592
        $homeLocationId = $this->generateId('location', 2);
593
594
        $location = $locationService->loadLocation($homeLocationId);
595
596
        $childCount = $locationService->getLocationChildCount($location);
597
598
        /* BEGIN: Use Case */
599
        // $homeLocationId is the ID of the "Home" location in an eZ Publish
600
        // demo installation
601
602
        $trashItem = $this->createTrashItem();
603
604
        // Get the new parent location
605
        $newParentLocation = $locationService->loadLocation($homeLocationId);
606
607
        // Recover location with new location
608
        $trashService->recover($trashItem, $newParentLocation);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 602 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...
609
        /* END: Use Case */
610
611
        $this->refreshSearch($repository);
612
613
        $this->assertEquals(
614
            $childCount + 1,
615
            $locationService->getLocationChildCount($location)
616
        );
617
618
        try {
619
            $trashService->loadTrashItem($trashItem->id);
620
            $this->fail('Trash item was not removed after being recovered.');
621
        } catch (NotFoundException $e) {
622
            // All well
623
        }
624
    }
625
626
    /**
627
     * Test recovering a location from trash to non existing location.
628
     *
629
     * @covers \eZ\Publish\API\Repository\TrashService::recover
630
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
631
     */
632 View Code Duplication
    public function testRecoverToNonExistingLocation()
633
    {
634
        $repository = $this->getRepository();
635
        $trashService = $repository->getTrashService();
636
        $locationService = $repository->getLocationService();
637
638
        $location = $locationService->loadLocation(44);
639
        $trashItem = $trashService->trash($location);
640
641
        $newParentLocation = new Location(
642
            array(
643
                'id' => 123456,
644
                'parentLocationId' => 123455,
645
            )
646
        );
647
        $trashService->recover($trashItem, $newParentLocation);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $trashService->trash($location) on line 639 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...
648
    }
649
650
    /**
651
     * Test for the findTrashItems() method.
652
     *
653
     * @see \eZ\Publish\API\Repository\TrashService::findTrashItems()
654
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
655
     */
656
    public function testFindTrashItems()
657
    {
658
        $repository = $this->getRepository();
659
        $trashService = $repository->getTrashService();
660
661
        /* BEGIN: Use Case */
662
        $this->createTrashItem();
663
664
        // Create a search query for all trashed items
665
        $query = new Query();
666
        $query->filter = new Criterion\LogicalAnd(
667
            array(
668
                new Criterion\Field('title', Criterion\Operator::LIKE, '*'),
669
            )
670
        );
671
672
        // Load all trashed locations
673
        $searchResult = $trashService->findTrashItems($query);
674
        /* END: Use Case */
675
676
        $this->assertInstanceOf(
677
            SearchResult::class,
678
            $searchResult
679
        );
680
681
        // 4 trashed locations from the sub tree
682
        $this->assertEquals(4, $searchResult->count);
0 ignored issues
show
Deprecated Code introduced by
The property eZ\Publish\API\Repositor...sh\SearchResult::$count has been deprecated with message: Property is here purely for BC with 5.x/6.x.

This property 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 property will be removed from the class and what other property to use instead.

Loading history...
683
        $this->assertEquals(4, $searchResult->totalCount);
684
    }
685
686
    /**
687
     * Test for the findTrashItems() method.
688
     *
689
     * @see \eZ\Publish\API\Repository\TrashService::findTrashItems()
690
     * @depends \eZ\Publish\API\Repository\Tests\TrashServiceTest::testFindTrashItems
691
     */
692
    public function testFindTrashItemsLimitedAccess()
693
    {
694
        $repository = $this->getRepository();
695
        $trashService = $repository->getTrashService();
696
697
        /* BEGIN: Use Case */
698
        $this->createTrashItem();
699
700
        // Create a search query for all trashed items
701
        $query = new Query();
702
        $query->filter = new Criterion\LogicalAnd(
703
            array(
704
                new Criterion\Field('title', Criterion\Operator::LIKE, '*'),
705
            )
706
        );
707
708
        // Create a user in the Editor user group.
709
        $user = $this->createUserVersion1();
710
711
        // Set the Editor user as current user, these users have no access to Trash by default.
712
        $repository->getPermissionResolver()->setCurrentUserReference($user);
713
714
        // Load all trashed locations
715
        $searchResult = $trashService->findTrashItems($query);
716
        /* END: Use Case */
717
718
        $this->assertInstanceOf(
719
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\SearchResult',
720
            $searchResult
721
        );
722
723
        // 0 trashed locations found, though 4 exist
724
        $this->assertEquals(0, $searchResult->count);
0 ignored issues
show
Deprecated Code introduced by
The property eZ\Publish\API\Repositor...sh\SearchResult::$count has been deprecated with message: Property is here purely for BC with 5.x/6.x.

This property 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 property will be removed from the class and what other property to use instead.

Loading history...
725
    }
726
727
    /**
728
     * Test for the emptyTrash() method.
729
     *
730
     * @see \eZ\Publish\API\Repository\TrashService::emptyTrash()
731
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testFindTrashItems
732
     */
733 View Code Duplication
    public function testEmptyTrash()
734
    {
735
        $repository = $this->getRepository();
736
        $trashService = $repository->getTrashService();
737
738
        /* BEGIN: Use Case */
739
        $this->createTrashItem();
740
741
        // Empty the trash
742
        $trashService->emptyTrash();
743
744
        // Create a search query for all trashed items
745
        $query = new Query();
746
        $query->filter = new Criterion\LogicalAnd(
747
            array(
748
                new Criterion\Field('title', Criterion\Operator::LIKE, '*'),
749
            )
750
        );
751
752
        // Load all trashed locations, search result should be empty
753
        $searchResult = $trashService->findTrashItems($query);
754
        /* END: Use Case */
755
756
        $this->assertEquals(0, $searchResult->count);
0 ignored issues
show
Deprecated Code introduced by
The property eZ\Publish\API\Repositor...sh\SearchResult::$count has been deprecated with message: Property is here purely for BC with 5.x/6.x.

This property 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 property will be removed from the class and what other property to use instead.

Loading history...
757
    }
758
759
    /**
760
     * Test for the deleteTrashItem() method.
761
     *
762
     * @see \eZ\Publish\API\Repository\TrashService::deleteTrashItem()
763
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testFindTrashItems
764
     */
765
    public function testDeleteTrashItem()
766
    {
767
        $repository = $this->getRepository();
768
        $trashService = $repository->getTrashService();
769
        $locationService = $repository->getLocationService();
770
771
        $demoDesignLocationId = $this->generateId('location', 56);
772
        /* BEGIN: Use Case */
773
        // $demoDesignLocationId is the ID of the "Demo Design" location in an eZ
774
        // Publish demo installation
775
776
        $trashItem = $this->createTrashItem();
777
778
        // Trash one more location
779
        $trashService->trash(
780
            $locationService->loadLocation($demoDesignLocationId)
781
        );
782
783
        // Empty the trash
784
        $trashService->deleteTrashItem($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 776 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...
785
786
        // Create a search query for all trashed items
787
        $query = new Query();
788
        $query->filter = new Criterion\LogicalAnd(
789
            array(
790
                new Criterion\Field('title', Criterion\Operator::LIKE, '*'),
791
            )
792
        );
793
794
        // Load all trashed locations, should only contain the Demo Design location
795
        $searchResult = $trashService->findTrashItems($query);
796
        /* END: Use Case */
797
798
        $foundIds = array_map(
799
            function ($trashItem) {
800
                return $trashItem->id;
801
            },
802
            $searchResult->items
803
        );
804
805
        $this->assertEquals(4, $searchResult->count);
0 ignored issues
show
Deprecated Code introduced by
The property eZ\Publish\API\Repositor...sh\SearchResult::$count has been deprecated with message: Property is here purely for BC with 5.x/6.x.

This property 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 property will be removed from the class and what other property to use instead.

Loading history...
806
        $this->assertTrue(
807
            in_array($demoDesignLocationId, $foundIds)
808
        );
809
    }
810
811
    /**
812
     * Test deleting a non existing trash item.
813
     *
814
     * @covers \eZ\Publish\API\Repository\TrashService::deleteTrashItem
815
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
816
     */
817
    public function testDeleteThrowsNotFoundExceptionForNonExistingTrashItem()
818
    {
819
        $repository = $this->getRepository();
820
        $trashService = $repository->getTrashService();
821
822
        $trashService->deleteTrashItem($this->getTrashItemDouble(
823
            12364,
824
            12345,
825
            12363
826
        ));
827
    }
828
829
    /**
830
     * Returns an array with the remoteIds of all child locations of the
831
     * <b>Community</b> location. It is stored in a local variable named
832
     * <b>$remoteIds</b>.
833
     *
834
     * @return string[]
835
     */
836
    private function createRemoteIdList()
837
    {
838
        $repository = $this->getRepository();
839
840
        /* BEGIN: Inline */
841
        // remoteId of the "Community" location in an eZ Publish demo installation
842
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
843
844
        // Load the location service
845
        $locationService = $repository->getLocationService();
846
847
        $remoteIds = array();
848
        $children = $locationService->loadLocationChildren($locationService->loadLocationByRemoteId($mediaRemoteId));
849
        foreach ($children->locations as $child) {
850
            $remoteIds[] = $child->remoteId;
851
            foreach ($locationService->loadLocationChildren($child)->locations as $grandChild) {
852
                $remoteIds[] = $grandChild->remoteId;
853
            }
854
        }
855
        /* END: Inline */
856
857
        return $remoteIds;
858
    }
859
860
    /**
861
     * @param Repository $repository
862
     * @param int $parentLocationId
863
     *
864
     * @return \eZ\Publish\API\Repository\Values\Content\Content
865
     */
866 View Code Duplication
    protected function createNewContentInPlaceTrashedOne(Repository $repository, $parentLocationId)
867
    {
868
        $contentService = $repository->getContentService();
869
        $locationService = $repository->getLocationService();
870
        $contentTypeService = $repository->getContentTypeService();
871
872
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
873
        $newContent = $contentService->newContentCreateStruct($contentType, 'eng-US');
874
        $newContent->setField('name', 'Media');
875
876
        $location = $locationService->newLocationCreateStruct($parentLocationId);
877
878
        $draftContent = $contentService->createContent($newContent, [$location]);
879
880
        return $contentService->publishVersion($draftContent->versionInfo);
881
    }
882
883
    /**
884
     * @param URLAliasService $urlAliasService
885
     * @param string $urlPath Url alias path
886
     *
887
     * @return \eZ\Publish\API\Repository\Values\Content\URLAlias
888
     */
889
    private function assertAliasExists(URLAliasService $urlAliasService, $urlPath)
890
    {
891
        $urlAlias = $urlAliasService->lookup($urlPath);
892
893
        $this->assertInstanceOf('\eZ\Publish\API\Repository\Values\Content\URLAlias', $urlAlias);
894
895
        return $urlAlias;
896
    }
897
898
    /**
899
     * @param URLAliasService $urlAliasService
900
     * @param string $urlPath Url alias path
901
     */
902
    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...
903
    {
904
        try {
905
            $this->getRepository()->getURLAliasService()->lookup($urlPath);
906
            $this->fail(sprintf('Alias [%s] should not exists', $urlPath));
907
        } catch (\eZ\Publish\API\Repository\Exceptions\NotFoundException $e) {
908
            $this->assertTrue(true);
909
        }
910
    }
911
912
    /**
913
     * Get Test Double for TrashItem for exception testing and similar.
914
     *
915
     * @param int $trashId
916
     * @param int $contentId
917
     * @param int $parentLocationId
918
     *
919
     * @return \eZ\Publish\API\Repository\Values\Content\TrashItem
920
     */
921
    private function getTrashItemDouble(int $trashId, int $contentId = 44, int $parentLocationId = 2): APITrashItem
922
    {
923
        return new TrashItem([
924
            'id' => $trashId,
925
            'parentLocationId' => $parentLocationId,
926
            'contentInfo' => new ContentInfo(['id' => $contentId]),
927
        ]);
928
    }
929
}
930