Completed
Push — validate_hasAccess_6.7 ( f2557d )
by André
28:12
created

TrashServiceTest   C

Complexity

Total Complexity 34

Size/Duplication

Total Lines 737
Duplicated Lines 14.52 %

Coupling/Cohesion

Components 1
Dependencies 18

Importance

Changes 0
Metric Value
wmc 34
lcom 1
cbo 18
dl 107
loc 737
rs 6.7466
c 0
b 0
f 0

22 Methods

Rating   Name   Duplication   Size   Complexity  
A testTrash() 0 11 1
B testTrashSetsExpectedTrashItemProperties() 0 27 1
A testTrashRemovesLocationFromMainStorage() 0 17 1
B testTrashRemovesChildLocationsFromMainStorage() 0 29 3
A testTrashDecrementsChildCountOnParentLocation() 20 20 1
A testLoadTrashItem() 0 22 1
A testLoadTrashItemThrowsNotFoundException() 0 13 1
B testRecover() 0 37 2
A testNotFoundAliasAfterRemoveIt() 18 18 1
B testAliasesForRemovedItems() 0 36 1
B testRecoverDoesNotRestoreChildLocations() 0 43 4
B testRecoverWithLocationCreateStructParameter() 0 43 2
B testRecoverIncrementsChildCountOnOriginalParent() 0 33 2
B testRecoverWithLocationCreateStructParameterIncrementsChildCountOnNewParent() 0 39 2
B testFindTrashItems() 28 28 1
B testFindTrashItemsLimitedAccess() 0 34 1
B testEmptyTrash() 25 25 1
B testDeleteTrashItem() 0 45 1
A createRemoteIdList() 0 23 3
A assertAliasExists() 0 8 1
A assertAliasNotExists() 0 9 2
A createNewContentInPlaceTrashedOne() 16 16 1

How to fix   Duplicated Code   

Duplicated Code

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

Common duplication problems, and corresponding solutions are:

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