Completed
Push — refactor-content-service-integ... ( 5a024e...9a41f2 )
by
unknown
19:04
created

testRevealContentWithHiddenParent()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 54

Duplication

Lines 11
Ratio 20.37 %

Importance

Changes 0
Metric Value
dl 11
loc 54
c 0
b 0
f 0
cc 3
nc 4
nop 0
rs 9.0036

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * File containing the ContentServiceTest 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\Exceptions\BadStateException;
12
use eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException;
13
use eZ\Publish\API\Repository\Exceptions\InvalidArgumentException as APIInvalidArgumentException;
14
use eZ\Publish\API\Repository\Values\Content\Content;
15
use eZ\Publish\API\Repository\Exceptions\UnauthorizedException;
16
use eZ\Publish\API\Repository\Values\Content\ContentCreateStruct;
17
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
18
use eZ\Publish\API\Repository\Values\Content\ContentMetadataUpdateStruct;
19
use eZ\Publish\API\Repository\Values\Content\Field;
20
use eZ\Publish\API\Repository\Values\Content\Location;
21
use eZ\Publish\API\Repository\Values\Content\URLAlias;
22
use eZ\Publish\API\Repository\Values\Content\Relation;
23
use eZ\Publish\API\Repository\Values\Content\VersionInfo;
24
use eZ\Publish\API\Repository\Values\User\Limitation\SectionLimitation;
25
use eZ\Publish\API\Repository\Values\User\Limitation\LocationLimitation;
26
use eZ\Publish\API\Repository\Values\User\Limitation\ContentTypeLimitation;
27
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
28
use DOMDocument;
29
use Exception;
30
use eZ\Publish\Core\Base\Exceptions\UnauthorizedException as CoreUnauthorizedException;
31
use eZ\Publish\Core\Repository\Values\Content\ContentUpdateStruct;
32
33
/**
34
 * Test case for operations in the ContentService using in memory storage.
35
 *
36
 * @see \eZ\Publish\API\Repository\ContentService
37
 * @group content
38
 */
