Completed
Push — 7.0_deprecation_removal ( e8d685...a29025 )
by André
11:11
created

testTrashDecrementsChildCountOnParentLocation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 11

Duplication

Lines 20
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nc 1
nop 0
dl 20
loc 20
rs 9.4285
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\Location as APILocation;
14
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
15
use eZ\Publish\API\Repository\Values\Content\Query;
16
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
17
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
18
use eZ\Publish\API\Repository\Values\Content\Trash\SearchResult;
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,
0 ignored issues
show
Documentation introduced by
The property $pathString is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
250
            $trashItemReloaded->pathString
0 ignored issues
show
Documentation introduced by
The property $pathString is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
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
        $trashItem = new TrashItem(['id' => 12364, 'parentLocationId' => 12363]);
336
        $trashService->recover($trashItem);
337
    }
338
339
    /**
340
     * Test for the trash() method.
341
     *
342
     * @see \eZ\Publish\API\Repository\TrashService::recover()
343
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
344
     *
345
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
346
     */
347 View Code Duplication
    public function testNotFoundAliasAfterRemoveIt()
348
    {
349
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
350
351
        $repository = $this->getRepository();
352
        $trashService = $repository->getTrashService();
353
        $urlAliasService = $repository->getURLAliasService();
354
        $locationService = $repository->getLocationService();
355
356
        // Double ->lookup() call because there where issue that one call was not enough to spot bug
357
        $urlAliasService->lookup('/Media');
358
        $urlAliasService->lookup('/Media');
359
360
        $mediaLocation = $locationService->loadLocationByRemoteId($mediaRemoteId);
361
        $trashService->trash($mediaLocation);
362
363
        $urlAliasService->lookup('/Media');
364
    }
365
366
    /**
367
     * Test for the recover() method.
368
     *
369
     * @see \eZ\Publish\API\Repository\TrashService::recover()
370
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
371
     */
372
    public function testAliasesForRemovedItems()
