Completed
Push — master ( 7c0e42...8c347f )
by André
14:17
created

TrashServiceTest::testLoadTrashItem()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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