39
class ContentServiceTest extends BaseContentServiceTest
40
{
41
    /** @var \eZ\Publish\API\Repository\PermissionResolver */
42
    private $permissionResolver;
43
44
    /** @var \eZ\Publish\API\Repository\ContentService */
45
    private $contentService;
46
47
    /** @var \eZ\Publish\API\Repository\LocationService */
48
    private $locationService;
49
50
    public function setUp(): void
51
    {
52
        parent::setUp();
53
54
        $repository = $this->getRepository();
55
        $this->permissionResolver = $repository->getPermissionResolver();
56
        $this->contentService = $repository->getContentService();
57
        $this->locationService = $repository->getLocationService();
58
    }
59
60
    /**
61
     * Test for the newContentCreateStruct() method.
62
     *
63
     * @see \eZ\Publish\API\Repository\ContentService::newContentCreateStruct()
64
     * @depends eZ\Publish\API\Repository\Tests\ContentTypeServiceTest::testLoadContentTypeByIdentifier
65
     * @group user
66
     * @group field-type
67
     */
68
    public function testNewContentCreateStruct()
69
    {
70
        /* BEGIN: Use Case */
71
        $contentTypeService = $this->getRepository()->getContentTypeService();
72
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
73
74
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
75
        /* END: Use Case */
76
77
        $this->assertInstanceOf(ContentCreateStruct::class, $contentCreate);
78
    }
79
80
    /**
81
     * Test for the createContent() method.
82
     *
83
     * @return \eZ\Publish\API\Repository\Values\Content\Content
84
     *
85
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
86
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testNewContentCreateStruct
87
     * @group user
88
     * @group field-type
89
     */
90
    public function testCreateContent()
91
    {
92
        if ($this->isVersion4()) {
93
            $this->markTestSkipped('This test requires eZ Publish 5');
94
        }
95
96
        /* BEGIN: Use Case */
97
        $contentTypeService = $this->getRepository()->getContentTypeService();
98
99
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
100
101
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
102
        $contentCreate->setField('name', 'My awesome forum');
103
104
        $contentCreate->remoteId = 'abcdef0123456789abcdef0123456789';
105
        $contentCreate->alwaysAvailable = true;
106
107
        $content = $this->contentService->createContent($contentCreate);
108
        /* END: Use Case */
109
110
        $this->assertInstanceOf(Content::class, $content);
111
112
        return $content;
113
    }
114
115
    /**
116
     * Test for the createContent() method.
117
     *
118
     * Tests made for issue #EZP-20955 where Anonymous user is granted access to create content
119
     * and should have access to do that.
120
     *
121
     * @return \eZ\Publish\API\Repository\Values\Content\Content
122
     *
123
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
124
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testNewContentCreateStruct
125
     * @group user
126
     * @group field-type
127
     */
128
    public function testCreateContentAndPublishWithPrivilegedAnonymousUser()
129
    {
130
        if ($this->isVersion4()) {
131
            $this->markTestSkipped('This test requires eZ Publish 5');
132
        }
133
134
        $anonymousUserId = $this->generateId('user', 10);
135
136
        $repository = $this->getRepository();
137
        $contentTypeService = $this->getRepository()->getContentTypeService();
138
        $roleService = $repository->getRoleService();
139
140
        // Give Anonymous user role additional rights
141
        $role = $roleService->loadRoleByIdentifier('Anonymous');
142
        $roleDraft = $roleService->createRoleDraft($role);
143
        $policyCreateStruct = $roleService->newPolicyCreateStruct('content', 'create');
144
        $policyCreateStruct->addLimitation(new SectionLimitation(['limitationValues' => [1]]));
145
        $policyCreateStruct->addLimitation(new LocationLimitation(['limitationValues' => [2]]));
146
        $policyCreateStruct->addLimitation(new ContentTypeLimitation(['limitationValues' => [1]]));
147
        $roleDraft = $roleService->addPolicyByRoleDraft($roleDraft, $policyCreateStruct);
148
149
        $policyCreateStruct = $roleService->newPolicyCreateStruct('content', 'publish');
150
        $policyCreateStruct->addLimitation(new SectionLimitation(['limitationValues' => [1]]));
151
        $policyCreateStruct->addLimitation(new LocationLimitation(['limitationValues' => [2]]));
152
        $policyCreateStruct->addLimitation(new ContentTypeLimitation(['limitationValues' => [1]]));
153
        $roleDraft = $roleService->addPolicyByRoleDraft($roleDraft, $policyCreateStruct);
154
        $roleService->publishRoleDraft($roleDraft);
155
156
        // Set Anonymous user as current
157
        $repository->getPermissionResolver()->setCurrentUserReference($repository->getUserService()->loadUser($anonymousUserId));
158
159
        // Create a new content object:
160
        $contentCreate = $this->contentService->newContentCreateStruct(
161
            $contentTypeService->loadContentTypeByIdentifier('folder'),
162
            'eng-GB'
163
        );
164
165
        $contentCreate->setField('name', 'Folder 1');
166
167
        $content = $this->contentService->createContent(
168
            $contentCreate,
169
            [$this->locationService->newLocationCreateStruct(2)]
170
        );
171
172
        $this->contentService->publishVersion(
173
            $content->getVersionInfo()
174
        );
175
    }
176
177
    /**
178
     * Test for the createContent() method.
179
     *
180
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
181
     *
182
     * @return \eZ\Publish\API\Repository\Values\Content\Content
183
     *
184
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
185
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
186
     */
187
    public function testCreateContentSetsContentInfo($content)
188
    {
189
        $this->assertInstanceOf(ContentInfo::class, $content->contentInfo);
190
191
        return $content;
192
    }
193
194
    /**
195
     * Test for the createContent() method.
196
     *
197
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
198
     *
199
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
200
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentSetsContentInfo
201
     */
202
    public function testCreateContentSetsExpectedContentInfo($content)
203
    {
204
        $this->assertEquals(
205
            [
206
                $content->id,
207
                28, // id of content type "forum"
208
                true,
209
                1,
210
                'abcdef0123456789abcdef0123456789',
211
                'eng-US',
212
                $this->getRepository()->getCurrentUser()->id,
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...itory::getCurrentUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::getCurrentUserReference() instead. Get current user. Loads the full user object if not already loaded, if you only need to know user id use {@see getCurrentUserReference()}

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

Loading history...
213
                false,
214
                null,
215
                // Main Location id for unpublished Content should be null
216
                null,
217
            ],
218
            [
219
                $content->contentInfo->id,
220
                $content->contentInfo->contentTypeId,
221
                $content->contentInfo->alwaysAvailable,
222
                $content->contentInfo->currentVersionNo,
223
                $content->contentInfo->remoteId,
224
                $content->contentInfo->mainLanguageCode,
225
                $content->contentInfo->ownerId,
226
                $content->contentInfo->published,
227
                $content->contentInfo->publishedDate,
228
                $content->contentInfo->mainLocationId,
229
            ]
230
        );
231
    }
232
233
    /**
234
     * Test for the createContent() method.
235
     *
236
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
237
     *
238
     * @return \eZ\Publish\API\Repository\Values\Content\Content
239
     *
240
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
241
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
242
     */
243
    public function testCreateContentSetsVersionInfo($content)
244
    {
245
        $this->assertInstanceOf(VersionInfo::class, $content->getVersionInfo());
246
247
        return $content;
248
    }
249
250
    /**
251
     * Test for the createContent() method.
252
     *
253
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
254
     *
255
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
256
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentSetsVersionInfo
257
     */
258
    public function testCreateContentSetsExpectedVersionInfo($content)
259
    {
260
        $this->assertEquals(
261
            [
262
                'status' => VersionInfo::STATUS_DRAFT,
263
                'versionNo' => 1,
264
                'creatorId' => $this->getRepository()->getCurrentUser()->id,
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...itory::getCurrentUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::getCurrentUserReference() instead. Get current user. Loads the full user object if not already loaded, if you only need to know user id use {@see getCurrentUserReference()}

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

Loading history...
265
                'initialLanguageCode' => 'eng-US',
266
            ],
267
            [
268
                'status' => $content->getVersionInfo()->status,
269
                'versionNo' => $content->getVersionInfo()->versionNo,
270
                'creatorId' => $content->getVersionInfo()->creatorId,
271
                'initialLanguageCode' => $content->getVersionInfo()->initialLanguageCode,
272
            ]
273
        );
274
        $this->assertTrue($content->getVersionInfo()->isDraft());
275
        $this->assertFalse($content->getVersionInfo()->isPublished());
276
        $this->assertFalse($content->getVersionInfo()->isArchived());
277
    }
278
279
    /**
280
     * Test for the createContent() method.
281
     *
282
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
283
     *
284
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
285
     * @depends testCreateContent
286
     */
287
    public function testCreateContentSetsExpectedContentType($content)
288
    {
289
        $contentType = $content->getContentType();
290
291
        $this->assertEquals(
292
            [
293
                $contentType->id,
294
                // Won't match as it's set to true in createContentDraftVersion1()
295
                //$contentType->defaultAlwaysAvailable,
296
                //$contentType->defaultSortField,
297
                //$contentType->defaultSortOrder,
298
            ],
299
            [
300
                $content->contentInfo->contentTypeId,
301
                //$content->contentInfo->alwaysAvailable,
302
                //$location->sortField,
303
                //$location->sortOrder,
304
            ]
305
        );
306
    }
307
308
    /**
309
     * Test for the createContent() method.
310
     *
311
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
312
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
313
     */
314
    public function testCreateContentThrowsInvalidArgumentException()
315
    {
316
        if ($this->isVersion4()) {
317
            $this->markTestSkipped('This test requires eZ Publish 5');
318
        }
319
320
        /* BEGIN: Use Case */
321
        $contentTypeService = $this->getRepository()->getContentTypeService();
322
323
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
324
325
        $contentCreate1 = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
326
        $contentCreate1->setField('name', 'An awesome Sidelfingen forum');
327
328
        $contentCreate1->remoteId = 'abcdef0123456789abcdef0123456789';
329
        $contentCreate1->alwaysAvailable = true;
330
331
        $draft = $this->contentService->createContent($contentCreate1);
332
        $this->contentService->publishVersion($draft->versionInfo);
333
334
        $contentCreate2 = $this->contentService->newContentCreateStruct($contentType, 'eng-GB');
335
        $contentCreate2->setField('name', 'An awesome Bielefeld forum');
336
337
        $contentCreate2->remoteId = 'abcdef0123456789abcdef0123456789';
338
        $contentCreate2->alwaysAvailable = false;
339
340
        $this->expectException(APIInvalidArgumentException::class);
341
        $this->contentService->createContent($contentCreate2);
342
        /* END: Use Case */
343
    }
344
345
    /**
346
     * Test for the createContent() method.
347
     *
348
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
349
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
350
     */
351 View Code Duplication
    public function testCreateContentThrowsInvalidArgumentExceptionOnFieldTypeNotAccept()
352
    {
353
        /* BEGIN: Use Case */
354
        $contentTypeService = $this->getRepository()->getContentTypeService();
355
356
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
357
358
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
359
        // The name field does only accept strings and null as its values
360
        $contentCreate->setField('name', new \stdClass());
361
362
        $this->expectException(APIInvalidArgumentException::class);
363
        $draft = $this->contentService->createContent($contentCreate);
0 ignored issues
show
Unused Code introduced by
$draft 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...
364
        /* END: Use Case */
365
    }
366
367
    /**
368
     * Test for the createContent() method.
369
     *
370
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
371
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
372
     */
373
    public function testCreateContentThrowsContentFieldValidationException()
374
    {
375
        /* BEGIN: Use Case */
376
        $contentTypeService = $this->getRepository()->getContentTypeService();
377
378
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
379
380
        $contentCreate1 = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
381
        $contentCreate1->setField('name', 'An awesome Sidelfingen folder');
382
        // Violates string length constraint
383
        $contentCreate1->setField('short_name', str_repeat('a', 200));
384
385
        $this->expectException(ContentFieldValidationException::class);
386
387
        // Throws ContentFieldValidationException, since short_name does not pass validation of the string length validator
388
        $draft = $this->contentService->createContent($contentCreate1);
0 ignored issues
show
Unused Code introduced by
$draft 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...
389
        /* END: Use Case */
390
    }
391
392
    /**
393
     * Test for the createContent() method.
394
     *
395
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
396
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
397
     */
398 View Code Duplication
    public function testCreateContentRequiredFieldMissing()
399
    {
400
        /* BEGIN: Use Case */
401
        $contentTypeService = $this->getRepository()->getContentTypeService();
402
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
403
404
        $contentCreate1 = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
405
        // Required field "name" is not set
406
407
        $this->expectException(ContentFieldValidationException::class);
408
409
        // Throws a ContentFieldValidationException, since a required field is missing
410
        $draft = $this->contentService->createContent($contentCreate1);
0 ignored issues
show
Unused Code introduced by
$draft 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...
411
        /* END: Use Case */
412
    }
413
414
    /**
415
     * Test for the createContent() method.
416
     *
417
     * NOTE: We have bidirectional dependencies between the ContentService and
418
     * the LocationService, so that we cannot use PHPUnit's test dependencies
419
     * here.
420
     *
421
     * @see \eZ\Publish\API\Repository\ContentService::createContent($contentCreateStruct, $locationCreateStructs)
422
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
423
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationByRemoteId
424
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
425
     * @group user
426
     */
427
    public function testCreateContentWithLocationCreateParameterDoesNotCreateLocationImmediately()
428
    {
429
        /* BEGIN: Use Case */
430
        $this->createContentDraftVersion1();
431
432
        $this->expectException(NotFoundException::class);
433
434
        // The location will not have been created, yet, so this throws an exception
435
        $this->locationService->loadLocationByRemoteId('0123456789abcdef0123456789abcdef');
436
        /* END: Use Case */
437
    }
438
439
    /**
440
     * Test for the createContent() method.
441
     *
442
     * @see \eZ\Publish\API\Repository\ContentService::createContent($contentCreateStruct, $locationCreateStructs)
443
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentWithLocationCreateParameterDoesNotCreateLocationImmediately
444
     */
445
    public function testCreateContentThrowsInvalidArgumentExceptionWithLocationCreateParameter()
446
    {
447
        $parentLocationId = $this->generateId('location', 56);
448
        /* BEGIN: Use Case */
449
        // $parentLocationId is a valid location ID
450
451
        $contentTypeService = $this->getRepository()->getContentTypeService();
452
453
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
454
455
        // Configure new locations
456
        $locationCreate1 = $this->locationService->newLocationCreateStruct($parentLocationId);
457
458
        $locationCreate1->priority = 23;
459
        $locationCreate1->hidden = true;
460
        $locationCreate1->remoteId = '0123456789abcdef0123456789aaaaaa';
461
        $locationCreate1->sortField = Location::SORT_FIELD_NODE_ID;
462
        $locationCreate1->sortOrder = Location::SORT_ORDER_DESC;
463
464
        $locationCreate2 = $this->locationService->newLocationCreateStruct($parentLocationId);
465
466
        $locationCreate2->priority = 42;
467
        $locationCreate2->hidden = true;
468
        $locationCreate2->remoteId = '0123456789abcdef0123456789bbbbbb';
469
        $locationCreate2->sortField = Location::SORT_FIELD_NODE_ID;
470
        $locationCreate2->sortOrder = Location::SORT_ORDER_DESC;
471
472
        // Configure new content object
473
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
474
475
        $contentCreate->setField('name', 'A awesome Sindelfingen forum');
476
        $contentCreate->remoteId = 'abcdef0123456789abcdef0123456789';
477
        $contentCreate->alwaysAvailable = true;
478
479
        // Create new content object under the specified location
480
        $draft = $this->contentService->createContent(
481
            $contentCreate,
482
            [$locationCreate1]
483
        );
484
        $this->contentService->publishVersion($draft->versionInfo);
485
486
        $this->expectException(APIInvalidArgumentException::class);
487
        // Content remoteId already exists,
488
        $this->contentService->createContent(
489
            $contentCreate,
490
            [$locationCreate2]
491
        );
492
        /* END: Use Case */
493
    }
494
495
    /**
496
     * Test for the loadContentInfo() method.
497
     *
498
     * @see \eZ\Publish\API\Repository\ContentService::loadContentInfo()
499
     * @group user
500
     */
501
    public function testLoadContentInfo()
502
    {
503
        $mediaFolderId = $this->generateId('object', 41);
504
        /* BEGIN: Use Case */
505
506
        // Load the ContentInfo for "Media" folder
507
        $contentInfo = $this->contentService->loadContentInfo($mediaFolderId);
508
        /* END: Use Case */
509
510
        $this->assertInstanceOf(ContentInfo::class, $contentInfo);
511
512
        return $contentInfo;
513
    }
514
515
    /**
516
     * Test for the returned value of the loadContentInfo() method.
517
     *
518
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
519
     * @covers \eZ\Publish\API\Repository\ContentService::loadContentInfo
520
     *
521
     * @param ContentInfo $contentInfo
522
     */
523
    public function testLoadContentInfoSetsExpectedContentInfo(ContentInfo $contentInfo)
524
    {
525
        $this->assertPropertiesCorrectUnsorted(
526
            $this->getExpectedMediaContentInfoProperties(),
527
            $contentInfo
528
        );
529
    }
530
531
    /**
532
     * Test for the loadContentInfo() method.
533
     *
534
     * @see \eZ\Publish\API\Repository\ContentService::loadContentInfo()
535
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
536
     */
537
    public function testLoadContentInfoThrowsNotFoundException()
538
    {
539
        $nonExistentContentId = $this->generateId('object', self::DB_INT_MAX);
540
        /* BEGIN: Use Case */
541
542
        $this->expectException(NotFoundException::class);
543
544
        // This call will fail with a NotFoundException
545
        $this->contentService->loadContentInfo($nonExistentContentId);
546
        /* END: Use Case */
547
    }
548
549
    /**
550
     * Test for the loadContentInfoList() method.
551
     *
552
     * @see \eZ\Publish\API\Repository\ContentService::loadContentInfoList()
553
     */
554
    public function testLoadContentInfoList()
555
    {
556
        $mediaFolderId = $this->generateId('object', 41);
557
        $list = $this->contentService->loadContentInfoList([$mediaFolderId]);
558
559
        $this->assertCount(1, $list);
560
        $this->assertEquals([$mediaFolderId], array_keys($list), 'Array key was not content id');
561
        $this->assertInstanceOf(
562
            ContentInfo::class,
563
            $list[$mediaFolderId]
564
        );
565
    }
566
567
    /**
568
     * Test for the loadContentInfoList() method.
569
     *
570
     * @see \eZ\Publish\API\Repository\ContentService::loadContentInfoList()
571
     * @depends testLoadContentInfoList
572
     */
573
    public function testLoadContentInfoListSkipsNotFoundItems()
574
    {
575
        $nonExistentContentId = $this->generateId('object', self::DB_INT_MAX);
576
        $list = $this->contentService->loadContentInfoList([$nonExistentContentId]);
577
578
        $this->assertCount(0, $list);
579
    }
580
581
    /**
582
     * Test for the loadContentInfoByRemoteId() method.
583
     *
584
     * @see \eZ\Publish\API\Repository\ContentService::loadContentInfoByRemoteId()
585
     */
586
    public function testLoadContentInfoByRemoteId()
587
    {
588
        /* BEGIN: Use Case */
589
        // Load the ContentInfo for "Media" folder
590
        $contentInfo = $this->contentService->loadContentInfoByRemoteId('faaeb9be3bd98ed09f606fc16d144eca');
591
        /* END: Use Case */
592
593
        $this->assertInstanceOf(ContentInfo::class, $contentInfo);
594
595
        return $contentInfo;
596
    }
597
598
    /**
599
     * Test for the returned value of the loadContentInfoByRemoteId() method.
600
     *
601
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfoByRemoteId
602
     * @covers \eZ\Publish\API\Repository\ContentService::loadContentInfoByRemoteId
603
     *
604
     * @param ContentInfo $contentInfo
605
     */
606 View Code Duplication
    public function testLoadContentInfoByRemoteIdSetsExpectedContentInfo(ContentInfo $contentInfo)
607
    {
608
        $this->assertPropertiesCorrectUnsorted(
609
            [
610
                'id' => 10,
611
                'contentTypeId' => 4,
612
                'name' => 'Anonymous User',
613
                'sectionId' => 2,
614
                'currentVersionNo' => 2,
615
                'published' => true,
616
                'ownerId' => 14,
617
                'modificationDate' => $this->createDateTime(1072180405),
618
                'publishedDate' => $this->createDateTime(1033920665),
619
                'alwaysAvailable' => 1,
620
                'remoteId' => 'faaeb9be3bd98ed09f606fc16d144eca',
621
                'mainLanguageCode' => 'eng-US',
622
                'mainLocationId' => 45,
623
            ],
624
            $contentInfo
625
        );
626
    }
627
628
    /**
629
     * Test for the loadContentInfoByRemoteId() method.
630
     *
631
     * @see \eZ\Publish\API\Repository\ContentService::loadContentInfoByRemoteId()
632
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfoByRemoteId
633
     */
634
    public function testLoadContentInfoByRemoteIdThrowsNotFoundException()
635
    {
636
        /* BEGIN: Use Case */
637
        $this->expectException(NotFoundException::class);
638
639
        $this->contentService->loadContentInfoByRemoteId('abcdefghijklmnopqrstuvwxyz0123456789');
640
        /* END: Use Case */
641
    }
642
643
    /**
644
     * Test for the loadVersionInfo() method.
645
     *
646
     * @see \eZ\Publish\API\Repository\ContentService::loadVersionInfo()
647
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
648
     * @group user
649
     */
650 View Code Duplication
    public function testLoadVersionInfo()
651
    {
652
        $mediaFolderId = $this->generateId('object', 41);
653
        /* BEGIN: Use Case */
654
        // $mediaFolderId contains the ID of the "Media" folder
655
656
        // Load the ContentInfo for "Media" folder
657
        $contentInfo = $this->contentService->loadContentInfo($mediaFolderId);
658
659
        // Now load the current version info of the "Media" folder
660
        $versionInfo = $this->contentService->loadVersionInfo($contentInfo);
661
        /* END: Use Case */
662
663
        $this->assertInstanceOf(
664
            VersionInfo::class,
665
            $versionInfo
666
        );
667
    }
668
669
    /**
670
     * Test for the loadVersionInfoById() method.
671
     *
672
     * @see \eZ\Publish\API\Repository\ContentService::loadVersionInfoById()
673
     */
674
    public function testLoadVersionInfoById()
675
    {
676
        $mediaFolderId = $this->generateId('object', 41);
677
        /* BEGIN: Use Case */
678
        // $mediaFolderId contains the ID of the "Media" folder
679
680
        // Load the VersionInfo for "Media" folder
681
        $versionInfo = $this->contentService->loadVersionInfoById($mediaFolderId);
682
        /* END: Use Case */
683
684
        $this->assertInstanceOf(
685
            VersionInfo::class,
686
            $versionInfo
687
        );
688
689
        return $versionInfo;
690
    }
691
692
    /**
693
     * Test for the returned value of the loadVersionInfoById() method.
694
     *
695
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfoById
696
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById
697
     *
698
     * @param VersionInfo $versionInfo
699
     */
700
    public function testLoadVersionInfoByIdSetsExpectedVersionInfo(VersionInfo $versionInfo)
701
    {
702
        $this->assertPropertiesCorrect(
703
            [
704
                'names' => [
705
                    'eng-US' => 'Media',
706
                ],
707
                'contentInfo' => new ContentInfo($this->getExpectedMediaContentInfoProperties()),
708
                'id' => 472,
709
                'versionNo' => 1,
710
                'modificationDate' => $this->createDateTime(1060695457),
711
                'creatorId' => 14,
712
                'creationDate' => $this->createDateTime(1060695450),
713
                'status' => VersionInfo::STATUS_PUBLISHED,
714
                'initialLanguageCode' => 'eng-US',
715
                'languageCodes' => [
716
                    'eng-US',
717
                ],
718
            ],
719
            $versionInfo
720
        );
721
        $this->assertTrue($versionInfo->isPublished());
722
        $this->assertFalse($versionInfo->isDraft());
723
        $this->assertFalse($versionInfo->isArchived());
724
    }
725
726
    /**
727
     * Test for the loadVersionInfoById() method.
728
     *
729
     * @see \eZ\Publish\API\Repository\ContentService::loadVersionInfoById()
730
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfoById
731
     */
732
    public function testLoadVersionInfoByIdThrowsNotFoundException()
733
    {
734
        $nonExistentContentId = $this->generateId('object', self::DB_INT_MAX);
735
        /* BEGIN: Use Case */
736
737
        $this->expectException(NotFoundException::class);
738
739
        $this->contentService->loadVersionInfoById($nonExistentContentId);
740
        /* END: Use Case */
741
    }
742
743
    /**
744
     * Test for the loadContentByContentInfo() method.
745
     *
746
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByContentInfo()
747
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
748
     */
749 View Code Duplication
    public function testLoadContentByContentInfo()
750
    {
751
        $mediaFolderId = $this->generateId('object', 41);
752
        /* BEGIN: Use Case */
753
        // $mediaFolderId contains the ID of the "Media" folder
754
755
        // Load the ContentInfo for "Media" folder
756
        $contentInfo = $this->contentService->loadContentInfo($mediaFolderId);
757
758
        // Now load the current content version for the info instance
759
        $content = $this->contentService->loadContentByContentInfo($contentInfo);
760
        /* END: Use Case */
761
762
        $this->assertInstanceOf(
763
            Content::class,
764
            $content
765
        );
766
    }
767
768
    /**
769
     * Test for the loadContentByVersionInfo() method.
770
     *
771
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByVersionInfo()
772
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfo
773
     */
774 View Code Duplication
    public function testLoadContentByVersionInfo()
775
    {
776
        $mediaFolderId = $this->generateId('object', 41);
777
        /* BEGIN: Use Case */
778
        // $mediaFolderId contains the ID of the "Media" folder
779
780
        // Load the ContentInfo for "Media" folder
781
        $contentInfo = $this->contentService->loadContentInfo($mediaFolderId);
782
783
        // Load the current VersionInfo
784
        $versionInfo = $this->contentService->loadVersionInfo($contentInfo);
785
786
        // Now load the current content version for the info instance
787
        $content = $this->contentService->loadContentByVersionInfo($versionInfo);
788
        /* END: Use Case */
789
790
        $this->assertInstanceOf(
791
            Content::class,
792
            $content
793
        );
794
    }
795
796
    /**
797
     * Test for the loadContent() method.
798
     *
799
     * @see \eZ\Publish\API\Repository\ContentService::loadContent()
800
     * @group user
801
     * @group field-type
802
     */
803
    public function testLoadContent()
804
    {
805
        $mediaFolderId = $this->generateId('object', 41);
806
        /* BEGIN: Use Case */
807
        // $mediaFolderId contains the ID of the "Media" folder
808
809
        // Load the Content for "Media" folder, any language and current version
810
        $content = $this->contentService->loadContent($mediaFolderId);
811
        /* END: Use Case */
812
813
        $this->assertInstanceOf(
814
            Content::class,
815
            $content
816
        );
817
    }
818
819
    /**
820
     * Test for the loadContent() method.
821
     *
822
     * @see \eZ\Publish\API\Repository\ContentService::loadContent()
823
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
824
     */
825
    public function testLoadContentThrowsNotFoundException()
826
    {
827
        $nonExistentContentId = $this->generateId('object', self::DB_INT_MAX);
828
        /* BEGIN: Use Case */
829
830
        $this->expectException(NotFoundException::class);
831
832
        $this->contentService->loadContent($nonExistentContentId);
833
        /* END: Use Case */
834
    }
835
836
    /**
837
     * Data provider for testLoadContentByRemoteId().
838
     *
839
     * @return array
840
     */
841
    public function contentRemoteIdVersionLanguageProvider()
842
    {
843
        return [
844
            ['f5c88a2209584891056f987fd965b0ba', null, null],
845
            ['f5c88a2209584891056f987fd965b0ba', ['eng-US'], null],
846
            ['f5c88a2209584891056f987fd965b0ba', null, 1],
847
            ['f5c88a2209584891056f987fd965b0ba', ['eng-US'], 1],
848
            ['a6e35cbcb7cd6ae4b691f3eee30cd262', null, null],
849
            ['a6e35cbcb7cd6ae4b691f3eee30cd262', ['eng-US'], null],
850
            ['a6e35cbcb7cd6ae4b691f3eee30cd262', null, 1],
851
            ['a6e35cbcb7cd6ae4b691f3eee30cd262', ['eng-US'], 1],
852
        ];
853
    }
854
855
    /**
856
     * Test for the loadContentByRemoteId() method.
857
     *
858
     * @covers \eZ\Publish\API\Repository\ContentService::loadContentByRemoteId
859
     * @dataProvider contentRemoteIdVersionLanguageProvider
860
     *
861
     * @param string $remoteId
862
     * @param array|null $languages
863
     * @param int $versionNo
864
     */
865
    public function testLoadContentByRemoteId($remoteId, $languages, $versionNo)
866
    {
867
        $content = $this->contentService->loadContentByRemoteId($remoteId, $languages, $versionNo);
868
869
        $this->assertInstanceOf(
870
            Content::class,
871
            $content
872
        );
873
874
        $this->assertEquals($remoteId, $content->contentInfo->remoteId);
875
        if ($languages !== null) {
876
            $this->assertEquals($languages, $content->getVersionInfo()->languageCodes);
877
        }
878
        $this->assertEquals($versionNo ?: 1, $content->getVersionInfo()->versionNo);
879
    }
880
881
    /**
882
     * Test for the loadContentByRemoteId() method.
883
     *
884
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByRemoteId()
885
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByRemoteId
886
     */
887
    public function testLoadContentByRemoteIdThrowsNotFoundException()
888
    {
889
        /* BEGIN: Use Case */
890
        $this->expectException(NotFoundException::class);
891
892
        // This call will fail with a "NotFoundException", because no content object exists for the given remoteId
893
        $this->contentService->loadContentByRemoteId('a1b1c1d1e1f1a2b2c2d2e2f2a3b3c3d3');
894
        /* END: Use Case */
895
    }
896
897
    /**
898
     * Test for the publishVersion() method.
899
     *
900
     * @return \eZ\Publish\API\Repository\Values\Content\Content
901
     *
902
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
903
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
904
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
905
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfo
906
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentWithLocationCreateParameterDoesNotCreateLocationImmediately
907
     * @group user
908
     * @group field-type
909
     */
910
    public function testPublishVersion()
911
    {
912
        $time = time();
913
        /* BEGIN: Use Case */
914
        $content = $this->createContentVersion1();
915
        /* END: Use Case */
916
917
        $this->assertInstanceOf(Content::class, $content);
918
        $this->assertTrue($content->contentInfo->published);
919
        $this->assertEquals(VersionInfo::STATUS_PUBLISHED, $content->versionInfo->status);
920
        $this->assertGreaterThanOrEqual($time, $content->contentInfo->publishedDate->getTimestamp());
921
        $this->assertGreaterThanOrEqual($time, $content->contentInfo->modificationDate->getTimestamp());
922
        $this->assertTrue($content->versionInfo->isPublished());
923
        $this->assertFalse($content->versionInfo->isDraft());
924
        $this->assertFalse($content->versionInfo->isArchived());
925
926
        return $content;
927
    }
928
929
    /**
930
     * Test for the publishVersion() method.
931
     *
932
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
933
     *
934
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
935
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
936
     */
937
    public function testPublishVersionSetsExpectedContentInfo($content)
938
    {
939
        $this->assertEquals(
940
            [
941
                $content->id,
942
                true,
943
                1,
944
                'abcdef0123456789abcdef0123456789',
945
                'eng-US',
946
                $this->getRepository()->getCurrentUser()->id,
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...itory::getCurrentUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::getCurrentUserReference() instead. Get current user. Loads the full user object if not already loaded, if you only need to know user id use {@see getCurrentUserReference()}

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

Loading history...
947
                true,
948
            ],
949
            [
950
                $content->contentInfo->id,
951
                $content->contentInfo->alwaysAvailable,
952
                $content->contentInfo->currentVersionNo,
953
                $content->contentInfo->remoteId,
954
                $content->contentInfo->mainLanguageCode,
955
                $content->contentInfo->ownerId,
956
                $content->contentInfo->published,
957
            ]
958
        );
959
960
        $this->assertNotNull($content->contentInfo->mainLocationId);
961
        $date = new \DateTime('1984/01/01');
962
        $this->assertGreaterThan(
963
            $date->getTimestamp(),
964
            $content->contentInfo->publishedDate->getTimestamp()
965
        );
966
    }
967
968
    /**
969
     * Test for the publishVersion() method.
970
     *
971
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
972
     *
973
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
974
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
975
     */
976
    public function testPublishVersionSetsExpectedVersionInfo($content)
977
    {
978
        $this->assertEquals(
979
            [
980
                $this->getRepository()->getCurrentUser()->id,
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...itory::getCurrentUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::getCurrentUserReference() instead. Get current user. Loads the full user object if not already loaded, if you only need to know user id use {@see getCurrentUserReference()}

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

Loading history...
981
                'eng-US',
982
                VersionInfo::STATUS_PUBLISHED,
983
                1,
984
            ],
985
            [
986
                $content->getVersionInfo()->creatorId,
987
                $content->getVersionInfo()->initialLanguageCode,
988
                $content->getVersionInfo()->status,
989
                $content->getVersionInfo()->versionNo,
990
            ]
991
        );
992
993
        $date = new \DateTime('1984/01/01');
994
        $this->assertGreaterThan(
995
            $date->getTimestamp(),
996
            $content->getVersionInfo()->modificationDate->getTimestamp()
997
        );
998
999
        $this->assertNotNull($content->getVersionInfo()->modificationDate);
1000
        $this->assertTrue($content->getVersionInfo()->isPublished());
1001
        $this->assertFalse($content->getVersionInfo()->isDraft());
1002
        $this->assertFalse($content->getVersionInfo()->isArchived());
1003
    }
1004
1005
    /**
1006
     * Test for the publishVersion() method.
1007
     *
1008
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
1009
     *
1010
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1011
     * @depends testPublishVersion
1012
     */
1013
    public function testPublishVersionSetsExpectedContentType($content)
1014
    {
1015
        $contentType = $content->getContentType();
1016
1017
        $this->assertEquals(
1018
            [
1019
                $contentType->id,
1020
                // won't be a match as it's set to true in createContentDraftVersion1()
1021
                //$contentType->defaultAlwaysAvailable,
1022
                //$contentType->defaultSortField,
1023
                //$contentType->defaultSortOrder,
1024
            ],
1025
            [
1026
                $content->contentInfo->contentTypeId,
1027
                //$content->contentInfo->alwaysAvailable,
1028
                //$location->sortField,
1029
                //$location->sortOrder,
1030
            ]
1031
        );
1032
    }
1033
1034
    /**
1035
     * Test for the publishVersion() method.
1036
     *
1037
     * @return \eZ\Publish\API\Repository\Values\Content\Content
1038
     *
1039
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1040
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentWithLocationCreateParameterDoesNotCreateLocationImmediately
1041
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
1042
     */
1043
    public function testPublishVersionCreatesLocationsDefinedOnCreate()
1044
    {
1045
        /* BEGIN: Use Case */
1046
        $content = $this->createContentVersion1();
1047
        /* END: Use Case */
1048
1049
        $location = $this->locationService->loadLocationByRemoteId(
1050
            '0123456789abcdef0123456789abcdef'
1051
        );
1052
1053
        $this->assertEquals(
1054
            $location->getContentInfo(),
1055
            $content->getVersionInfo()->getContentInfo()
1056
        );
1057
1058
        return [$content, $location];
1059
    }
1060
1061
    /**
1062
     * Test for the publishVersion() method.
1063
     *
1064
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1065
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionCreatesLocationsDefinedOnCreate
1066
     */
1067
    public function testCreateContentWithLocationCreateParameterCreatesExpectedLocation(array $testData)
1068
    {
1069
        /** @var \eZ\Publish\API\Repository\Values\Content\Content $content */
1070
        /** @var \eZ\Publish\API\Repository\Values\Content\Location $location */
1071
        list($content, $location) = $testData;
1072
1073
        $parentLocationId = $this->generateId('location', 56);
1074
        $parentLocation = $this->getRepository()->getLocationService()->loadLocation($parentLocationId);
1075
        $mainLocationId = $content->getVersionInfo()->getContentInfo()->mainLocationId;
1076
1077
        $this->assertPropertiesCorrect(
1078
            [
1079
                'id' => $mainLocationId,
1080
                'priority' => 23,
1081
                'hidden' => true,
1082
                'invisible' => true,
1083
                'remoteId' => '0123456789abcdef0123456789abcdef',
1084
                'parentLocationId' => $parentLocationId,
1085
                'pathString' => $parentLocation->pathString . $mainLocationId . '/',
1086
                'depth' => $parentLocation->depth + 1,
1087
                'sortField' => Location::SORT_FIELD_NODE_ID,
1088
                'sortOrder' => Location::SORT_ORDER_DESC,
1089
            ],
1090
            $location
1091
        );
1092
    }
1093
1094
    /**
1095
     * Test for the publishVersion() method.
1096
     *
1097
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1098
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
1099
     */
1100
    public function testPublishVersionThrowsBadStateException()
1101
    {
1102
        /* BEGIN: Use Case */
1103
        $draft = $this->createContentDraftVersion1();
1104
1105
        // Publish the content draft
1106
        $this->contentService->publishVersion($draft->getVersionInfo());
1107
1108
        $this->expectException(BadStateException::class);
1109
1110
        // This call will fail with a "BadStateException", because the version is already published.
1111
        $this->contentService->publishVersion($draft->getVersionInfo());
1112
        /* END: Use Case */
1113
    }
1114
1115
    /**
1116
     * Test that publishVersion() does not affect publishedDate (assuming previous version exists).
1117
     *
1118
     * @covers \eZ\Publish\API\Repository\ContentService::publishVersion
1119
     */
1120
    public function testPublishVersionDoesNotChangePublishedDate()
1121
    {
1122
        $publishedContent = $this->createContentVersion1();
1123
1124
        // force timestamps to differ
1125
        sleep(1);
1126
1127
        $contentDraft = $this->contentService->createContentDraft($publishedContent->contentInfo);
1128
        $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
1129
        $contentUpdateStruct->setField('name', 'New name');
1130
        $contentDraft = $this->contentService->updateContent($contentDraft->versionInfo, $contentUpdateStruct);
1131
        $republishedContent = $this->contentService->publishVersion($contentDraft->versionInfo);
1132
1133
        $this->assertEquals(
1134
            $publishedContent->contentInfo->publishedDate->getTimestamp(),
1135
            $republishedContent->contentInfo->publishedDate->getTimestamp()
1136
        );
1137
        $this->assertGreaterThan(
1138
            $publishedContent->contentInfo->modificationDate->getTimestamp(),
1139
            $republishedContent->contentInfo->modificationDate->getTimestamp()
1140
        );
1141
    }
1142
1143
    /**
1144
     * Test for the createContentDraft() method.
1145
     *
1146
     * @return \eZ\Publish\API\Repository\Values\Content\Content
1147
     *
1148
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1149
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
1150
     * @group user
1151
     */
1152
    public function testCreateContentDraft()
1153
    {
1154
        /* BEGIN: Use Case */
1155
        $content = $this->createContentVersion1();
1156
1157
        // Now we create a new draft from the published content
1158
        $draftedContent = $this->contentService->createContentDraft($content->contentInfo);
1159
        /* END: Use Case */
1160
1161
        $this->assertInstanceOf(
1162
            Content::class,
1163
            $draftedContent
1164
        );
1165
1166
        return $draftedContent;
1167
    }
1168
1169
    /**
1170
     * Test for the createContentDraft() method.
1171
     *
1172
     * Test that editor has access to edit own draft.
1173
     * Note: Editors have access to version_read, which is needed to load content drafts.
1174
     *
1175
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1176
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
1177
     * @group user
1178
     */
1179
    public function testCreateContentDraftAndLoadAccess()
1180
    {
1181
        /* BEGIN: Use Case */
1182
        $user = $this->createUserVersion1();
1183
1184
        // Set new editor as user
1185
        $this->permissionResolver->setCurrentUserReference($user);
1186
1187
        // Create draft
1188
        $draft = $this->createContentDraftVersion1(2, 'folder');
1189
1190
        // Try to load the draft
1191
        $loadedDraft = $this->contentService->loadContent($draft->id);
1192
1193
        /* END: Use Case */
1194
1195
        $this->assertEquals($draft->id, $loadedDraft->id);
1196
    }
1197
1198
    /**
1199
     * Test for the createContentDraft() method.
1200
     *
1201
     * @param \eZ\Publish\API\Repository\Values\Content\Content $draft
1202
     *
1203
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1204
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1205
     */
1206
    public function testCreateContentDraftSetsExpectedProperties($draft)
1207
    {
1208
        $this->assertEquals(
1209
            [
1210
                'fieldCount' => 2,
1211
                'relationCount' => 0,
1212
            ],
1213
            [
1214
                'fieldCount' => count($draft->getFields()),
1215
                'relationCount' => count($this->getRepository()->getContentService()->loadRelations($draft->getVersionInfo())),
1216
            ]
1217
        );
1218
    }
1219
1220
    /**
1221
     * Test for the createContentDraft() method.
1222
     *
1223
     * @param \eZ\Publish\API\Repository\Values\Content\Content $draft
1224
     *
1225
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1226
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1227
     */
1228
    public function testCreateContentDraftSetsContentInfo($draft)
1229
    {
1230
        $contentInfo = $draft->contentInfo;
1231
1232
        $this->assertEquals(
1233
            [
1234
                $draft->id,
1235
                true,
1236
                1,
1237
                'eng-US',
1238
                $this->getRepository()->getCurrentUser()->id,
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...itory::getCurrentUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::getCurrentUserReference() instead. Get current user. Loads the full user object if not already loaded, if you only need to know user id use {@see getCurrentUserReference()}

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

Loading history...
1239
                'abcdef0123456789abcdef0123456789',
1240
                1,
1241
            ],
1242
            [
1243
                $contentInfo->id,
1244
                $contentInfo->alwaysAvailable,
1245
                $contentInfo->currentVersionNo,
1246
                $contentInfo->mainLanguageCode,
1247
                $contentInfo->ownerId,
1248
                $contentInfo->remoteId,
1249
                $contentInfo->sectionId,
1250
            ]
1251
        );
1252
    }
1253
1254
    /**
1255
     * Test for the createContentDraft() method.
1256
     *
1257
     * @param \eZ\Publish\API\Repository\Values\Content\Content $draft
1258
     *
1259
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1260
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1261
     */
1262
    public function testCreateContentDraftSetsVersionInfo($draft)
1263
    {
1264
        $versionInfo = $draft->getVersionInfo();
1265
1266
        $this->assertEquals(
1267
            [
1268
                'creatorId' => $this->getRepository()->getCurrentUser()->id,
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...itory::getCurrentUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::getCurrentUserReference() instead. Get current user. Loads the full user object if not already loaded, if you only need to know user id use {@see getCurrentUserReference()}

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

Loading history...
1269
                'initialLanguageCode' => 'eng-US',
1270
                'languageCodes' => [0 => 'eng-US'],
1271
                'status' => VersionInfo::STATUS_DRAFT,
1272
                'versionNo' => 2,
1273
            ],
1274
            [
1275
                'creatorId' => $versionInfo->creatorId,
1276
                'initialLanguageCode' => $versionInfo->initialLanguageCode,
1277
                'languageCodes' => $versionInfo->languageCodes,
1278
                'status' => $versionInfo->status,
1279
                'versionNo' => $versionInfo->versionNo,
1280
            ]
1281
        );
1282
        $this->assertTrue($versionInfo->isDraft());
1283
        $this->assertFalse($versionInfo->isPublished());
1284
        $this->assertFalse($versionInfo->isArchived());
1285
    }
1286
1287
    /**
1288
     * Test for the createContentDraft() method.
1289
     *
1290
     * @param \eZ\Publish\API\Repository\Values\Content\Content $draft
1291
     *
1292
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1293
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1294
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfo
1295
     */
1296
    public function testCreateContentDraftLoadVersionInfoStillLoadsPublishedVersion($draft)
0 ignored issues
show
Unused Code introduced by
The parameter $draft 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...
1297
    {
1298
        /* BEGIN: Use Case */
1299
        $content = $this->createContentVersion1();
1300
1301
        // Now we create a new draft from the published content
1302
        $this->contentService->createContentDraft($content->contentInfo);
1303
1304
        // This call will still load the published version
1305
        $versionInfoPublished = $this->contentService->loadVersionInfo($content->contentInfo);
1306
        /* END: Use Case */
1307
1308
        $this->assertEquals(1, $versionInfoPublished->versionNo);
1309
    }
1310
1311
    /**
1312
     * Test for the createContentDraft() method.
1313
     *
1314
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1315
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
1316
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1317
     */
1318 View Code Duplication
    public function testCreateContentDraftLoadContentStillLoadsPublishedVersion()
1319
    {
1320
        /* BEGIN: Use Case */
1321
        $content = $this->createContentVersion1();
1322
1323
        // Now we create a new draft from the published content
1324
        $this->contentService->createContentDraft($content->contentInfo);
1325
1326
        // This call will still load the published content version
1327
        $contentPublished = $this->contentService->loadContent($content->id);
1328
        /* END: Use Case */
1329
1330
        $this->assertEquals(1, $contentPublished->getVersionInfo()->versionNo);
1331
    }
1332
1333
    /**
1334
     * Test for the createContentDraft() method.
1335
     *
1336
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1337
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByRemoteId
1338
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1339
     */
1340 View Code Duplication
    public function testCreateContentDraftLoadContentByRemoteIdStillLoadsPublishedVersion()
1341
    {
1342
        /* BEGIN: Use Case */
1343
        $content = $this->createContentVersion1();
1344
1345
        // Now we create a new draft from the published content
1346
        $this->contentService->createContentDraft($content->contentInfo);
1347
1348
        // This call will still load the published content version
1349
        $contentPublished = $this->contentService->loadContentByRemoteId('abcdef0123456789abcdef0123456789');
1350
        /* END: Use Case */
1351
1352
        $this->assertEquals(1, $contentPublished->getVersionInfo()->versionNo);
1353
    }
1354
1355
    /**
1356
     * Test for the createContentDraft() method.
1357
     *
1358
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1359
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByContentInfo
1360
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1361
     */
1362 View Code Duplication
    public function testCreateContentDraftLoadContentByContentInfoStillLoadsPublishedVersion()
1363
    {
1364
        /* BEGIN: Use Case */
1365
        $content = $this->createContentVersion1();
1366
1367
        // Now we create a new draft from the published content
1368
        $this->contentService->createContentDraft($content->contentInfo);
1369
1370
        // This call will still load the published content version
1371
        $contentPublished = $this->contentService->loadContentByContentInfo($content->contentInfo);
1372
        /* END: Use Case */
1373
1374
        $this->assertEquals(1, $contentPublished->getVersionInfo()->versionNo);
1375
    }
1376
1377
    /**
1378
     * Test for the newContentUpdateStruct() method.
1379
     *
1380
     * @covers \eZ\Publish\API\Repository\ContentService::newContentUpdateStruct
1381
     * @group user
1382
     */
1383
    public function testNewContentUpdateStruct()
1384
    {
1385
        /* BEGIN: Use Case */
1386
        $updateStruct = $this->contentService->newContentUpdateStruct();
1387
        /* END: Use Case */
1388
1389
        $this->assertInstanceOf(
1390
            ContentUpdateStruct::class,
1391
            $updateStruct
1392
        );
1393
1394
        $this->assertPropertiesCorrect(
1395
            [
1396
                'initialLanguageCode' => null,
1397
                'fields' => [],
1398
            ],
1399
            $updateStruct
1400
        );
1401
    }
1402
1403
    /**
1404
     * Test for the updateContent() method.
1405
     *
1406
     * @return \eZ\Publish\API\Repository\Values\Content\Content
1407
     *
1408
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1409
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testNewContentUpdateStruct
1410
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1411
     * @group user
1412
     * @group field-type
1413
     */
1414
    public function testUpdateContent()
1415
    {
1416
        /* BEGIN: Use Case */
1417
        $draftVersion2 = $this->createUpdatedDraftVersion2();
1418
        /* END: Use Case */
1419
1420
        $this->assertInstanceOf(
1421
            Content::class,
1422
            $draftVersion2
1423
        );
1424
1425
        $this->assertEquals(
1426
            $this->generateId('user', 10),
1427
            $draftVersion2->versionInfo->creatorId,
1428
            'creatorId is not properly set on new Version'
1429
        );
1430
1431
        return $draftVersion2;
1432
    }
1433
1434
    /**
1435
     * Test for the updateContent_WithDifferentUser() method.
1436
     *
1437
     * @return \eZ\Publish\API\Repository\Values\Content\Content
1438
     *
1439
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1440
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testNewContentUpdateStruct
1441
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1442
     * @group user
1443
     * @group field-type
1444
     */
1445
    public function testUpdateContentWithDifferentUser()
1446
    {
1447
        /* BEGIN: Use Case */
1448
        $arrayWithDraftVersion2 = $this->createUpdatedDraftVersion2NotAdmin();
1449
        /* END: Use Case */
1450
1451
        $this->assertInstanceOf(
1452
            Content::class,
1453
            $arrayWithDraftVersion2[0]
1454
        );
1455
1456
        $this->assertEquals(
1457
            $this->generateId('user', $arrayWithDraftVersion2[1]),
1458
            $arrayWithDraftVersion2[0]->versionInfo->creatorId,
1459
            'creatorId is not properly set on new Version'
1460
        );
1461
1462
        return $arrayWithDraftVersion2[0];
1463
    }
1464
1465
    /**
1466
     * Test for the updateContent() method.
1467
     *
1468
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
1469
     *
1470
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1471
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1472
     */
1473
    public function testUpdateContentSetsExpectedFields($content)
1474
    {
1475
        $actual = $this->normalizeFields($content->getFields());
1476
1477
        $expected = [
1478
            new Field(
1479
                [
1480
                    'id' => 0,
1481
                    'value' => true,
1482
                    'languageCode' => 'eng-GB',
1483
                    'fieldDefIdentifier' => 'description',
1484
                    'fieldTypeIdentifier' => 'ezrichtext',
1485
                ]
1486
            ),
1487
            new Field(
1488
                [
1489
                    'id' => 0,
1490
                    'value' => true,
1491
                    'languageCode' => 'eng-US',
1492
                    'fieldDefIdentifier' => 'description',
1493
                    'fieldTypeIdentifier' => 'ezrichtext',
1494
                ]
1495
            ),
1496
            new Field(
1497
                [
1498
                    'id' => 0,
1499
                    'value' => true,
1500
                    'languageCode' => 'eng-GB',
1501
                    'fieldDefIdentifier' => 'name',
1502
                    'fieldTypeIdentifier' => 'ezstring',
1503
                ]
1504
            ),
1505
            new Field(
1506
                [
1507
                    'id' => 0,
1508
                    'value' => true,
1509
                    'languageCode' => 'eng-US',
1510
                    'fieldDefIdentifier' => 'name',
1511
                    'fieldTypeIdentifier' => 'ezstring',
1512
                ]
1513
            ),
1514
        ];
1515
1516
        $this->assertEquals($expected, $actual);
1517
    }
1518
1519
    /**
1520
     * Test for the updateContent() method.
1521
     *
1522
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1523
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1524
     */
1525
    public function testUpdateContentThrowsBadStateException()
1526
    {
1527
        /* BEGIN: Use Case */
1528
        $content = $this->createContentVersion1();
1529
1530
        // Now create an update struct and modify some fields
1531
        $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
1532
        $contentUpdateStruct->setField('title', 'An awesome² story about ezp.');
1533
        $contentUpdateStruct->setField('title', 'An awesome²³ story about ezp.', 'eng-GB');
1534
1535
        $contentUpdateStruct->initialLanguageCode = 'eng-US';
1536
1537
        $this->expectException(BadStateException::class);
1538
1539
        // This call will fail with a "BadStateException", because $publishedContent is not a draft.
1540
        $this->contentService->updateContent(
1541
            $content->getVersionInfo(),
1542
            $contentUpdateStruct
1543
        );
1544
        /* END: Use Case */
1545
    }
1546
1547
    /**
1548
     * Test for the updateContent() method.
1549
     *
1550
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1551
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1552
     */
1553 View Code Duplication
    public function testUpdateContentThrowsInvalidArgumentExceptionWhenFieldTypeDoesNotAccept()
1554
    {
1555
        /* BEGIN: Use Case */
1556
        $draft = $this->createContentDraftVersion1();
1557
1558
        // Now create an update struct and modify some fields
1559
        $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
1560
        // The name field does not accept a stdClass object as its input
1561
        $contentUpdateStruct->setField('name', new \stdClass(), 'eng-US');
1562
1563
        $this->expectException(APIInvalidArgumentException::class);
1564
        // is not accepted
1565
        $this->contentService->updateContent(
1566
            $draft->getVersionInfo(),
1567
            $contentUpdateStruct
1568
        );
1569
        /* END: Use Case */
1570
    }
1571
1572
    /**
1573
     * Test for the updateContent() method.
1574
     *
1575
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1576
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1577
     */
1578 View Code Duplication
    public function testUpdateContentWhenMandatoryFieldIsEmpty()
1579
    {
1580
        /* BEGIN: Use Case */
1581
        $draft = $this->createContentDraftVersion1();
1582
1583
        // Now create an update struct and set a mandatory field to null
1584
        $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
1585
        $contentUpdateStruct->setField('name', null);
1586
1587
        // Don't set this, then the above call without languageCode will fail
1588
        $contentUpdateStruct->initialLanguageCode = 'eng-US';
1589
1590
        $this->expectException(ContentFieldValidationException::class);
1591
1592
        // This call will fail with a "ContentFieldValidationException", because the mandatory "name" field is empty.
1593
        $this->contentService->updateContent(
1594
            $draft->getVersionInfo(),
1595
            $contentUpdateStruct
1596
        );
1597
        /* END: Use Case */
1598
    }
1599
1600
    /**
1601
     * Test for the updateContent() method.
1602
     *
1603
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1604
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1605
     */
1606
    public function testUpdateContentThrowsContentFieldValidationException()
1607
    {
1608
        /* BEGIN: Use Case */
1609
        $contentTypeService = $this->getRepository()->getContentTypeService();
1610
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
1611
1612
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
1613
        $contentCreate->setField('name', 'An awesome Sidelfingen folder');
1614
1615
        $draft = $this->contentService->createContent($contentCreate);
1616
1617
        $contentUpdate = $this->contentService->newContentUpdateStruct();
1618
        // Violates string length constraint
1619
        $contentUpdate->setField('short_name', str_repeat('a', 200), 'eng-US');
1620
1621
        $this->expectException(ContentFieldValidationException::class);
1622
1623
        // Throws ContentFieldValidationException because the string length validation of the field "short_name" fails
1624
        $this->contentService->updateContent($draft->getVersionInfo(), $contentUpdate);
1625
        /* END: Use Case */
1626
    }
1627
1628
    /**
1629
     * Test for the updateContent() method.
1630
     *
1631
     * @covers \eZ\Publish\API\Repository\ContentService::updateContent()
1632
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1633
     */
1634
    public function testUpdateContentValidatorIgnoresRequiredFieldsOfNotUpdatedLanguages()
1635
    {
1636
        /* BEGIN: Use Case */
1637
        $contentTypeService = $this->getRepository()->getContentTypeService();
1638
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
1639
1640
        // Create multilangual content
1641
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
1642
        $contentCreate->setField('name', 'An awesome Sidelfingen folder', 'eng-US');
1643
        $contentCreate->setField('name', 'An awesome Sidelfingen folder', 'eng-GB');
1644
1645
        $contentDraft = $this->contentService->createContent($contentCreate);
1646
1647
        // 2. Update content type definition
1648
        $contentTypeDraft = $contentTypeService->createContentTypeDraft($contentType);
1649
1650
        $fieldDefinition = $contentType->getFieldDefinition('description');
1651
        $fieldDefinitionUpdate = $contentTypeService->newFieldDefinitionUpdateStruct();
1652
        $fieldDefinitionUpdate->identifier = 'description';
1653
        $fieldDefinitionUpdate->isRequired = true;
1654
1655
        $contentTypeService->updateFieldDefinition(
1656
            $contentTypeDraft,
1657
            $fieldDefinition,
1658
            $fieldDefinitionUpdate
1659
        );
1660
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
1661
1662
        // 3. Update only eng-US translation
1663
        $description = new DOMDocument();
1664
        $description->loadXML(<<<XML
1665
<?xml version="1.0" encoding="UTF-8"?>
1666
<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ezxhtml="http://ez.no/xmlns/ezpublish/docbook/xhtml" xmlns:ezcustom="http://ez.no/xmlns/ezpublish/docbook/custom" version="5.0-variant ezpublish-1.0">
1667
    <para>Lorem ipsum dolor</para>
1668
</section>
1669
XML
1670
        );
1671
1672
        $contentUpdate = $this->contentService->newContentUpdateStruct();
1673
        $contentUpdate->setField('name', 'An awesome Sidelfingen folder (updated)', 'eng-US');
1674
        $contentUpdate->setField('description', $description);
1675
1676
        $this->contentService->updateContent($contentDraft->getVersionInfo(), $contentUpdate);
1677
        /* END: Use Case */
1678
    }
1679
1680
    /**
1681
     * Test for the updateContent() method.
1682
     *
1683
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1684
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1685
     */
1686
    public function testUpdateContentWithNotUpdatingMandatoryField()
1687
    {
1688
        /* BEGIN: Use Case */
1689
        $draft = $this->createContentDraftVersion1();
1690
1691
        // Now create an update struct which does not overwrite mandatory
1692
        // fields
1693
        $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
1694
        $contentUpdateStruct->setField(
1695
            'description',
1696
            '<?xml version="1.0" encoding="UTF-8"?><section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0-variant ezpublish-1.0"/>'
1697
        );
1698
1699
        // Don't set this, then the above call without languageCode will fail
1700
        $contentUpdateStruct->initialLanguageCode = 'eng-US';
1701
1702
        // This will only update the "description" field in the "eng-US"
1703
        // language
1704
        $updatedDraft = $this->contentService->updateContent(
1705
            $draft->getVersionInfo(),
1706
            $contentUpdateStruct
1707
        );
1708
        /* END: Use Case */
1709
1710
        foreach ($updatedDraft->getFields() as $field) {
1711
            if ($field->languageCode === 'eng-US' && $field->fieldDefIdentifier === 'name' && $field->value !== null) {
1712
                // Found field
1713
                return;
1714
            }
1715
        }
1716
        $this->fail(
1717
            'Field with identifier "name" in language "eng-US" could not be found or has empty value.'
1718
        );
1719
    }
1720
1721
    /**
1722
     * Test for the createContentDraft() method.
1723
     *
1724
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft($contentInfo, $versionInfo)
1725
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1726
     */
1727 View Code Duplication
    public function testCreateContentDraftWithSecondParameter()
1728
    {
1729
        /* BEGIN: Use Case */
1730
        $contentVersion2 = $this->createContentVersion2();
1731
1732
        // Now we create a new draft from the initial version
1733
        $draftedContentReloaded = $this->contentService->createContentDraft(
1734
            $contentVersion2->contentInfo,
1735
            $contentVersion2->getVersionInfo()
1736
        );
1737
        /* END: Use Case */
1738
1739
        $this->assertEquals(3, $draftedContentReloaded->getVersionInfo()->versionNo);
1740
    }
1741
1742
    /**
1743
     * Test for the createContentDraft() method with third parameter.
1744
     *
1745
     * @covers \eZ\Publish\Core\Repository\ContentService::createContentDraft
1746
     */
1747
    public function testCreateContentDraftWithThirdParameter()
1748
    {
1749
        $content = $this->contentService->loadContent(4);
1750
        $user = $this->createUserVersion1();
1751
1752
        $draftContent = $this->contentService->createContentDraft(
1753
            $content->contentInfo,
1754
            $content->getVersionInfo(),
1755
            $user
1756
        );
1757
1758
        $this->assertInstanceOf(
1759
            Content::class,
1760
            $draftContent
1761
        );
1762
    }
1763
1764
    /**
1765
     * Test for the publishVersion() method.
1766
     *
1767
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1768
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
1769
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1770
     */
1771 View Code Duplication
    public function testPublishVersionFromContentDraft()
1772
    {
1773
        /* BEGIN: Use Case */
1774
        $contentVersion2 = $this->createContentVersion2();
1775
        /* END: Use Case */
1776
1777
        $versionInfo = $this->contentService->loadVersionInfo($contentVersion2->contentInfo);
1778
1779
        $this->assertEquals(
1780
            [
1781
                'status' => VersionInfo::STATUS_PUBLISHED,
1782
                'versionNo' => 2,
1783
            ],
1784
            [
1785
                'status' => $versionInfo->status,
1786
                'versionNo' => $versionInfo->versionNo,
1787
            ]
1788
        );
1789
        $this->assertTrue($versionInfo->isPublished());
1790
        $this->assertFalse($versionInfo->isDraft());
1791
        $this->assertFalse($versionInfo->isArchived());
1792
    }
1793
1794
    /**
1795
     * Test for the publishVersion() method.
1796
     *
1797
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1798
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
1799
     */
1800 View Code Duplication
    public function testPublishVersionFromContentDraftArchivesOldVersion()
1801
    {
1802
        /* BEGIN: Use Case */
1803
        $contentVersion2 = $this->createContentVersion2();
1804
        /* END: Use Case */
1805
1806
        $versionInfo = $this->contentService->loadVersionInfo($contentVersion2->contentInfo, 1);
1807
1808
        $this->assertEquals(
1809
            [
1810
                'status' => VersionInfo::STATUS_ARCHIVED,
1811
                'versionNo' => 1,
1812
            ],
1813
            [
1814
                'status' => $versionInfo->status,
1815
                'versionNo' => $versionInfo->versionNo,
1816
            ]
1817
        );
1818
        $this->assertTrue($versionInfo->isArchived());
1819
        $this->assertFalse($versionInfo->isDraft());
1820
        $this->assertFalse($versionInfo->isPublished());
1821
    }
1822
1823
    /**
1824
     * Test for the publishVersion() method.
1825
     *
1826
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1827
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
1828
     */
1829
    public function testPublishVersionFromContentDraftUpdatesContentInfoCurrentVersion()
1830
    {
1831
        /* BEGIN: Use Case */
1832
        $contentVersion2 = $this->createContentVersion2();
1833
        /* END: Use Case */
1834
1835
        $this->assertEquals(2, $contentVersion2->contentInfo->currentVersionNo);
1836
    }
1837
1838
    /**
1839
     * Test for the publishVersion() method.
1840
     *
1841
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1842
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
1843
     */
1844 View Code Duplication
    public function testPublishVersionFromOldContentDraftArchivesNewerVersionNo()
1845
    {
1846
        /* BEGIN: Use Case */
1847
        $content = $this->createContentVersion1();
1848
1849
        // Create a new draft with versionNo = 2
1850
        $draftedContentVersion2 = $this->contentService->createContentDraft($content->contentInfo);
1851
1852
        // Create another new draft with versionNo = 3
1853
        $draftedContentVersion3 = $this->contentService->createContentDraft($content->contentInfo);
1854
1855
        // Publish draft with versionNo = 3
1856
        $this->contentService->publishVersion($draftedContentVersion3->getVersionInfo());
1857
1858
        // Publish the first draft with versionNo = 2
1859
        // currentVersionNo is now 2, versionNo 3 will be archived
1860
        $publishedDraft = $this->contentService->publishVersion($draftedContentVersion2->getVersionInfo());
1861
        /* END: Use Case */
1862
1863
        $this->assertEquals(2, $publishedDraft->contentInfo->currentVersionNo);
1864
    }
1865
1866
    /**
1867
     * Test for the publishVersion() method, and that it creates limited archives.
1868
     *
1869
     * @todo Adapt this when per content type archive limited is added on repository Content Type model.
1870
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1871
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
1872
     */
1873
    public function testPublishVersionNotCreatingUnlimitedArchives()
1874
    {
1875
        $content = $this->createContentVersion1();
1876
1877
        // load first to make sure list gets updated also (cache)
1878
        $versionInfoList = $this->contentService->loadVersions($content->contentInfo);
1879
        $this->assertEquals(1, count($versionInfoList));
1880
        $this->assertEquals(1, $versionInfoList[0]->versionNo);
1881
1882
        // Create a new draft with versionNo = 2
1883
        $draftedContentVersion = $this->contentService->createContentDraft($content->contentInfo);
1884
        $this->contentService->publishVersion($draftedContentVersion->getVersionInfo());
1885
1886
        // Create a new draft with versionNo = 3
1887
        $draftedContentVersion = $this->contentService->createContentDraft($content->contentInfo);
1888
        $this->contentService->publishVersion($draftedContentVersion->getVersionInfo());
1889
1890
        // Create a new draft with versionNo = 4
1891
        $draftedContentVersion = $this->contentService->createContentDraft($content->contentInfo);
1892
        $this->contentService->publishVersion($draftedContentVersion->getVersionInfo());
1893
1894
        // Create a new draft with versionNo = 5
1895
        $draftedContentVersion = $this->contentService->createContentDraft($content->contentInfo);
1896
        $this->contentService->publishVersion($draftedContentVersion->getVersionInfo());
1897
1898
        // Create a new draft with versionNo = 6
1899
        $draftedContentVersion = $this->contentService->createContentDraft($content->contentInfo);
1900
        $this->contentService->publishVersion($draftedContentVersion->getVersionInfo());
1901
1902
        // Create a new draft with versionNo = 7
1903
        $draftedContentVersion = $this->contentService->createContentDraft($content->contentInfo);
1904
        $this->contentService->publishVersion($draftedContentVersion->getVersionInfo());
1905
1906
        $versionInfoList = $this->contentService->loadVersions($content->contentInfo);
1907
1908
        $this->assertEquals(6, count($versionInfoList));
1909
        $this->assertEquals(2, $versionInfoList[0]->versionNo);
1910
        $this->assertEquals(7, $versionInfoList[5]->versionNo);
1911
1912
        $this->assertEquals(
1913
            [
1914
                VersionInfo::STATUS_ARCHIVED,
1915
                VersionInfo::STATUS_ARCHIVED,
1916
                VersionInfo::STATUS_ARCHIVED,
1917
                VersionInfo::STATUS_ARCHIVED,
1918
                VersionInfo::STATUS_ARCHIVED,
1919
                VersionInfo::STATUS_PUBLISHED,
1920
            ],
1921
            [
1922
                $versionInfoList[0]->status,
1923
                $versionInfoList[1]->status,
1924
                $versionInfoList[2]->status,
1925
                $versionInfoList[3]->status,
1926
                $versionInfoList[4]->status,
1927
                $versionInfoList[5]->status,
1928
            ]
1929
        );
1930
    }
1931
1932
    /**
1933
     * Test for the newContentMetadataUpdateStruct() method.
1934
     *
1935
     * @covers \eZ\Publish\API\Repository\ContentService::newContentMetadataUpdateStruct
1936
     * @group user
1937
     */
1938
    public function testNewContentMetadataUpdateStruct()
1939
    {
1940
        /* BEGIN: Use Case */
1941
        // Creates a new metadata update struct
1942
        $metadataUpdate = $this->contentService->newContentMetadataUpdateStruct();
1943
1944
        foreach ($metadataUpdate as $propertyName => $propertyValue) {
0 ignored issues
show
Bug introduced by
The expression $metadataUpdate of type object<eZ\Publish\API\Re...ntMetadataUpdateStruct> is not traversable.
Loading history...
1945
            $this->assertNull($propertyValue, "Property '{$propertyName}' initial value should be null'");
1946
        }
1947
1948
        $metadataUpdate->remoteId = 'aaaabbbbccccddddeeeeffff11112222';
1949
        $metadataUpdate->mainLanguageCode = 'eng-GB';
1950
        $metadataUpdate->alwaysAvailable = false;
1951
        /* END: Use Case */
1952
1953
        $this->assertInstanceOf(
1954
            ContentMetadataUpdateStruct::class,
1955
            $metadataUpdate
1956
        );
1957
    }
1958
1959
    /**
1960
     * Test for the updateContentMetadata() method.
1961
     *
1962
     * @return \eZ\Publish\API\Repository\Values\Content\Content
1963
     *
1964
     * @see \eZ\Publish\API\Repository\ContentService::updateContentMetadata()
1965
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
1966
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testNewContentMetadataUpdateStruct
1967
     * @group user
1968
     */
1969
    public function testUpdateContentMetadata()
1970
    {
1971
        /* BEGIN: Use Case */
1972
        $content = $this->createContentVersion1();
1973
1974
        // Creates a metadata update struct
1975
        $metadataUpdate = $this->contentService->newContentMetadataUpdateStruct();
1976
1977
        $metadataUpdate->remoteId = 'aaaabbbbccccddddeeeeffff11112222';
1978
        $metadataUpdate->mainLanguageCode = 'eng-GB';
1979
        $metadataUpdate->alwaysAvailable = false;
1980
        $metadataUpdate->publishedDate = $this->createDateTime(441759600); // 1984/01/01
1981
        $metadataUpdate->modificationDate = $this->createDateTime(441759600); // 1984/01/01
1982
1983
        // Update the metadata of the published content object
1984
        $content = $this->contentService->updateContentMetadata(
1985
            $content->contentInfo,
1986
            $metadataUpdate
1987
        );
1988
        /* END: Use Case */
1989
1990
        $this->assertInstanceOf(
1991
            Content::class,
1992
            $content
1993
        );
1994
1995
        return $content;
1996
    }
1997
1998
    /**
1999
     * Test for the updateContentMetadata() method.
2000
     *
2001
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
2002
     *
2003
     * @see \eZ\Publish\API\Repository\ContentService::updateContentMetadata()
2004
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContentMetadata
2005
     */
2006
    public function testUpdateContentMetadataSetsExpectedProperties($content)
2007
    {
2008
        $contentInfo = $content->contentInfo;
2009
2010
        $this->assertEquals(
2011
            [
2012
                'remoteId' => 'aaaabbbbccccddddeeeeffff11112222',
2013
                'sectionId' => $this->generateId('section', 1),
2014
                'alwaysAvailable' => false,
2015
                'currentVersionNo' => 1,
2016
                'mainLanguageCode' => 'eng-GB',
2017
                'modificationDate' => $this->createDateTime(441759600),
2018
                'ownerId' => $this->getRepository()->getCurrentUser()->id,
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\API\Repositor...itory::getCurrentUser() has been deprecated with message: since 6.6, to be removed. Use PermissionResolver::getCurrentUserReference() instead. Get current user. Loads the full user object if not already loaded, if you only need to know user id use {@see getCurrentUserReference()}

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

Loading history...
2019
                'published' => true,
2020
                'publishedDate' => $this->createDateTime(441759600),
2021
            ],
2022
            [
2023
                'remoteId' => $contentInfo->remoteId,
2024
                'sectionId' => $contentInfo->sectionId,
2025
                'alwaysAvailable' => $contentInfo->alwaysAvailable,
2026
                'currentVersionNo' => $contentInfo->currentVersionNo,
2027
                'mainLanguageCode' => $contentInfo->mainLanguageCode,
2028
                'modificationDate' => $contentInfo->modificationDate,
2029
                'ownerId' => $contentInfo->ownerId,
2030
                'published' => $contentInfo->published,
2031
                'publishedDate' => $contentInfo->publishedDate,
2032
            ]
2033
        );
2034
    }
2035
2036
    /**
2037
     * Test for the updateContentMetadata() method.
2038
     *
2039
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
2040
     *
2041
     * @see \eZ\Publish\API\Repository\ContentService::updateContentMetadata()
2042
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContentMetadata
2043
     */
2044
    public function testUpdateContentMetadataNotUpdatesContentVersion($content)
2045
    {
2046
        $this->assertEquals(1, $content->getVersionInfo()->versionNo);
2047
    }
2048
2049
    /**
2050
     * Test for the updateContentMetadata() method.
2051
     *
2052
     * @covers \eZ\Publish\API\Repository\ContentService::updateContentMetadata()
2053
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContentMetadata
2054
     */
2055
    public function testUpdateContentMetadataThrowsInvalidArgumentExceptionOnDuplicateRemoteId()
2056
    {
2057
        /* BEGIN: Use Case */
2058
        // RemoteId of the "Media" page of an eZ Publish demo installation
2059
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
2060
2061
        $content = $this->createContentVersion1();
2062
2063
        // Creates a metadata update struct
2064
        $metadataUpdate = $this->contentService->newContentMetadataUpdateStruct();
2065
        $metadataUpdate->remoteId = $mediaRemoteId;
2066
2067
        $this->expectException(APIInvalidArgumentException::class);
2068
        // specified remoteId is already used by the "Media" page.
2069
        $this->contentService->updateContentMetadata(
2070
            $content->contentInfo,
2071
            $metadataUpdate
2072
        );
2073
        /* END: Use Case */
2074
    }
2075
2076
    /**
2077
     * Test for the updateContentMetadata() method.
2078
     *
2079
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContentMetadata
2080
     */
2081
    public function testUpdateContentMetadataThrowsInvalidArgumentExceptionOnNoMetadataPropertiesSet()
2082
    {
2083
        $contentInfo = $this->contentService->loadContentInfo(4);
2084
        $contentMetadataUpdateStruct = $this->contentService->newContentMetadataUpdateStruct();
2085
2086
        $this->expectException(APIInvalidArgumentException::class);
2087
        $this->contentService->updateContentMetadata($contentInfo, $contentMetadataUpdateStruct);
2088
    }
2089
2090
    /**
2091
     * Test for the deleteContent() method.
2092
     *
2093
     * @see \eZ\Publish\API\Repository\ContentService::deleteContent()
2094
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
2095
     */
2096 View Code Duplication
    public function testDeleteContent()
2097
    {
2098
        /* BEGIN: Use Case */
2099
        $contentVersion2 = $this->createContentVersion2();
2100
2101
        // Load the locations for this content object
2102
        $locations = $this->locationService->loadLocations($contentVersion2->contentInfo);
2103
2104
        // This will delete the content, all versions and the associated locations
2105
        $this->contentService->deleteContent($contentVersion2->contentInfo);
2106
        /* END: Use Case */
2107
2108
        $this->expectException(NotFoundException::class);
2109
2110
        foreach ($locations as $location) {
2111
            $this->locationService->loadLocation($location->id);
2112
        }
2113
    }
2114
2115
    /**
2116
     * Test for the deleteContent() method.
2117
     *
2118
     * Test for issue EZP-21057:
2119
     * "contentService: Unable to delete a content with an empty file attribute"
2120
     *
2121
     * @see \eZ\Publish\API\Repository\ContentService::deleteContent()
2122
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
2123
     */
2124 View Code Duplication
    public function testDeleteContentWithEmptyBinaryField()
2125
    {
2126
        /* BEGIN: Use Case */
2127
        $contentVersion = $this->createContentVersion1EmptyBinaryField();
2128
2129
        // Load the locations for this content object
2130
        $locations = $this->locationService->loadLocations($contentVersion->contentInfo);
2131
2132
        // This will delete the content, all versions and the associated locations
2133
        $this->contentService->deleteContent($contentVersion->contentInfo);
2134
        /* END: Use Case */
2135
2136
        $this->expectException(NotFoundException::class);
2137
2138
        foreach ($locations as $location) {
2139
            $this->locationService->loadLocation($location->id);
2140
        }
2141
    }
2142
2143
    /**
2144
     * Test for the loadContentDrafts() method.
2145
     *
2146
     * @see \eZ\Publish\API\Repository\ContentService::loadContentDrafts()
2147
     */
2148
    public function testLoadContentDraftsReturnsEmptyArrayByDefault()
2149
    {
2150
        /* BEGIN: Use Case */
2151
        $contentDrafts = $this->contentService->loadContentDrafts();
2152
        /* END: Use Case */
2153
2154
        $this->assertSame([], $contentDrafts);
2155
    }
2156
2157
    /**
2158
     * Test for the loadContentDrafts() method.
2159
     *
2160
     * @see \eZ\Publish\API\Repository\ContentService::loadContentDrafts()
2161
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
2162
     */
2163
    public function testLoadContentDrafts()
2164
    {
2165
        /* BEGIN: Use Case */
2166
        // Remote ids of the "Media" and the "eZ Publish Demo Design ..." page
2167
        // of a eZ Publish demo installation.
2168
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
2169
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
2170
2171
        // "Media" content object
2172
        $mediaContentInfo = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
2173
2174
        // "eZ Publish Demo Design ..." content object
2175
        $demoDesignContentInfo = $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId);
2176
2177
        // Create some drafts
2178
        $this->contentService->createContentDraft($mediaContentInfo);
2179
        $this->contentService->createContentDraft($demoDesignContentInfo);
2180
2181
        // Now $contentDrafts should contain two drafted versions
2182
        $draftedVersions = $this->contentService->loadContentDrafts();
2183
        /* END: Use Case */
2184
2185
        $actual = [
2186
            $draftedVersions[0]->status,
2187
            $draftedVersions[0]->getContentInfo()->remoteId,
2188
            $draftedVersions[1]->status,
2189
            $draftedVersions[1]->getContentInfo()->remoteId,
2190
        ];
2191
        sort($actual, SORT_STRING);
2192
2193
        $this->assertEquals(
2194
            [
2195
                VersionInfo::STATUS_DRAFT,
2196
                VersionInfo::STATUS_DRAFT,
2197
                $demoDesignRemoteId,
2198
                $mediaRemoteId,
2199
            ],
2200
            $actual
2201
        );
2202
    }