373
    {
374
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
375
376
        $repository = $this->getRepository();
377
        $trashService = $repository->getTrashService();
378
        $urlAliasService = $repository->getURLAliasService();
379
        $locationService = $repository->getLocationService();
380
381
        // Double ->lookup() call because there where issue that one call was not enough to spot bug
382
        $urlAliasService->lookup('/Media');
383
        $trashedLocationAlias = $urlAliasService->lookup('/Media');
384
385
        $mediaLocation = $locationService->loadLocationByRemoteId($mediaRemoteId);
386
        $trashItem = $trashService->trash($mediaLocation);
387
        $this->assertAliasNotExists($urlAliasService, '/Media');
388
389
        $this->createNewContentInPlaceTrashedOne($repository, $mediaLocation->parentLocationId);
390
391
        $createdLocationAlias = $urlAliasService->lookup('/Media');
392
393
        $this->assertNotEquals(
394
            $trashedLocationAlias->destination,
395
            $createdLocationAlias->destination,
396
            'Destination for /media url should changed'
397
        );
398
399
        $recoveredLocation = $trashService->recover($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $trashService->trash($mediaLocation) on line 386 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...
400
        $recoveredLocationAlias = $urlAliasService->lookup('/Media2');
401
        $recoveredLocationAliasReverse = $urlAliasService->reverseLookup($recoveredLocation);
402
403
        $this->assertEquals($recoveredLocationAlias->destination, $recoveredLocationAliasReverse->destination);
404
405
        $this->assertNotEquals($recoveredLocationAliasReverse->destination, $trashedLocationAlias->destination);
406
        $this->assertNotEquals($recoveredLocationAliasReverse->destination, $createdLocationAlias->destination);
407
    }
408
409
    /**
410
     * Test for the recover() method.
411
     *
412
     * @see \eZ\Publish\API\Repository\TrashService::recover()
413
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testRecover
414
     */
415
    public function testRecoverDoesNotRestoreChildLocations()
416
    {
417
        $repository = $this->getRepository();
418
        $trashService = $repository->getTrashService();
419
        $locationService = $repository->getLocationService();
420
421
        $remoteIds = $this->createRemoteIdList();
422
423
        // Unset remote ID of actually restored location
424
        unset($remoteIds[array_search('3f6d92f8044aed134f32153517850f5a', $remoteIds)]);
425
426
        $trashItem = $this->createTrashItem();
427
428
        $trashService->recover($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 426 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
430
        $this->assertGreaterThan(
431
            0,
432
            count($remoteIds),
433
            "There should be at least one 'Community' child location."
434
        );
435
436
        // None of the child locations will be available again
437
        foreach ($remoteIds as $remoteId) {
438
            try {
439
                $locationService->loadLocationByRemoteId($remoteId);
440
                $this->fail(
441
                    sprintf(
442
                        'Location with remote ID "%s" unexpectedly restored.',
443
                        $remoteId
444
                    )
445
                );
446
            } catch (NotFoundException $e) {
447
                // All well
448
            }
449
        }
450
451
        try {
452
            $trashService->loadTrashItem($trashItem->id);
453
            $this->fail('Trash item was not removed after being recovered.');
454
        } catch (NotFoundException $e) {
455
            // All well
456
        }
457
    }
458
459
    /**
460
     * Test for the recover() method.
461
     *
462
     * @see \eZ\Publish\API\Repository\TrashService::recover($trashItem, $newParentLocation)
463
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testRecover
464
     *
465
     * @todo Fix naming
466
     */
467
    public function testRecoverWithLocationCreateStructParameter()
468
    {
469
        $repository = $this->getRepository();
470
        $trashService = $repository->getTrashService();
471
        $locationService = $repository->getLocationService();
472
473
        $homeLocationId = $this->generateId('location', 2);
474
        /* BEGIN: Use Case */
475
        // $homeLocationId is the ID of the "Home" location in an eZ Publish
476
        // demo installation
477
478
        $trashItem = $this->createTrashItem();
479
480
        // Get the new parent location
481
        $newParentLocation = $locationService->loadLocation($homeLocationId);
482
483
        // Recover location with new location
484
        $location = $trashService->recover($trashItem, $newParentLocation);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 478 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...
485
        /* END: Use Case */
486
487
        $this->assertPropertiesCorrect(
488
            array(
489
                'remoteId' => $trashItem->remoteId,
490
                'parentLocationId' => $homeLocationId,
491
                // Not the full sub tree is restored
492
                'depth' => $newParentLocation->depth + 1,
493
                'hidden' => false,
494
                'invisible' => $trashItem->invisible,
0 ignored issues
show
Documentation introduced by
The property $invisible is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
495
                'pathString' => $newParentLocation->pathString . $this->parseId('location', $location->id) . '/',
496
                'priority' => 0,
497
                'sortField' => APILocation::SORT_FIELD_NAME,
498
                'sortOrder' => APILocation::SORT_ORDER_ASC,
499
            ),
500
            $location
501
        );
502
503
        try {
504
            $trashService->loadTrashItem($trashItem->id);
0 ignored issues
show
Documentation introduced by
The property $id is declared protected in eZ\Publish\API\Repository\Values\Content\Location. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
505
            $this->fail('Trash item was not removed after being recovered.');
506
        } catch (NotFoundException $e) {
507
            // All well
508
        }
509
    }
510
511
    /**
512
     * Test for the recover() method.
513
     *
514
     * @see \eZ\Publish\API\Repository\TrashService::recover($trashItem)
515
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testRecover
516
     */
517
    public function testRecoverIncrementsChildCountOnOriginalParent()
518
    {
519
        $repository = $this->getRepository();
520
        $trashService = $repository->getTrashService();
521
        $locationService = $repository->getLocationService();
522
523
        $location = $locationService->loadLocation($this->generateId('location', 1));
524
525
        $trashItem = $this->createTrashItem();
526
527
        $this->refreshSearch($repository);
528
529
        /* BEGIN: Use Case */
530
        $childCount = $locationService->getLocationChildCount($location);
531
532
        // Recover location with new location
533
        $trashService->recover($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 525 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...
534
        /* END: Use Case */
535
536
        $this->refreshSearch($repository);
537
538
        $this->assertEquals(
539
            $childCount + 1,
540
            $locationService->getLocationChildCount($location)
541
        );
542
543
        try {
544
            $trashService->loadTrashItem($trashItem->id);
545
            $this->fail('Trash item was not removed after being recovered.');
546
        } catch (NotFoundException $e) {
547
            // All well
548
        }
549
    }
550
551
    /**
552
     * Test for the recover() method.
553
     *
554
     * @see \eZ\Publish\API\Repository\TrashService::recover($trashItem, $newParentLocation)
555
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testRecoverWithLocationCreateStructParameter
556
     */
557
    public function testRecoverWithLocationCreateStructParameterIncrementsChildCountOnNewParent()
558
    {
559
        $repository = $this->getRepository();
560
        $trashService = $repository->getTrashService();
561
        $locationService = $repository->getLocationService();
562
563
        $homeLocationId = $this->generateId('location', 2);
564
565
        $location = $locationService->loadLocation($homeLocationId);
566
567
        $childCount = $locationService->getLocationChildCount($location);
568
569
        /* BEGIN: Use Case */
570
        // $homeLocationId is the ID of the "Home" location in an eZ Publish
571
        // demo installation
572
573
        $trashItem = $this->createTrashItem();
574
575
        // Get the new parent location
576
        $newParentLocation = $locationService->loadLocation($homeLocationId);
577
578
        // Recover location with new location
579
        $trashService->recover($trashItem, $newParentLocation);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 573 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...
580
        /* END: Use Case */
581
582
        $this->refreshSearch($repository);
583
584
        $this->assertEquals(
585
            $childCount + 1,
586
            $locationService->getLocationChildCount($location)
587
        );
588
589
        try {
590
            $trashService->loadTrashItem($trashItem->id);
591
            $this->fail('Trash item was not removed after being recovered.');
592
        } catch (NotFoundException $e) {
593
            // All well
594
        }
595
    }
596
597
    /**
598
     * Test recovering a location from trash to non existing location.
599
     *
600
     * @covers \eZ\Publish\API\Repository\TrashService::recover
601
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
602
     */
603 View Code Duplication
    public function testRecoverToNonExistingLocation()
604
    {
605
        $repository = $this->getRepository();
606
        $trashService = $repository->getTrashService();
607
        $locationService = $repository->getLocationService();
608
609
        $location = $locationService->loadLocation(44);
610
        $trashItem = $trashService->trash($location);
611
612
        $newParentLocation = new Location(
613
            array(
614
                'id' => 123456,
615
                'parentLocationId' => 123455,
616
            )
617
        );
618
        $trashService->recover($trashItem, $newParentLocation);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $trashService->trash($location) on line 610 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...
619
    }
620
621
    /**
622
     * Test for the findTrashItems() method.
623
     *
624
     * @see \eZ\Publish\API\Repository\TrashService::findTrashItems()
625
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testTrash
626
     */
627
    public function testFindTrashItems()
628
    {
629
        $repository = $this->getRepository();
630
        $trashService = $repository->getTrashService();
631
632
        /* BEGIN: Use Case */
633
        $this->createTrashItem();
634
635
        // Create a search query for all trashed items
636
        $query = new Query();
637
        $query->filter = new Criterion\LogicalAnd(
638
            array(
639
                new Criterion\Field('title', Criterion\Operator::LIKE, '*'),
640
            )
641
        );
642
643
        // Load all trashed locations
644
        $searchResult = $trashService->findTrashItems($query);
645
        /* END: Use Case */
646
647
        $this->assertInstanceOf(
648
            SearchResult::class,
649
            $searchResult
650
        );
651
652
        // 4 trashed locations from the sub tree
653
        $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...
654
        $this->assertEquals(4, $searchResult->totalCount);
655
    }
656
657
    /**
658
     * Test for the findTrashItems() method.
659
     *
660
     * @see \eZ\Publish\API\Repository\TrashService::findTrashItems()
661
     * @depends \eZ\Publish\API\Repository\Tests\TrashServiceTest::testFindTrashItems
662
     */
663
    public function testFindTrashItemsLimitedAccess()
664
    {
665
        $repository = $this->getRepository();
666
        $trashService = $repository->getTrashService();
667
668
        /* BEGIN: Use Case */
669
        $this->createTrashItem();
670
671
        // Create a search query for all trashed items
672
        $query = new Query();
673
        $query->filter = new Criterion\LogicalAnd(
674
            array(
675
                new Criterion\Field('title', Criterion\Operator::LIKE, '*'),
676
            )
677
        );
678
679
        // Create a user in the Editor user group.
680
        $user = $this->createUserVersion1();
681
682
        // Set the Editor user as current user, these users have no access to Trash by default.
683
        $repository->getPermissionResolver()->setCurrentUserReference($user);
684
685
        // Load all trashed locations
686
        $searchResult = $trashService->findTrashItems($query);
687
        /* END: Use Case */
688
689
        $this->assertInstanceOf(
690
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\SearchResult',
691
            $searchResult
692
        );
693
694
        // 0 trashed locations found, though 4 exist
695
        $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...
696
    }
697
698
    /**
699
     * Test for the emptyTrash() method.
700
     *
701
     * @see \eZ\Publish\API\Repository\TrashService::emptyTrash()
702
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testFindTrashItems
703
     */
704
    public function testEmptyTrash()
705
    {
706
        $repository = $this->getRepository();
707
        $trashService = $repository->getTrashService();
708
709
        /* BEGIN: Use Case */
710
        $this->createTrashItem();
711
712
        // Empty the trash
713
        $trashService->emptyTrash();
714
715
        // Create a search query for all trashed items
716
        $query = new Query();
717
        $query->filter = new Criterion\LogicalAnd(
718
            array(
719
                new Criterion\Field('title', Criterion\Operator::LIKE, '*'),
720
            )
721
        );
722
723
        // Load all trashed locations, search result should be empty
724
        $searchResult = $trashService->findTrashItems($query);
725
        /* END: Use Case */
726
727
        $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...
728
    }
729
730
    /**
731
     * Test for the deleteTrashItem() method.
732
     *
733
     * @see \eZ\Publish\API\Repository\TrashService::deleteTrashItem()
734
     * @depends eZ\Publish\API\Repository\Tests\TrashServiceTest::testFindTrashItems
735
     */
736
    public function testDeleteTrashItem()
737
    {
738
        $repository = $this->getRepository();
739
        $trashService = $repository->getTrashService();
740
        $locationService = $repository->getLocationService();
741
742
        $demoDesignLocationId = $this->generateId('location', 56);
743
        /* BEGIN: Use Case */
744
        // $demoDesignLocationId is the ID of the "Demo Design" location in an eZ
745
        // Publish demo installation
746
747
        $trashItem = $this->createTrashItem();
748
749
        // Trash one more location
750
        $trashService->trash(
751
            $locationService->loadLocation($demoDesignLocationId)
752
        );
753
754
        // Empty the trash
755
        $trashService->deleteTrashItem($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $this->createTrashItem() on line 747 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...
756
757
        // Create a search query for all trashed items
758
        $query = new Query();
759
        $query->filter = new Criterion\LogicalAnd(
760
            array(
761
                new Criterion\Field('title', Criterion\Operator::LIKE, '*'),
762
            )
763
        );
764
765
        // Load all trashed locations, should only contain the Demo Design location
766
        $searchResult = $trashService->findTrashItems($query);
767
        /* END: Use Case */
768
769
        $foundIds = array_map(
770
            function ($trashItem) {
771
                return $trashItem->id;
772
            },
773
            $searchResult->items
774
        );
775
776
        $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...
777
        $this->assertTrue(
778
            in_array($demoDesignLocationId, $foundIds)
779
        );
780
    }
781
782
    /**
783
     * Test deleting a non existing trash item.
784
     *
785
     * @covers \eZ\Publish\API\Repository\TrashService::deleteTrashItem
786
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
787
     */
788
    public function testDeleteThrowsNotFoundExceptionForNonExistingTrashItem()
789
    {
790
        $repository = $this->getRepository();
791
        $trashService = $repository->getTrashService();
792
793
        $trashItem = new TrashItem(['id' => 123456]);
794
        $trashService->deleteTrashItem($trashItem);
795
    }
796
797
    /**
798
     * Returns an array with the remoteIds of all child locations of the
799
     * <b>Community</b> location. It is stored in a local variable named
800
     * <b>$remoteIds</b>.
801
     *
802
     * @return string[]
803
     */
804
    private function createRemoteIdList()
805
    {
806
        $repository = $this->getRepository();
807
808
        /* BEGIN: Inline */
809
        // remoteId of the "Community" location in an eZ Publish demo installation
810
        $mediaRemoteId = '75c715a51699d2d309a924eca6a95145';
811
812
        // Load the location service
813
        $locationService = $repository->getLocationService();
814
815
        $remoteIds = array();
816
        $children = $locationService->loadLocationChildren($locationService->loadLocationByRemoteId($mediaRemoteId));
817
        foreach ($children->locations as $child) {
818
            $remoteIds[] = $child->remoteId;
819
            foreach ($locationService->loadLocationChildren($child)->locations as $grandChild) {
820
                $remoteIds[] = $grandChild->remoteId;
821
            }
822
        }
823
        /* END: Inline */
824
825
        return $remoteIds;
826
    }
827
828
    /**
829
     * @param Repository $repository
830
     * @param int $parentLocationId
831
     *
832
     * @return \eZ\Publish\API\Repository\Values\Content\Content
833
     */
834
    protected function createNewContentInPlaceTrashedOne(Repository $repository, $parentLocationId)
835
    {
836
        $contentService = $repository->getContentService();
837
        $locationService = $repository->getLocationService();
838
        $contentTypeService = $repository->getContentTypeService();
839
840
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
841
        $newContent = $contentService->newContentCreateStruct($contentType, 'eng-US');
842
        $newContent->setField('name', 'Media');
843
844
        $location = $locationService->newLocationCreateStruct($parentLocationId);
845
846
        $draftContent = $contentService->createContent($newContent, [$location]);
847
848
        return $contentService->publishVersion($draftContent->versionInfo);
849
    }
850
851
    /**
852
     * @param URLAliasService $urlAliasService
853
     * @param string $urlPath Url alias path
854
     *
855
     * @return \eZ\Publish\API\Repository\Values\Content\URLAlias
856
     */
857
    private function assertAliasExists(URLAliasService $urlAliasService, $urlPath)
858
    {
859
        $urlAlias = $urlAliasService->lookup($urlPath);
860
861
        $this->assertInstanceOf('\eZ\Publish\API\Repository\Values\Content\URLAlias', $urlAlias);
862
863
        return $urlAlias;
864
    }
865
866
    /**
867
     * @param URLAliasService $urlAliasService
868
     * @param string $urlPath Url alias path
869
     */
870
    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...
871
    {
872
        try {
873
            $this->getRepository()->getURLAliasService()->lookup($urlPath);
874
            $this->fail(sprintf('Alias [%s] should not exists', $urlPath));
875
        } catch (\eZ\Publish\API\Repository\Exceptions\NotFoundException $e) {
876
            $this->assertTrue(true);
877
        }
878
    }
879
}
880