Completed
Push — 6.7 ( ec4621...8ad775 )
by André
17:03
created

TrashBase::getTrashItem()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 3
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File contains: eZ\Publish\Core\Repository\Tests\Service\Integration\TrashBase 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\Core\Repository\Tests\Service\Integration;
10
11
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
12
use eZ\Publish\Core\Repository\Tests\Service\Integration\Base as BaseServiceTest;
13
use eZ\Publish\Core\Repository\Values\Content\TrashItem;
14
use eZ\Publish\Core\Repository\Values\Content\Location;
15
use eZ\Publish\API\Repository\Values\Content\Query;
16
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
17
use eZ\Publish\API\Repository\Exceptions\PropertyNotFoundException as PropertyNotFound;
18
use eZ\Publish\API\Repository\Exceptions\PropertyReadOnlyException;
19
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
20
use eZ\Publish\API\Repository\Tests\BaseTest as APIBaseTest;
21
22
/**
23
 * Test case for Trash Service.
24
 */
25
abstract class TrashBase extends BaseServiceTest
26
{
27
    /**
28
     * Test a new class and default values on properties.
29
     *
30
     * @covers \eZ\Publish\API\Repository\Values\Content\TrashItem::__construct
31
     */
32 View Code Duplication
    public function testNewClass()
33
    {
34
        $trashItem = new TrashItem();
35
36
        $this->assertPropertiesCorrect(
37
            array(
38
                'id' => null,
39
                'priority' => null,
40
                'hidden' => null,
41
                'invisible' => null,
42
                'remoteId' => null,
43
                'parentLocationId' => null,
44
                'pathString' => null,
45
                'depth' => null,
46
                'sortField' => null,
47
                'sortOrder' => null,
48
            ),
49
            $trashItem
50
        );
51
    }
52
53
    /**
54
     * Test retrieving missing property.
55
     *
56
     * @covers \eZ\Publish\API\Repository\Values\Content\TrashItem::__get
57
     */
58
    public function testMissingProperty()
59
    {
60
        try {
61
            $trashItem = new TrashItem();
62
            $value = $trashItem->notDefined;
0 ignored issues
show
Documentation introduced by
The property notDefined does not exist on object<eZ\Publish\Core\R...lues\Content\TrashItem>. Since you implemented __set, maybe consider adding a @property annotation.

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...
Unused Code introduced by
$value is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
63
            self::fail('Succeeded getting non existing property');
64
        } catch (PropertyNotFound $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
65
        }
66
    }
67
68
    /**
69
     * Test setting read only property.
70
     *
71
     * @covers \eZ\Publish\API\Repository\Values\Content\TrashItem::__set
72
     */
73
    public function testReadOnlyProperty()
74
    {
75
        try {
76
            $trashItem = new TrashItem();
77
            $trashItem->id = 42;
78
            self::fail('Succeeded setting read only property');
79
        } catch (PropertyReadOnlyException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
80
        }
81
    }
82
83
    /**
84
     * Test if property exists.
85
     *
86
     * @covers \eZ\Publish\API\Repository\Values\Content\TrashItem::__isset
87
     */
88
    public function testIsPropertySet()
89
    {
90
        $trashItem = new TrashItem();
91
        $value = isset($trashItem->notDefined);
92
        self::assertEquals(false, $value);
93
94
        $value = isset($trashItem->id);
95
        self::assertEquals(true, $value);
96
    }
97
98
    /**
99
     * Test unsetting a property.
100
     *
101
     * @covers \eZ\Publish\API\Repository\Values\Content\TrashItem::__unset
102
     */
103
    public function testUnsetProperty()
104
    {
105
        $trashItem = new TrashItem(array('id' => 2));
106
        try {
107
            unset($trashItem->id);
108
            self::fail('Unsetting read-only property succeeded');
109
        } catch (PropertyReadOnlyException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
110
        }
111
    }
112
113
    /**
114
     * Test loading a trash item.
115
     *
116
     * @covers \eZ\Publish\API\Repository\TrashService::loadTrashItem
117
     */
118 View Code Duplication
    public function testLoadTrashItem()
119
    {
120
        $locationService = $this->repository->getLocationService();
121
        $trashService = $this->repository->getTrashService();
122
123
        $trashItem = $location = $trashService->trash($locationService->loadLocation(44));
124
        $loadedTrashItem = $trashService->loadTrashItem($location->id);
125
126
        self::assertInstanceOf('\\eZ\\Publish\\API\\Repository\\Values\\Content\\TrashItem', $trashItem);
127
128
        self::assertSameClassPropertiesCorrect(
129
            array(
130
                'id',
131
                'priority',
132
                'hidden',
133
                'invisible',
134
                'remoteId',
135
                'parentLocationId',
136
                'pathString',
137
                'depth',
138
                'sortField',
139
                'sortOrder',
140
            ),
141
            $trashItem,
142
            $loadedTrashItem
143
        );
144
    }
145
146
    /**
147
     * Test loading a trash item throwing NotFoundException.
148
     *
149
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
150
     * @covers \eZ\Publish\API\Repository\TrashService::loadTrashItem
151
     */
152
    public function testLoadTrashItemThrowsNotFoundException()
153
    {
154
        $trashService = $this->repository->getTrashService();
155
        $trashService->loadTrashItem(44);
156
    }
157
158
    /**
159
     * Test sending a location to trash.
160
     *
161
     * @covers \eZ\Publish\API\Repository\TrashService::trash
162
     */
163 View Code Duplication
    public function testTrash()
164
    {
165
        $locationService = $this->repository->getLocationService();
166
        $trashService = $this->repository->getTrashService();
167
168
        $location = $locationService->loadLocation(44);
169
        $trashItem = $trashService->trash($location);
170
171
        self::assertInstanceOf('\\eZ\\Publish\\API\\Repository\\Values\\Content\\TrashItem', $trashItem);
172
173
        self::assertSameClassPropertiesCorrect(
174
            array(
175
                'id',
176
                'priority',
177
                'hidden',
178
                'invisible',
179
                'remoteId',
180
                'parentLocationId',
181
                'pathString',
182
                'depth',
183
                'sortField',
184
                'sortOrder',
185
            ),
186
            $location,
187
            $trashItem
188
        );
189
    }
190
191
    /**
192
     * Test sending a location to trash.
193
     *
194
     * @covers \eZ\Publish\API\Repository\TrashService::trash
195
     */
196
    public function testTrashUpdatesMainLocation()
197
    {
198
        $contentService = $this->repository->getContentService();
199
        $locationService = $this->repository->getLocationService();
200
        $trashService = $this->repository->getTrashService();
201
202
        $contentInfo = $contentService->loadContentInfo(42);
203
204
        // Create additional location that will become new main location
205
        $location = $locationService->createLocation(
206
            $contentInfo,
207
            new LocationCreateStruct(array('parentLocationId' => 2))
208
        );
209
210
        $trashService->trash(
211
            $locationService->loadLocation($contentInfo->mainLocationId)
212
        );
213
214
        self::assertEquals(
215
            $location->id,
216
            $contentService->loadContentInfo(42)->mainLocationId
217
        );
218
    }
219
220
    /**
221
     * Test sending a location to trash.
222
     *
223
     * @covers \eZ\Publish\API\Repository\TrashService::trash
224
     */
225 View Code Duplication
    public function testTrashReturnsNull()
226
    {
227
        $contentService = $this->repository->getContentService();
228
        $locationService = $this->repository->getLocationService();
229
        $trashService = $this->repository->getTrashService();
230
231
        // Create additional location to trash
232
        $location = $locationService->createLocation(
233
            $contentService->loadContentInfo(42),
234
            new LocationCreateStruct(array('parentLocationId' => 2))
235
        );
236
237
        $trashItem = $trashService->trash($location);
238
239
        self::assertNull($trashItem);
240
    }
241
242
    /**
243
     * Test recovering a location from trash to original location.
244
     *
245
     * @covers \eZ\Publish\API\Repository\TrashService::recover
246
     */
247
    public function testRecover()
248
    {
249
        $locationService = $this->repository->getLocationService();
250
        $trashService = $this->repository->getTrashService();
251
252
        $location = $locationService->loadLocation(44);
253
        $trashItem = $trashService->trash($location);
254
255
        $recoveredLocation = $trashService->recover($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $trashService->trash($location) on line 253 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...
256
257
        self::assertInstanceOf('\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location', $recoveredLocation);
258
259
        self::assertSameClassPropertiesCorrect(
260
            array(
261
                'priority',
262
                'hidden',
263
                'invisible',
264
                'remoteId',
265
                'parentLocationId',
266
                'depth',
267
                'sortField',
268
                'sortOrder',
269
            ),
270
            $location,
271
            $recoveredLocation
272
        );
273
274
        $parentLocation = $locationService->loadLocation($location->parentLocationId);
275
        $newPathString = $parentLocation->pathString . $recoveredLocation->id . '/';
276
277
        self::assertEquals($newPathString, $recoveredLocation->pathString);
278
        self::assertGreaterThan(0, $recoveredLocation->id);
279
        self::assertEquals($recoveredLocation->id, $recoveredLocation->contentInfo->mainLocationId);
280
    }
281
282
    /**
283
     * Test recovering a non existing trash item.
284
     *
285
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
286
     * @covers \eZ\Publish\API\Repository\TrashService::recover
287
     */
288
    public function testRecoverNonExistingTrashItem()
289
    {
290
        $trashService = $this->repository->getTrashService();
291
292
        $trashService->recover(
293
            $this->getTrashItem(APIBaseTest::DB_INT_MAX, 2, APIBaseTest::DB_INT_MAX)
294
        );
295
    }
296
297
    /**
298
     * Test recovering a location from trash to different location.
299
     *
300
     * @covers \eZ\Publish\API\Repository\TrashService::recover
301
     */
302
    public function testRecoverToDifferentLocation()
303
    {
304
        // @todo: remove creating test locations when field types are fully functional
305
        // Create test locations
306
        $deleteLocationId = $this->createTestContentLocation(5)->contentInfo->mainLocationId;
307
        $recoverLocationId = $this->createTestContentLocation(5)->contentInfo->mainLocationId;
308
309
        /* BEGIN: Use Case */
310
        $locationService = $this->repository->getLocationService();
311
        $trashService = $this->repository->getTrashService();
312
313
        $location = $locationService->loadLocation($deleteLocationId);
314
        $trashItem = $trashService->trash($location);
315
316
        $newParentLocation = $locationService->loadLocation($recoverLocationId);
317
318
        $recoveredLocation = $trashService->recover($trashItem, $newParentLocation);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $trashService->trash($location) on line 314 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...
319
        /* END: Use Case */
320
321
        self::assertInstanceOf('\\eZ\\Publish\\API\\Repository\\Values\\Content\\Location', $recoveredLocation);
322
323
        self::assertSameClassPropertiesCorrect(
324
            array(
325
                'priority',
326
                'hidden',
327
                'invisible',
328
                'remoteId',
329
                'depth',
330
                'sortField',
331
                'sortOrder',
332
            ),
333
            $location,
334
            $recoveredLocation,
335
            array('depth')
336
        );
337
338
        $parentLocation = $locationService->loadLocation($recoveredLocation->parentLocationId);
339
        $newPathString = $parentLocation->pathString . $recoveredLocation->id . '/';
340
341
        self::assertEquals($parentLocation->depth + 1, $recoveredLocation->depth);
342
        self::assertEquals($newPathString, $recoveredLocation->pathString);
343
        self::assertGreaterThan(0, $recoveredLocation->id);
344
        self::assertEquals($newParentLocation->id, $recoveredLocation->parentLocationId);
345
    }
346
347
    /**
348
     * Test recovering a location from trash to non existing location.
349
     *
350
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
351
     * @covers \eZ\Publish\API\Repository\TrashService::recover
352
     */
353
    public function testRecoverToNonExistingLocation()
354
    {
355
        $locationService = $this->repository->getLocationService();
356
        $trashService = $this->repository->getTrashService();
357
358
        $location = $locationService->loadLocation(44);
359
        $trashItem = $trashService->trash($location);
360
361
        $newParentLocation = new Location(
362
            array(
363
                'id' => APIBaseTest::DB_INT_MAX,
364
                'parentLocationId' => APIBaseTest::DB_INT_MAX,
365
            )
366
        );
367
        $trashService->recover($trashItem, $newParentLocation);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $trashService->trash($location) on line 359 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...
368
    }
369
370
    /**
371
     * Test deleting a trash item.
372
     *
373
     * @covers \eZ\Publish\API\Repository\TrashService::deleteTrashItem
374
     */
375 View Code Duplication
    public function testDeleteTrashItem()
376
    {
377
        $locationService = $this->repository->getLocationService();
378
        $trashService = $this->repository->getTrashService();
379
380
        $location = $locationService->loadLocation(44);
381
        $trashItem = $trashService->trash($location);
382
383
        $trashService->deleteTrashItem($trashItem);
0 ignored issues
show
Bug introduced by
It seems like $trashItem defined by $trashService->trash($location) on line 381 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...
384
385
        try {
386
            $trashService->loadTrashItem($trashItem->id);
387
            self::fail('Succeeded loading deleted trash item');
388
        } catch (NotFoundException $e) {
389
            // Do nothing
390
        }
391
    }
392
393
    /**
394
     * Test deleting a non existing trash item.
395
     *
396
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
397
     * @covers \eZ\Publish\API\Repository\TrashService::deleteTrashItem
398
     */
399
    public function testDeleteNonExistingTrashItem()
400
    {
401
        $trashService = $this->repository->getTrashService();
402
403
        $trashService->deleteTrashItem(
404
            $this->getTrashItem(APIBaseTest::DB_INT_MAX)
405
        );
406
    }
407
408
    /**
409
     * Test searching for trash items.
410
     *
411
     * @covers \eZ\Publish\API\Repository\TrashService::findTrashItems
412
     * @covers \eZ\Publish\API\Repository\TrashService::emptyTrash
413
     */
414
    public function testFindTrashItemsAndEmptyTrash()
415
    {
416
        // @todo: remove creating test location when field types are fully functional
417
        $newLocationId = $this->createTestContentLocation(5)->contentInfo->mainLocationId;
418
419
        $locationService = $this->repository->getLocationService();
420
        $trashService = $this->repository->getTrashService();
421
422
        $searchResult = $trashService->findTrashItems(new Query());
423
        $countBeforeTrashing = $searchResult->count;
424
425
        $location = $locationService->loadLocation($newLocationId);
426
        $trashService->trash($location);
427
428
        $searchResult = $trashService->findTrashItems(new Query());
429
        $countAfterTrashing = $searchResult->count;
430
431
        self::assertGreaterThan($countBeforeTrashing, $countAfterTrashing);
432
433
        $trashService->emptyTrash();
434
        $searchResult = $trashService->findTrashItems(new Query());
435
436
        self::assertEquals(0, $searchResult->count);
437
    }
438
439
    /**
440
     * @param int $parentLocationId
441
     *
442
     * @return \eZ\Publish\API\Repository\Values\Content\Content
443
     */
444 View Code Duplication
    protected function createTestContentLocation($parentLocationId)
445
    {
446
        $contentService = $this->repository->getContentService();
447
        $contentTypeService = $this->repository->getContentTypeService();
448
        // User Group content type
449
        $contentType = $contentTypeService->loadContentType(3);
450
451
        $contentCreate = $contentService->newContentCreateStruct($contentType, 'eng-GB');
452
        $contentCreate->setField('name', 'dummy value');
453
        $contentCreate->sectionId = 1;
454
        $contentCreate->ownerId = 14;
455
        $contentCreate->remoteId = md5(uniqid(get_class($this), true));
456
        $contentCreate->alwaysAvailable = true;
457
458
        $locationCreates = array(
459
            new LocationCreateStruct(
460
                array(
461
                    //priority = 0
462
                    //hidden = false
463
                    'remoteId' => md5(uniqid(get_class($this), true)),
464
                    //sortField = Location::SORT_FIELD_NAME
465
                    //sortOrder = Location::SORT_ORDER_ASC
466
                    'parentLocationId' => $parentLocationId,
467
                )
468
            ),
469
        );
470
471
        return $contentService->publishVersion(
472
            $contentService->createContent(
473
                $contentCreate,
474
                $locationCreates
475
            )->versionInfo
476
        );
477
    }
478
479
    private function getTrashItem($id, $contentId = 44, $parentLocationId = 2)
480
    {
481
        return new TrashItem([
482
            'id' => $id,
483
            'parentLocationId' => $parentLocationId,
484
            'contentInfo' => new ContentInfo(['id' => $contentId]),
485
        ]);
486
    }
487
}
488