2203
2204
    /**
2205
     * Test for the loadContentDrafts() method.
2206
     *
2207
     * @see \eZ\Publish\API\Repository\ContentService::loadContentDrafts($user)
2208
     */
2209
    public function testLoadContentDraftsWithFirstParameter()
2210
    {
2211
        /* BEGIN: Use Case */
2212
        $user = $this->createUserVersion1();
2213
2214
        // Get current user
2215
        $oldCurrentUser = $this->permissionResolver->getCurrentUserReference();
2216
2217
        // Set new editor as user
2218
        $this->permissionResolver->setCurrentUserReference($user);
2219
2220
        // Remote id of the "Media" content object in an eZ Publish demo installation.
2221
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
2222
2223
        // "Media" content object
2224
        $mediaContentInfo = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
2225
2226
        // Create a content draft
2227
        $this->contentService->createContentDraft($mediaContentInfo);
2228
2229
        // Reset to previous current user
2230
        $this->permissionResolver->setCurrentUserReference($oldCurrentUser);
2231
2232
        // Now $contentDrafts for the previous current user and the new user
2233
        $newCurrentUserDrafts = $this->contentService->loadContentDrafts($user);
2234
        $oldCurrentUserDrafts = $this->contentService->loadContentDrafts();
2235
        /* END: Use Case */
2236
2237
        $this->assertSame([], $oldCurrentUserDrafts);
2238
2239
        $this->assertEquals(
2240
            [
2241
                VersionInfo::STATUS_DRAFT,
2242
                $mediaRemoteId,
2243
            ],
2244
            [
2245
                $newCurrentUserDrafts[0]->status,
2246
                $newCurrentUserDrafts[0]->getContentInfo()->remoteId,
2247
            ]
2248
        );
2249
        $this->assertTrue($newCurrentUserDrafts[0]->isDraft());
2250
        $this->assertFalse($newCurrentUserDrafts[0]->isArchived());
2251
        $this->assertFalse($newCurrentUserDrafts[0]->isPublished());
2252
    }
2253
2254
    /**
2255
     * Test for the loadVersionInfo() method.
2256
     *
2257
     * @see \eZ\Publish\API\Repository\ContentService::loadVersionInfo($contentInfo, $versionNo)
2258
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
2259
     */
2260 View Code Duplication
    public function testLoadVersionInfoWithSecondParameter()
2261
    {
2262
        /* BEGIN: Use Case */
2263
        $publishedContent = $this->createContentVersion1();
2264
2265
        $draftContent = $this->contentService->createContentDraft($publishedContent->contentInfo);
0 ignored issues
show
Unused Code introduced by
$draftContent 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...
2266
2267
        // Will return the VersionInfo of the $draftContent
2268
        $versionInfo = $this->contentService->loadVersionInfoById($publishedContent->id, 2);
2269
        /* END: Use Case */
2270
2271
        $this->assertEquals(2, $versionInfo->versionNo);
2272
2273
        // Check that ContentInfo contained in VersionInfo has correct main Location id set
2274
        $this->assertEquals(
2275
            $publishedContent->getVersionInfo()->getContentInfo()->mainLocationId,
2276
            $versionInfo->getContentInfo()->mainLocationId
2277
        );
2278
    }
2279
2280
    /**
2281
     * Test for the loadVersionInfo() method.
2282
     *
2283
     * @see \eZ\Publish\API\Repository\ContentService::loadVersionInfo($contentInfo, $versionNo)
2284
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfoWithSecondParameter
2285
     */
2286
    public function testLoadVersionInfoThrowsNotFoundExceptionWithSecondParameter()
2287
    {
2288
        /* BEGIN: Use Case */
2289
        $draft = $this->createContentDraftVersion1();
2290
2291
        $this->expectException(NotFoundException::class);
2292
2293
        // This call will fail with a "NotFoundException", because not versionNo 2 exists for this content object.
2294
        $this->contentService->loadVersionInfo($draft->contentInfo, 2);
2295
        /* END: Use Case */
2296
    }
2297
2298
    /**
2299
     * Test for the loadVersionInfoById() method.
2300
     *
2301
     * @see \eZ\Publish\API\Repository\ContentService::loadVersionInfoById($contentId, $versionNo)
2302
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfoWithSecondParameter
2303
     */
2304
    public function testLoadVersionInfoByIdWithSecondParameter()
2305
    {
2306
        /* BEGIN: Use Case */
2307
        $publishedContent = $this->createContentVersion1();
2308
2309
        $draftContent = $this->contentService->createContentDraft($publishedContent->contentInfo);
2310
2311
        // Will return the VersionInfo of the $draftContent
2312
        $versionInfo = $this->contentService->loadVersionInfoById($publishedContent->id, 2);
2313
        /* END: Use Case */
2314
2315
        $this->assertEquals(2, $versionInfo->versionNo);
2316
2317
        // Check that ContentInfo contained in VersionInfo has correct main Location id set
2318
        $this->assertEquals(
2319
            $publishedContent->getVersionInfo()->getContentInfo()->mainLocationId,
2320
            $versionInfo->getContentInfo()->mainLocationId
2321
        );
2322
2323
        return [
2324
            'versionInfo' => $versionInfo,
2325
            'draftContent' => $draftContent,
2326
        ];
2327
    }
2328
2329
    /**
2330
     * Test for the returned value of the loadVersionInfoById() method.
2331
     *
2332
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfoByIdWithSecondParameter
2333
     * @covers \eZ\Publish\API\Repository\ContentService::loadVersionInfoById
2334
     *
2335
     * @param array $data
2336
     */
2337
    public function testLoadVersionInfoByIdWithSecondParameterSetsExpectedVersionInfo(array $data)
2338
    {
2339
        /** @var VersionInfo $versionInfo */
2340
        $versionInfo = $data['versionInfo'];
2341
        /** @var \eZ\Publish\API\Repository\Values\Content\Content $draftContent */
2342
        $draftContent = $data['draftContent'];
2343
2344
        $this->assertPropertiesCorrect(
2345
            [
2346
                'names' => [
2347
                    'eng-US' => 'An awesome forum',
2348
                ],
2349
                'contentInfo' => new ContentInfo([
2350
                    'id' => $draftContent->contentInfo->id,
2351
                    'contentTypeId' => 28,
2352
                    'name' => 'An awesome forum',
2353
                    'sectionId' => 1,
2354
                    'currentVersionNo' => 1,
2355
                    'published' => true,
2356
                    'ownerId' => 14,
2357
                    // this Content Object is created at the test runtime
2358
                    'modificationDate' => $versionInfo->contentInfo->modificationDate,
2359
                    'publishedDate' => $versionInfo->contentInfo->publishedDate,
2360
                    'alwaysAvailable' => 1,
2361
                    'remoteId' => 'abcdef0123456789abcdef0123456789',
2362
                    'mainLanguageCode' => 'eng-US',
2363
                    'mainLocationId' => $draftContent->contentInfo->mainLocationId,
2364
                    'status' => ContentInfo::STATUS_PUBLISHED,
2365
                ]),
2366
                'id' => $draftContent->versionInfo->id,
2367
                'versionNo' => 2,
2368
                'creatorId' => 14,
2369
                'status' => 0,
2370
                'initialLanguageCode' => 'eng-US',
2371
                'languageCodes' => [
2372
                    'eng-US',
2373
                ],
2374
            ],
2375
            $versionInfo
2376
        );
2377
    }
2378
2379
    /**
2380
     * Test for the loadVersionInfoById() method.
2381
     *
2382
     * @see \eZ\Publish\API\Repository\ContentService::loadVersionInfoById($contentId, $versionNo)
2383
     */
2384
    public function testLoadVersionInfoByIdThrowsNotFoundExceptionWithSecondParameter()
2385
    {
2386
        /* BEGIN: Use Case */
2387
        $content = $this->createContentVersion1();
2388
2389
        $this->expectException(NotFoundException::class);
2390
2391
        // This call will fail with a "NotFoundException", because not versionNo 2 exists for this content object.
2392
        $this->contentService->loadVersionInfoById($content->id, 2);
2393
        /* END: Use Case */
2394
    }
2395
2396
    /**
2397
     * Test for the loadContentByVersionInfo() method.
2398
     *
2399
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByVersionInfo($versionInfo, $languages)
2400
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
2401
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByVersionInfo
2402
     */
2403
    public function testLoadContentByVersionInfoWithSecondParameter()
2404
    {
2405
        $sectionId = $this->generateId('section', 1);
2406
        /* BEGIN: Use Case */
2407
        $contentTypeService = $this->getRepository()->getContentTypeService();
2408
2409
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
2410
2411
        $contentCreateStruct = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
2412
2413
        $contentCreateStruct->setField('name', 'Sindelfingen forum²');
2414
2415
        $contentCreateStruct->setField('name', 'Sindelfingen forum²³', 'eng-GB');
2416
2417
        $contentCreateStruct->remoteId = 'abcdef0123456789abcdef0123456789';
2418
        // $sectionId contains the ID of section 1
2419
        $contentCreateStruct->sectionId = $sectionId;
2420
        $contentCreateStruct->alwaysAvailable = true;
2421
2422
        // Create a new content draft
2423
        $content = $this->contentService->createContent($contentCreateStruct);
2424
2425
        // Now publish this draft
2426
        $publishedContent = $this->contentService->publishVersion($content->getVersionInfo());
2427
2428
        // Will return a content instance with fields in "eng-US"
2429
        $reloadedContent = $this->contentService->loadContentByVersionInfo(
2430
            $publishedContent->getVersionInfo(),
2431
            [
2432
                'eng-GB',
2433
            ],
2434
            false
2435
        );
2436
        /* END: Use Case */
2437
2438
        $actual = [];
2439
        foreach ($reloadedContent->getFields() as $field) {
2440
            $actual[] = new Field(
2441
                [
2442
                    'id' => 0,
2443
                    'value' => ($field->value !== null ? true : null), // Actual value tested by FieldType integration tests
2444
                    'languageCode' => $field->languageCode,
2445
                    'fieldDefIdentifier' => $field->fieldDefIdentifier,
2446
                ]
2447
            );
2448
        }
2449
        usort(
2450
            $actual,
2451 View Code Duplication
            function ($field1, $field2) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2452
                if (0 === ($return = strcasecmp($field1->fieldDefIdentifier, $field2->fieldDefIdentifier))) {
2453
                    return strcasecmp($field1->languageCode, $field2->languageCode);
2454
                }
2455
2456
                return $return;
2457
            }
2458
        );
2459
2460
        $expected = [
2461
            new Field(
2462
                [
2463
                    'id' => 0,
2464
                    'value' => true,
2465
                    'languageCode' => 'eng-GB',
2466
                    'fieldDefIdentifier' => 'description',
2467
                ]
2468
            ),
2469
            new Field(
2470
                [
2471
                    'id' => 0,
2472
                    'value' => true,
2473
                    'languageCode' => 'eng-GB',
2474
                    'fieldDefIdentifier' => 'name',
2475
                ]
2476
            ),
2477
        ];
2478
2479
        $this->assertEquals($expected, $actual);
2480
    }
2481
2482
    /**
2483
     * Test for the loadContentByContentInfo() method.
2484
     *
2485
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByContentInfo($contentInfo, $languages)
2486
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByContentInfo
2487
     */
2488
    public function testLoadContentByContentInfoWithLanguageParameters()
2489
    {
2490
        $sectionId = $this->generateId('section', 1);
2491
        /* BEGIN: Use Case */
2492
        $contentTypeService = $this->getRepository()->getContentTypeService();
2493
2494
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
2495
2496
        $contentCreateStruct = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
2497
2498
        $contentCreateStruct->setField('name', 'Sindelfingen forum²');
2499
2500
        $contentCreateStruct->setField('name', 'Sindelfingen forum²³', 'eng-GB');
2501
2502
        $contentCreateStruct->remoteId = 'abcdef0123456789abcdef0123456789';
2503
        // $sectionId contains the ID of section 1
2504
        $contentCreateStruct->sectionId = $sectionId;
2505
        $contentCreateStruct->alwaysAvailable = true;
2506
2507
        // Create a new content draft
2508
        $content = $this->contentService->createContent($contentCreateStruct);
2509
2510
        // Now publish this draft
2511
        $publishedContent = $this->contentService->publishVersion($content->getVersionInfo());
2512
2513
        // Will return a content instance with fields in "eng-US"
2514
        $reloadedContent = $this->contentService->loadContentByContentInfo(
2515
            $publishedContent->contentInfo,
2516
            [
2517
                'eng-US',
2518
            ],
2519
            null,
2520
            false
2521
        );
2522
        /* END: Use Case */
2523
2524
        $actual = $this->normalizeFields($reloadedContent->getFields());
2525
2526
        $expected = [
2527
            new Field(
2528
                [
2529
                    'id' => 0,
2530
                    'value' => true,
2531
                    'languageCode' => 'eng-US',
2532
                    'fieldDefIdentifier' => 'description',
2533
                    'fieldTypeIdentifier' => 'ezrichtext',
2534
                ]
2535
            ),
2536
            new Field(
2537
                [
2538
                    'id' => 0,
2539
                    'value' => true,
2540
                    'languageCode' => 'eng-US',
2541
                    'fieldDefIdentifier' => 'name',
2542
                    'fieldTypeIdentifier' => 'ezstring',
2543
                ]
2544
            ),
2545
        ];
2546
2547
        $this->assertEquals($expected, $actual);
2548
2549
        // Will return a content instance with fields in "eng-GB" (versions prior to 6.0.0-beta9 returned "eng-US" also)
2550
        $reloadedContent = $this->contentService->loadContentByContentInfo(
2551
            $publishedContent->contentInfo,
2552
            [
2553
                'eng-GB',
2554
            ],
2555
            null,
2556
            true
2557
        );
2558
2559
        $actual = $this->normalizeFields($reloadedContent->getFields());
2560
2561
        $expected = [
2562
            new Field(
2563
                [
2564
                    'id' => 0,
2565
                    'value' => true,
2566
                    'languageCode' => 'eng-GB',
2567
                    'fieldDefIdentifier' => 'description',
2568
                    'fieldTypeIdentifier' => 'ezrichtext',
2569
                ]
2570
            ),
2571
            new Field(
2572
                [
2573
                    'id' => 0,
2574
                    'value' => true,
2575
                    'languageCode' => 'eng-GB',
2576
                    'fieldDefIdentifier' => 'name',
2577
                    'fieldTypeIdentifier' => 'ezstring',
2578
                ]
2579
            ),
2580
        ];
2581
2582
        $this->assertEquals($expected, $actual);
2583
2584
        // Will return a content instance with fields in main language "eng-US", as "fre-FR" does not exists
2585
        $reloadedContent = $this->contentService->loadContentByContentInfo(
2586
            $publishedContent->contentInfo,
2587
            [
2588
                'fre-FR',
2589
            ],
2590
            null,
2591
            true
2592
        );
2593
2594
        $actual = $this->normalizeFields($reloadedContent->getFields());
2595
2596
        $expected = [
2597
            new Field(
2598
                [
2599
                    'id' => 0,
2600
                    'value' => true,
2601
                    'languageCode' => 'eng-US',
2602
                    'fieldDefIdentifier' => 'description',
2603
                    'fieldTypeIdentifier' => 'ezrichtext',
2604
                ]
2605
            ),
2606
            new Field(
2607
                [
2608
                    'id' => 0,
2609
                    'value' => true,
2610
                    'languageCode' => 'eng-US',
2611
                    'fieldDefIdentifier' => 'name',
2612
                    'fieldTypeIdentifier' => 'ezstring',
2613
                ]
2614
            ),
2615
        ];
2616
2617
        $this->assertEquals($expected, $actual);
2618
    }
2619
2620
    /**
2621
     * Test for the loadContentByContentInfo() method.
2622
     *
2623
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByContentInfo($contentInfo, $languages, $versionNo)
2624
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByContentInfo
2625
     */
2626 View Code Duplication
    public function testLoadContentByContentInfoWithVersionNumberParameter()
2627
    {
2628
        /* BEGIN: Use Case */
2629
        $publishedContent = $this->createContentVersion1();
2630
2631
        $draftContent = $this->contentService->createContentDraft($publishedContent->contentInfo);
0 ignored issues
show
Unused Code introduced by
$draftContent 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...
2632
2633
        // This content instance is identical to $draftContent
2634
        $draftContentReloaded = $this->contentService->loadContentByContentInfo(
2635
            $publishedContent->contentInfo,
2636
            null,
2637
            2
2638
        );
2639
        /* END: Use Case */
2640
2641
        $this->assertEquals(
2642
            2,
2643
            $draftContentReloaded->getVersionInfo()->versionNo
2644
        );
2645
2646
        // Check that ContentInfo contained in reloaded draft Content has correct main Location id set
2647
        $this->assertEquals(
2648
            $publishedContent->versionInfo->contentInfo->mainLocationId,
2649
            $draftContentReloaded->versionInfo->contentInfo->mainLocationId
2650
        );
2651
    }
2652
2653
    /**
2654
     * Test for the loadContentByContentInfo() method.
2655
     *
2656
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByContentInfo($contentInfo, $languages, $versionNo)
2657
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByContentInfoWithVersionNumberParameter
2658
     */
2659
    public function testLoadContentByContentInfoThrowsNotFoundExceptionWithVersionNumberParameter()
2660
    {
2661
        /* BEGIN: Use Case */
2662
        $content = $this->createContentVersion1();
2663
2664
        $this->expectException(NotFoundException::class);
2665
2666
        // This call will fail with a "NotFoundException", because no content with versionNo = 2 exists.
2667
        $this->contentService->loadContentByContentInfo($content->contentInfo, null, 2);
2668
        /* END: Use Case */
2669
    }
2670
2671
    /**
2672
     * Test for the loadContent() method.
2673
     *
2674
     * @see \eZ\Publish\API\Repository\ContentService::loadContent($contentId, $languages)
2675
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
2676
     */
2677
    public function testLoadContentWithSecondParameter()
2678
    {
2679
        /* BEGIN: Use Case */
2680
        $draft = $this->createMultipleLanguageDraftVersion1();
2681
2682
        // This draft contains those fields localized with "eng-GB"
2683
        $draftLocalized = $this->contentService->loadContent($draft->id, ['eng-GB'], null, false);
2684
        /* END: Use Case */
2685
2686
        $this->assertLocaleFieldsEquals($draftLocalized->getFields(), 'eng-GB');
2687
2688
        return $draft;
2689
    }
2690
2691
    /**
2692
     * Test for the loadContent() method using undefined translation.
2693
     *
2694
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentWithSecondParameter
2695
     *
2696
     * @param \eZ\Publish\API\Repository\Values\Content\Content $contentDraft
2697
     */
2698
    public function testLoadContentWithSecondParameterThrowsNotFoundException(Content $contentDraft)
2699
    {
2700
        $this->expectException(NotFoundException::class);
2701
2702
        $this->contentService->loadContent($contentDraft->id, ['ger-DE'], null, false);
2703
    }
2704
2705
    /**
2706
     * Test for the loadContent() method.
2707
     *
2708
     * @see \eZ\Publish\API\Repository\ContentService::loadContent($contentId, $languages, $versionNo)
2709
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
2710
     */
2711 View Code Duplication
    public function testLoadContentWithThirdParameter()
2712
    {
2713
        /* BEGIN: Use Case */
2714
        $publishedContent = $this->createContentVersion1();
2715
2716
        $this->contentService->createContentDraft($publishedContent->contentInfo);
2717
2718
        // This content instance is identical to $draftContent
2719
        $draftContentReloaded = $this->contentService->loadContent($publishedContent->id, null, 2);
2720
        /* END: Use Case */
2721
2722
        $this->assertEquals(2, $draftContentReloaded->getVersionInfo()->versionNo);
2723
2724
        // Check that ContentInfo contained in reloaded draft Content has correct main Location id set
2725
        $this->assertEquals(
2726
            $publishedContent->versionInfo->contentInfo->mainLocationId,
2727
            $draftContentReloaded->versionInfo->contentInfo->mainLocationId
2728
        );
2729
    }
2730
2731
    /**
2732
     * Test for the loadContent() method.
2733
     *
2734
     * @see \eZ\Publish\API\Repository\ContentService::loadContent($contentId, $languages, $versionNo)
2735
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentWithThirdParameter
2736
     */
2737
    public function testLoadContentThrowsNotFoundExceptionWithThirdParameter()
2738
    {
2739
        /* BEGIN: Use Case */
2740
        $content = $this->createContentVersion1();
2741
2742
        $this->expectException(NotFoundException::class);
2743
2744
        // This call will fail with a "NotFoundException", because for this content object no versionNo=2 exists.
2745
        $this->contentService->loadContent($content->id, null, 2);
2746
        /* END: Use Case */
2747
    }
2748
2749
    /**
2750
     * Test for the loadContentByRemoteId() method.
2751
     *
2752
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByRemoteId($remoteId, $languages)
2753
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
2754
     */
2755
    public function testLoadContentByRemoteIdWithSecondParameter()
2756
    {
2757
        /* BEGIN: Use Case */
2758
        $draft = $this->createMultipleLanguageDraftVersion1();
2759
2760
        $this->contentService->publishVersion($draft->versionInfo);
2761
2762
        // This draft contains those fields localized with "eng-GB"
2763
        $draftLocalized = $this->contentService->loadContentByRemoteId(
2764
            $draft->contentInfo->remoteId,
2765
            ['eng-GB'],
2766
            null,
2767
            false
2768
        );
2769
        /* END: Use Case */
2770
2771
        $this->assertLocaleFieldsEquals($draftLocalized->getFields(), 'eng-GB');
2772
    }
2773
2774
    /**
2775
     * Test for the loadContentByRemoteId() method.
2776
     *
2777
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByRemoteId($remoteId, $languages, $versionNo)
2778
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
2779
     */
2780 View Code Duplication
    public function testLoadContentByRemoteIdWithThirdParameter()
2781
    {
2782
        /* BEGIN: Use Case */
2783
        $publishedContent = $this->createContentVersion1();
2784
2785
        $this->contentService->createContentDraft($publishedContent->contentInfo);
2786
2787
        // This content instance is identical to $draftContent
2788
        $draftContentReloaded = $this->contentService->loadContentByRemoteId(
2789
            $publishedContent->contentInfo->remoteId,
2790
            null,
2791
            2
2792
        );
2793
        /* END: Use Case */
2794
2795
        $this->assertEquals(2, $draftContentReloaded->getVersionInfo()->versionNo);
2796
2797
        // Check that ContentInfo contained in reloaded draft Content has correct main Location id set
2798
        $this->assertEquals(
2799
            $publishedContent->versionInfo->contentInfo->mainLocationId,
2800
            $draftContentReloaded->versionInfo->contentInfo->mainLocationId
2801
        );
2802
    }
2803
2804
    /**
2805
     * Test for the loadContentByRemoteId() method.
2806
     *
2807
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByRemoteId($remoteId, $languages, $versionNo)
2808
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByRemoteIdWithThirdParameter
2809
     */
2810
    public function testLoadContentByRemoteIdThrowsNotFoundExceptionWithThirdParameter()
2811
    {
2812
        /* BEGIN: Use Case */
2813
        $content = $this->createContentVersion1();
2814
2815
        $this->expectException(NotFoundException::class);
2816
2817
        // This call will fail with a "NotFoundException", because for this content object no versionNo=2 exists.
2818
        $this->contentService->loadContentByRemoteId(
2819
            $content->contentInfo->remoteId,
2820
            null,
2821
            2
2822
        );
2823
        /* END: Use Case */
2824
    }
2825
2826
    /**
2827
     * Test that retrieval of translated name field respects prioritized language list.
2828
     *
2829
     * @dataProvider getPrioritizedLanguageList
2830
     * @param string[]|null $languageCodes
2831
     */
2832
    public function testLoadContentWithPrioritizedLanguagesList($languageCodes)
2833
    {
2834
        $content = $this->createContentVersion2();
2835
2836
        $content = $this->contentService->loadContent($content->id, $languageCodes);
2837
2838
        $expectedName = $content->getVersionInfo()->getName(
2839
            isset($languageCodes[0]) ? $languageCodes[0] : null
2840
        );
2841
        $nameValue = $content->getFieldValue('name');
2842
        /** @var \eZ\Publish\Core\FieldType\TextLine\Value $nameValue */
2843
        self::assertEquals($expectedName, $nameValue->text);
2844
        self::assertEquals($expectedName, $content->getVersionInfo()->getName());
2845
        // Also check value on shortcut method on content
2846
        self::assertEquals($expectedName, $content->getName());
2847
    }
2848
2849
    /**
2850
     * @return array
2851
     */
2852
    public function getPrioritizedLanguageList()
2853
    {
2854
        return [
2855
            [['eng-US']],
2856
            [['eng-GB']],
2857
            [['eng-GB', 'eng-US']],
2858
            [['eng-US', 'eng-GB']],
2859
        ];
2860
    }
2861
2862
    /**
2863
     * Test for the deleteVersion() method.
2864
     *
2865
     * @see \eZ\Publish\API\Repository\ContentService::deleteVersion()
2866
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
2867
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
2868
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
2869
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
2870
     */
2871
    public function testDeleteVersion()
2872
    {
2873
        /* BEGIN: Use Case */
2874
        $content = $this->createContentVersion1();
2875
2876
        // Create new draft, because published or last version of the Content can't be deleted
2877
        $draft = $this->contentService->createContentDraft(
2878
            $content->getVersionInfo()->getContentInfo()
2879
        );
2880
2881
        // Delete the previously created draft
2882
        $this->contentService->deleteVersion($draft->getVersionInfo());
2883
        /* END: Use Case */
2884
2885
        $versions = $this->contentService->loadVersions($content->getVersionInfo()->getContentInfo());
2886
2887
        $this->assertCount(1, $versions);
2888
        $this->assertEquals(
2889
            $content->getVersionInfo()->id,
2890
            $versions[0]->id
2891
        );
2892
    }
2893
2894
    /**
2895
     * Test for the deleteVersion() method.
2896
     *
2897
     * @see \eZ\Publish\API\Repository\ContentService::deleteVersion()
2898
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
2899
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
2900
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
2901
     */
2902
    public function testDeleteVersionThrowsBadStateExceptionOnPublishedVersion()
2903
    {
2904
        /* BEGIN: Use Case */
2905
        $content = $this->createContentVersion1();
2906
2907
        $this->expectException(BadStateException::class);
2908
2909
        // This call will fail with a "BadStateException", because the content version is currently published.
2910
        $this->contentService->deleteVersion($content->getVersionInfo());
2911
        /* END: Use Case */
2912
    }
2913
2914
    /**
2915
     * Test for the deleteVersion() method.
2916
     *
2917
     * @see \eZ\Publish\API\Repository\ContentService::deleteVersion()
2918
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
2919
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
2920
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
2921
     */
2922
    public function testDeleteVersionWorksIfOnlyVersionIsDraft()
2923
    {
2924
        /* BEGIN: Use Case */
2925
        $draft = $this->createContentDraftVersion1();
2926
2927
        $this->contentService->deleteVersion($draft->getVersionInfo());
2928
2929
        $this->expectException(NotFoundException::class);
2930
2931
        // This call will fail with a "NotFound", because we allow to delete content if remaining version is draft.
2932
        // Can normally only happen if there where always only a draft to begin with, simplifies UI edit API usage.
2933
        $this->contentService->loadContent($draft->id);
2934
        /* END: Use Case */
2935
    }
2936
2937
    /**
2938
     * Test for the loadVersions() method.
2939
     *
2940
     * @see \eZ\Publish\API\Repository\ContentService::loadVersions()
2941
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
2942
     *
2943
     * @return VersionInfo[]
2944
     */
2945
    public function testLoadVersions()
2946
    {
2947
        /* BEGIN: Use Case */
2948
        $contentVersion2 = $this->createContentVersion2();
2949
2950
        // Load versions of this ContentInfo instance
2951
        $versions = $this->contentService->loadVersions($contentVersion2->contentInfo);
2952
        /* END: Use Case */
2953
2954
        $expectedVersionsOrder = [
2955
            $this->contentService->loadVersionInfo($contentVersion2->contentInfo, 1),
2956
            $this->contentService->loadVersionInfo($contentVersion2->contentInfo, 2),
2957
        ];
2958
2959
        $this->assertEquals($expectedVersionsOrder, $versions);
2960
2961
        return $versions;
2962
    }
2963
2964
    /**
2965
     * Test for the loadVersions() method.
2966
     *
2967
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersions
2968
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersions
2969
     *
2970
     * @param VersionInfo[] $versions
2971
     */
2972
    public function testLoadVersionsSetsExpectedVersionInfo(array $versions)
2973
    {
2974
        $this->assertCount(2, $versions);
2975
2976
        $expectedVersions = [
2977
            [
2978
                'versionNo' => 1,
2979
                'creatorId' => 14,
2980
                'status' => VersionInfo::STATUS_ARCHIVED,
2981
                'initialLanguageCode' => 'eng-US',
2982
                'languageCodes' => ['eng-US'],
2983
            ],
2984
            [
2985
                'versionNo' => 2,
2986
                'creatorId' => 10,
2987
                'status' => VersionInfo::STATUS_PUBLISHED,
2988
                'initialLanguageCode' => 'eng-US',
2989
                'languageCodes' => ['eng-US', 'eng-GB'],
2990
            ],
2991
        ];
2992
2993
        $this->assertPropertiesCorrect($expectedVersions[0], $versions[0]);
2994
        $this->assertPropertiesCorrect($expectedVersions[1], $versions[1]);
2995
        $this->assertEquals(
2996
            $versions[0]->creationDate->getTimestamp(),
2997
            $versions[1]->creationDate->getTimestamp(),
2998
            'Creation time did not match within delta of 2 seconds',
2999
            2
3000
        );
3001
        $this->assertEquals(
3002
            $versions[0]->modificationDate->getTimestamp(),
3003
            $versions[1]->modificationDate->getTimestamp(),
3004
            'Creation time did not match within delta of 2 seconds',
3005
            2
3006
        );
3007
        $this->assertTrue($versions[0]->isArchived());
3008
        $this->assertFalse($versions[0]->isDraft());
3009
        $this->assertFalse($versions[0]->isPublished());
3010
3011
        $this->assertTrue($versions[1]->isPublished());
3012
        $this->assertFalse($versions[1]->isDraft());
3013
        $this->assertFalse($versions[1]->isArchived());
3014
    }
3015
3016
    /**
3017
     * Test for the copyContent() method.
3018
     *
3019
     * @see \eZ\Publish\API\Repository\ContentService::copyContent()
3020
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
3021
     * @group field-type
3022
     */
3023 View Code Duplication
    public function testCopyContent()
3024
    {
3025
        $parentLocationId = $this->generateId('location', 56);
3026
3027
        /* BEGIN: Use Case */
3028
        $contentVersion2 = $this->createMultipleLanguageContentVersion2();
3029
3030
        // Configure new target location
3031
        $targetLocationCreate = $this->locationService->newLocationCreateStruct($parentLocationId);
3032
3033
        $targetLocationCreate->priority = 42;
3034
        $targetLocationCreate->hidden = true;
3035
        $targetLocationCreate->remoteId = '01234abcdef5678901234abcdef56789';
3036
        $targetLocationCreate->sortField = Location::SORT_FIELD_NODE_ID;
3037
        $targetLocationCreate->sortOrder = Location::SORT_ORDER_DESC;
3038
3039
        // Copy content with all versions and drafts
3040
        $contentCopied = $this->contentService->copyContent(
3041
            $contentVersion2->contentInfo,
3042
            $targetLocationCreate
3043
        );
3044
        /* END: Use Case */
3045
3046
        $this->assertInstanceOf(
3047
            Content::class,
3048
            $contentCopied
3049
        );
3050
3051
        $this->assertNotEquals(
3052
            $contentVersion2->contentInfo->remoteId,
3053
            $contentCopied->contentInfo->remoteId
3054
        );
3055
3056
        $this->assertNotEquals(
3057
            $contentVersion2->id,
3058
            $contentCopied->id
3059
        );
3060
3061
        $this->assertEquals(
3062
            2,
3063
            count($this->contentService->loadVersions($contentCopied->contentInfo))
3064
        );
3065
3066
        $this->assertEquals(2, $contentCopied->getVersionInfo()->versionNo);
3067
3068
        $this->assertAllFieldsEquals($contentCopied->getFields());
3069
3070
        $this->assertDefaultContentStates($contentCopied->contentInfo);
3071
3072
        $this->assertNotNull(
3073
            $contentCopied->contentInfo->mainLocationId,
3074
            'Expected main location to be set given we provided a LocationCreateStruct'
3075
        );
3076
    }
3077
3078
    /**
3079
     * Test for the copyContent() method with ezsettings.default.content.retain_owner_on_copy set to false
3080
     * See settings/test/integration_legacy.yml for service override.
3081
     *
3082
     * @see \eZ\Publish\API\Repository\ContentService::copyContent()
3083
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
3084
     * @group field-type
3085
     */
3086
    public function testCopyContentWithNewOwner()
3087
    {
3088
        $parentLocationId = $this->generateId('location', 56);
3089
3090
        $userService = $this->getRepository()->getUserService();
3091
3092
        $newOwner = $this->createUser('new_owner', 'foo', 'bar');
3093
        /* BEGIN: Use Case */
3094
        /** @var \eZ\Publish\API\Repository\Values\Content\Content $contentVersion2 */
3095
        $contentVersion2 = $this->createContentDraftVersion1(
3096
            $parentLocationId,
3097
            'forum',
3098
            'name',
3099
            $newOwner
3100
        );
3101
3102
        // Configure new target location
3103
        $targetLocationCreate = $this->locationService->newLocationCreateStruct($parentLocationId);
3104
3105
        $targetLocationCreate->priority = 42;
3106
        $targetLocationCreate->hidden = true;
3107
        $targetLocationCreate->remoteId = '01234abcdef5678901234abcdef56789';
3108
        $targetLocationCreate->sortField = Location::SORT_FIELD_NODE_ID;
3109
        $targetLocationCreate->sortOrder = Location::SORT_ORDER_DESC;
3110
3111
        // Copy content with all versions and drafts
3112
        $contentCopied = $this->contentService->copyContent(
3113
            $contentVersion2->contentInfo,
3114
            $targetLocationCreate
3115
        );
3116
        /* END: Use Case */
3117
3118
        $this->assertEquals(
3119
            $newOwner->id,
3120
            $contentVersion2->contentInfo->ownerId
3121
        );
3122
        $this->assertEquals(
3123
            $userService->loadUserByLogin('admin')->getUserId(),
3124
            $contentCopied->contentInfo->ownerId
3125
        );
3126
    }
3127
3128
    /**
3129
     * Test for the copyContent() method.
3130
     *
3131
     * @see \eZ\Publish\API\Repository\ContentService::copyContent($contentInfo, $destinationLocationCreateStruct, $versionInfo)
3132
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCopyContent
3133
     */
3134 View Code Duplication
    public function testCopyContentWithGivenVersion()
3135
    {
3136
        $parentLocationId = $this->generateId('location', 56);
3137
3138
        /* BEGIN: Use Case */
3139
        $contentVersion2 = $this->createContentVersion2();
3140
3141
        // Configure new target location
3142
        $targetLocationCreate = $this->locationService->newLocationCreateStruct($parentLocationId);
3143
3144
        $targetLocationCreate->priority = 42;
3145
        $targetLocationCreate->hidden = true;
3146
        $targetLocationCreate->remoteId = '01234abcdef5678901234abcdef56789';
3147
        $targetLocationCreate->sortField = Location::SORT_FIELD_NODE_ID;
3148
        $targetLocationCreate->sortOrder = Location::SORT_ORDER_DESC;
3149
3150
        // Copy only the initial version
3151
        $contentCopied = $this->contentService->copyContent(
3152
            $contentVersion2->contentInfo,
3153
            $targetLocationCreate,
3154
            $this->contentService->loadVersionInfo($contentVersion2->contentInfo, 1)
3155
        );
3156
        /* END: Use Case */
3157
3158
        $this->assertInstanceOf(
3159
            Content::class,
3160
            $contentCopied
3161
        );
3162
3163
        $this->assertNotEquals(
3164
            $contentVersion2->contentInfo->remoteId,
3165
            $contentCopied->contentInfo->remoteId
3166
        );
3167
3168
        $this->assertNotEquals(
3169
            $contentVersion2->id,
3170
            $contentCopied->id
3171
        );
3172
3173
        $this->assertEquals(
3174
            1,
3175
            count($this->contentService->loadVersions($contentCopied->contentInfo))
3176
        );
3177
3178
        $this->assertEquals(1, $contentCopied->getVersionInfo()->versionNo);
3179
3180
        $this->assertNotNull(
3181
            $contentCopied->contentInfo->mainLocationId,
3182
            'Expected main location to be set given we provided a LocationCreateStruct'
3183
        );
3184
    }
3185
3186
    /**
3187
     * Test for the addRelation() method.
3188
     *
3189
     * @return \eZ\Publish\API\Repository\Values\Content\Content
3190
     *
3191
     * @see \eZ\Publish\API\Repository\ContentService::addRelation()
3192
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
3193
     */
3194 View Code Duplication
    public function testAddRelation()
3195
    {
3196
        /* BEGIN: Use Case */
3197
        // RemoteId of the "Media" content of an eZ Publish demo installation
3198
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3199
3200
        $draft = $this->createContentDraftVersion1();
3201
3202
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3203
3204
        // Create relation between new content object and "Media" page
3205
        $relation = $this->contentService->addRelation(
3206
            $draft->getVersionInfo(),
3207
            $media
3208
        );
3209
        /* END: Use Case */
3210
3211
        $this->assertInstanceOf(
3212
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Relation',
3213
            $relation
3214
        );
3215
3216
        return $this->contentService->loadRelations($draft->getVersionInfo());
3217
    }
3218
3219
    /**
3220
     * Test for the addRelation() method.
3221
     *
3222
     * @param \eZ\Publish\API\Repository\Values\Content\Relation[] $relations
3223
     *
3224
     * @see \eZ\Publish\API\Repository\ContentService::addRelation()
3225
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3226
     */
3227
    public function testAddRelationAddsRelationToContent($relations)
3228
    {
3229
        $this->assertEquals(
3230
            1,
3231
            count($relations)
3232
        );
3233
    }
3234
3235
    /**
3236
     * @param \eZ\Publish\API\Repository\Values\Content\Relation[] $relations
3237
     */
3238
    protected function assertExpectedRelations($relations)
3239
    {
3240
        $this->assertEquals(
3241
            [
3242
                'type' => Relation::COMMON,
3243
                'sourceFieldDefinitionIdentifier' => null,
3244
                'sourceContentInfo' => 'abcdef0123456789abcdef0123456789',
3245
                'destinationContentInfo' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
3246
            ],
3247
            [
3248
                'type' => $relations[0]->type,
3249
                'sourceFieldDefinitionIdentifier' => $relations[0]->sourceFieldDefinitionIdentifier,
3250
                'sourceContentInfo' => $relations[0]->sourceContentInfo->remoteId,
3251
                'destinationContentInfo' => $relations[0]->destinationContentInfo->remoteId,
3252
            ]
3253
        );
3254
    }
3255
3256
    /**
3257
     * Test for the addRelation() method.
3258
     *
3259
     * @param \eZ\Publish\API\Repository\Values\Content\Relation[] $relations
3260
     *
3261
     * @see \eZ\Publish\API\Repository\ContentService::addRelation()
3262
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3263
     */
3264
    public function testAddRelationSetsExpectedRelations($relations)
3265
    {
3266
        $this->assertExpectedRelations($relations);
3267
    }
3268
3269
    /**
3270
     * Test for the createContentDraft() method.
3271
     *
3272
     * @return \eZ\Publish\API\Repository\Values\Content\Relation[]
3273
     *
3274
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
3275
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelationSetsExpectedRelations
3276
     */
3277 View Code Duplication
    public function testCreateContentDraftWithRelations()
3278
    {
3279
        // RemoteId of the "Media" content of an eZ Publish demo installation
3280
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3281
        $draft = $this->createContentDraftVersion1();
3282
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3283
3284
        // Create relation between new content object and "Media" page
3285
        $this->contentService->addRelation(
3286
            $draft->getVersionInfo(),
3287
            $media
3288
        );
3289
3290
        $content = $this->contentService->publishVersion($draft->versionInfo);
3291
        $newDraft = $this->contentService->createContentDraft($content->contentInfo);
3292
3293
        return $this->contentService->loadRelations($newDraft->getVersionInfo());
3294
    }
3295
3296
    /**
3297
     * Test for the createContentDraft() method.
3298
     *
3299
     * @param \eZ\Publish\API\Repository\Values\Content\Relation[] $relations
3300
     *
3301
     * @return \eZ\Publish\API\Repository\Values\Content\Relation[]
3302
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraftWithRelations
3303
     */
3304
    public function testCreateContentDraftWithRelationsCreatesRelations($relations)
3305
    {
3306
        $this->assertEquals(
3307
            1,
3308
            count($relations)
3309
        );
3310
3311
        return $relations;
3312
    }
3313
3314
    /**
3315
     * Test for the createContentDraft() method.
3316
     *
3317
     * @param \eZ\Publish\API\Repository\Values\Content\Relation[] $relations
3318
     *
3319
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraftWithRelationsCreatesRelations
3320
     */
3321
    public function testCreateContentDraftWithRelationsCreatesExpectedRelations($relations)
3322
    {
3323
        $this->assertExpectedRelations($relations);
3324
    }
3325
3326
    /**
3327
     * Test for the addRelation() method.
3328
     *
3329
     * @see \eZ\Publish\API\Repository\ContentService::addRelation()
3330
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3331
     */
3332
    public function testAddRelationThrowsBadStateException()
3333
    {
3334
        /* BEGIN: Use Case */
3335
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3336
3337
        $content = $this->createContentVersion1();
3338
3339
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3340
3341
        $this->expectException(BadStateException::class);
3342
3343
        // This call will fail with a "BadStateException", because content is published and not a draft.
3344
        $this->contentService->addRelation(
3345
            $content->getVersionInfo(),
3346
            $media
3347
        );
3348
        /* END: Use Case */
3349
    }
3350
3351
    /**
3352
     * Test for the loadRelations() method.
3353
     *
3354
     * @see \eZ\Publish\API\Repository\ContentService::loadRelations()
3355
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3356
     */
3357
    public function testLoadRelations()
3358
    {
3359
        /* BEGIN: Use Case */
3360
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3361
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
3362
3363
        $draft = $this->createContentDraftVersion1();
3364
3365
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3366
        $demoDesign = $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId);
3367
3368
        // Create relation between new content object and "Media" page
3369
        $this->contentService->addRelation(
3370
            $draft->getVersionInfo(),
3371
            $media
3372
        );
3373
3374
        // Create another relation with the "Demo Design" page
3375
        $this->contentService->addRelation(
3376
            $draft->getVersionInfo(),
3377
            $demoDesign
3378
        );
3379
3380
        $relations = $this->contentService->loadRelations($draft->getVersionInfo());
3381
        /* END: Use Case */
3382
3383
        usort(
3384
            $relations,
3385
            function ($rel1, $rel2) {
3386
                return strcasecmp(
3387
                    $rel2->getDestinationContentInfo()->remoteId,
3388
                    $rel1->getDestinationContentInfo()->remoteId
3389
                );
3390
            }
3391
        );
3392
3393
        $this->assertEquals(
3394
            [
3395
                [
3396
                    'sourceContentInfo' => 'abcdef0123456789abcdef0123456789',
3397
                    'destinationContentInfo' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
3398
                ],
3399
                [
3400
                    'sourceContentInfo' => 'abcdef0123456789abcdef0123456789',
3401
                    'destinationContentInfo' => '8b8b22fe3c6061ed500fbd2b377b885f',
3402
                ],
3403
            ],
3404
            [
3405
                [
3406
                    'sourceContentInfo' => $relations[0]->sourceContentInfo->remoteId,
3407
                    'destinationContentInfo' => $relations[0]->destinationContentInfo->remoteId,
3408
                ],
3409
                [
3410
                    'sourceContentInfo' => $relations[1]->sourceContentInfo->remoteId,
3411
                    'destinationContentInfo' => $relations[1]->destinationContentInfo->remoteId,
3412
                ],
3413
            ]
3414
        );
3415
    }
3416
3417
    /**
3418
     * Test for the loadRelations() method.
3419
     *
3420
     * @see \eZ\Publish\API\Repository\ContentService::loadRelations()
3421
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3422
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadRelations
3423
     */
3424
    public function testLoadRelationsSkipsArchivedContent()
3425
    {
3426
        /* BEGIN: Use Case */
3427
        $trashService = $this->getRepository()->getTrashService();
3428
        // Remote ids of the "Media" and the "eZ Publish Demo Design ..." page
3429
        // of a eZ Publish demo installation.
3430
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3431
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
3432
3433
        $draft = $this->createContentDraftVersion1();
3434
3435
        // Load other content objects
3436
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3437
        $demoDesign = $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId);
3438
3439
        // Create relation between new content object and "Media" page
3440
        $this->contentService->addRelation(
3441
            $draft->getVersionInfo(),
3442
            $media
3443
        );
3444
3445
        // Create another relation with the "Demo Design" page
3446
        $this->contentService->addRelation(
3447
            $draft->getVersionInfo(),
3448
            $demoDesign
3449
        );
3450
3451
        $demoDesignLocation = $this->locationService->loadLocation($demoDesign->mainLocationId);
3452
3453
        // Trashing Content's last Location will change its status to archived,
3454
        // in this case relation towards it will not be loaded.
3455
        $trashService->trash($demoDesignLocation);
3456
3457
        // Load all relations
3458
        $relations = $this->contentService->loadRelations($draft->getVersionInfo());
3459
        /* END: Use Case */
3460
3461
        $this->assertCount(1, $relations);
3462
        $this->assertEquals(
3463
            [
3464
                [
3465
                    'sourceContentInfo' => 'abcdef0123456789abcdef0123456789',
3466
                    'destinationContentInfo' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
3467
                ],
3468
            ],
3469
            [
3470
                [
3471
                    'sourceContentInfo' => $relations[0]->sourceContentInfo->remoteId,
3472
                    'destinationContentInfo' => $relations[0]->destinationContentInfo->remoteId,
3473
                ],
3474
            ]
3475
        );
3476
    }
3477
3478
    /**
3479
     * Test for the loadRelations() method.
3480
     *
3481
     * @see \eZ\Publish\API\Repository\ContentService::loadRelations()
3482
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3483
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadRelations
3484
     */
3485
    public function testLoadRelationsSkipsDraftContent()
3486
    {
3487
        /* BEGIN: Use Case */
3488
        // Remote ids of the "Media" and the "eZ Publish Demo Design ..." page
3489
        // of a eZ Publish demo installation.
3490
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3491
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
3492
3493
        $draft = $this->createContentDraftVersion1();
3494
3495
        // Load other content objects
3496
        $media = $this->contentService->loadContentByRemoteId($mediaRemoteId);
3497
        $demoDesign = $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId);
3498
3499
        // Create draft of "Media" page
3500
        $mediaDraft = $this->contentService->createContentDraft($media->contentInfo);
3501
3502
        // Create relation between "Media" page and new content object draft.
3503
        // This relation will not be loaded before the draft is published.
3504
        $this->contentService->addRelation(
3505
            $mediaDraft->getVersionInfo(),
3506
            $draft->getVersionInfo()->getContentInfo()
3507
        );
3508
3509
        // Create another relation with the "Demo Design" page
3510
        $this->contentService->addRelation(
3511
            $mediaDraft->getVersionInfo(),
3512
            $demoDesign
3513
        );
3514
3515
        // Load all relations
3516
        $relations = $this->contentService->loadRelations($mediaDraft->getVersionInfo());
3517
        /* END: Use Case */
3518
3519
        $this->assertCount(1, $relations);
3520
        $this->assertEquals(
3521
            [
3522
                [
3523
                    'sourceContentInfo' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
3524
                    'destinationContentInfo' => '8b8b22fe3c6061ed500fbd2b377b885f',
3525
                ],
3526
            ],
3527
            [
3528
                [
3529
                    'sourceContentInfo' => $relations[0]->sourceContentInfo->remoteId,
3530
                    'destinationContentInfo' => $relations[0]->destinationContentInfo->remoteId,
3531
                ],
3532
            ]
3533
        );
3534
    }
3535
3536
    /**
3537
     * Test for the loadReverseRelations() method.
3538
     *
3539
     * @see \eZ\Publish\API\Repository\ContentService::loadReverseRelations()
3540
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3541
     */
3542
    public function testLoadReverseRelations()
3543
    {
3544
        /* BEGIN: Use Case */
3545
        // Remote ids of the "Media" and the "eZ Publish Demo Design ..." page
3546
        // of a eZ Publish demo installation.
3547
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3548
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
3549
3550
        $versionInfo = $this->createContentVersion1()->getVersionInfo();
3551
        $contentInfo = $versionInfo->getContentInfo();
3552
3553
        // Create some drafts
3554
        $mediaDraft = $this->contentService->createContentDraft(
3555
            $this->contentService->loadContentInfoByRemoteId($mediaRemoteId)
3556
        );
3557
        $demoDesignDraft = $this->contentService->createContentDraft(
3558
            $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId)
3559
        );
3560
3561
        // Create relation between new content object and "Media" page
3562
        $relation1 = $this->contentService->addRelation(
3563
            $mediaDraft->getVersionInfo(),
3564
            $contentInfo
3565
        );
3566
3567
        // Create another relation with the "Demo Design" page
3568
        $relation2 = $this->contentService->addRelation(
3569
            $demoDesignDraft->getVersionInfo(),
3570
            $contentInfo
3571
        );
3572
3573
        // Publish drafts, so relations become active
3574
        $this->contentService->publishVersion($mediaDraft->getVersionInfo());
3575
        $this->contentService->publishVersion($demoDesignDraft->getVersionInfo());
3576
3577
        // Load all relations
3578
        $relations = $this->contentService->loadRelations($versionInfo);
3579
        $reverseRelations = $this->contentService->loadReverseRelations($contentInfo);
3580
        /* END: Use Case */
3581
3582
        $this->assertEquals($contentInfo->id, $relation1->getDestinationContentInfo()->id);
3583
        $this->assertEquals($mediaDraft->id, $relation1->getSourceContentInfo()->id);
3584
3585
        $this->assertEquals($contentInfo->id, $relation2->getDestinationContentInfo()->id);
3586
        $this->assertEquals($demoDesignDraft->id, $relation2->getSourceContentInfo()->id);
3587
3588
        $this->assertEquals(0, count($relations));
3589
        $this->assertEquals(2, count($reverseRelations));
3590
3591
        usort(
3592
            $reverseRelations,
3593
            function ($rel1, $rel2) {
3594
                return strcasecmp(
3595
                    $rel2->getSourceContentInfo()->remoteId,
3596
                    $rel1->getSourceContentInfo()->remoteId
3597
                );
3598
            }
3599
        );
3600
3601
        $this->assertEquals(
3602
            [
3603
                [
3604
                    'sourceContentInfo' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
3605
                    'destinationContentInfo' => 'abcdef0123456789abcdef0123456789',
3606
                ],
3607
                [
3608
                    'sourceContentInfo' => '8b8b22fe3c6061ed500fbd2b377b885f',
3609
                    'destinationContentInfo' => 'abcdef0123456789abcdef0123456789',
3610
                ],
3611
            ],
3612
            [
3613
                [
3614
                    'sourceContentInfo' => $reverseRelations[0]->sourceContentInfo->remoteId,
3615
                    'destinationContentInfo' => $reverseRelations[0]->destinationContentInfo->remoteId,
3616
                ],
3617
                [
3618
                    'sourceContentInfo' => $reverseRelations[1]->sourceContentInfo->remoteId,
3619
                    'destinationContentInfo' => $reverseRelations[1]->destinationContentInfo->remoteId,
3620
                ],
3621
            ]
3622
        );
3623
    }
3624
3625
    /**
3626
     * Test for the loadReverseRelations() method.
3627
     *
3628
     * @see \eZ\Publish\API\Repository\ContentService::loadReverseRelations()
3629
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3630
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadReverseRelations
3631
     */
3632
    public function testLoadReverseRelationsSkipsArchivedContent()
3633
    {
3634
        /* BEGIN: Use Case */
3635
        $trashService = $this->getRepository()->getTrashService();
3636
        // Remote ids of the "Media" and the "eZ Publish Demo Design ..." page
3637
        // of a eZ Publish demo installation.
3638
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3639
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
3640
3641
        $versionInfo = $this->createContentVersion1()->getVersionInfo();
3642
        $contentInfo = $versionInfo->getContentInfo();
3643
3644
        // Create some drafts
3645
        $mediaDraft = $this->contentService->createContentDraft(
3646
            $this->contentService->loadContentInfoByRemoteId($mediaRemoteId)
3647
        );
3648
        $demoDesignDraft = $this->contentService->createContentDraft(
3649
            $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId)
3650
        );
3651
3652
        // Create relation between new content object and "Media" page
3653
        $relation1 = $this->contentService->addRelation(
3654
            $mediaDraft->getVersionInfo(),
3655
            $contentInfo
3656
        );
3657
3658
        // Create another relation with the "Demo Design" page
3659
        $relation2 = $this->contentService->addRelation(
3660
            $demoDesignDraft->getVersionInfo(),
3661
            $contentInfo
3662
        );
3663
3664
        // Publish drafts, so relations become active
3665
        $this->contentService->publishVersion($mediaDraft->getVersionInfo());
3666
        $this->contentService->publishVersion($demoDesignDraft->getVersionInfo());
3667
3668
        $demoDesignLocation = $this->locationService->loadLocation($demoDesignDraft->contentInfo->mainLocationId);
3669
3670
        // Trashing Content's last Location will change its status to archived,
3671
        // in this case relation from it will not be loaded.
3672
        $trashService->trash($demoDesignLocation);
3673
3674
        // Load all relations
3675
        $relations = $this->contentService->loadRelations($versionInfo);
3676
        $reverseRelations = $this->contentService->loadReverseRelations($contentInfo);
3677
        /* END: Use Case */
3678
3679
        $this->assertEquals($contentInfo->id, $relation1->getDestinationContentInfo()->id);
3680
        $this->assertEquals($mediaDraft->id, $relation1->getSourceContentInfo()->id);
3681
3682
        $this->assertEquals($contentInfo->id, $relation2->getDestinationContentInfo()->id);
3683
        $this->assertEquals($demoDesignDraft->id, $relation2->getSourceContentInfo()->id);
3684
3685
        $this->assertEquals(0, count($relations));
3686
        $this->assertEquals(1, count($reverseRelations));
3687
3688
        $this->assertEquals(
3689
            [
3690
                [
3691
                    'sourceContentInfo' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
3692
                    'destinationContentInfo' => 'abcdef0123456789abcdef0123456789',
3693
                ],
3694
            ],
3695
            [
3696
                [
3697
                    'sourceContentInfo' => $reverseRelations[0]->sourceContentInfo->remoteId,
3698
                    'destinationContentInfo' => $reverseRelations[0]->destinationContentInfo->remoteId,
3699
                ],
3700
            ]
3701
        );
3702
    }
3703
3704
    /**
3705
     * Test for the loadReverseRelations() method.
3706
     *
3707
     * @see \eZ\Publish\API\Repository\ContentService::loadReverseRelations()
3708
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3709
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadReverseRelations
3710
     */
3711
    public function testLoadReverseRelationsSkipsDraftContent()
3712
    {
3713
        /* BEGIN: Use Case */
3714
        // Remote ids of the "Media" and the "eZ Publish Demo Design ..." page
3715
        // of a eZ Publish demo installation.
3716
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3717
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
3718
3719
        // Load "Media" page Content
3720
        $media = $this->contentService->loadContentByRemoteId($mediaRemoteId);
3721
3722
        // Create some drafts
3723
        $newDraftVersionInfo = $this->createContentDraftVersion1()->getVersionInfo();
3724
        $demoDesignDraft = $this->contentService->createContentDraft(
3725
            $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId)
3726
        );
3727
3728
        // Create relation between "Media" page and new content object
3729
        $relation1 = $this->contentService->addRelation(
3730
            $newDraftVersionInfo,
3731
            $media->contentInfo
3732
        );
3733
3734
        // Create another relation with the "Demo Design" page
3735
        $relation2 = $this->contentService->addRelation(
3736
            $demoDesignDraft->getVersionInfo(),
3737
            $media->contentInfo
3738
        );
3739
3740
        // Publish drafts, so relations become active
3741
        $this->contentService->publishVersion($demoDesignDraft->getVersionInfo());
3742
        // We will not publish new Content draft, therefore relation from it
3743
        // will not be loaded as reverse relation for "Media" page
3744
        //$this->contentService->publishVersion( $newDraftVersionInfo );
3745
3746
        // Load all relations
3747
        $relations = $this->contentService->loadRelations($media->versionInfo);
3748
        $reverseRelations = $this->contentService->loadReverseRelations($media->contentInfo);
3749
        /* END: Use Case */
3750
3751
        $this->assertEquals($media->contentInfo->id, $relation1->getDestinationContentInfo()->id);
3752
        $this->assertEquals($newDraftVersionInfo->contentInfo->id, $relation1->getSourceContentInfo()->id);
3753
3754
        $this->assertEquals($media->contentInfo->id, $relation2->getDestinationContentInfo()->id);
3755
        $this->assertEquals($demoDesignDraft->id, $relation2->getSourceContentInfo()->id);
3756
3757
        $this->assertEquals(0, count($relations));
3758
        $this->assertEquals(1, count($reverseRelations));
3759
3760
        $this->assertEquals(
3761
            [
3762
                [
3763
                    'sourceContentInfo' => '8b8b22fe3c6061ed500fbd2b377b885f',
3764
                    'destinationContentInfo' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
3765
                ],
3766
            ],
3767
            [
3768
                [
3769
                    'sourceContentInfo' => $reverseRelations[0]->sourceContentInfo->remoteId,
3770
                    'destinationContentInfo' => $reverseRelations[0]->destinationContentInfo->remoteId,
3771
                ],
3772
            ]
3773
        );
3774
    }
3775
3776
    /**
3777
     * Test for the deleteRelation() method.
3778
     *
3779
     * @see \eZ\Publish\API\Repository\ContentService::deleteRelation()
3780
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadRelations
3781
     */
3782 View Code Duplication
    public function testDeleteRelation()
3783
    {
3784
        /* BEGIN: Use Case */
3785
        // Remote ids of the "Media" and the "Demo Design" page of a eZ Publish
3786
        // demo installation.
3787
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3788
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
3789
3790
        $draft = $this->createContentDraftVersion1();
3791
3792
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3793
        $demoDesign = $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId);
3794
3795
        // Establish some relations
3796
        $this->contentService->addRelation($draft->getVersionInfo(), $media);
3797
        $this->contentService->addRelation($draft->getVersionInfo(), $demoDesign);
3798
3799
        // Delete one of the currently created relations
3800
        $this->contentService->deleteRelation($draft->getVersionInfo(), $media);
3801
3802
        // The relations array now contains only one element
3803
        $relations = $this->contentService->loadRelations($draft->getVersionInfo());
3804
        /* END: Use Case */
3805
3806
        $this->assertEquals(1, count($relations));
3807
    }
3808
3809
    /**
3810
     * Test for the deleteRelation() method.
3811
     *
3812
     * @see \eZ\Publish\API\Repository\ContentService::deleteRelation()
3813
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testDeleteRelation
3814
     */
3815
    public function testDeleteRelationThrowsBadStateException()
3816
    {
3817
        /* BEGIN: Use Case */
3818
        // RemoteId of the "Media" page of an eZ Publish demo installation
3819
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3820
3821
        $content = $this->createContentVersion1();
3822
3823
        // Load the destination object
3824
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3825
3826
        // Create a new draft
3827
        $draftVersion2 = $this->contentService->createContentDraft($content->contentInfo);
3828
3829
        // Add a relation
3830
        $this->contentService->addRelation($draftVersion2->getVersionInfo(), $media);
3831
3832
        // Publish new version
3833
        $contentVersion2 = $this->contentService->publishVersion(
3834
            $draftVersion2->getVersionInfo()
3835
        );
3836
3837
        $this->expectException(BadStateException::class);
3838
3839
        // This call will fail with a "BadStateException", because content is published and not a draft.
3840
        $this->contentService->deleteRelation(
3841
            $contentVersion2->getVersionInfo(),
3842
            $media
3843
        );
3844
        /* END: Use Case */
3845
    }
3846
3847
    /**
3848
     * Test for the deleteRelation() method.
3849
     *
3850
     * @see \eZ\Publish\API\Repository\ContentService::deleteRelation()
3851
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testDeleteRelation
3852
     */
3853 View Code Duplication
    public function testDeleteRelationThrowsInvalidArgumentException()
3854
    {
3855
        /* BEGIN: Use Case */
3856
        // RemoteId of the "Media" page of an eZ Publish demo installation
3857
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3858
3859
        $draft = $this->createContentDraftVersion1();
3860
3861
        // Load the destination object
3862
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3863
3864
        // This call will fail with a "InvalidArgumentException", because no relation exists between $draft and $media.
3865
        $this->expectException(APIInvalidArgumentException::class);
3866
        $this->contentService->deleteRelation(
3867
            $draft->getVersionInfo(),
3868
            $media
3869
        );
3870
        /* END: Use Case */
3871
    }
3872
3873
    /**
3874
     * Test for the createContent() method.
3875
     *
3876
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
3877
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
3878
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
3879
     */
3880
    public function testCreateContentInTransactionWithRollback()
3881
    {
3882
        if ($this->isVersion4()) {
3883
            $this->markTestSkipped('This test requires eZ Publish 5');
3884
        }
3885
3886
        $repository = $this->getRepository();
3887
3888
        /* BEGIN: Use Case */
3889
        $contentTypeService = $this->getRepository()->getContentTypeService();
3890
3891
        // Start a transaction
3892
        $repository->beginTransaction();
3893
3894
        try {
3895
            $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
3896
3897
            // Get a content create struct and set mandatory properties
3898
            $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
3899
            $contentCreate->setField('name', 'Sindelfingen forum');
3900
3901
            $contentCreate->remoteId = 'abcdef0123456789abcdef0123456789';
3902
            $contentCreate->alwaysAvailable = true;
3903
3904
            // Create a new content object
3905
            $contentId = $this->contentService->createContent($contentCreate)->id;
3906
        } catch (Exception $e) {
3907
            // Cleanup hanging transaction on error
3908
            $repository->rollback();
3909
            throw $e;
3910
        }
3911
3912
        // Rollback all changes
3913
        $repository->rollback();
3914
3915
        try {
3916
            // This call will fail with a "NotFoundException"
3917
            $this->contentService->loadContent($contentId);
3918
        } catch (NotFoundException $e) {
3919
            // This is expected
3920
            return;
3921
        }
3922
        /* END: Use Case */
3923
3924
        $this->fail('Content object still exists after rollback.');
3925
    }
3926
3927
    /**
3928
     * Test for the createContent() method.
3929
     *
3930
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
3931
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
3932
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
3933
     */
3934
    public function testCreateContentInTransactionWithCommit()
3935
    {
3936
        if ($this->isVersion4()) {
3937
            $this->markTestSkipped('This test requires eZ Publish 5');
3938
        }
3939
3940
        $repository = $this->getRepository();
3941
3942
        /* BEGIN: Use Case */
3943
        $contentTypeService = $repository->getContentTypeService();
3944
3945
        // Start a transaction
3946
        $repository->beginTransaction();
3947
3948
        try {
3949
            $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
3950
3951
            // Get a content create struct and set mandatory properties
3952
            $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
3953
            $contentCreate->setField('name', 'Sindelfingen forum');
3954
3955
            $contentCreate->remoteId = 'abcdef0123456789abcdef0123456789';
3956
            $contentCreate->alwaysAvailable = true;
3957
3958
            // Create a new content object
3959
            $contentId = $this->contentService->createContent($contentCreate)->id;
3960
3961
            // Commit changes
3962
            $repository->commit();
3963
        } catch (Exception $e) {
3964
            // Cleanup hanging transaction on error
3965
            $repository->rollback();
3966
            throw $e;
3967
        }
3968
3969
        // Load the new content object
3970
        $content = $this->contentService->loadContent($contentId);
3971
        /* END: Use Case */
3972
3973
        $this->assertEquals($contentId, $content->id);
3974
    }
3975
3976
    /**
3977
     * Test for the createContent() method.
3978
     *
3979
     * @see \eZ\Publish\API\Repository\ContentService::createContent($contentCreateStruct, $locationCreateStructs)
3980
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentWithLocationCreateParameterDoesNotCreateLocationImmediately
3981
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentThrowsNotFoundException
3982
     */
3983
    public function testCreateContentWithLocationCreateParameterInTransactionWithRollback()
3984
    {
3985
        $repository = $this->getRepository();
3986
3987
        /* BEGIN: Use Case */
3988
        // Start a transaction
3989
        $repository->beginTransaction();
3990
3991
        try {
3992
            $draft = $this->createContentDraftVersion1();
3993
        } catch (Exception $e) {
3994
            // Cleanup hanging transaction on error
3995
            $repository->rollback();
3996
            throw $e;
3997
        }
3998
3999
        $contentId = $draft->id;
4000
4001
        // Roleback the transaction
4002
        $repository->rollback();
4003
4004
        try {
4005
            // This call will fail with a "NotFoundException"
4006
            $this->contentService->loadContent($contentId);
4007
        } catch (NotFoundException $e) {
4008
            return;
4009
        }
4010
        /* END: Use Case */
4011
4012
        $this->fail('Can still load content object after rollback.');
4013
    }
4014
4015
    /**
4016
     * Test for the createContent() method.
4017
     *
4018
     * @see \eZ\Publish\API\Repository\ContentService::createContent($contentCreateStruct, $locationCreateStructs)
4019
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentWithLocationCreateParameterDoesNotCreateLocationImmediately
4020
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentThrowsNotFoundException
4021
     */
4022
    public function testCreateContentWithLocationCreateParameterInTransactionWithCommit()
4023
    {
4024
        $repository = $this->getRepository();
4025
4026
        /* BEGIN: Use Case */
4027
        // Start a transaction
4028
        $repository->beginTransaction();
4029
4030
        try {
4031
            $draft = $this->createContentDraftVersion1();
4032
4033
            $contentId = $draft->id;
4034
4035
            // Roleback the transaction
4036
            $repository->commit();
4037
        } catch (Exception $e) {
4038
            // Cleanup hanging transaction on error
4039
            $repository->rollback();
4040
            throw $e;
4041
        }
4042
4043
        // Load the new content object
4044
        $content = $this->contentService->loadContent($contentId);
4045
        /* END: Use Case */
4046
4047
        $this->assertEquals($contentId, $content->id);
4048
    }
4049
4050
    /**
4051
     * Test for the createContentDraft() method.
4052
     *
4053
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
4054
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
4055
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
4056
     */
4057
    public function testCreateContentDraftInTransactionWithRollback()
4058
    {
4059
        $repository = $this->getRepository();
4060
4061
        $contentId = $this->generateId('object', 12);
4062
        /* BEGIN: Use Case */
4063
        // $contentId is the ID of the "Administrator users" user group
4064
4065
        // Load the user group content object
4066
        $content = $this->contentService->loadContent($contentId);
4067
4068
        // Start a new transaction
4069
        $repository->beginTransaction();
4070
4071
        try {
4072
            // Create a new draft
4073
            $drafted = $this->contentService->createContentDraft($content->contentInfo);
4074
4075
            // Store version number for later reuse
4076
            $versionNo = $drafted->versionInfo->versionNo;
4077
        } catch (Exception $e) {
4078
            // Cleanup hanging transaction on error
4079
            $repository->rollback();
4080
            throw $e;
4081
        }
4082
4083
        // Rollback
4084
        $repository->rollback();
4085
4086
        try {
4087
            // This call will fail with a "NotFoundException"
4088
            $this->contentService->loadContent($contentId, null, $versionNo);
4089
        } catch (NotFoundException $e) {
4090
            return;
4091
        }
4092
        /* END: Use Case */
4093
4094
        $this->fail('Can still load content draft after rollback');
4095
    }
4096
4097
    /**
4098
     * Test for the createContentDraft() method.
4099
     *
4100
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
4101
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
4102
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
4103
     */
4104 View Code Duplication
    public function testCreateContentDraftInTransactionWithCommit()
4105
    {
4106
        $repository = $this->getRepository();
4107
4108
        $contentId = $this->generateId('object', 12);
4109
        /* BEGIN: Use Case */
4110
        // $contentId is the ID of the "Administrator users" user group
4111
4112
        // Load the user group content object
4113
        $content = $this->contentService->loadContent($contentId);
4114
4115
        // Start a new transaction
4116
        $repository->beginTransaction();
4117
4118
        try {
4119
            // Create a new draft
4120
            $drafted = $this->contentService->createContentDraft($content->contentInfo);
4121
4122
            // Store version number for later reuse
4123
            $versionNo = $drafted->versionInfo->versionNo;
4124
4125
            // Commit all changes
4126
            $repository->commit();
4127
        } catch (Exception $e) {
4128
            // Cleanup hanging transaction on error
4129
            $repository->rollback();
4130
            throw $e;
4131
        }
4132
4133
        $content = $this->contentService->loadContent($contentId, null, $versionNo);
4134
        /* END: Use Case */
4135
4136
        $this->assertEquals(
4137
            $versionNo,
4138
            $content->getVersionInfo()->versionNo
4139
        );
4140
    }
4141
4142
    /**
4143
     * Test for the publishVersion() method.
4144
     *
4145
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
4146
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
4147
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
4148
     */
4149 View Code Duplication
    public function testPublishVersionInTransactionWithRollback()
4150
    {
4151
        $repository = $this->getRepository();
4152
4153
        $contentId = $this->generateId('object', 12);
4154
        /* BEGIN: Use Case */
4155
        // $contentId is the ID of the "Administrator users" user group
4156
4157
        // Load the user group content object
4158
        $content = $this->contentService->loadContent($contentId);
4159
4160
        // Start a new transaction
4161
        $repository->beginTransaction();
4162
4163
        try {
4164
            $draftVersion = $this->contentService->createContentDraft($content->contentInfo)->getVersionInfo();
4165
4166
            // Publish a new version
4167
            $content = $this->contentService->publishVersion($draftVersion);
4168
4169
            // Store version number for later reuse
4170
            $versionNo = $content->versionInfo->versionNo;
4171
        } catch (Exception $e) {
4172
            // Cleanup hanging transaction on error
4173
            $repository->rollback();
4174
            throw $e;
4175
        }
4176
4177
        // Rollback
4178
        $repository->rollback();
4179
4180
        try {
4181
            // This call will fail with a "NotFoundException"
4182
            $this->contentService->loadContent($contentId, null, $versionNo);
4183
        } catch (NotFoundException $e) {
4184
            return;
4185
        }
4186
        /* END: Use Case */
4187
4188
        $this->fail('Can still load content draft after rollback');
4189
    }
4190
4191
    /**
4192
     * Test for the publishVersion() method.
4193
     *
4194
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
4195
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
4196
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfo
4197
     */
4198 View Code Duplication
    public function testPublishVersionInTransactionWithCommit()
4199
    {
4200
        $repository = $this->getRepository();
4201
4202
        /* BEGIN: Use Case */
4203
        // ID of the "Administrator users" user group
4204
        $contentId = 12;
4205
4206
        // Load the user group content object
4207
        $template = $this->contentService->loadContent($contentId);
4208
4209
        // Start a new transaction
4210
        $repository->beginTransaction();
4211
4212
        try {
4213
            // Publish a new version
4214
            $content = $this->contentService->publishVersion(
4215
                $this->contentService->createContentDraft($template->contentInfo)->getVersionInfo()
4216
            );
4217
4218
            // Store version number for later reuse
4219
            $versionNo = $content->versionInfo->versionNo;
4220
4221
            // Commit all changes
4222
            $repository->commit();
4223
        } catch (Exception $e) {
4224
            // Cleanup hanging transaction on error
4225
            $repository->rollback();
4226
            throw $e;
4227
        }
4228
4229
        // Load current version info
4230
        $versionInfo = $this->contentService->loadVersionInfo($content->contentInfo);
4231
        /* END: Use Case */
4232
4233
        $this->assertEquals($versionNo, $versionInfo->versionNo);
4234
    }
4235
4236
    /**
4237
     * Test for the updateContent() method.
4238
     *
4239
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
4240
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
4241
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
4242
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4243
     */
4244 View Code Duplication
    public function testUpdateContentInTransactionWithRollback()
4245
    {
4246
        $repository = $this->getRepository();
4247
4248
        $contentId = $this->generateId('object', 12);
4249
        /* BEGIN: Use Case */
4250
        // $contentId is the ID of the "Administrator users" user group
4251
4252
        // Create a new user group draft
4253
        $draft = $this->contentService->createContentDraft(
4254
            $this->contentService->loadContentInfo($contentId)
4255
        );
4256
4257
        // Get an update struct and change the group name
4258
        $contentUpdate = $this->contentService->newContentUpdateStruct();
4259
        $contentUpdate->setField('name', 'Administrators', 'eng-US');
4260
4261
        // Start a transaction
4262
        $repository->beginTransaction();
4263
4264
        try {
4265
            // Update the group name
4266
            $draft = $this->contentService->updateContent(
4267
                $draft->getVersionInfo(),
4268
                $contentUpdate
4269
            );
4270
4271
            // Publish updated version
4272
            $this->contentService->publishVersion($draft->getVersionInfo());
4273
        } catch (Exception $e) {
4274
            // Cleanup hanging transaction on error
4275
            $repository->rollback();
4276
            throw $e;
4277
        }
4278
4279
        // Rollback all changes.
4280
        $repository->rollback();
4281
4282
        // Name will still be "Administrator users"
4283
        $name = $this->contentService->loadContent($contentId)->getFieldValue('name');
4284
        /* END: Use Case */
4285
4286
        $this->assertEquals('Administrator users', $name);
4287
    }
4288
4289
    /**
4290
     * Test for the updateContent() method.
4291
     *
4292
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
4293
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
4294
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
4295
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4296
     */
4297 View Code Duplication
    public function testUpdateContentInTransactionWithCommit()
4298
    {
4299
        $repository = $this->getRepository();
4300
4301
        $contentId = $this->generateId('object', 12);
4302
        /* BEGIN: Use Case */
4303
        // $contentId is the ID of the "Administrator users" user group
4304
4305
        // Create a new user group draft
4306
        $draft = $this->contentService->createContentDraft(
4307
            $this->contentService->loadContentInfo($contentId)
4308
        );
4309
4310
        // Get an update struct and change the group name
4311
        $contentUpdate = $this->contentService->newContentUpdateStruct();
4312
        $contentUpdate->setField('name', 'Administrators', 'eng-US');
4313
4314
        // Start a transaction
4315
        $repository->beginTransaction();
4316
4317
        try {
4318
            // Update the group name
4319
            $draft = $this->contentService->updateContent(
4320
                $draft->getVersionInfo(),
4321
                $contentUpdate
4322
            );
4323
4324
            // Publish updated version
4325
            $this->contentService->publishVersion($draft->getVersionInfo());
4326
4327
            // Commit all changes.
4328
            $repository->commit();
4329
        } catch (Exception $e) {
4330
            // Cleanup hanging transaction on error
4331
            $repository->rollback();
4332
            throw $e;
4333
        }
4334
4335
        // Name is now "Administrators"
4336
        $name = $this->contentService->loadContent($contentId)->getFieldValue('name', 'eng-US');
4337
        /* END: Use Case */
4338
4339
        $this->assertEquals('Administrators', $name);
4340
    }
4341
4342
    /**
4343
     * Test for the updateContentMetadata() method.
4344
     *
4345
     * @see \eZ\Publish\API\Repository\ContentService::updateContentMetadata()
4346
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContentMetadata
4347
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4348
     */
4349 View Code Duplication
    public function testUpdateContentMetadataInTransactionWithRollback()
4350
    {
4351
        $repository = $this->getRepository();
4352
4353
        $contentId = $this->generateId('object', 12);
4354
        /* BEGIN: Use Case */
4355
        // $contentId is the ID of the "Administrator users" user group
4356
4357
        // Load a ContentInfo object
4358
        $contentInfo = $this->contentService->loadContentInfo($contentId);
4359
4360
        // Store remoteId for later testing
4361
        $remoteId = $contentInfo->remoteId;
4362
4363
        // Start a transaction
4364
        $repository->beginTransaction();
4365
4366
        try {
4367
            // Get metadata update struct and change remoteId
4368
            $metadataUpdate = $this->contentService->newContentMetadataUpdateStruct();
4369
            $metadataUpdate->remoteId = md5(microtime(true));
4370
4371
            // Update the metadata of the published content object
4372
            $this->contentService->updateContentMetadata(
4373
                $contentInfo,
4374
                $metadataUpdate
4375
            );
4376
        } catch (Exception $e) {
4377
            // Cleanup hanging transaction on error
4378
            $repository->rollback();
4379
            throw $e;
4380
        }
4381
4382
        // Rollback all changes.
4383
        $repository->rollback();
4384
4385
        // Load current remoteId
4386
        $remoteIdReloaded = $this->contentService->loadContentInfo($contentId)->remoteId;
4387
        /* END: Use Case */
4388
4389
        $this->assertEquals($remoteId, $remoteIdReloaded);
4390
    }
4391
4392
    /**
4393
     * Test for the updateContentMetadata() method.
4394
     *
4395
     * @see \eZ\Publish\API\Repository\ContentService::updateContentMetadata()
4396
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContentMetadata
4397
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4398
     */
4399 View Code Duplication
    public function testUpdateContentMetadataInTransactionWithCommit()
4400
    {
4401
        $repository = $this->getRepository();
4402
4403
        $contentId = $this->generateId('object', 12);
4404
        /* BEGIN: Use Case */
4405
        // $contentId is the ID of the "Administrator users" user group
4406
4407
        // Load a ContentInfo object
4408
        $contentInfo = $this->contentService->loadContentInfo($contentId);
4409
4410
        // Store remoteId for later testing
4411
        $remoteId = $contentInfo->remoteId;
4412
4413
        // Start a transaction
4414
        $repository->beginTransaction();
4415
4416
        try {
4417
            // Get metadata update struct and change remoteId
4418
            $metadataUpdate = $this->contentService->newContentMetadataUpdateStruct();
4419
            $metadataUpdate->remoteId = md5(microtime(true));
4420
4421
            // Update the metadata of the published content object
4422
            $this->contentService->updateContentMetadata(
4423
                $contentInfo,
4424
                $metadataUpdate
4425
            );
4426
4427
            // Commit all changes.
4428
            $repository->commit();
4429
        } catch (Exception $e) {
4430
            // Cleanup hanging transaction on error
4431
            $repository->rollback();
4432
            throw $e;
4433
        }
4434
4435
        // Load current remoteId
4436
        $remoteIdReloaded = $this->contentService->loadContentInfo($contentId)->remoteId;
4437
        /* END: Use Case */
4438
4439
        $this->assertNotEquals($remoteId, $remoteIdReloaded);
4440
    }
4441
4442
    /**
4443
     * Test for the deleteVersion() method.
4444
     *
4445
     * @see \eZ\Publish\API\Repository\ContentService::deleteVersion()
4446
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
4447
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4448
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentDrafts
4449
     */
4450 View Code Duplication
    public function testDeleteVersionInTransactionWithRollback()
4451
    {
4452
        $repository = $this->getRepository();
4453
4454
        $contentId = $this->generateId('object', 12);
4455
        /* BEGIN: Use Case */
4456
        // $contentId is the ID of the "Administrator users" user group
4457
4458
        // Start a new transaction
4459
        $repository->beginTransaction();
4460
4461
        try {
4462
            // Create a new draft
4463
            $draft = $this->contentService->createContentDraft(
4464
                $this->contentService->loadContentInfo($contentId)
4465
            );
4466
4467
            $this->contentService->deleteVersion($draft->getVersionInfo());
4468
        } catch (Exception $e) {
4469
            // Cleanup hanging transaction on error
4470
            $repository->rollback();
4471
            throw $e;
4472
        }
4473
4474
        // Rollback all changes.
4475
        $repository->rollback();
4476
4477
        // This array will be empty
4478
        $drafts = $this->contentService->loadContentDrafts();
4479
        /* END: Use Case */
4480
4481
        $this->assertSame([], $drafts);
4482
    }
4483
4484
    /**
4485
     * Test for the deleteVersion() method.
4486
     *
4487
     * @see \eZ\Publish\API\Repository\ContentService::deleteVersion()
4488
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
4489
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4490
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentDrafts
4491
     */
4492 View Code Duplication
    public function testDeleteVersionInTransactionWithCommit()
4493
    {
4494
        $repository = $this->getRepository();
4495
4496
        $contentId = $this->generateId('object', 12);
4497
        /* BEGIN: Use Case */
4498
        // $contentId is the ID of the "Administrator users" user group
4499
4500
        // Start a new transaction
4501
        $repository->beginTransaction();
4502
4503
        try {
4504
            // Create a new draft
4505
            $draft = $this->contentService->createContentDraft(
4506
                $this->contentService->loadContentInfo($contentId)
4507
            );
4508
4509
            $this->contentService->deleteVersion($draft->getVersionInfo());
4510
4511
            // Commit all changes.
4512
            $repository->commit();
4513
        } catch (Exception $e) {
4514
            // Cleanup hanging transaction on error
4515
            $repository->rollback();
4516
            throw $e;
4517
        }
4518
4519
        // This array will contain no element
4520
        $drafts = $this->contentService->loadContentDrafts();
4521
        /* END: Use Case */
4522
4523
        $this->assertSame([], $drafts);
4524
    }
4525
4526
    /**
4527
     * Test for the deleteContent() method.
4528
     *
4529
     * @see \eZ\Publish\API\Repository\ContentService::deleteContent()
4530
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testDeleteContent
4531
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4532
     */
4533
    public function testDeleteContentInTransactionWithRollback()
4534
    {
4535
        $repository = $this->getRepository();
4536
4537
        $contentId = $this->generateId('object', 11);
4538
        /* BEGIN: Use Case */
4539
        // $contentId is the ID of the "Members" user group in an eZ Publish
4540
        // demo installation
4541
4542
        // Load a ContentInfo instance
4543
        $contentInfo = $this->contentService->loadContentInfo($contentId);
4544
4545
        // Start a new transaction
4546
        $repository->beginTransaction();
4547
4548
        try {
4549
            // Delete content object
4550
            $this->contentService->deleteContent($contentInfo);
4551
        } catch (Exception $e) {
4552
            // Cleanup hanging transaction on error
4553
            $repository->rollback();
4554
            throw $e;
4555
        }
4556
4557
        // Rollback all changes
4558
        $repository->rollback();
4559
4560
        // This call will return the original content object
4561
        $contentInfo = $this->contentService->loadContentInfo($contentId);
4562
        /* END: Use Case */
4563
4564
        $this->assertEquals($contentId, $contentInfo->id);
4565
    }
4566
4567
    /**
4568
     * Test for the deleteContent() method.
4569
     *
4570
     * @see \eZ\Publish\API\Repository\ContentService::deleteContent()
4571
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testDeleteContent
4572
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4573
     */
4574
    public function testDeleteContentInTransactionWithCommit()
4575
    {
4576
        $repository = $this->getRepository();
4577
4578
        $contentId = $this->generateId('object', 11);
4579
        /* BEGIN: Use Case */
4580
        // $contentId is the ID of the "Members" user group in an eZ Publish
4581
        // demo installation
4582
4583
        // Load a ContentInfo instance
4584
        $contentInfo = $this->contentService->loadContentInfo($contentId);
4585
4586
        // Start a new transaction
4587
        $repository->beginTransaction();
4588
4589
        try {
4590
            // Delete content object
4591
            $this->contentService->deleteContent($contentInfo);
4592
4593
            // Commit all changes
4594
            $repository->commit();
4595
        } catch (Exception $e) {
4596
            // Cleanup hanging transaction on error
4597
            $repository->rollback();
4598
            throw $e;
4599
        }
4600
4601
        // Deleted content info is not found anymore
4602
        try {
4603
            $this->contentService->loadContentInfo($contentId);
4604
        } catch (NotFoundException $e) {
4605
            return;
4606
        }
4607
        /* END: Use Case */
4608
4609
        $this->fail('Can still load ContentInfo after commit.');
4610
    }
4611
4612
    /**
4613
     * Test for the copyContent() method.
4614
     *
4615
     * @see \eZ\Publish\API\Repository\ContentService::copyContent()
4616
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCopyContent
4617
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
4618
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
4619
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
4620
     */
4621 View Code Duplication
    public function testCopyContentInTransactionWithRollback()
4622
    {
4623
        $repository = $this->getRepository();
4624
4625
        $contentId = $this->generateId('object', 11);
4626
        $locationId = $this->generateId('location', 13);
4627
        /* BEGIN: Use Case */
4628
        // $contentId is the ID of the "Members" user group in an eZ Publish
4629
        // demo installation
4630
4631
        // $locationId is the ID of the "Administrator users" group location
4632
4633
        // Load content object to copy
4634
        $content = $this->contentService->loadContent($contentId);
4635
4636
        // Create new target location
4637
        $locationCreate = $this->locationService->newLocationCreateStruct($locationId);
4638
4639
        // Start a new transaction
4640
        $repository->beginTransaction();
4641
4642
        try {
4643
            // Copy content with all versions and drafts
4644
            $this->contentService->copyContent(
4645
                $content->contentInfo,
4646
                $locationCreate
4647
            );
4648
        } catch (Exception $e) {
4649
            // Cleanup hanging transaction on error
4650
            $repository->rollback();
4651
            throw $e;
4652
        }
4653
4654
        // Rollback all changes
4655
        $repository->rollback();
4656
4657
        $this->refreshSearch($repository);
4658
4659
        // This array will only contain a single admin user object
4660
        $locations = $this->locationService->loadLocationChildren(
4661
            $this->locationService->loadLocation($locationId)
4662
        )->locations;
4663
        /* END: Use Case */
4664
4665
        $this->assertEquals(1, count($locations));
4666
    }
4667
4668
    /**
4669
     * Test for the copyContent() method.
4670
     *
4671
     * @see \eZ\Publish\API\Repository\ContentService::copyContent()
4672
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCopyContent
4673
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
4674
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
4675
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
4676
     */
4677 View Code Duplication
    public function testCopyContentInTransactionWithCommit()
4678
    {
4679
        $repository = $this->getRepository();
4680
4681
        $contentId = $this->generateId('object', 11);
4682
        $locationId = $this->generateId('location', 13);
4683
        /* BEGIN: Use Case */
4684
        // $contentId is the ID of the "Members" user group in an eZ Publish
4685
        // demo installation
4686
4687
        // $locationId is the ID of the "Administrator users" group location
4688
4689
        // Load content object to copy
4690
        $content = $this->contentService->loadContent($contentId);
4691
4692
        // Create new target location
4693
        $locationCreate = $this->locationService->newLocationCreateStruct($locationId);
4694
4695
        // Start a new transaction
4696
        $repository->beginTransaction();
4697
4698
        try {
4699
            // Copy content with all versions and drafts
4700
            $contentCopied = $this->contentService->copyContent(
0 ignored issues
show
Unused Code introduced by
$contentCopied 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...
4701
                $content->contentInfo,
4702
                $locationCreate
4703
            );
4704
4705
            // Commit all changes
4706
            $repository->commit();
4707
        } catch (Exception $e) {
4708
            // Cleanup hanging transaction on error
4709
            $repository->rollback();
4710
            throw $e;
4711
        }
4712
4713
        $this->refreshSearch($repository);
4714
4715
        // This will contain the admin user and the new child location
4716
        $locations = $this->locationService->loadLocationChildren(
4717
            $this->locationService->loadLocation($locationId)
4718
        )->locations;
4719
        /* END: Use Case */
4720
4721
        $this->assertEquals(2, count($locations));
4722
    }
4723
4724
    public function testURLAliasesCreatedForNewContent()
4725
    {
4726
        $urlAliasService = $this->getRepository()->getURLAliasService();
4727
4728
        /* BEGIN: Use Case */
4729
        $draft = $this->createContentDraftVersion1();
4730
4731
        // Automatically creates a new URLAlias for the content
4732
        $liveContent = $this->contentService->publishVersion($draft->getVersionInfo());
4733
        /* END: Use Case */
4734
4735
        $location = $this->locationService->loadLocation(
4736
            $liveContent->getVersionInfo()->getContentInfo()->mainLocationId
4737
        );
4738
4739
        $aliases = $urlAliasService->listLocationAliases($location, false);
4740
4741
        $this->assertAliasesCorrect(
4742
            [
4743
                '/Design/Plain-site/An-awesome-forum' => [
4744
                    'type' => URLAlias::LOCATION,
4745
                    'destination' => $location->id,
4746
                    'path' => '/Design/Plain-site/An-awesome-forum',
4747
                    'languageCodes' => ['eng-US'],
4748
                    'isHistory' => false,
4749
                    'isCustom' => false,
4750
                    'forward' => false,
4751
                ],
4752
            ],
4753
            $aliases
4754
        );
4755
    }
4756
4757
    public function testURLAliasesCreatedForUpdatedContent()
4758
    {
4759
        $urlAliasService = $this->getRepository()->getURLAliasService();
4760
4761
        /* BEGIN: Use Case */
4762
        $draft = $this->createUpdatedDraftVersion2();
4763
4764
        $location = $this->locationService->loadLocation(
4765
            $draft->getVersionInfo()->getContentInfo()->mainLocationId
4766
        );
4767
4768
        // Load and assert URL aliases before publishing updated Content, so that
4769
        // SPI cache is warmed up and cache invalidation is also tested.
4770
        $aliases = $urlAliasService->listLocationAliases($location, false);
4771
4772
        $this->assertAliasesCorrect(
4773
            [
4774
                '/Design/Plain-site/An-awesome-forum' => [
4775
                    'type' => URLAlias::LOCATION,
4776
                    'destination' => $location->id,
4777
                    'path' => '/Design/Plain-site/An-awesome-forum',
4778
                    'languageCodes' => ['eng-US'],
4779
                    'alwaysAvailable' => true,
4780
                    'isHistory' => false,
4781
                    'isCustom' => false,
4782
                    'forward' => false,
4783
                ],
4784
            ],
4785
            $aliases
4786
        );
4787
4788
        // Automatically marks old aliases for the content as history
4789
        // and creates new aliases, based on the changes
4790
        $liveContent = $this->contentService->publishVersion($draft->getVersionInfo());
4791
        /* END: Use Case */
4792
4793
        $location = $this->locationService->loadLocation(
4794
            $liveContent->getVersionInfo()->getContentInfo()->mainLocationId
4795
        );
4796
4797
        $aliases = $urlAliasService->listLocationAliases($location, false);
4798
4799
        $this->assertAliasesCorrect(
4800
            [
4801
                '/Design/Plain-site/An-awesome-forum2' => [
4802
                    'type' => URLAlias::LOCATION,
4803
                    'destination' => $location->id,
4804
                    'path' => '/Design/Plain-site/An-awesome-forum2',
4805
                    'languageCodes' => ['eng-US'],
4806
                    'alwaysAvailable' => true,
4807
                    'isHistory' => false,
4808
                    'isCustom' => false,
4809
                    'forward' => false,
4810
                ],
4811
                '/Design/Plain-site/An-awesome-forum23' => [
4812
                    'type' => URLAlias::LOCATION,
4813
                    'destination' => $location->id,
4814
                    'path' => '/Design/Plain-site/An-awesome-forum23',
4815
                    'languageCodes' => ['eng-GB'],
4816
                    'alwaysAvailable' => true,
4817
                    'isHistory' => false,
4818
                    'isCustom' => false,
4819
                    'forward' => false,
4820
                ],
4821
            ],
4822
            $aliases
4823
        );
4824
    }
4825
4826
    public function testCustomURLAliasesNotHistorizedOnUpdatedContent()
4827
    {
4828
        /* BEGIN: Use Case */
4829
        $urlAliasService = $this->getRepository()->getURLAliasService();
4830
4831
        $content = $this->createContentVersion1();
4832
4833
        // Create a custom URL alias
4834
        $urlAliasService->createUrlAlias(
4835
            $this->locationService->loadLocation(
4836
                $content->getVersionInfo()->getContentInfo()->mainLocationId
4837
            ),
4838
            '/my/fancy/story-about-ez-publish',
4839
            'eng-US'
4840
        );
4841
4842
        $draftVersion2 = $this->contentService->createContentDraft($content->contentInfo);
4843
4844
        $contentUpdate = $this->contentService->newContentUpdateStruct();
4845
        $contentUpdate->initialLanguageCode = 'eng-US';
4846
        $contentUpdate->setField('name', 'Amazing Bielefeld forum');
4847
4848
        $draftVersion2 = $this->contentService->updateContent(
4849
            $draftVersion2->getVersionInfo(),
4850
            $contentUpdate
4851
        );
4852
4853
        // Only marks auto-generated aliases as history
4854
        // the custom one is left untouched
4855
        $liveContent = $this->contentService->publishVersion($draftVersion2->getVersionInfo());
4856
        /* END: Use Case */
4857
4858
        $location = $this->locationService->loadLocation(
4859
            $liveContent->getVersionInfo()->getContentInfo()->mainLocationId
4860
        );
4861
4862
        $aliases = $urlAliasService->listLocationAliases($location);
4863
4864
        $this->assertAliasesCorrect(
4865
            [
4866
                '/my/fancy/story-about-ez-publish' => [
4867
                    'type' => URLAlias::LOCATION,
4868
                    'destination' => $location->id,
4869
                    'path' => '/my/fancy/story-about-ez-publish',
4870
                    'languageCodes' => ['eng-US'],
4871
                    'isHistory' => false,
4872
                    'isCustom' => true,
4873
                    'forward' => false,
4874
                    'alwaysAvailable' => false,
4875
                ],
4876
            ],
4877
            $aliases
4878
        );
4879
    }
4880
4881
    /**
4882
     * Test to ensure that old versions are not affected by updates to newer
4883
     * drafts.
4884
     */
4885
    public function testUpdatingDraftDoesNotUpdateOldVersions()
4886
    {
4887
        $contentVersion2 = $this->createContentVersion2();
4888
4889
        $loadedContent1 = $this->contentService->loadContent($contentVersion2->id, null, 1);
4890
        $loadedContent2 = $this->contentService->loadContent($contentVersion2->id, null, 2);
4891
4892
        $this->assertNotEquals(
4893
            $loadedContent1->getFieldValue('name', 'eng-US'),
4894
            $loadedContent2->getFieldValue('name', 'eng-US')
4895
        );
4896
    }
4897
4898
    /**
4899
     * Test scenario with writer and publisher users.
4900
     * Writer can only create content. Publisher can publish this content.
4901
     */
4902
    public function testPublishWorkflow()
4903
    {
4904
        $this->createRoleWithPolicies('Publisher', [
4905
            ['module' => 'content', 'function' => 'read'],
4906
            ['module' => 'content', 'function' => 'create'],
4907
            ['module' => 'content', 'function' => 'publish'],
4908
        ]);
4909
4910
        $this->createRoleWithPolicies('Writer', [
4911
            ['module' => 'content', 'function' => 'read'],
4912
            ['module' => 'content', 'function' => 'create'],
4913
        ]);
4914
4915
        $writerUser = $this->createCustomUserWithLogin(
4916
            'writer',
4917
            '[email protected]',
4918
            'Writers',
4919
            'Writer'
4920
        );
4921
4922
        $publisherUser = $this->createCustomUserWithLogin(
4923
            'publisher',
4924
            '[email protected]',
4925
            'Publishers',
4926
            'Publisher'
4927
        );
4928
4929
        $this->permissionResolver->setCurrentUserReference($writerUser);
4930
        $draft = $this->createContentDraftVersion1();
4931
4932
        $this->permissionResolver->setCurrentUserReference($publisherUser);
4933
        $content = $this->contentService->publishVersion($draft->versionInfo);
4934
4935
        $this->contentService->loadContent($content->id);
4936
    }
4937
4938
    /**
4939
     * Test publish / content policy is required to be able to publish content.
4940
     */
4941
    public function testPublishContentWithoutPublishPolicyThrowsException()
4942
    {
4943
        $this->createRoleWithPolicies('Writer', [
4944
            ['module' => 'content', 'function' => 'read'],
4945
            ['module' => 'content', 'function' => 'create'],
4946
            ['module' => 'content', 'function' => 'edit'],
4947
        ]);
4948
        $writerUser = $this->createCustomUserWithLogin(
4949
            'writer',
4950
            '[email protected]',
4951
            'Writers',
4952
            'Writer'
4953
        );
4954
        $this->permissionResolver->setCurrentUserReference($writerUser);
4955
4956
        $this->expectException(CoreUnauthorizedException::class);
4957
        $this->expectExceptionMessageRegExp('/User does not have access to \'publish\' \'content\'/');
4958
4959
        $this->createContentVersion1();
4960
    }
4961
4962
    /**
4963
     * Test removal of the specific translation from all the Versions of a Content Object.
4964
     *
4965
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslation
4966
     */
4967
    public function testDeleteTranslation()
4968
    {
4969
        $content = $this->createContentVersion2();
4970
4971
        // create multiple versions to exceed archive limit
4972
        for ($i = 0; $i < 5; ++$i) {
4973
            $contentDraft = $this->contentService->createContentDraft($content->contentInfo);
4974
            $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
4975
            $contentDraft = $this->contentService->updateContent(
4976
                $contentDraft->versionInfo,
4977
                $contentUpdateStruct
4978
            );
4979
            $this->contentService->publishVersion($contentDraft->versionInfo);
4980
        }
4981
4982
        $this->contentService->deleteTranslation($content->contentInfo, 'eng-GB');
4983
4984
        $this->assertTranslationDoesNotExist('eng-GB', $content->id);
4985
    }
4986
4987
    /**
4988
     * Test deleting a Translation which is initial for some Version, updates initialLanguageCode
4989
     * with mainLanguageCode (assuming they are different).
4990
     */
4991
    public function testDeleteTranslationUpdatesInitialLanguageCodeVersion()
4992
    {
4993
        $content = $this->createContentVersion2();
4994
        // create another, copied, version
4995
        $contentDraft = $this->contentService->updateContent(
4996
            $this->contentService->createContentDraft($content->contentInfo)->versionInfo,
4997
            $this->contentService->newContentUpdateStruct()
4998
        );
4999
        $publishedContent = $this->contentService->publishVersion($contentDraft->versionInfo);
5000
5001
        // remove first version with only one translation as it is not the subject of this test
5002
        $this->contentService->deleteVersion(
5003
            $this->contentService->loadVersionInfo($publishedContent->contentInfo, 1)
5004
        );
5005
5006
        // sanity check
5007
        self::assertEquals('eng-US', $content->contentInfo->mainLanguageCode);
5008
        self::assertEquals('eng-US', $content->versionInfo->initialLanguageCode);
5009
5010
        // update mainLanguageCode so it is different than initialLanguageCode for Version
5011
        $contentMetadataUpdateStruct = $this->contentService->newContentMetadataUpdateStruct();
5012
        $contentMetadataUpdateStruct->mainLanguageCode = 'eng-GB';
5013
        $content = $this->contentService->updateContentMetadata($publishedContent->contentInfo, $contentMetadataUpdateStruct);
5014
5015
        $this->contentService->deleteTranslation($content->contentInfo, 'eng-US');
5016
5017
        $this->assertTranslationDoesNotExist('eng-US', $content->id);
5018
    }
5019
5020
    /**
5021
     * Test removal of the specific translation properly updates languages of the URL alias.
5022
     *
5023
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslation
5024
     */
5025
    public function testDeleteTranslationUpdatesUrlAlias()
5026
    {
5027
        $urlAliasService = $this->getRepository()->getURLAliasService();
5028
5029
        $content = $this->createContentVersion2();
5030
        $mainLocation = $this->locationService->loadLocation($content->contentInfo->mainLocationId);
5031
5032
        // create custom URL alias for Content main Location
5033
        $urlAliasService->createUrlAlias($mainLocation, '/my-custom-url', 'eng-GB');
5034
5035
        // create secondary Location for Content
5036
        $secondaryLocation = $this->locationService->createLocation(
5037
            $content->contentInfo,
5038
            $this->locationService->newLocationCreateStruct(2)
5039
        );
5040
5041
        // create custom URL alias for Content secondary Location
5042
        $urlAliasService->createUrlAlias($secondaryLocation, '/my-secondary-url', 'eng-GB');
5043
5044
        // delete Translation
5045
        $this->contentService->deleteTranslation($content->contentInfo, 'eng-GB');
5046
5047
        foreach ([$mainLocation, $secondaryLocation] as $location) {
5048
            // check auto-generated URL aliases
5049
            foreach ($urlAliasService->listLocationAliases($location, false) as $alias) {
5050
                self::assertNotContains('eng-GB', $alias->languageCodes);
5051
            }
5052
5053
            // check custom URL aliases
5054
            foreach ($urlAliasService->listLocationAliases($location) as $alias) {
5055
                self::assertNotContains('eng-GB', $alias->languageCodes);
5056
            }
5057
        }
5058
    }
5059
5060
    /**
5061
     * Test removal of a main translation throws BadStateException.
5062
     *
5063
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslation
5064
     */
5065
    public function testDeleteTranslationMainLanguageThrowsBadStateException()
5066
    {
5067
        $content = $this->createContentVersion2();
5068
5069
        // delete first version which has only one translation
5070
        $this->contentService->deleteVersion($this->contentService->loadVersionInfo($content->contentInfo, 1));
5071
5072
        // try to delete main translation
5073
        $this->expectException(BadStateException::class);
5074
        $this->expectExceptionMessage('Specified translation is the main translation of the Content Object');
5075
5076
        $this->contentService->deleteTranslation($content->contentInfo, $content->contentInfo->mainLanguageCode);
5077
    }
5078
5079
    /**
5080
     * Test removal of a Translation is possible when some archived Versions have only this Translation.
5081
     *
5082
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslation
5083
     */
5084
    public function testDeleteTranslationDeletesSingleTranslationVersions()
5085
    {
5086
        // content created by the createContentVersion1 method has eng-US translation only.
5087
        $content = $this->createContentVersion1();
5088
5089
        // create new version and add eng-GB translation
5090
        $contentDraft = $this->contentService->createContentDraft($content->contentInfo);
5091
        $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
5092
        $contentUpdateStruct->setField('name', 'Awesome Board', 'eng-GB');
5093
        $contentDraft = $this->contentService->updateContent($contentDraft->versionInfo, $contentUpdateStruct);
5094
        $publishedContent = $this->contentService->publishVersion($contentDraft->versionInfo);
5095
5096
        // update mainLanguageCode to avoid exception related to that
5097
        $contentMetadataUpdateStruct = $this->contentService->newContentMetadataUpdateStruct();
5098
        $contentMetadataUpdateStruct->mainLanguageCode = 'eng-GB';
5099
5100
        $content = $this->contentService->updateContentMetadata($publishedContent->contentInfo, $contentMetadataUpdateStruct);
5101
5102
        $this->contentService->deleteTranslation($content->contentInfo, 'eng-US');
5103
5104
        $this->assertTranslationDoesNotExist('eng-US', $content->id);
5105
    }
5106
5107
    /**
5108
     * Test removal of the translation by the user who is not allowed to delete a content
5109
     * throws UnauthorizedException.
5110
     *
5111
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslation
5112
     */
5113
    public function testDeleteTranslationThrowsUnauthorizedException()
5114
    {
5115
        $content = $this->createContentVersion2();
5116
5117
        // create user that can read/create/edit but cannot delete content
5118
        $this->createRoleWithPolicies('Writer', [
5119
            ['module' => 'content', 'function' => 'read'],
5120
            ['module' => 'content', 'function' => 'versionread'],
5121
            ['module' => 'content', 'function' => 'create'],
5122
            ['module' => 'content', 'function' => 'edit'],
5123
        ]);
5124
        $writerUser = $this->createCustomUserWithLogin(
5125
            'writer',
5126
            '[email protected]',
5127
            'Writers',
5128
            'Writer'
5129
        );
5130
        $this->permissionResolver->setCurrentUserReference($writerUser);
5131
5132
        $this->expectException(UnauthorizedException::class);
5133
        $this->expectExceptionMessage('User does not have access to \'remove\' \'content\'');
5134
5135
        $this->contentService->deleteTranslation($content->contentInfo, 'eng-GB');
5136
    }
5137
5138
    /**
5139
     * Test removal of a non-existent translation throws InvalidArgumentException.
5140
     *
5141
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslation
5142
     */
5143
    public function testDeleteTranslationThrowsInvalidArgumentException()
5144
    {
5145
        // content created by the createContentVersion1 method has eng-US translation only.
5146
        $content = $this->createContentVersion1();
5147
5148
        $this->expectException(APIInvalidArgumentException::class);
5149
        $this->expectExceptionMessage('Argument \'$languageCode\' is invalid: ger-DE does not exist in the Content item');
5150
5151
        $this->contentService->deleteTranslation($content->contentInfo, 'ger-DE');
5152
    }
5153
5154
    /**
5155
     * Test deleting a Translation from Draft.
5156
     *
5157
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslationFromDraft
5158
     */
5159
    public function testDeleteTranslationFromDraft()
5160
    {
5161
        $languageCode = 'eng-GB';
5162
        $content = $this->createMultipleLanguageContentVersion2();
5163
        $draft = $this->contentService->createContentDraft($content->contentInfo);
5164
        $draft = $this->contentService->deleteTranslationFromDraft($draft->versionInfo, $languageCode);
5165
        $content = $this->contentService->publishVersion($draft->versionInfo);
5166
5167
        $loadedContent = $this->contentService->loadContent($content->id);
5168
        self::assertNotContains($languageCode, $loadedContent->versionInfo->languageCodes);
5169
        self::assertEmpty($loadedContent->getFieldsByLanguage($languageCode));
5170
    }
5171
5172
    /**
5173
     * Get values for multilingual field.
5174
     *
5175
     * @return array
5176
     */
5177
    public function providerForDeleteTranslationFromDraftRemovesUrlAliasOnPublishing()
5178
    {
5179
        return [
5180
            [
5181
                ['eng-US' => 'US Name', 'eng-GB' => 'GB Name'],
5182
            ],
5183
            [
5184
                ['eng-US' => 'Same Name', 'eng-GB' => 'Same Name'],
5185
            ],
5186
        ];
5187
    }
5188
5189
    /**
5190
     * Test deleting a Translation from Draft removes previously stored URL aliases for published Content.
5191
     *
5192
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslationFromDraft
5193
     *
5194
     * @dataProvider providerForDeleteTranslationFromDraftRemovesUrlAliasOnPublishing
5195
     *
5196
     * @param string[] $fieldValues translated field values
5197
     *
5198
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
5199
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
5200
     * @throws NotFoundException
5201
     * @throws UnauthorizedException
5202
     */
5203
    public function testDeleteTranslationFromDraftRemovesUrlAliasOnPublishing(array $fieldValues)
5204
    {
5205
        $urlAliasService = $this->getRepository()->getURLAliasService();
5206
5207
        // set language code to be removed
5208
        $languageCode = 'eng-GB';
5209
        $draft = $this->createMultilingualContentDraft(
5210
            'folder',
5211
            2,
5212
            'eng-US',
5213
            [
5214
                'name' => [
5215
                    'eng-GB' => $fieldValues['eng-GB'],
5216
                    'eng-US' => $fieldValues['eng-US'],
5217
                ],
5218
            ]
5219
        );
5220
        $content = $this->contentService->publishVersion($draft->versionInfo);
5221
5222
        // create secondary location
5223
        $this->locationService->createLocation(
5224
            $content->contentInfo,
5225
            $this->locationService->newLocationCreateStruct(5)
5226
        );
5227
5228
        // sanity check
5229
        $locations = $this->locationService->loadLocations($content->contentInfo);
5230
        self::assertCount(2, $locations, 'Sanity check: Expected to find 2 Locations');
5231
        foreach ($locations as $location) {
5232
            $urlAliasService->createUrlAlias($location, '/us-custom_' . $location->id, 'eng-US');
5233
            $urlAliasService->createUrlAlias($location, '/gb-custom_' . $location->id, 'eng-GB');
5234
5235
            // check default URL aliases
5236
            $aliases = $urlAliasService->listLocationAliases($location, false, $languageCode);
5237
            self::assertNotEmpty($aliases, 'Sanity check: URL alias for the translation does not exist');
5238
5239
            // check custom URL aliases
5240
            $aliases = $urlAliasService->listLocationAliases($location, true, $languageCode);
5241
            self::assertNotEmpty($aliases, 'Sanity check: Custom URL alias for the translation does not exist');
5242
        }
5243
5244
        // delete translation and publish new version
5245
        $draft = $this->contentService->createContentDraft($content->contentInfo);
5246
        $draft = $this->contentService->deleteTranslationFromDraft($draft->versionInfo, $languageCode);
5247
        $this->contentService->publishVersion($draft->versionInfo);
5248
5249
        // check that aliases does not exist
5250
        foreach ($locations as $location) {
5251
            // check default URL aliases
5252
            $aliases = $urlAliasService->listLocationAliases($location, false, $languageCode);
5253
            self::assertEmpty($aliases, 'URL alias for the deleted translation still exists');
5254
5255
            // check custom URL aliases
5256
            $aliases = $urlAliasService->listLocationAliases($location, true, $languageCode);
5257
            self::assertEmpty($aliases, 'Custom URL alias for the deleted translation still exists');
5258
        }
5259
    }
5260
5261
    /**
5262
     * Test that URL aliases for deleted Translations are properly archived.
5263
     */
5264
    public function testDeleteTranslationFromDraftArchivesUrlAliasOnPublishing()
5265
    {
5266
        $urlAliasService = $this->getRepository()->getURLAliasService();
5267
5268
        $content = $this->contentService->publishVersion(
5269
            $this->createMultilingualContentDraft(
5270
                'folder',
5271
                2,
5272
                'eng-US',
5273
                [
5274
                    'name' => [
5275
                        'eng-GB' => 'BritishEnglishContent',
5276
                        'eng-US' => 'AmericanEnglishContent',
5277
                    ],
5278
                ]
5279
            )->versionInfo
5280
        );
5281
5282
        $unrelatedContent = $this->contentService->publishVersion(
5283
            $this->createMultilingualContentDraft(
5284
                'folder',
5285
                2,
5286
                'eng-US',
5287
                [
5288
                    'name' => [
5289
                        'eng-GB' => 'AnotherBritishContent',
5290
                        'eng-US' => 'AnotherAmericanContent',
5291
                    ],
5292
                ]
5293
            )->versionInfo
5294
        );
5295
5296
        $urlAlias = $urlAliasService->lookup('/BritishEnglishContent');
5297
        self::assertFalse($urlAlias->isHistory);
5298
        self::assertEquals($urlAlias->path, '/BritishEnglishContent');
5299
        self::assertEquals($urlAlias->destination, $content->contentInfo->mainLocationId);
5300
5301
        $draft = $this->contentService->deleteTranslationFromDraft(
5302
            $this->contentService->createContentDraft($content->contentInfo)->versionInfo,
5303
            'eng-GB'
5304
        );
5305
        $content = $this->contentService->publishVersion($draft->versionInfo);
5306
5307
        $urlAlias = $urlAliasService->lookup('/BritishEnglishContent');
5308
        self::assertTrue($urlAlias->isHistory);
5309
        self::assertEquals($urlAlias->path, '/BritishEnglishContent');
5310
        self::assertEquals($urlAlias->destination, $content->contentInfo->mainLocationId);
5311
5312
        $unrelatedUrlAlias = $urlAliasService->lookup('/AnotherBritishContent');
5313
        self::assertFalse($unrelatedUrlAlias->isHistory);
5314
        self::assertEquals($unrelatedUrlAlias->path, '/AnotherBritishContent');
5315
        self::assertEquals($unrelatedUrlAlias->destination, $unrelatedContent->contentInfo->mainLocationId);
5316
    }
5317
5318
    /**
5319
     * Test deleting a Translation from Draft which has single Translation throws BadStateException.
5320
     *
5321
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslationFromDraft
5322
     */
5323
    public function testDeleteTranslationFromDraftThrowsBadStateExceptionOnSingleTranslation()
5324
    {
5325
        // create Content with single Translation
5326
        $publishedContent = $this->contentService->publishVersion(
5327
            $this->createContentDraft(
5328
                'forum',
5329
                2,
5330
                ['name' => 'Eng-US Version name']
5331
            )->versionInfo
5332
        );
5333
5334
        // update mainLanguageCode to avoid exception related to trying to delete main Translation
5335
        $contentMetadataUpdateStruct = $this->contentService->newContentMetadataUpdateStruct();
5336
        $contentMetadataUpdateStruct->mainLanguageCode = 'eng-GB';
5337
        $publishedContent = $this->contentService->updateContentMetadata(
5338
            $publishedContent->contentInfo,
5339
            $contentMetadataUpdateStruct
5340
        );
5341
5342
        // create single Translation Version from the first one
5343
        $draft = $this->contentService->createContentDraft(
5344
            $publishedContent->contentInfo,
5345
            $publishedContent->versionInfo
5346
        );
5347
5348
        $this->expectException(BadStateException::class);
5349
        $this->expectExceptionMessage('Specified Translation is the only one Content Object Version has');
5350
5351
        // attempt to delete Translation
5352
        $this->contentService->deleteTranslationFromDraft($draft->versionInfo, 'eng-US');
5353
    }
5354
5355
    /**
5356
     * Test deleting the Main Translation from Draft throws BadStateException.
5357
     *
5358
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslationFromDraft
5359
     */
5360
    public function testDeleteTranslationFromDraftThrowsBadStateExceptionOnMainTranslation()
5361
    {
5362
        $mainLanguageCode = 'eng-US';
5363
        $draft = $this->createMultilingualContentDraft(
5364
            'forum',
5365
            2,
5366
            $mainLanguageCode,
5367
            [
5368
                'name' => [
5369
                    'eng-US' => 'An awesome eng-US forum',
5370
                    'eng-GB' => 'An awesome eng-GB forum',
5371
                ],
5372
            ]
5373
        );
5374
5375
        $this->expectException(BadStateException::class);
5376
        $this->expectExceptionMessage('Specified Translation is the main Translation of the Content Object');
5377
5378
        $this->contentService->deleteTranslationFromDraft($draft->versionInfo, $mainLanguageCode);
5379
    }
5380
5381
    /**
5382
     * Test deleting the Translation from Published Version throws BadStateException.
5383
     *
5384
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslationFromDraft
5385
     */
5386
    public function testDeleteTranslationFromDraftThrowsBadStateExceptionOnPublishedVersion()
5387
    {
5388
        $languageCode = 'eng-US';
5389
        $content = $this->createMultipleLanguageContentVersion2();
5390
        $draft = $this->contentService->createContentDraft($content->contentInfo);
5391
        $publishedContent = $this->contentService->publishVersion($draft->versionInfo);
5392
5393
        $this->expectException(BadStateException::class);
5394
        $this->expectExceptionMessage('Version is not a draft');
5395
5396
        $this->contentService->deleteTranslationFromDraft($publishedContent->versionInfo, $languageCode);
5397
    }
5398
5399
    /**
5400
     * Test deleting a Translation from Draft throws UnauthorizedException if user cannot edit Content.
5401
     *
5402
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslationFromDraft
5403
     */
5404
    public function testDeleteTranslationFromDraftThrowsUnauthorizedException()
5405
    {
5406
        $languageCode = 'eng-GB';
5407
        $content = $this->createMultipleLanguageContentVersion2();
5408
        $draft = $this->contentService->createContentDraft($content->contentInfo);
5409
5410
        // create user that can read/create/delete but cannot edit or content
5411
        $this->createRoleWithPolicies('Writer', [
5412
            ['module' => 'content', 'function' => 'read'],
5413
            ['module' => 'content', 'function' => 'versionread'],
5414
            ['module' => 'content', 'function' => 'create'],
5415
            ['module' => 'content', 'function' => 'delete'],
5416
        ]);
5417
        $writerUser = $this->createCustomUserWithLogin(
5418
            'user',
5419
            '[email protected]',
5420
            'Writers',
5421
            'Writer'
5422
        );
5423
        $this->permissionResolver->setCurrentUserReference($writerUser);
5424
5425
        $this->expectException(UnauthorizedException::class);
5426
        $this->expectExceptionMessage('User does not have access to \'edit\' \'content\'');
5427
5428
        $this->contentService->deleteTranslationFromDraft($draft->versionInfo, $languageCode);
5429
    }
5430
5431
    /**
5432
     * Test deleting a non-existent Translation from Draft throws InvalidArgumentException.
5433
     *
5434
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslationFromDraft
5435
     */
5436
    public function testDeleteTranslationFromDraftThrowsInvalidArgumentException()
5437
    {
5438
        $languageCode = 'ger-DE';
5439
        $content = $this->createMultipleLanguageContentVersion2();
5440
        $draft = $this->contentService->createContentDraft($content->contentInfo);
5441
        $this->expectException(APIInvalidArgumentException::class);
5442
        $this->expectExceptionMessageRegExp('/The Version \(ContentId=\d+, VersionNo=\d+\) is not translated into ger-DE/');
5443
        $this->contentService->deleteTranslationFromDraft($draft->versionInfo, $languageCode);
5444
    }
5445
5446
    /**
5447
     * Test loading list of Content items.
5448
     */
5449
    public function testLoadContentListByContentInfo()
5450
    {
5451
        $allLocationsCount = $this->locationService->getAllLocationsCount();
5452
        $contentInfoList = array_map(
5453
            function (Location $location) {
5454
                return $location->contentInfo;
5455
            },
5456
            $this->locationService->loadAllLocations(0, $allLocationsCount)
5457
        );
5458
5459
        $contentList = $this->contentService->loadContentListByContentInfo($contentInfoList);
5460
        self::assertCount(count($contentInfoList), $contentList);
5461
        foreach ($contentList as $content) {
5462
            try {
5463
                $loadedContent = $this->contentService->loadContent($content->id);
5464
                self::assertEquals($loadedContent, $content, "Failed to properly bulk-load Content {$content->id}");
5465
            } catch (NotFoundException $e) {
5466
                self::fail("Failed to load Content {$content->id}: {$e->getMessage()}");
5467
            } catch (UnauthorizedException $e) {
5468
                self::fail("Failed to load Content {$content->id}: {$e->getMessage()}");
5469
            }
5470
        }
5471
    }
5472
5473
    /**
5474
     * Test loading content versions after removing exactly two drafts.
5475
     *
5476
     * @see https://jira.ez.no/browse/EZP-30271
5477
     *
5478
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteVersion
5479
     */
5480
    public function testLoadVersionsAfterDeletingTwoDrafts()
5481
    {
5482
        $content = $this->createFolder(['eng-GB' => 'Foo'], 2);
5483
5484
        // First update and publish
5485
        $modifiedContent = $this->updateFolder($content, ['eng-GB' => 'Foo1']);
5486
        $content = $this->contentService->publishVersion($modifiedContent->versionInfo);
5487
5488
        // Second update and publish
5489
        $modifiedContent = $this->updateFolder($content, ['eng-GB' => 'Foo2']);
5490
        $content = $this->contentService->publishVersion($modifiedContent->versionInfo);
5491
5492
        // Create drafts
5493
        $this->updateFolder($content, ['eng-GB' => 'Foo3']);
5494
        $this->updateFolder($content, ['eng-GB' => 'Foo4']);
5495
5496
        $versions = $this->contentService->loadVersions($content->contentInfo);
5497
5498
        foreach ($versions as $key => $version) {
5499
            if ($version->isDraft()) {
5500
                $this->contentService->deleteVersion($version);
5501
                unset($versions[$key]);
5502
            }
5503
        }
5504
5505
        $this->assertEquals($versions, $this->contentService->loadVersions($content->contentInfo));
5506
    }
5507
5508
    /**
5509
     * Tests loading list of content versions of status draft.
5510
     */
5511
    public function testLoadVersionsOfStatusDraft()
5512
    {
5513
        $content = $this->createContentVersion1();
5514
5515
        $this->contentService->createContentDraft($content->contentInfo);
5516
        $this->contentService->createContentDraft($content->contentInfo);
5517
        $this->contentService->createContentDraft($content->contentInfo);
5518
5519
        $versions = $this->contentService->loadVersions($content->contentInfo, VersionInfo::STATUS_DRAFT);
5520
5521
        $this->assertSame(\count($versions), 3);
5522
    }
5523
5524
    /**
5525
     * Tests loading list of content versions of status archived.
5526
     */
5527
    public function testLoadVersionsOfStatusArchived()
5528
    {
5529
        $content = $this->createContentVersion1();
5530
5531
        $draft1 = $this->contentService->createContentDraft($content->contentInfo);
5532
        $this->contentService->publishVersion($draft1->versionInfo);
5533
5534
        $draft2 = $this->contentService->createContentDraft($content->contentInfo);
5535
        $this->contentService->publishVersion($draft2->versionInfo);
5536
5537
        $versions = $this->contentService->loadVersions($content->contentInfo, VersionInfo::STATUS_ARCHIVED);
5538
5539
        $this->assertSame(\count($versions), 2);
5540
    }
5541
5542
    /**
5543
     * Asserts that all aliases defined in $expectedAliasProperties with the
5544
     * given properties are available in $actualAliases and not more.
5545
     *
5546
     * @param array $expectedAliasProperties
5547
     * @param array $actualAliases
5548
     */
5549
    private function assertAliasesCorrect(array $expectedAliasProperties, array $actualAliases)
5550
    {
5551
        foreach ($actualAliases as $actualAlias) {
5552
            if (!isset($expectedAliasProperties[$actualAlias->path])) {
5553
                $this->fail(
5554
                    sprintf(
5555
                        'Alias with path "%s" in languages "%s" not expected.',
5556
                        $actualAlias->path,
5557
                        implode(', ', $actualAlias->languageCodes)
5558
                    )
5559
                );
5560
            }
5561
5562
            foreach ($expectedAliasProperties[$actualAlias->path] as $propertyName => $propertyValue) {
5563
                $this->assertEquals(
5564
                    $propertyValue,
5565
                    $actualAlias->$propertyName,
5566
                    sprintf(
5567
                        'Property $%s incorrect on alias with path "%s" in languages "%s".',
5568
                        $propertyName,
5569
                        $actualAlias->path,
5570
                        implode(', ', $actualAlias->languageCodes)
5571
                    )
5572
                );
5573
            }
5574
5575
            unset($expectedAliasProperties[$actualAlias->path]);
5576
        }
5577
5578
        if (!empty($expectedAliasProperties)) {
5579
            $this->fail(
5580
                sprintf(
5581
                    'Missing expected aliases with paths "%s".',
5582
                    implode('", "', array_keys($expectedAliasProperties))
5583
                )
5584
            );
5585
        }
5586
    }
5587
5588
    /**
5589
     * Asserts that the given fields are equal to the default fields fixture.
5590
     *
5591
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $fields
5592
     */
5593
    private function assertAllFieldsEquals(array $fields)
5594
    {
5595
        $actual = $this->normalizeFields($fields);
5596
        $expected = $this->normalizeFields($this->createFieldsFixture());
5597
5598
        $this->assertEquals($expected, $actual);
5599
    }
5600
5601
    /**
5602
     * Asserts that the given fields are equal to a language filtered set of the
5603
     * default fields fixture.
5604
     *
5605
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $fields
5606
     * @param string $languageCode
5607
     */
5608
    private function assertLocaleFieldsEquals(array $fields, $languageCode)
5609
    {
5610
        $actual = $this->normalizeFields($fields);
5611
5612
        $expected = [];
5613
        foreach ($this->normalizeFields($this->createFieldsFixture()) as $field) {
5614
            if ($field->languageCode !== $languageCode) {
5615
                continue;
5616
            }
5617
            $expected[] = $field;
5618
        }
5619
5620
        $this->assertEquals($expected, $actual);
5621
    }
5622
5623
    /**
5624
     * This method normalizes a set of fields and returns a normalized set.
5625
     *
5626
     * Normalization means it resets the storage specific field id to zero and
5627
     * it sorts the field by their identifier and their language code. In
5628
     * addition, the field value is removed, since this one depends on the
5629
     * specific FieldType, which is tested in a dedicated integration test.
5630
     *
5631
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $fields
5632
     *
5633
     * @return \eZ\Publish\API\Repository\Values\Content\Field[]
5634
     */
5635
    private function normalizeFields(array $fields)
5636
    {
5637
        $normalized = [];
5638
        foreach ($fields as $field) {
5639
            $normalized[] = new Field(
5640
                [
5641
                    'id' => 0,
5642
                    'value' => ($field->value !== null ? true : null),
5643
                    'languageCode' => $field->languageCode,
5644
                    'fieldDefIdentifier' => $field->fieldDefIdentifier,
5645
                    'fieldTypeIdentifier' => $field->fieldTypeIdentifier,
5646
                ]
5647
            );
5648
        }
5649
        usort(
5650
            $normalized,
5651 View Code Duplication
            function ($field1, $field2) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
5652
                if (0 === ($return = strcasecmp($field1->fieldDefIdentifier, $field2->fieldDefIdentifier))) {
5653
                    return strcasecmp($field1->languageCode, $field2->languageCode);
5654
                }
5655
5656
                return $return;
5657
            }
5658
        );
5659
5660
        return $normalized;
5661
    }
5662
5663
    /**
5664
     * Returns a filtered set of the default fields fixture.
5665
     *
5666
     * @param string $languageCode
5667
     *
5668
     * @return \eZ\Publish\API\Repository\Values\Content\Field[]
5669
     */
5670
    private function createLocaleFieldsFixture($languageCode)
5671
    {
5672
        $fields = [];
5673
        foreach ($this->createFieldsFixture() as $field) {
5674
            if (null === $field->languageCode || $languageCode === $field->languageCode) {
5675
                $fields[] = $field;
5676
            }
5677
        }
5678
5679
        return $fields;
5680
    }
5681
5682
    /**
5683
     * Asserts that given Content has default ContentStates.
5684
     *
5685
     * @param ContentInfo $contentInfo
5686
     */
5687 View Code Duplication
    private function assertDefaultContentStates(ContentInfo $contentInfo)
5688
    {
5689
        $objectStateService = $this->getRepository()->getObjectStateService();
5690
5691
        $objectStateGroups = $objectStateService->loadObjectStateGroups();
5692
5693
        foreach ($objectStateGroups as $objectStateGroup) {
5694
            $contentState = $objectStateService->getContentState($contentInfo, $objectStateGroup);
5695
            foreach ($objectStateService->loadObjectStates($objectStateGroup) as $objectState) {
5696
                // Only check the first object state which is the default one.
5697
                $this->assertEquals(
5698
                    $objectState,
5699
                    $contentState
5700
                );
5701
                break;
5702
            }
5703
        }
5704
    }
5705
5706
    /**
5707
     * Assert that given Content has no references to a translation specified by the $languageCode.
5708
     *
5709
     * @param string $languageCode
5710
     * @param int $contentId
5711
     */
5712
    private function assertTranslationDoesNotExist($languageCode, $contentId)
5713
    {
5714
        $content = $this->contentService->loadContent($contentId);
5715
5716
        foreach ($content->fields as $fieldIdentifier => $field) {
5717
            /** @var array $field */
5718
            self::assertArrayNotHasKey($languageCode, $field);
5719
            self::assertNotEquals($languageCode, $content->contentInfo->mainLanguageCode);
5720
            self::assertArrayNotHasKey($languageCode, $content->versionInfo->getNames());
5721
            self::assertNotEquals($languageCode, $content->versionInfo->initialLanguageCode);
5722
            self::assertNotContains($languageCode, $content->versionInfo->languageCodes);
5723
        }
5724
        foreach ($this->contentService->loadVersions($content->contentInfo) as $versionInfo) {
5725
            self::assertArrayNotHasKey($languageCode, $versionInfo->getNames());
5726
            self::assertNotEquals($languageCode, $versionInfo->contentInfo->mainLanguageCode);
5727
            self::assertNotEquals($languageCode, $versionInfo->initialLanguageCode);
5728
            self::assertNotContains($languageCode, $versionInfo->languageCodes);
5729
        }
5730
    }
5731
5732
    /**
5733
     * Returns the default fixture of fields used in most tests.
5734
     *
5735
     * @return \eZ\Publish\API\Repository\Values\Content\Field[]
5736
     */
5737
    private function createFieldsFixture()
5738
    {
5739
        return [
5740
            new Field(
5741
                [
5742
                    'id' => 0,
5743
                    'value' => 'Foo',
5744
                    'languageCode' => 'eng-US',
5745
                    'fieldDefIdentifier' => 'description',
5746
                    'fieldTypeIdentifier' => 'ezrichtext',
5747
                ]
5748
            ),
5749
            new Field(
5750
                [
5751
                    'id' => 0,
5752
                    'value' => 'Bar',
5753
                    'languageCode' => 'eng-GB',
5754
                    'fieldDefIdentifier' => 'description',
5755
                    'fieldTypeIdentifier' => 'ezrichtext',
5756
                ]
5757
            ),
5758
            new Field(
5759
                [
5760
                    'id' => 0,
5761
                    'value' => 'An awesome multi-lang forum²',
5762
                    'languageCode' => 'eng-US',
5763
                    'fieldDefIdentifier' => 'name',
5764
                    'fieldTypeIdentifier' => 'ezstring',
5765
                ]
5766
            ),
5767
            new Field(
5768
                [
5769
                    'id' => 0,
5770
                    'value' => 'An awesome multi-lang forum²³',
5771
                    'languageCode' => 'eng-GB',
5772
                    'fieldDefIdentifier' => 'name',
5773
                    'fieldTypeIdentifier' => 'ezstring',
5774
                ]
5775
            ),
5776
        ];
5777
    }
5778
5779
    /**
5780
     * Gets expected property values for the "Media" ContentInfo ValueObject.
5781
     *
5782
     * @return array
5783
     */
5784 View Code Duplication
    private function getExpectedMediaContentInfoProperties()
5785
    {
5786
        return [
5787
            'id' => 41,
5788
            'contentTypeId' => 1,
5789
            'name' => 'Media',
5790
            'sectionId' => 3,
5791
            'currentVersionNo' => 1,
5792
            'published' => true,
5793
            'ownerId' => 14,
5794
            'modificationDate' => $this->createDateTime(1060695457),
5795
            'publishedDate' => $this->createDateTime(1060695457),
5796
            'alwaysAvailable' => 1,
5797
            'remoteId' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
5798
            'mainLanguageCode' => 'eng-US',
5799
            'mainLocationId' => 43,
5800
            'status' => ContentInfo::STATUS_PUBLISHED,
5801
        ];
5802
    }
5803
5804
    /**
5805
     * @covers \eZ\Publish\API\Repository\ContentService::hideContent
5806
     *
5807
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
5808
     * @throws NotFoundException
5809
     * @throws UnauthorizedException
5810
     */
5811
    public function testHideContent(): void
5812
    {
5813
        $contentTypeService = $this->getRepository()->getContentTypeService();
5814
5815
        $locationCreateStructs = array_map(
5816
            function (Location $parentLocation) {
5817
                return $this->locationService->newLocationCreateStruct($parentLocation->id);
5818
            },
5819
            $this->createParentLocationsForHideReveal(2)
5820
        );
5821
5822
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
5823
5824
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
5825
        $contentCreate->setField('name', 'Folder to hide');
5826
5827
        $content = $this->contentService->createContent(
5828
            $contentCreate,
5829
            $locationCreateStructs
5830
        );
5831
5832
        $publishedContent = $this->contentService->publishVersion($content->versionInfo);
5833
        $locations = $this->locationService->loadLocations($publishedContent->contentInfo);
5834
5835
        // Sanity check
5836
        $this->assertCount(3, $locations);
5837
        $this->assertCount(0, $this->filterHiddenLocations($locations));
5838
5839
        /* BEGIN: Use Case */
5840
        $this->contentService->hideContent($publishedContent->contentInfo);
5841
        /* END: Use Case */
5842
5843
        $locations = $this->locationService->loadLocations($publishedContent->contentInfo);
5844
        $this->assertCount(3, $locations);
5845
        $this->assertCount(3, $this->filterHiddenLocations($locations));
5846
    }
5847
5848
    /**
5849
     * @covers \eZ\Publish\API\Repository\ContentService::revealContent
5850
     *
5851
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
5852
     * @throws NotFoundException
5853
     * @throws UnauthorizedException
5854
     */
5855
    public function testRevealContent()
5856
    {
5857
        $contentTypeService = $this->getRepository()->getContentTypeService();
5858
5859
        $locationCreateStructs = array_map(
5860
            function (Location $parentLocation) {
5861
                return $this->locationService->newLocationCreateStruct($parentLocation->id);
5862
            },
5863
            $this->createParentLocationsForHideReveal(2)
5864
        );
5865
5866
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
5867
5868
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
5869
        $contentCreate->setField('name', 'Folder to hide');
5870
5871
        $locationCreateStructs[0]->hidden = true;
5872
5873
        $content = $this->contentService->createContent(
5874
            $contentCreate,
5875
            $locationCreateStructs
5876
        );
5877
5878
        $publishedContent = $this->contentService->publishVersion($content->versionInfo);
5879
        $locations = $this->locationService->loadLocations($publishedContent->contentInfo);
5880
5881
        // Sanity check
5882
        $hiddenLocations = $this->filterHiddenLocations($locations);
5883
        $this->assertCount(3, $locations);
5884
        $this->assertCount(1, $hiddenLocations);
5885
5886
        // BEGIN: Use Case
5887
        $this->contentService->hideContent($publishedContent->contentInfo);
5888
        $this->assertCount(
5889
            3,
5890
            $this->filterHiddenLocations(
5891
                $this->locationService->loadLocations($publishedContent->contentInfo)
5892
            )
5893
        );
5894
5895
        $this->contentService->revealContent($publishedContent->contentInfo);
5896
        // END: Use Case
5897
5898
        $locations = $this->locationService->loadLocations($publishedContent->contentInfo);
5899
        $hiddenLocationsAfterReveal = $this->filterHiddenLocations($locations);
5900
        $this->assertCount(3, $locations);
5901
        $this->assertCount(1, $hiddenLocationsAfterReveal);
5902
        $this->assertEquals($hiddenLocations, $hiddenLocationsAfterReveal);
5903
    }
5904
5905
    /**
5906
     * @depends testRevealContent
5907
     */
5908
    public function testRevealContentWithHiddenParent()
5909
    {
5910
        $contentTypeService = $this->getRepository()->getContentTypeService();
5911
5912
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
5913
5914
        $contentNames = [
5915
            'Parent Content',
5916
            'Child (Nesting 1)',
5917
            'Child (Nesting 2)',
5918
            'Child (Nesting 3)',
5919
            'Child (Nesting 4)',
5920
        ];
5921
5922
        $parentLocation = $this->locationService->newLocationCreateStruct(
5923
            $this->generateId('location', 2)
5924
        );
5925
5926
        /** @var Content[] $contents */
5927
        $contents = [];
5928
5929 View Code Duplication
        foreach ($contentNames as $contentName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
5930
            $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
5931
            $contentCreate->setField('name', $contentName);
5932
5933
            $content = $this->contentService->createContent($contentCreate, [$parentLocation]);
5934
            $contents[] = $publishedContent = $this->contentService->publishVersion($content->versionInfo);
5935
5936
            $parentLocation = $this->locationService->newLocationCreateStruct(
5937
                $this->generateId('location', $publishedContent->contentInfo->mainLocationId)
5938
            );
5939
        }
5940
5941
        $this->contentService->hideContent($contents[0]->contentInfo);
5942
        $this->contentService->hideContent($contents[2]->contentInfo);
5943
        $this->contentService->revealContent($contents[2]->contentInfo);
5944
5945
        $parentContent = $this->contentService->loadContent($contents[0]->id);
5946
        $parentLocation = $this->locationService->loadLocation($parentContent->contentInfo->mainLocationId);
5947
        $parentSublocations = $this->locationService->loadLocationList([
5948
            $contents[1]->contentInfo->mainLocationId,
5949
            $contents[2]->contentInfo->mainLocationId,
5950
            $contents[3]->contentInfo->mainLocationId,
5951
            $contents[4]->contentInfo->mainLocationId,
5952
        ]);
5953
5954
        // Parent remains invisible
5955
        self::assertTrue($parentLocation->invisible);
5956
5957
        // All parent sublocations remain invisible as well
5958
        foreach ($parentSublocations as $parentSublocation) {
5959
            self::assertTrue($parentSublocation->invisible);
5960
        }
5961
    }
5962
5963
    /**
5964
     * @depends testRevealContent
5965
     */
5966
    public function testRevealContentWithHiddenChildren()
5967
    {
5968
        $contentTypeService = $this->getRepository()->getContentTypeService();
5969
5970
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
5971
5972
        $contentNames = [
5973
            'Parent Content',
5974
            'Child (Nesting 1)',
5975
            'Child (Nesting 2)',
5976
            'Child (Nesting 3)',
5977
            'Child (Nesting 4)',
5978
        ];
5979
5980
        $parentLocation = $this->locationService->newLocationCreateStruct(
5981
            $this->generateId('location', 2)
5982
        );
5983
5984
        /** @var Content[] $contents */
5985
        $contents = [];
5986
5987 View Code Duplication
        foreach ($contentNames as $contentName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
5988
            $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
5989
            $contentCreate->setField('name', $contentName);
5990
5991
            $content = $this->contentService->createContent($contentCreate, [$parentLocation]);
5992
            $contents[] = $publishedContent = $this->contentService->publishVersion($content->versionInfo);
5993
5994
            $parentLocation = $this->locationService->newLocationCreateStruct(
5995
                $this->generateId('location', $publishedContent->contentInfo->mainLocationId)
5996
            );
5997
        }
5998
5999
        $this->contentService->hideContent($contents[0]->contentInfo);
6000
        $this->contentService->hideContent($contents[2]->contentInfo);
6001
        $this->contentService->revealContent($contents[0]->contentInfo);
6002
6003
        $directChildContent = $this->contentService->loadContent($contents[1]->id);
6004
        $directChildLocation = $this->locationService->loadLocation($directChildContent->contentInfo->mainLocationId);
6005
6006
        $childContent = $this->contentService->loadContent($contents[2]->id);
6007
        $childLocation = $this->locationService->loadLocation($childContent->contentInfo->mainLocationId);
6008
        $childSublocations = $this->locationService->loadLocationList([
6009
            $contents[3]->contentInfo->mainLocationId,
6010
            $contents[4]->contentInfo->mainLocationId,
6011
        ]);
6012
6013
        // Direct child content is not hidden
6014
        self::assertFalse($directChildContent->contentInfo->isHidden);
6015
6016
        // Direct child content location is still invisible
6017
        self::assertFalse($directChildLocation->invisible);
6018
6019
        // Child content is still hidden
6020
        self::assertTrue($childContent->contentInfo->isHidden);
6021
6022
        // Child content location is still invisible
6023
        self::assertTrue($childLocation->invisible);
6024
6025
        // All childs sublocations remain invisible as well
6026
        foreach ($childSublocations as $childSublocation) {
6027
            self::assertTrue($childSublocation->invisible);
6028
        }
6029
    }
6030
6031
    public function testHideContentWithParentLocation()
6032
    {
6033
        $contentTypeService = $this->getRepository()->getContentTypeService();
6034
6035
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
6036
6037
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
6038
        $contentCreate->setField('name', 'Parent');
6039
6040
        $content = $this->contentService->createContent(
6041
            $contentCreate,
6042
            [
6043
                $this->locationService->newLocationCreateStruct(
6044
                    $this->generateId('location', 2)
6045
                ),
6046
            ]
6047
        );
6048
6049
        $publishedContent = $this->contentService->publishVersion($content->versionInfo);
6050
6051
        /* BEGIN: Use Case */
6052
        $this->contentService->hideContent($publishedContent->contentInfo);
6053
        /* END: Use Case */
6054
6055
        $locations = $this->locationService->loadLocations($publishedContent->contentInfo);
6056
6057
        $childContentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
6058
        $childContentCreate->setField('name', 'Child');
6059
6060
        $childContent = $this->contentService->createContent(
6061
            $childContentCreate,
6062
            [
6063
                $this->locationService->newLocationCreateStruct(
6064
                    $locations[0]->id
6065
                ),
6066
            ]
6067
        );
6068
6069
        $publishedChildContent = $this->contentService->publishVersion($childContent->versionInfo);
6070
6071
        $childLocations = $this->locationService->loadLocations($publishedChildContent->contentInfo);
6072
6073
        $this->assertTrue($locations[0]->hidden);
6074
        $this->assertTrue($locations[0]->invisible);
6075
6076
        $this->assertFalse($childLocations[0]->hidden);
6077
        $this->assertTrue($childLocations[0]->invisible);
6078
    }
6079
6080
    public function testChangeContentName()
6081
    {
6082
        $contentDraft = $this->createContentDraft(
6083
            'folder',
6084
            $this->generateId('location', 2),
6085
            [
6086
                'name' => 'Marco',
6087
            ]
6088
        );
6089
6090
        $publishedContent = $this->contentService->publishVersion($contentDraft->versionInfo);
6091
        $contentMetadataUpdateStruct = new ContentMetadataUpdateStruct([
6092
            'name' => 'Polo',
6093
        ]);
6094
        $this->contentService->updateContentMetadata($publishedContent->contentInfo, $contentMetadataUpdateStruct);
6095
6096
        $updatedContent = $this->contentService->loadContent($publishedContent->id);
6097
6098
        $this->assertEquals('Marco', $publishedContent->contentInfo->name);
6099
        $this->assertEquals('Polo', $updatedContent->contentInfo->name);
6100
    }
6101
6102
    public function testCopyTranslationsFromPublishedToDraft()
6103
    {
6104
        $contentDraft = $this->createContentDraft(
6105
            'folder',
6106
            $this->generateId('location', 2),
6107
            [
6108
                'name' => 'Folder US',
6109
            ]
6110
        );
6111
6112
        $publishedContent = $this->contentService->publishVersion($contentDraft->versionInfo);
6113
6114
        $deDraft = $this->contentService->createContentDraft($publishedContent->contentInfo);
6115
6116
        $contentUpdateStruct = new ContentUpdateStruct([
6117
            'initialLanguageCode' => 'ger-DE',
6118
            'fields' => $contentDraft->getFields(),
6119
        ]);
6120
6121
        $contentUpdateStruct->setField('name', 'Folder GER', 'ger-DE');
6122
6123
        $deContent = $this->contentService->updateContent($deDraft->versionInfo, $contentUpdateStruct);
6124
6125
        $updatedContent = $this->contentService->loadContent($deContent->id, null, $deContent->versionInfo->versionNo);
6126
        $this->assertEquals(
6127
            [
6128
                'eng-US' => 'Folder US',
6129
                'ger-DE' => 'Folder GER',
6130
            ],
6131
            $updatedContent->fields['name']
6132
        );
6133
6134
        $gbDraft = $this->contentService->createContentDraft($publishedContent->contentInfo);
6135
6136
        $contentUpdateStruct = new ContentUpdateStruct([
6137
            'initialLanguageCode' => 'eng-GB',
6138
            'fields' => $contentDraft->getFields(),
6139
        ]);
6140
6141
        $contentUpdateStruct->setField('name', 'Folder GB', 'eng-GB');
6142
6143
        $gbContent = $this->contentService->updateContent($gbDraft->versionInfo, $contentUpdateStruct);
6144
        $this->contentService->publishVersion($gbDraft->versionInfo);
6145
        $updatedContent = $this->contentService->loadContent($gbContent->id, null, $gbContent->versionInfo->versionNo);
6146
        $this->assertEquals(
6147
            [
6148
                'eng-US' => 'Folder US',
6149
                'eng-GB' => 'Folder GB',
6150
            ],
6151
            $updatedContent->fields['name']
6152
        );
6153
6154
        $dePublished = $this->contentService->publishVersion($deDraft->versionInfo);
6155
        $this->assertEquals(
6156
            [
6157
                'eng-US' => 'Folder US',
6158
                'ger-DE' => 'Folder GER',
6159
                'eng-GB' => 'Folder GB',
6160
            ],
6161
            $dePublished->fields['name']
6162
        );
6163
    }
6164
6165
    /**
6166
     * Create structure of parent folders with Locations to be used for Content hide/reveal tests.
6167
     *
6168
     * @param int $parentLocationId
6169
     *
6170
     * @return \eZ\Publish\API\Repository\Values\Content\Location[] A list of Locations aimed to be parents
6171
     *
6172
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
6173
     * @throws NotFoundException
6174
     * @throws UnauthorizedException
6175
     */
6176
    private function createParentLocationsForHideReveal(int $parentLocationId): array
6177
    {
6178
        $parentFoldersLocationsIds = [
6179
            $this->createFolder(['eng-US' => 'P1'], $parentLocationId)->contentInfo->mainLocationId,
6180
            $this->createFolder(['eng-US' => 'P2'], $parentLocationId)->contentInfo->mainLocationId,
6181
            $this->createFolder(['eng-US' => 'P3'], $parentLocationId)->contentInfo->mainLocationId,
6182
        ];
6183
6184
        return array_values($this->locationService->loadLocationList($parentFoldersLocationsIds));
6185
    }
6186
6187
    /**
6188
     * Filter Locations list by hidden only.
6189
     *
6190
     * @param \eZ\Publish\API\Repository\Values\Content\Location[] $locations
6191
     *
6192
     * @return array
6193
     */
6194
    private function filterHiddenLocations(array $locations): array
6195
    {
6196
        return array_values(
6197
            array_filter(
6198
                $locations,
6199
                function (Location $location) {
6200
                    return $location->hidden;
6201
                }
6202
            )
6203
        );
6204
    }
6205
6206
    public function testPublishVersionWithSelectedLanguages()
6207
    {
6208
        $publishedContent = $this->createFolder(
6209
            [
6210
                'eng-US' => 'Published US',
6211
                'ger-DE' => 'Published DE',
6212
            ],
6213
            $this->generateId('location', 2)
6214
        );
6215
6216
        $draft = $this->contentService->createContentDraft($publishedContent->contentInfo);
6217
        $contentUpdateStruct = new ContentUpdateStruct([
6218
            'initialLanguageCode' => 'eng-US',
6219
        ]);
6220
        $contentUpdateStruct->setField('name', 'Draft 1 US', 'eng-US');
6221
        $contentUpdateStruct->setField('name', 'Draft 1 DE', 'ger-DE');
6222
6223
        $this->contentService->updateContent($draft->versionInfo, $contentUpdateStruct);
6224
6225
        $this->contentService->publishVersion($draft->versionInfo, ['ger-DE']);
6226
        $content = $this->contentService->loadContent($draft->contentInfo->id);
6227
        $this->assertEquals(
6228
            [
6229
                'eng-US' => 'Published US',
6230
                'ger-DE' => 'Draft 1 DE',
6231
            ],
6232
            $content->fields['name']
6233
        );
6234
    }
6235
6236
    public function testCreateContentWithRomanianSpecialCharsInTitle()
6237
    {
6238
        $baseName = 'ȘșțȚdfdf';
6239
        $expectedPath = '/SstTdfdf';
6240
6241
        $this->createFolder(['eng-US' => $baseName], 2);
6242
6243
        $urlAliasService = $this->getRepository()->getURLAliasService();
6244
        $urlAlias = $urlAliasService->lookup($expectedPath);
6245
        $this->assertSame($expectedPath, $urlAlias->path);
6246
    }
6247
}
6248