Completed
Push — EZP-30427 ( 8c1757...93ffe2 )
by
unknown
17:19
created

testLoadContentDraftListWithForUserWithLimitation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 35
c 0
b 0
f 0
cc 1
nc 1
nop 0
rs 9.36
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\UnauthorizedContentDraftListItem;
22
use eZ\Publish\API\Repository\Values\Content\URLAlias;
23
use eZ\Publish\API\Repository\Values\Content\Relation;
24
use eZ\Publish\API\Repository\Values\Content\VersionInfo;
25
use eZ\Publish\API\Repository\Values\User\Limitation\SectionLimitation;
26
use eZ\Publish\API\Repository\Values\User\Limitation\LocationLimitation;
27
use eZ\Publish\API\Repository\Values\User\Limitation\ContentTypeLimitation;
28
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
29
use DOMDocument;
30
use Exception;
31
use eZ\Publish\API\Repository\Values\User\User;
32
use eZ\Publish\Core\Base\Exceptions\UnauthorizedException as CoreUnauthorizedException;
33
use eZ\Publish\Core\Repository\Values\Content\ContentUpdateStruct;
34
use InvalidArgumentException;
35
36
/**
37
 * Test case for operations in the ContentService using in memory storage.
38
 *
39
 * @see \eZ\Publish\API\Repository\ContentService
40
 * @group content
41
 */
42
class ContentServiceTest extends BaseContentServiceTest
43
{
44
    /** @var \eZ\Publish\API\Repository\PermissionResolver */
45
    private $permissionResolver;
46
47
    /** @var \eZ\Publish\API\Repository\ContentService */
48
    private $contentService;
49
50
    /** @var \eZ\Publish\API\Repository\LocationService */
51
    private $locationService;
52
53
    public function setUp(): void
54
    {
55
        parent::setUp();
56
57
        $repository = $this->getRepository();
58
        $this->permissionResolver = $repository->getPermissionResolver();
59
        $this->contentService = $repository->getContentService();
60
        $this->locationService = $repository->getLocationService();
61
    }
62
63
    /**
64
     * Test for the newContentCreateStruct() method.
65
     *
66
     * @see \eZ\Publish\API\Repository\ContentService::newContentCreateStruct()
67
     * @depends eZ\Publish\API\Repository\Tests\ContentTypeServiceTest::testLoadContentTypeByIdentifier
68
     * @group user
69
     * @group field-type
70
     */
71
    public function testNewContentCreateStruct()
72
    {
73
        /* BEGIN: Use Case */
74
        $contentTypeService = $this->getRepository()->getContentTypeService();
75
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
76
77
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
78
        /* END: Use Case */
79
80
        $this->assertInstanceOf(ContentCreateStruct::class, $contentCreate);
81
    }
82
83
    /**
84
     * Test for the createContent() method.
85
     *
86
     * @return \eZ\Publish\API\Repository\Values\Content\Content
87
     *
88
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
89
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testNewContentCreateStruct
90
     * @group user
91
     * @group field-type
92
     */
93
    public function testCreateContent()
94
    {
95
        if ($this->isVersion4()) {
96
            $this->markTestSkipped('This test requires eZ Publish 5');
97
        }
98
99
        /* BEGIN: Use Case */
100
        $contentTypeService = $this->getRepository()->getContentTypeService();
101
102
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
103
104
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
105
        $contentCreate->setField('name', 'My awesome forum');
106
107
        $contentCreate->remoteId = 'abcdef0123456789abcdef0123456789';
108
        $contentCreate->alwaysAvailable = true;
109
110
        $content = $this->contentService->createContent($contentCreate);
111
        /* END: Use Case */
112
113
        $this->assertInstanceOf(Content::class, $content);
114
115
        return $content;
116
    }
117
118
    /**
119
     * Test for the createContent() method.
120
     *
121
     * Tests made for issue #EZP-20955 where Anonymous user is granted access to create content
122
     * and should have access to do that.
123
     *
124
     * @return \eZ\Publish\API\Repository\Values\Content\Content
125
     *
126
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
127
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testNewContentCreateStruct
128
     * @group user
129
     * @group field-type
130
     */
131
    public function testCreateContentAndPublishWithPrivilegedAnonymousUser()
132
    {
133
        if ($this->isVersion4()) {
134
            $this->markTestSkipped('This test requires eZ Publish 5');
135
        }
136
137
        $anonymousUserId = $this->generateId('user', 10);
138
139
        $repository = $this->getRepository();
140
        $contentTypeService = $this->getRepository()->getContentTypeService();
141
        $roleService = $repository->getRoleService();
142
143
        // Give Anonymous user role additional rights
144
        $role = $roleService->loadRoleByIdentifier('Anonymous');
145
        $roleDraft = $roleService->createRoleDraft($role);
146
        $policyCreateStruct = $roleService->newPolicyCreateStruct('content', 'create');
147
        $policyCreateStruct->addLimitation(new SectionLimitation(['limitationValues' => [1]]));
148
        $policyCreateStruct->addLimitation(new LocationLimitation(['limitationValues' => [2]]));
149
        $policyCreateStruct->addLimitation(new ContentTypeLimitation(['limitationValues' => [1]]));
150
        $roleDraft = $roleService->addPolicyByRoleDraft($roleDraft, $policyCreateStruct);
151
152
        $policyCreateStruct = $roleService->newPolicyCreateStruct('content', 'publish');
153
        $policyCreateStruct->addLimitation(new SectionLimitation(['limitationValues' => [1]]));
154
        $policyCreateStruct->addLimitation(new LocationLimitation(['limitationValues' => [2]]));
155
        $policyCreateStruct->addLimitation(new ContentTypeLimitation(['limitationValues' => [1]]));
156
        $roleDraft = $roleService->addPolicyByRoleDraft($roleDraft, $policyCreateStruct);
157
        $roleService->publishRoleDraft($roleDraft);
158
159
        // Set Anonymous user as current
160
        $repository->getPermissionResolver()->setCurrentUserReference($repository->getUserService()->loadUser($anonymousUserId));
161
162
        // Create a new content object:
163
        $contentCreate = $this->contentService->newContentCreateStruct(
164
            $contentTypeService->loadContentTypeByIdentifier('folder'),
165
            'eng-GB'
166
        );
167
168
        $contentCreate->setField('name', 'Folder 1');
169
170
        $content = $this->contentService->createContent(
171
            $contentCreate,
172
            [$this->locationService->newLocationCreateStruct(2)]
173
        );
174
175
        $this->contentService->publishVersion(
176
            $content->getVersionInfo()
177
        );
178
    }
179
180
    /**
181
     * Test for the createContent() method.
182
     *
183
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
184
     *
185
     * @return \eZ\Publish\API\Repository\Values\Content\Content
186
     *
187
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
188
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
189
     */
190
    public function testCreateContentSetsContentInfo($content)
191
    {
192
        $this->assertInstanceOf(ContentInfo::class, $content->contentInfo);
193
194
        return $content;
195
    }
196
197
    /**
198
     * Test for the createContent() method.
199
     *
200
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
201
     *
202
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
203
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentSetsContentInfo
204
     */
205
    public function testCreateContentSetsExpectedContentInfo($content)
206
    {
207
        $this->assertEquals(
208
            [
209
                $content->id,
210
                28, // id of content type "forum"
211
                true,
212
                1,
213
                'abcdef0123456789abcdef0123456789',
214
                'eng-US',
215
                $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...
216
                false,
217
                null,
218
                // Main Location id for unpublished Content should be null
219
                null,
220
            ],
221
            [
222
                $content->contentInfo->id,
223
                $content->contentInfo->contentTypeId,
224
                $content->contentInfo->alwaysAvailable,
225
                $content->contentInfo->currentVersionNo,
226
                $content->contentInfo->remoteId,
227
                $content->contentInfo->mainLanguageCode,
228
                $content->contentInfo->ownerId,
229
                $content->contentInfo->published,
230
                $content->contentInfo->publishedDate,
231
                $content->contentInfo->mainLocationId,
232
            ]
233
        );
234
    }
235
236
    /**
237
     * Test for the createContent() method.
238
     *
239
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
240
     *
241
     * @return \eZ\Publish\API\Repository\Values\Content\Content
242
     *
243
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
244
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
245
     */
246
    public function testCreateContentSetsVersionInfo($content)
247
    {
248
        $this->assertInstanceOf(VersionInfo::class, $content->getVersionInfo());
249
250
        return $content;
251
    }
252
253
    /**
254
     * Test for the createContent() method.
255
     *
256
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
257
     *
258
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
259
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentSetsVersionInfo
260
     */
261
    public function testCreateContentSetsExpectedVersionInfo($content)
262
    {
263
        $this->assertEquals(
264
            [
265
                'status' => VersionInfo::STATUS_DRAFT,
266
                'versionNo' => 1,
267
                '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...
268
                'initialLanguageCode' => 'eng-US',
269
            ],
270
            [
271
                'status' => $content->getVersionInfo()->status,
272
                'versionNo' => $content->getVersionInfo()->versionNo,
273
                'creatorId' => $content->getVersionInfo()->creatorId,
274
                'initialLanguageCode' => $content->getVersionInfo()->initialLanguageCode,
275
            ]
276
        );
277
        $this->assertTrue($content->getVersionInfo()->isDraft());
278
        $this->assertFalse($content->getVersionInfo()->isPublished());
279
        $this->assertFalse($content->getVersionInfo()->isArchived());
280
    }
281
282
    /**
283
     * Test for the createContent() method.
284
     *
285
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
286
     *
287
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
288
     * @depends testCreateContent
289
     */
290
    public function testCreateContentSetsExpectedContentType($content)
291
    {
292
        $contentType = $content->getContentType();
293
294
        $this->assertEquals(
295
            [
296
                $contentType->id,
297
                // Won't match as it's set to true in createContentDraftVersion1()
298
                //$contentType->defaultAlwaysAvailable,
299
                //$contentType->defaultSortField,
300
                //$contentType->defaultSortOrder,
301
            ],
302
            [
303
                $content->contentInfo->contentTypeId,
304
                //$content->contentInfo->alwaysAvailable,
305
                //$location->sortField,
306
                //$location->sortOrder,
307
            ]
308
        );
309
    }
310
311
    /**
312
     * Test for the createContent() method.
313
     *
314
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
315
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
316
     */
317
    public function testCreateContentThrowsInvalidArgumentException()
318
    {
319
        if ($this->isVersion4()) {
320
            $this->markTestSkipped('This test requires eZ Publish 5');
321
        }
322
323
        /* BEGIN: Use Case */
324
        $contentTypeService = $this->getRepository()->getContentTypeService();
325
326
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
327
328
        $contentCreate1 = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
329
        $contentCreate1->setField('name', 'An awesome Sidelfingen forum');
330
331
        $contentCreate1->remoteId = 'abcdef0123456789abcdef0123456789';
332
        $contentCreate1->alwaysAvailable = true;
333
334
        $draft = $this->contentService->createContent($contentCreate1);
335
        $this->contentService->publishVersion($draft->versionInfo);
336
337
        $contentCreate2 = $this->contentService->newContentCreateStruct($contentType, 'eng-GB');
338
        $contentCreate2->setField('name', 'An awesome Bielefeld forum');
339
340
        $contentCreate2->remoteId = 'abcdef0123456789abcdef0123456789';
341
        $contentCreate2->alwaysAvailable = false;
342
343
        $this->expectException(APIInvalidArgumentException::class);
344
        $this->contentService->createContent($contentCreate2);
345
        /* END: Use Case */
346
    }
347
348
    /**
349
     * Test for the createContent() method.
350
     *
351
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
352
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
353
     */
354 View Code Duplication
    public function testCreateContentThrowsInvalidArgumentExceptionOnFieldTypeNotAccept()
355
    {
356
        /* BEGIN: Use Case */
357
        $contentTypeService = $this->getRepository()->getContentTypeService();
358
359
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
360
361
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
362
        // The name field does only accept strings and null as its values
363
        $contentCreate->setField('name', new \stdClass());
364
365
        $this->expectException(APIInvalidArgumentException::class);
366
        $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...
367
        /* END: Use Case */
368
    }
369
370
    /**
371
     * Test for the createContent() method.
372
     *
373
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
374
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
375
     */
376
    public function testCreateContentThrowsContentFieldValidationException()
377
    {
378
        /* BEGIN: Use Case */
379
        $contentTypeService = $this->getRepository()->getContentTypeService();
380
381
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
382
383
        $contentCreate1 = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
384
        $contentCreate1->setField('name', 'An awesome Sidelfingen folder');
385
        // Violates string length constraint
386
        $contentCreate1->setField('short_name', str_repeat('a', 200));
387
388
        $this->expectException(ContentFieldValidationException::class);
389
390
        // Throws ContentFieldValidationException, since short_name does not pass validation of the string length validator
391
        $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...
392
        /* END: Use Case */
393
    }
394
395
    /**
396
     * Test for the createContent() method.
397
     *
398
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
399
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
400
     */
401 View Code Duplication
    public function testCreateContentRequiredFieldMissing()
402
    {
403
        /* BEGIN: Use Case */
404
        $contentTypeService = $this->getRepository()->getContentTypeService();
405
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
406
407
        $contentCreate1 = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
408
        // Required field "name" is not set
409
410
        $this->expectException(ContentFieldValidationException::class);
411
412
        // Throws a ContentFieldValidationException, since a required field is missing
413
        $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...
414
        /* END: Use Case */
415
    }
416
417
    /**
418
     * Test for the createContent() method.
419
     *
420
     * NOTE: We have bidirectional dependencies between the ContentService and
421
     * the LocationService, so that we cannot use PHPUnit's test dependencies
422
     * here.
423
     *
424
     * @see \eZ\Publish\API\Repository\ContentService::createContent($contentCreateStruct, $locationCreateStructs)
425
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testCreateLocation
426
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationByRemoteId
427
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
428
     * @group user
429
     */
430
    public function testCreateContentWithLocationCreateParameterDoesNotCreateLocationImmediately()
431
    {
432
        /* BEGIN: Use Case */
433
        $this->createContentDraftVersion1();
434
435
        $this->expectException(NotFoundException::class);
436
437
        // The location will not have been created, yet, so this throws an exception
438
        $this->locationService->loadLocationByRemoteId('0123456789abcdef0123456789abcdef');
439
        /* END: Use Case */
440
    }
441
442
    /**
443
     * Test for the createContent() method.
444
     *
445
     * @see \eZ\Publish\API\Repository\ContentService::createContent($contentCreateStruct, $locationCreateStructs)
446
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentWithLocationCreateParameterDoesNotCreateLocationImmediately
447
     */
448
    public function testCreateContentThrowsInvalidArgumentExceptionWithLocationCreateParameter()
449
    {
450
        $parentLocationId = $this->generateId('location', 56);
451
        /* BEGIN: Use Case */
452
        // $parentLocationId is a valid location ID
453
454
        $contentTypeService = $this->getRepository()->getContentTypeService();
455
456
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
457
458
        // Configure new locations
459
        $locationCreate1 = $this->locationService->newLocationCreateStruct($parentLocationId);
460
461
        $locationCreate1->priority = 23;
462
        $locationCreate1->hidden = true;
463
        $locationCreate1->remoteId = '0123456789abcdef0123456789aaaaaa';
464
        $locationCreate1->sortField = Location::SORT_FIELD_NODE_ID;
465
        $locationCreate1->sortOrder = Location::SORT_ORDER_DESC;
466
467
        $locationCreate2 = $this->locationService->newLocationCreateStruct($parentLocationId);
468
469
        $locationCreate2->priority = 42;
470
        $locationCreate2->hidden = true;
471
        $locationCreate2->remoteId = '0123456789abcdef0123456789bbbbbb';
472
        $locationCreate2->sortField = Location::SORT_FIELD_NODE_ID;
473
        $locationCreate2->sortOrder = Location::SORT_ORDER_DESC;
474
475
        // Configure new content object
476
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
477
478
        $contentCreate->setField('name', 'A awesome Sindelfingen forum');
479
        $contentCreate->remoteId = 'abcdef0123456789abcdef0123456789';
480
        $contentCreate->alwaysAvailable = true;
481
482
        // Create new content object under the specified location
483
        $draft = $this->contentService->createContent(
484
            $contentCreate,
485
            [$locationCreate1]
486
        );
487
        $this->contentService->publishVersion($draft->versionInfo);
488
489
        $this->expectException(APIInvalidArgumentException::class);
490
        // Content remoteId already exists,
491
        $this->contentService->createContent(
492
            $contentCreate,
493
            [$locationCreate2]
494
        );
495
        /* END: Use Case */
496
    }
497
498
    /**
499
     * Test for the loadContentInfo() method.
500
     *
501
     * @see \eZ\Publish\API\Repository\ContentService::loadContentInfo()
502
     * @group user
503
     */
504
    public function testLoadContentInfo()
505
    {
506
        $mediaFolderId = $this->generateId('object', 41);
507
        /* BEGIN: Use Case */
508
509
        // Load the ContentInfo for "Media" folder
510
        $contentInfo = $this->contentService->loadContentInfo($mediaFolderId);
511
        /* END: Use Case */
512
513
        $this->assertInstanceOf(ContentInfo::class, $contentInfo);
514
515
        return $contentInfo;
516
    }
517
518
    /**
519
     * Test for the returned value of the loadContentInfo() method.
520
     *
521
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
522
     * @covers \eZ\Publish\API\Repository\ContentService::loadContentInfo
523
     *
524
     * @param ContentInfo $contentInfo
525
     */
526
    public function testLoadContentInfoSetsExpectedContentInfo(ContentInfo $contentInfo)
527
    {
528
        $this->assertPropertiesCorrectUnsorted(
529
            $this->getExpectedMediaContentInfoProperties(),
530
            $contentInfo
531
        );
532
    }
533
534
    /**
535
     * Test for the loadContentInfo() method.
536
     *
537
     * @see \eZ\Publish\API\Repository\ContentService::loadContentInfo()
538
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
539
     */
540
    public function testLoadContentInfoThrowsNotFoundException()
541
    {
542
        $nonExistentContentId = $this->generateId('object', self::DB_INT_MAX);
543
        /* BEGIN: Use Case */
544
545
        $this->expectException(NotFoundException::class);
546
547
        // This call will fail with a NotFoundException
548
        $this->contentService->loadContentInfo($nonExistentContentId);
549
        /* END: Use Case */
550
    }
551
552
    /**
553
     * Test for the loadContentInfoList() method.
554
     *
555
     * @see \eZ\Publish\API\Repository\ContentService::loadContentInfoList()
556
     */
557
    public function testLoadContentInfoList()
558
    {
559
        $mediaFolderId = $this->generateId('object', 41);
560
        $list = $this->contentService->loadContentInfoList([$mediaFolderId]);
561
562
        $this->assertCount(1, $list);
563
        $this->assertEquals([$mediaFolderId], array_keys($list), 'Array key was not content id');
564
        $this->assertInstanceOf(
565
            ContentInfo::class,
566
            $list[$mediaFolderId]
567
        );
568
    }
569
570
    /**
571
     * Test for the loadContentInfoList() method.
572
     *
573
     * @see \eZ\Publish\API\Repository\ContentService::loadContentInfoList()
574
     * @depends testLoadContentInfoList
575
     */
576
    public function testLoadContentInfoListSkipsNotFoundItems()
577
    {
578
        $nonExistentContentId = $this->generateId('object', self::DB_INT_MAX);
579
        $list = $this->contentService->loadContentInfoList([$nonExistentContentId]);
580
581
        $this->assertCount(0, $list);
582
    }
583
584
    /**
585
     * Test for the loadContentInfoByRemoteId() method.
586
     *
587
     * @see \eZ\Publish\API\Repository\ContentService::loadContentInfoByRemoteId()
588
     */
589
    public function testLoadContentInfoByRemoteId()
590
    {
591
        /* BEGIN: Use Case */
592
        // Load the ContentInfo for "Media" folder
593
        $contentInfo = $this->contentService->loadContentInfoByRemoteId('faaeb9be3bd98ed09f606fc16d144eca');
594
        /* END: Use Case */
595
596
        $this->assertInstanceOf(ContentInfo::class, $contentInfo);
597
598
        return $contentInfo;
599
    }
600
601
    /**
602
     * Test for the returned value of the loadContentInfoByRemoteId() method.
603
     *
604
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfoByRemoteId
605
     * @covers \eZ\Publish\API\Repository\ContentService::loadContentInfoByRemoteId
606
     *
607
     * @param ContentInfo $contentInfo
608
     */
609 View Code Duplication
    public function testLoadContentInfoByRemoteIdSetsExpectedContentInfo(ContentInfo $contentInfo)
610
    {
611
        $this->assertPropertiesCorrectUnsorted(
612
            [
613
                'id' => 10,
614
                'contentTypeId' => 4,
615
                'name' => 'Anonymous User',
616
                'sectionId' => 2,
617
                'currentVersionNo' => 2,
618
                'published' => true,
619
                'ownerId' => 14,
620
                'modificationDate' => $this->createDateTime(1072180405),
621
                'publishedDate' => $this->createDateTime(1033920665),
622
                'alwaysAvailable' => 1,
623
                'remoteId' => 'faaeb9be3bd98ed09f606fc16d144eca',
624
                'mainLanguageCode' => 'eng-US',
625
                'mainLocationId' => 45,
626
            ],
627
            $contentInfo
628
        );
629
    }
630
631
    /**
632
     * Test for the loadContentInfoByRemoteId() method.
633
     *
634
     * @see \eZ\Publish\API\Repository\ContentService::loadContentInfoByRemoteId()
635
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfoByRemoteId
636
     */
637
    public function testLoadContentInfoByRemoteIdThrowsNotFoundException()
638
    {
639
        /* BEGIN: Use Case */
640
        $this->expectException(NotFoundException::class);
641
642
        $this->contentService->loadContentInfoByRemoteId('abcdefghijklmnopqrstuvwxyz0123456789');
643
        /* END: Use Case */
644
    }
645
646
    /**
647
     * Test for the loadVersionInfo() method.
648
     *
649
     * @see \eZ\Publish\API\Repository\ContentService::loadVersionInfo()
650
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
651
     * @group user
652
     */
653 View Code Duplication
    public function testLoadVersionInfo()
654
    {
655
        $mediaFolderId = $this->generateId('object', 41);
656
        /* BEGIN: Use Case */
657
        // $mediaFolderId contains the ID of the "Media" folder
658
659
        // Load the ContentInfo for "Media" folder
660
        $contentInfo = $this->contentService->loadContentInfo($mediaFolderId);
661
662
        // Now load the current version info of the "Media" folder
663
        $versionInfo = $this->contentService->loadVersionInfo($contentInfo);
664
        /* END: Use Case */
665
666
        $this->assertInstanceOf(
667
            VersionInfo::class,
668
            $versionInfo
669
        );
670
    }
671
672
    /**
673
     * Test for the loadVersionInfoById() method.
674
     *
675
     * @see \eZ\Publish\API\Repository\ContentService::loadVersionInfoById()
676
     */
677
    public function testLoadVersionInfoById()
678
    {
679
        $mediaFolderId = $this->generateId('object', 41);
680
        /* BEGIN: Use Case */
681
        // $mediaFolderId contains the ID of the "Media" folder
682
683
        // Load the VersionInfo for "Media" folder
684
        $versionInfo = $this->contentService->loadVersionInfoById($mediaFolderId);
685
        /* END: Use Case */
686
687
        $this->assertInstanceOf(
688
            VersionInfo::class,
689
            $versionInfo
690
        );
691
692
        return $versionInfo;
693
    }
694
695
    /**
696
     * Test for the returned value of the loadVersionInfoById() method.
697
     *
698
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfoById
699
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById
700
     *
701
     * @param VersionInfo $versionInfo
702
     */
703
    public function testLoadVersionInfoByIdSetsExpectedVersionInfo(VersionInfo $versionInfo)
704
    {
705
        $this->assertPropertiesCorrect(
706
            [
707
                'names' => [
708
                    'eng-US' => 'Media',
709
                ],
710
                'contentInfo' => new ContentInfo($this->getExpectedMediaContentInfoProperties()),
711
                'id' => 472,
712
                'versionNo' => 1,
713
                'modificationDate' => $this->createDateTime(1060695457),
714
                'creatorId' => 14,
715
                'creationDate' => $this->createDateTime(1060695450),
716
                'status' => VersionInfo::STATUS_PUBLISHED,
717
                'initialLanguageCode' => 'eng-US',
718
                'languageCodes' => [
719
                    'eng-US',
720
                ],
721
            ],
722
            $versionInfo
723
        );
724
        $this->assertTrue($versionInfo->isPublished());
725
        $this->assertFalse($versionInfo->isDraft());
726
        $this->assertFalse($versionInfo->isArchived());
727
    }
728
729
    /**
730
     * Test for the loadVersionInfoById() method.
731
     *
732
     * @see \eZ\Publish\API\Repository\ContentService::loadVersionInfoById()
733
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfoById
734
     */
735
    public function testLoadVersionInfoByIdThrowsNotFoundException()
736
    {
737
        $nonExistentContentId = $this->generateId('object', self::DB_INT_MAX);
738
        /* BEGIN: Use Case */
739
740
        $this->expectException(NotFoundException::class);
741
742
        $this->contentService->loadVersionInfoById($nonExistentContentId);
743
        /* END: Use Case */
744
    }
745
746
    /**
747
     * Test for the loadContentByContentInfo() method.
748
     *
749
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByContentInfo()
750
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
751
     */
752 View Code Duplication
    public function testLoadContentByContentInfo()
753
    {
754
        $mediaFolderId = $this->generateId('object', 41);
755
        /* BEGIN: Use Case */
756
        // $mediaFolderId contains the ID of the "Media" folder
757
758
        // Load the ContentInfo for "Media" folder
759
        $contentInfo = $this->contentService->loadContentInfo($mediaFolderId);
760
761
        // Now load the current content version for the info instance
762
        $content = $this->contentService->loadContentByContentInfo($contentInfo);
763
        /* END: Use Case */
764
765
        $this->assertInstanceOf(
766
            Content::class,
767
            $content
768
        );
769
    }
770
771
    /**
772
     * Test for the loadContentByVersionInfo() method.
773
     *
774
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByVersionInfo()
775
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfo
776
     */
777 View Code Duplication
    public function testLoadContentByVersionInfo()
778
    {
779
        $mediaFolderId = $this->generateId('object', 41);
780
        /* BEGIN: Use Case */
781
        // $mediaFolderId contains the ID of the "Media" folder
782
783
        // Load the ContentInfo for "Media" folder
784
        $contentInfo = $this->contentService->loadContentInfo($mediaFolderId);
785
786
        // Load the current VersionInfo
787
        $versionInfo = $this->contentService->loadVersionInfo($contentInfo);
788
789
        // Now load the current content version for the info instance
790
        $content = $this->contentService->loadContentByVersionInfo($versionInfo);
791
        /* END: Use Case */
792
793
        $this->assertInstanceOf(
794
            Content::class,
795
            $content
796
        );
797
    }
798
799
    /**
800
     * Test for the loadContent() method.
801
     *
802
     * @see \eZ\Publish\API\Repository\ContentService::loadContent()
803
     * @group user
804
     * @group field-type
805
     */
806
    public function testLoadContent()
807
    {
808
        $mediaFolderId = $this->generateId('object', 41);
809
        /* BEGIN: Use Case */
810
        // $mediaFolderId contains the ID of the "Media" folder
811
812
        // Load the Content for "Media" folder, any language and current version
813
        $content = $this->contentService->loadContent($mediaFolderId);
814
        /* END: Use Case */
815
816
        $this->assertInstanceOf(
817
            Content::class,
818
            $content
819
        );
820
    }
821
822
    /**
823
     * Test for the loadContent() method.
824
     *
825
     * @see \eZ\Publish\API\Repository\ContentService::loadContent()
826
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
827
     */
828
    public function testLoadContentThrowsNotFoundException()
829
    {
830
        $nonExistentContentId = $this->generateId('object', self::DB_INT_MAX);
831
        /* BEGIN: Use Case */
832
833
        $this->expectException(NotFoundException::class);
834
835
        $this->contentService->loadContent($nonExistentContentId);
836
        /* END: Use Case */
837
    }
838
839
    /**
840
     * Data provider for testLoadContentByRemoteId().
841
     *
842
     * @return array
843
     */
844
    public function contentRemoteIdVersionLanguageProvider()
845
    {
846
        return [
847
            ['f5c88a2209584891056f987fd965b0ba', null, null],
848
            ['f5c88a2209584891056f987fd965b0ba', ['eng-US'], null],
849
            ['f5c88a2209584891056f987fd965b0ba', null, 1],
850
            ['f5c88a2209584891056f987fd965b0ba', ['eng-US'], 1],
851
            ['a6e35cbcb7cd6ae4b691f3eee30cd262', null, null],
852
            ['a6e35cbcb7cd6ae4b691f3eee30cd262', ['eng-US'], null],
853
            ['a6e35cbcb7cd6ae4b691f3eee30cd262', null, 1],
854
            ['a6e35cbcb7cd6ae4b691f3eee30cd262', ['eng-US'], 1],
855
        ];
856
    }
857
858
    /**
859
     * Test for the loadContentByRemoteId() method.
860
     *
861
     * @covers \eZ\Publish\API\Repository\ContentService::loadContentByRemoteId
862
     * @dataProvider contentRemoteIdVersionLanguageProvider
863
     *
864
     * @param string $remoteId
865
     * @param array|null $languages
866
     * @param int $versionNo
867
     */
868
    public function testLoadContentByRemoteId($remoteId, $languages, $versionNo)
869
    {
870
        $content = $this->contentService->loadContentByRemoteId($remoteId, $languages, $versionNo);
871
872
        $this->assertInstanceOf(
873
            Content::class,
874
            $content
875
        );
876
877
        $this->assertEquals($remoteId, $content->contentInfo->remoteId);
878
        if ($languages !== null) {
879
            $this->assertEquals($languages, $content->getVersionInfo()->languageCodes);
880
        }
881
        $this->assertEquals($versionNo ?: 1, $content->getVersionInfo()->versionNo);
882
    }
883
884
    /**
885
     * Test for the loadContentByRemoteId() method.
886
     *
887
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByRemoteId()
888
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByRemoteId
889
     */
890
    public function testLoadContentByRemoteIdThrowsNotFoundException()
891
    {
892
        /* BEGIN: Use Case */
893
        $this->expectException(NotFoundException::class);
894
895
        // This call will fail with a "NotFoundException", because no content object exists for the given remoteId
896
        $this->contentService->loadContentByRemoteId('a1b1c1d1e1f1a2b2c2d2e2f2a3b3c3d3');
897
        /* END: Use Case */
898
    }
899
900
    /**
901
     * Test for the publishVersion() method.
902
     *
903
     * @return \eZ\Publish\API\Repository\Values\Content\Content
904
     *
905
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
906
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
907
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
908
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfo
909
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentWithLocationCreateParameterDoesNotCreateLocationImmediately
910
     * @group user
911
     * @group field-type
912
     */
913
    public function testPublishVersion()
914
    {
915
        $time = time();
916
        /* BEGIN: Use Case */
917
        $content = $this->createContentVersion1();
918
        /* END: Use Case */
919
920
        $this->assertInstanceOf(Content::class, $content);
921
        $this->assertTrue($content->contentInfo->published);
922
        $this->assertEquals(VersionInfo::STATUS_PUBLISHED, $content->versionInfo->status);
923
        $this->assertGreaterThanOrEqual($time, $content->contentInfo->publishedDate->getTimestamp());
924
        $this->assertGreaterThanOrEqual($time, $content->contentInfo->modificationDate->getTimestamp());
925
        $this->assertTrue($content->versionInfo->isPublished());
926
        $this->assertFalse($content->versionInfo->isDraft());
927
        $this->assertFalse($content->versionInfo->isArchived());
928
929
        return $content;
930
    }
931
932
    /**
933
     * Test for the publishVersion() method.
934
     *
935
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
936
     *
937
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
938
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
939
     */
940
    public function testPublishVersionSetsExpectedContentInfo($content)
941
    {
942
        $this->assertEquals(
943
            [
944
                $content->id,
945
                true,
946
                1,
947
                'abcdef0123456789abcdef0123456789',
948
                'eng-US',
949
                $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...
950
                true,
951
            ],
952
            [
953
                $content->contentInfo->id,
954
                $content->contentInfo->alwaysAvailable,
955
                $content->contentInfo->currentVersionNo,
956
                $content->contentInfo->remoteId,
957
                $content->contentInfo->mainLanguageCode,
958
                $content->contentInfo->ownerId,
959
                $content->contentInfo->published,
960
            ]
961
        );
962
963
        $this->assertNotNull($content->contentInfo->mainLocationId);
964
        $date = new \DateTime('1984/01/01');
965
        $this->assertGreaterThan(
966
            $date->getTimestamp(),
967
            $content->contentInfo->publishedDate->getTimestamp()
968
        );
969
    }
970
971
    /**
972
     * Test for the publishVersion() method.
973
     *
974
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
975
     *
976
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
977
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
978
     */
979
    public function testPublishVersionSetsExpectedVersionInfo($content)
980
    {
981
        $this->assertEquals(
982
            [
983
                $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...
984
                'eng-US',
985
                VersionInfo::STATUS_PUBLISHED,
986
                1,
987
            ],
988
            [
989
                $content->getVersionInfo()->creatorId,
990
                $content->getVersionInfo()->initialLanguageCode,
991
                $content->getVersionInfo()->status,
992
                $content->getVersionInfo()->versionNo,
993
            ]
994
        );
995
996
        $date = new \DateTime('1984/01/01');
997
        $this->assertGreaterThan(
998
            $date->getTimestamp(),
999
            $content->getVersionInfo()->modificationDate->getTimestamp()
1000
        );
1001
1002
        $this->assertNotNull($content->getVersionInfo()->modificationDate);
1003
        $this->assertTrue($content->getVersionInfo()->isPublished());
1004
        $this->assertFalse($content->getVersionInfo()->isDraft());
1005
        $this->assertFalse($content->getVersionInfo()->isArchived());
1006
    }
1007
1008
    /**
1009
     * Test for the publishVersion() method.
1010
     *
1011
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
1012
     *
1013
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1014
     * @depends testPublishVersion
1015
     */
1016
    public function testPublishVersionSetsExpectedContentType($content)
1017
    {
1018
        $contentType = $content->getContentType();
1019
1020
        $this->assertEquals(
1021
            [
1022
                $contentType->id,
1023
                // won't be a match as it's set to true in createContentDraftVersion1()
1024
                //$contentType->defaultAlwaysAvailable,
1025
                //$contentType->defaultSortField,
1026
                //$contentType->defaultSortOrder,
1027
            ],
1028
            [
1029
                $content->contentInfo->contentTypeId,
1030
                //$content->contentInfo->alwaysAvailable,
1031
                //$location->sortField,
1032
                //$location->sortOrder,
1033
            ]
1034
        );
1035
    }
1036
1037
    /**
1038
     * Test for the publishVersion() method.
1039
     *
1040
     * @return \eZ\Publish\API\Repository\Values\Content\Content
1041
     *
1042
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1043
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentWithLocationCreateParameterDoesNotCreateLocationImmediately
1044
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
1045
     */
1046
    public function testPublishVersionCreatesLocationsDefinedOnCreate()
1047
    {
1048
        /* BEGIN: Use Case */
1049
        $content = $this->createContentVersion1();
1050
        /* END: Use Case */
1051
1052
        $location = $this->locationService->loadLocationByRemoteId(
1053
            '0123456789abcdef0123456789abcdef'
1054
        );
1055
1056
        $this->assertEquals(
1057
            $location->getContentInfo(),
1058
            $content->getVersionInfo()->getContentInfo()
1059
        );
1060
1061
        return [$content, $location];
1062
    }
1063
1064
    /**
1065
     * Test for the publishVersion() method.
1066
     *
1067
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1068
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionCreatesLocationsDefinedOnCreate
1069
     */
1070
    public function testCreateContentWithLocationCreateParameterCreatesExpectedLocation(array $testData)
1071
    {
1072
        /** @var \eZ\Publish\API\Repository\Values\Content\Content $content */
1073
        /** @var \eZ\Publish\API\Repository\Values\Content\Location $location */
1074
        list($content, $location) = $testData;
1075
1076
        $parentLocationId = $this->generateId('location', 56);
1077
        $parentLocation = $this->getRepository()->getLocationService()->loadLocation($parentLocationId);
1078
        $mainLocationId = $content->getVersionInfo()->getContentInfo()->mainLocationId;
1079
1080
        $this->assertPropertiesCorrect(
1081
            [
1082
                'id' => $mainLocationId,
1083
                'priority' => 23,
1084
                'hidden' => true,
1085
                'invisible' => true,
1086
                'remoteId' => '0123456789abcdef0123456789abcdef',
1087
                'parentLocationId' => $parentLocationId,
1088
                'pathString' => $parentLocation->pathString . $mainLocationId . '/',
1089
                'depth' => $parentLocation->depth + 1,
1090
                'sortField' => Location::SORT_FIELD_NODE_ID,
1091
                'sortOrder' => Location::SORT_ORDER_DESC,
1092
            ],
1093
            $location
1094
        );
1095
    }
1096
1097
    /**
1098
     * Test for the publishVersion() method.
1099
     *
1100
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1101
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
1102
     */
1103
    public function testPublishVersionThrowsBadStateException()
1104
    {
1105
        /* BEGIN: Use Case */
1106
        $draft = $this->createContentDraftVersion1();
1107
1108
        // Publish the content draft
1109
        $this->contentService->publishVersion($draft->getVersionInfo());
1110
1111
        $this->expectException(BadStateException::class);
1112
1113
        // This call will fail with a "BadStateException", because the version is already published.
1114
        $this->contentService->publishVersion($draft->getVersionInfo());
1115
        /* END: Use Case */
1116
    }
1117
1118
    /**
1119
     * Test that publishVersion() does not affect publishedDate (assuming previous version exists).
1120
     *
1121
     * @covers \eZ\Publish\API\Repository\ContentService::publishVersion
1122
     */
1123
    public function testPublishVersionDoesNotChangePublishedDate()
1124
    {
1125
        $publishedContent = $this->createContentVersion1();
1126
1127
        // force timestamps to differ
1128
        sleep(1);
1129
1130
        $contentDraft = $this->contentService->createContentDraft($publishedContent->contentInfo);
1131
        $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
1132
        $contentUpdateStruct->setField('name', 'New name');
1133
        $contentDraft = $this->contentService->updateContent($contentDraft->versionInfo, $contentUpdateStruct);
1134
        $republishedContent = $this->contentService->publishVersion($contentDraft->versionInfo);
1135
1136
        $this->assertEquals(
1137
            $publishedContent->contentInfo->publishedDate->getTimestamp(),
1138
            $republishedContent->contentInfo->publishedDate->getTimestamp()
1139
        );
1140
        $this->assertGreaterThan(
1141
            $publishedContent->contentInfo->modificationDate->getTimestamp(),
1142
            $republishedContent->contentInfo->modificationDate->getTimestamp()
1143
        );
1144
    }
1145
1146
    /**
1147
     * Test for the createContentDraft() method.
1148
     *
1149
     * @return \eZ\Publish\API\Repository\Values\Content\Content
1150
     *
1151
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1152
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
1153
     * @group user
1154
     */
1155
    public function testCreateContentDraft()
1156
    {
1157
        /* BEGIN: Use Case */
1158
        $content = $this->createContentVersion1();
1159
1160
        // Now we create a new draft from the published content
1161
        $draftedContent = $this->contentService->createContentDraft($content->contentInfo);
1162
        /* END: Use Case */
1163
1164
        $this->assertInstanceOf(
1165
            Content::class,
1166
            $draftedContent
1167
        );
1168
1169
        return $draftedContent;
1170
    }
1171
1172
    /**
1173
     * Test for the createContentDraft() method.
1174
     *
1175
     * Test that editor has access to edit own draft.
1176
     * Note: Editors have access to version_read, which is needed to load content drafts.
1177
     *
1178
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1179
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
1180
     * @group user
1181
     */
1182
    public function testCreateContentDraftAndLoadAccess()
1183
    {
1184
        /* BEGIN: Use Case */
1185
        $user = $this->createUserVersion1();
1186
1187
        // Set new editor as user
1188
        $this->permissionResolver->setCurrentUserReference($user);
1189
1190
        // Create draft
1191
        $draft = $this->createContentDraftVersion1(2, 'folder');
1192
1193
        // Try to load the draft
1194
        $loadedDraft = $this->contentService->loadContent($draft->id);
1195
1196
        /* END: Use Case */
1197
1198
        $this->assertEquals($draft->id, $loadedDraft->id);
1199
    }
1200
1201
    /**
1202
     * Test for the createContentDraft() method.
1203
     *
1204
     * @param \eZ\Publish\API\Repository\Values\Content\Content $draft
1205
     *
1206
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1207
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1208
     */
1209
    public function testCreateContentDraftSetsExpectedProperties($draft)
1210
    {
1211
        $this->assertEquals(
1212
            [
1213
                'fieldCount' => 2,
1214
                'relationCount' => 0,
1215
            ],
1216
            [
1217
                'fieldCount' => count($draft->getFields()),
1218
                'relationCount' => count($this->getRepository()->getContentService()->loadRelations($draft->getVersionInfo())),
1219
            ]
1220
        );
1221
    }
1222
1223
    /**
1224
     * Test for the createContentDraft() method.
1225
     *
1226
     * @param \eZ\Publish\API\Repository\Values\Content\Content $draft
1227
     *
1228
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1229
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1230
     */
1231
    public function testCreateContentDraftSetsContentInfo($draft)
1232
    {
1233
        $contentInfo = $draft->contentInfo;
1234
1235
        $this->assertEquals(
1236
            [
1237
                $draft->id,
1238
                true,
1239
                1,
1240
                'eng-US',
1241
                $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...
1242
                'abcdef0123456789abcdef0123456789',
1243
                1,
1244
            ],
1245
            [
1246
                $contentInfo->id,
1247
                $contentInfo->alwaysAvailable,
1248
                $contentInfo->currentVersionNo,
1249
                $contentInfo->mainLanguageCode,
1250
                $contentInfo->ownerId,
1251
                $contentInfo->remoteId,
1252
                $contentInfo->sectionId,
1253
            ]
1254
        );
1255
    }
1256
1257
    /**
1258
     * Test for the createContentDraft() method.
1259
     *
1260
     * @param \eZ\Publish\API\Repository\Values\Content\Content $draft
1261
     *
1262
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1263
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1264
     */
1265
    public function testCreateContentDraftSetsVersionInfo($draft)
1266
    {
1267
        $versionInfo = $draft->getVersionInfo();
1268
1269
        $this->assertEquals(
1270
            [
1271
                '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...
1272
                'initialLanguageCode' => 'eng-US',
1273
                'languageCodes' => [0 => 'eng-US'],
1274
                'status' => VersionInfo::STATUS_DRAFT,
1275
                'versionNo' => 2,
1276
            ],
1277
            [
1278
                'creatorId' => $versionInfo->creatorId,
1279
                'initialLanguageCode' => $versionInfo->initialLanguageCode,
1280
                'languageCodes' => $versionInfo->languageCodes,
1281
                'status' => $versionInfo->status,
1282
                'versionNo' => $versionInfo->versionNo,
1283
            ]
1284
        );
1285
        $this->assertTrue($versionInfo->isDraft());
1286
        $this->assertFalse($versionInfo->isPublished());
1287
        $this->assertFalse($versionInfo->isArchived());
1288
    }
1289
1290
    /**
1291
     * Test for the createContentDraft() method.
1292
     *
1293
     * @param \eZ\Publish\API\Repository\Values\Content\Content $draft
1294
     *
1295
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1296
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1297
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfo
1298
     */
1299
    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...
1300
    {
1301
        /* BEGIN: Use Case */
1302
        $content = $this->createContentVersion1();
1303
1304
        // Now we create a new draft from the published content
1305
        $this->contentService->createContentDraft($content->contentInfo);
1306
1307
        // This call will still load the published version
1308
        $versionInfoPublished = $this->contentService->loadVersionInfo($content->contentInfo);
1309
        /* END: Use Case */
1310
1311
        $this->assertEquals(1, $versionInfoPublished->versionNo);
1312
    }
1313
1314
    /**
1315
     * Test for the createContentDraft() method.
1316
     *
1317
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1318
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
1319
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1320
     */
1321 View Code Duplication
    public function testCreateContentDraftLoadContentStillLoadsPublishedVersion()
1322
    {
1323
        /* BEGIN: Use Case */
1324
        $content = $this->createContentVersion1();
1325
1326
        // Now we create a new draft from the published content
1327
        $this->contentService->createContentDraft($content->contentInfo);
1328
1329
        // This call will still load the published content version
1330
        $contentPublished = $this->contentService->loadContent($content->id);
1331
        /* END: Use Case */
1332
1333
        $this->assertEquals(1, $contentPublished->getVersionInfo()->versionNo);
1334
    }
1335
1336
    /**
1337
     * Test for the createContentDraft() method.
1338
     *
1339
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1340
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByRemoteId
1341
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1342
     */
1343 View Code Duplication
    public function testCreateContentDraftLoadContentByRemoteIdStillLoadsPublishedVersion()
1344
    {
1345
        /* BEGIN: Use Case */
1346
        $content = $this->createContentVersion1();
1347
1348
        // Now we create a new draft from the published content
1349
        $this->contentService->createContentDraft($content->contentInfo);
1350
1351
        // This call will still load the published content version
1352
        $contentPublished = $this->contentService->loadContentByRemoteId('abcdef0123456789abcdef0123456789');
1353
        /* END: Use Case */
1354
1355
        $this->assertEquals(1, $contentPublished->getVersionInfo()->versionNo);
1356
    }
1357
1358
    /**
1359
     * Test for the createContentDraft() method.
1360
     *
1361
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
1362
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByContentInfo
1363
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1364
     */
1365 View Code Duplication
    public function testCreateContentDraftLoadContentByContentInfoStillLoadsPublishedVersion()
1366
    {
1367
        /* BEGIN: Use Case */
1368
        $content = $this->createContentVersion1();
1369
1370
        // Now we create a new draft from the published content
1371
        $this->contentService->createContentDraft($content->contentInfo);
1372
1373
        // This call will still load the published content version
1374
        $contentPublished = $this->contentService->loadContentByContentInfo($content->contentInfo);
1375
        /* END: Use Case */
1376
1377
        $this->assertEquals(1, $contentPublished->getVersionInfo()->versionNo);
1378
    }
1379
1380
    /**
1381
     * Test for the newContentUpdateStruct() method.
1382
     *
1383
     * @covers \eZ\Publish\API\Repository\ContentService::newContentUpdateStruct
1384
     * @group user
1385
     */
1386
    public function testNewContentUpdateStruct()
1387
    {
1388
        /* BEGIN: Use Case */
1389
        $updateStruct = $this->contentService->newContentUpdateStruct();
1390
        /* END: Use Case */
1391
1392
        $this->assertInstanceOf(
1393
            ContentUpdateStruct::class,
1394
            $updateStruct
1395
        );
1396
1397
        $this->assertPropertiesCorrect(
1398
            [
1399
                'initialLanguageCode' => null,
1400
                'fields' => [],
1401
            ],
1402
            $updateStruct
1403
        );
1404
    }
1405
1406
    /**
1407
     * Test for the updateContent() method.
1408
     *
1409
     * @return \eZ\Publish\API\Repository\Values\Content\Content
1410
     *
1411
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1412
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testNewContentUpdateStruct
1413
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1414
     * @group user
1415
     * @group field-type
1416
     */
1417
    public function testUpdateContent()
1418
    {
1419
        /* BEGIN: Use Case */
1420
        $draftVersion2 = $this->createUpdatedDraftVersion2();
1421
        /* END: Use Case */
1422
1423
        $this->assertInstanceOf(
1424
            Content::class,
1425
            $draftVersion2
1426
        );
1427
1428
        $this->assertEquals(
1429
            $this->generateId('user', 10),
1430
            $draftVersion2->versionInfo->creatorId,
1431
            'creatorId is not properly set on new Version'
1432
        );
1433
1434
        return $draftVersion2;
1435
    }
1436
1437
    /**
1438
     * Test for the updateContent_WithDifferentUser() method.
1439
     *
1440
     * @return \eZ\Publish\API\Repository\Values\Content\Content
1441
     *
1442
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1443
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testNewContentUpdateStruct
1444
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
1445
     * @group user
1446
     * @group field-type
1447
     */
1448
    public function testUpdateContentWithDifferentUser()
1449
    {
1450
        /* BEGIN: Use Case */
1451
        $arrayWithDraftVersion2 = $this->createUpdatedDraftVersion2NotAdmin();
1452
        /* END: Use Case */
1453
1454
        $this->assertInstanceOf(
1455
            Content::class,
1456
            $arrayWithDraftVersion2[0]
1457
        );
1458
1459
        $this->assertEquals(
1460
            $this->generateId('user', $arrayWithDraftVersion2[1]),
1461
            $arrayWithDraftVersion2[0]->versionInfo->creatorId,
1462
            'creatorId is not properly set on new Version'
1463
        );
1464
1465
        return $arrayWithDraftVersion2[0];
1466
    }
1467
1468
    /**
1469
     * Test for the updateContent() method.
1470
     *
1471
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
1472
     *
1473
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1474
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1475
     */
1476
    public function testUpdateContentSetsExpectedFields($content)
1477
    {
1478
        $actual = $this->normalizeFields($content->getFields());
1479
1480
        $expected = [
1481
            new Field(
1482
                [
1483
                    'id' => 0,
1484
                    'value' => true,
1485
                    'languageCode' => 'eng-GB',
1486
                    'fieldDefIdentifier' => 'description',
1487
                    'fieldTypeIdentifier' => 'ezrichtext',
1488
                ]
1489
            ),
1490
            new Field(
1491
                [
1492
                    'id' => 0,
1493
                    'value' => true,
1494
                    'languageCode' => 'eng-US',
1495
                    'fieldDefIdentifier' => 'description',
1496
                    'fieldTypeIdentifier' => 'ezrichtext',
1497
                ]
1498
            ),
1499
            new Field(
1500
                [
1501
                    'id' => 0,
1502
                    'value' => true,
1503
                    'languageCode' => 'eng-GB',
1504
                    'fieldDefIdentifier' => 'name',
1505
                    'fieldTypeIdentifier' => 'ezstring',
1506
                ]
1507
            ),
1508
            new Field(
1509
                [
1510
                    'id' => 0,
1511
                    'value' => true,
1512
                    'languageCode' => 'eng-US',
1513
                    'fieldDefIdentifier' => 'name',
1514
                    'fieldTypeIdentifier' => 'ezstring',
1515
                ]
1516
            ),
1517
        ];
1518
1519
        $this->assertEquals($expected, $actual);
1520
    }
1521
1522
    /**
1523
     * Test for the updateContent() method.
1524
     *
1525
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1526
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1527
     */
1528
    public function testUpdateContentThrowsBadStateException()
1529
    {
1530
        /* BEGIN: Use Case */
1531
        $content = $this->createContentVersion1();
1532
1533
        // Now create an update struct and modify some fields
1534
        $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
1535
        $contentUpdateStruct->setField('title', 'An awesome² story about ezp.');
1536
        $contentUpdateStruct->setField('title', 'An awesome²³ story about ezp.', 'eng-GB');
1537
1538
        $contentUpdateStruct->initialLanguageCode = 'eng-US';
1539
1540
        $this->expectException(BadStateException::class);
1541
1542
        // This call will fail with a "BadStateException", because $publishedContent is not a draft.
1543
        $this->contentService->updateContent(
1544
            $content->getVersionInfo(),
1545
            $contentUpdateStruct
1546
        );
1547
        /* END: Use Case */
1548
    }
1549
1550
    /**
1551
     * Test for the updateContent() method.
1552
     *
1553
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1554
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1555
     */
1556 View Code Duplication
    public function testUpdateContentThrowsInvalidArgumentExceptionWhenFieldTypeDoesNotAccept()
1557
    {
1558
        /* BEGIN: Use Case */
1559
        $draft = $this->createContentDraftVersion1();
1560
1561
        // Now create an update struct and modify some fields
1562
        $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
1563
        // The name field does not accept a stdClass object as its input
1564
        $contentUpdateStruct->setField('name', new \stdClass(), 'eng-US');
1565
1566
        $this->expectException(APIInvalidArgumentException::class);
1567
        // is not accepted
1568
        $this->contentService->updateContent(
1569
            $draft->getVersionInfo(),
1570
            $contentUpdateStruct
1571
        );
1572
        /* END: Use Case */
1573
    }
1574
1575
    /**
1576
     * Test for the updateContent() method.
1577
     *
1578
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1579
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1580
     */
1581 View Code Duplication
    public function testUpdateContentWhenMandatoryFieldIsEmpty()
1582
    {
1583
        /* BEGIN: Use Case */
1584
        $draft = $this->createContentDraftVersion1();
1585
1586
        // Now create an update struct and set a mandatory field to null
1587
        $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
1588
        $contentUpdateStruct->setField('name', null);
1589
1590
        // Don't set this, then the above call without languageCode will fail
1591
        $contentUpdateStruct->initialLanguageCode = 'eng-US';
1592
1593
        $this->expectException(ContentFieldValidationException::class);
1594
1595
        // This call will fail with a "ContentFieldValidationException", because the mandatory "name" field is empty.
1596
        $this->contentService->updateContent(
1597
            $draft->getVersionInfo(),
1598
            $contentUpdateStruct
1599
        );
1600
        /* END: Use Case */
1601
    }
1602
1603
    /**
1604
     * Test for the updateContent() method.
1605
     *
1606
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1607
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1608
     */
1609
    public function testUpdateContentThrowsContentFieldValidationException()
1610
    {
1611
        /* BEGIN: Use Case */
1612
        $contentTypeService = $this->getRepository()->getContentTypeService();
1613
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
1614
1615
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
1616
        $contentCreate->setField('name', 'An awesome Sidelfingen folder');
1617
1618
        $draft = $this->contentService->createContent($contentCreate);
1619
1620
        $contentUpdate = $this->contentService->newContentUpdateStruct();
1621
        // Violates string length constraint
1622
        $contentUpdate->setField('short_name', str_repeat('a', 200), 'eng-US');
1623
1624
        $this->expectException(ContentFieldValidationException::class);
1625
1626
        // Throws ContentFieldValidationException because the string length validation of the field "short_name" fails
1627
        $this->contentService->updateContent($draft->getVersionInfo(), $contentUpdate);
1628
        /* END: Use Case */
1629
    }
1630
1631
    /**
1632
     * Test for the updateContent() method.
1633
     *
1634
     * @covers \eZ\Publish\API\Repository\ContentService::updateContent()
1635
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1636
     */
1637
    public function testUpdateContentValidatorIgnoresRequiredFieldsOfNotUpdatedLanguages()
1638
    {
1639
        /* BEGIN: Use Case */
1640
        $contentTypeService = $this->getRepository()->getContentTypeService();
1641
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
1642
1643
        // Create multilangual content
1644
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
1645
        $contentCreate->setField('name', 'An awesome Sidelfingen folder', 'eng-US');
1646
        $contentCreate->setField('name', 'An awesome Sidelfingen folder', 'eng-GB');
1647
1648
        $contentDraft = $this->contentService->createContent($contentCreate);
1649
1650
        // 2. Update content type definition
1651
        $contentTypeDraft = $contentTypeService->createContentTypeDraft($contentType);
1652
1653
        $fieldDefinition = $contentType->getFieldDefinition('description');
1654
        $fieldDefinitionUpdate = $contentTypeService->newFieldDefinitionUpdateStruct();
1655
        $fieldDefinitionUpdate->identifier = 'description';
1656
        $fieldDefinitionUpdate->isRequired = true;
1657
1658
        $contentTypeService->updateFieldDefinition(
1659
            $contentTypeDraft,
1660
            $fieldDefinition,
1661
            $fieldDefinitionUpdate
1662
        );
1663
        $contentTypeService->publishContentTypeDraft($contentTypeDraft);
1664
1665
        // 3. Update only eng-US translation
1666
        $description = new DOMDocument();
1667
        $description->loadXML(<<<XML
1668
<?xml version="1.0" encoding="UTF-8"?>
1669
<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">
1670
    <para>Lorem ipsum dolor</para>
1671
</section>
1672
XML
1673
        );
1674
1675
        $contentUpdate = $this->contentService->newContentUpdateStruct();
1676
        $contentUpdate->setField('name', 'An awesome Sidelfingen folder (updated)', 'eng-US');
1677
        $contentUpdate->setField('description', $description);
1678
1679
        $this->contentService->updateContent($contentDraft->getVersionInfo(), $contentUpdate);
1680
        /* END: Use Case */
1681
    }
1682
1683
    /**
1684
     * Test for the updateContent() method.
1685
     *
1686
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
1687
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1688
     */
1689
    public function testUpdateContentWithNotUpdatingMandatoryField()
1690
    {
1691
        /* BEGIN: Use Case */
1692
        $draft = $this->createContentDraftVersion1();
1693
1694
        // Now create an update struct which does not overwrite mandatory
1695
        // fields
1696
        $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
1697
        $contentUpdateStruct->setField(
1698
            'description',
1699
            '<?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"/>'
1700
        );
1701
1702
        // Don't set this, then the above call without languageCode will fail
1703
        $contentUpdateStruct->initialLanguageCode = 'eng-US';
1704
1705
        // This will only update the "description" field in the "eng-US"
1706
        // language
1707
        $updatedDraft = $this->contentService->updateContent(
1708
            $draft->getVersionInfo(),
1709
            $contentUpdateStruct
1710
        );
1711
        /* END: Use Case */
1712
1713
        foreach ($updatedDraft->getFields() as $field) {
1714
            if ($field->languageCode === 'eng-US' && $field->fieldDefIdentifier === 'name' && $field->value !== null) {
1715
                // Found field
1716
                return;
1717
            }
1718
        }
1719
        $this->fail(
1720
            'Field with identifier "name" in language "eng-US" could not be found or has empty value.'
1721
        );
1722
    }
1723
1724
    /**
1725
     * Test for the createContentDraft() method.
1726
     *
1727
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft($contentInfo, $versionInfo)
1728
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1729
     */
1730 View Code Duplication
    public function testCreateContentDraftWithSecondParameter()
1731
    {
1732
        /* BEGIN: Use Case */
1733
        $contentVersion2 = $this->createContentVersion2();
1734
1735
        // Now we create a new draft from the initial version
1736
        $draftedContentReloaded = $this->contentService->createContentDraft(
1737
            $contentVersion2->contentInfo,
1738
            $contentVersion2->getVersionInfo()
1739
        );
1740
        /* END: Use Case */
1741
1742
        $this->assertEquals(3, $draftedContentReloaded->getVersionInfo()->versionNo);
1743
    }
1744
1745
    /**
1746
     * Test for the createContentDraft() method with third parameter.
1747
     *
1748
     * @covers \eZ\Publish\Core\Repository\ContentService::createContentDraft
1749
     */
1750
    public function testCreateContentDraftWithThirdParameter()
1751
    {
1752
        $content = $this->contentService->loadContent(4);
1753
        $user = $this->createUserVersion1();
1754
1755
        $draftContent = $this->contentService->createContentDraft(
1756
            $content->contentInfo,
1757
            $content->getVersionInfo(),
1758
            $user
1759
        );
1760
1761
        $this->assertInstanceOf(
1762
            Content::class,
1763
            $draftContent
1764
        );
1765
    }
1766
1767
    /**
1768
     * Test for the publishVersion() method.
1769
     *
1770
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1771
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
1772
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
1773
     */
1774 View Code Duplication
    public function testPublishVersionFromContentDraft()
1775
    {
1776
        /* BEGIN: Use Case */
1777
        $contentVersion2 = $this->createContentVersion2();
1778
        /* END: Use Case */
1779
1780
        $versionInfo = $this->contentService->loadVersionInfo($contentVersion2->contentInfo);
1781
1782
        $this->assertEquals(
1783
            [
1784
                'status' => VersionInfo::STATUS_PUBLISHED,
1785
                'versionNo' => 2,
1786
            ],
1787
            [
1788
                'status' => $versionInfo->status,
1789
                'versionNo' => $versionInfo->versionNo,
1790
            ]
1791
        );
1792
        $this->assertTrue($versionInfo->isPublished());
1793
        $this->assertFalse($versionInfo->isDraft());
1794
        $this->assertFalse($versionInfo->isArchived());
1795
    }
1796
1797
    /**
1798
     * Test for the publishVersion() method.
1799
     *
1800
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1801
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
1802
     */
1803 View Code Duplication
    public function testPublishVersionFromContentDraftArchivesOldVersion()
1804
    {
1805
        /* BEGIN: Use Case */
1806
        $contentVersion2 = $this->createContentVersion2();
1807
        /* END: Use Case */
1808
1809
        $versionInfo = $this->contentService->loadVersionInfo($contentVersion2->contentInfo, 1);
1810
1811
        $this->assertEquals(
1812
            [
1813
                'status' => VersionInfo::STATUS_ARCHIVED,
1814
                'versionNo' => 1,
1815
            ],
1816
            [
1817
                'status' => $versionInfo->status,
1818
                'versionNo' => $versionInfo->versionNo,
1819
            ]
1820
        );
1821
        $this->assertTrue($versionInfo->isArchived());
1822
        $this->assertFalse($versionInfo->isDraft());
1823
        $this->assertFalse($versionInfo->isPublished());
1824
    }
1825
1826
    /**
1827
     * Test for the publishVersion() method.
1828
     *
1829
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1830
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
1831
     */
1832
    public function testPublishVersionFromContentDraftUpdatesContentInfoCurrentVersion()
1833
    {
1834
        /* BEGIN: Use Case */
1835
        $contentVersion2 = $this->createContentVersion2();
1836
        /* END: Use Case */
1837
1838
        $this->assertEquals(2, $contentVersion2->contentInfo->currentVersionNo);
1839
    }
1840
1841
    /**
1842
     * Test for the publishVersion() method.
1843
     *
1844
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1845
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
1846
     */
1847 View Code Duplication
    public function testPublishVersionFromOldContentDraftArchivesNewerVersionNo()
1848
    {
1849
        /* BEGIN: Use Case */
1850
        $content = $this->createContentVersion1();
1851
1852
        // Create a new draft with versionNo = 2
1853
        $draftedContentVersion2 = $this->contentService->createContentDraft($content->contentInfo);
1854
1855
        // Create another new draft with versionNo = 3
1856
        $draftedContentVersion3 = $this->contentService->createContentDraft($content->contentInfo);
1857
1858
        // Publish draft with versionNo = 3
1859
        $this->contentService->publishVersion($draftedContentVersion3->getVersionInfo());
1860
1861
        // Publish the first draft with versionNo = 2
1862
        // currentVersionNo is now 2, versionNo 3 will be archived
1863
        $publishedDraft = $this->contentService->publishVersion($draftedContentVersion2->getVersionInfo());
1864
        /* END: Use Case */
1865
1866
        $this->assertEquals(2, $publishedDraft->contentInfo->currentVersionNo);
1867
    }
1868
1869
    /**
1870
     * Test for the publishVersion() method, and that it creates limited archives.
1871
     *
1872
     * @todo Adapt this when per content type archive limited is added on repository Content Type model.
1873
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
1874
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
1875
     */
1876
    public function testPublishVersionNotCreatingUnlimitedArchives()
1877
    {
1878
        $content = $this->createContentVersion1();
1879
1880
        // load first to make sure list gets updated also (cache)
1881
        $versionInfoList = $this->contentService->loadVersions($content->contentInfo);
1882
        $this->assertEquals(1, count($versionInfoList));
1883
        $this->assertEquals(1, $versionInfoList[0]->versionNo);
1884
1885
        // Create a new draft with versionNo = 2
1886
        $draftedContentVersion = $this->contentService->createContentDraft($content->contentInfo);
1887
        $this->contentService->publishVersion($draftedContentVersion->getVersionInfo());
1888
1889
        // Create a new draft with versionNo = 3
1890
        $draftedContentVersion = $this->contentService->createContentDraft($content->contentInfo);
1891
        $this->contentService->publishVersion($draftedContentVersion->getVersionInfo());
1892
1893
        // Create a new draft with versionNo = 4
1894
        $draftedContentVersion = $this->contentService->createContentDraft($content->contentInfo);
1895
        $this->contentService->publishVersion($draftedContentVersion->getVersionInfo());
1896
1897
        // Create a new draft with versionNo = 5
1898
        $draftedContentVersion = $this->contentService->createContentDraft($content->contentInfo);
1899
        $this->contentService->publishVersion($draftedContentVersion->getVersionInfo());
1900
1901
        // Create a new draft with versionNo = 6
1902
        $draftedContentVersion = $this->contentService->createContentDraft($content->contentInfo);
1903
        $this->contentService->publishVersion($draftedContentVersion->getVersionInfo());
1904
1905
        // Create a new draft with versionNo = 7
1906
        $draftedContentVersion = $this->contentService->createContentDraft($content->contentInfo);
1907
        $this->contentService->publishVersion($draftedContentVersion->getVersionInfo());
1908
1909
        $versionInfoList = $this->contentService->loadVersions($content->contentInfo);
1910
1911
        $this->assertEquals(6, count($versionInfoList));
1912
        $this->assertEquals(2, $versionInfoList[0]->versionNo);
1913
        $this->assertEquals(7, $versionInfoList[5]->versionNo);
1914
1915
        $this->assertEquals(
1916
            [
1917
                VersionInfo::STATUS_ARCHIVED,
1918
                VersionInfo::STATUS_ARCHIVED,
1919
                VersionInfo::STATUS_ARCHIVED,
1920
                VersionInfo::STATUS_ARCHIVED,
1921
                VersionInfo::STATUS_ARCHIVED,
1922
                VersionInfo::STATUS_PUBLISHED,
1923
            ],
1924
            [
1925
                $versionInfoList[0]->status,
1926
                $versionInfoList[1]->status,
1927
                $versionInfoList[2]->status,
1928
                $versionInfoList[3]->status,
1929
                $versionInfoList[4]->status,
1930
                $versionInfoList[5]->status,
1931
            ]
1932
        );
1933
    }
1934
1935
    /**
1936
     * Test for the newContentMetadataUpdateStruct() method.
1937
     *
1938
     * @covers \eZ\Publish\API\Repository\ContentService::newContentMetadataUpdateStruct
1939
     * @group user
1940
     */
1941
    public function testNewContentMetadataUpdateStruct()
1942
    {
1943
        /* BEGIN: Use Case */
1944
        // Creates a new metadata update struct
1945
        $metadataUpdate = $this->contentService->newContentMetadataUpdateStruct();
1946
1947
        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...
1948
            $this->assertNull($propertyValue, "Property '{$propertyName}' initial value should be null'");
1949
        }
1950
1951
        $metadataUpdate->remoteId = 'aaaabbbbccccddddeeeeffff11112222';
1952
        $metadataUpdate->mainLanguageCode = 'eng-GB';
1953
        $metadataUpdate->alwaysAvailable = false;
1954
        /* END: Use Case */
1955
1956
        $this->assertInstanceOf(
1957
            ContentMetadataUpdateStruct::class,
1958
            $metadataUpdate
1959
        );
1960
    }
1961
1962
    /**
1963
     * Test for the updateContentMetadata() method.
1964
     *
1965
     * @return \eZ\Publish\API\Repository\Values\Content\Content
1966
     *
1967
     * @see \eZ\Publish\API\Repository\ContentService::updateContentMetadata()
1968
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
1969
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testNewContentMetadataUpdateStruct
1970
     * @group user
1971
     */
1972
    public function testUpdateContentMetadata()
1973
    {
1974
        /* BEGIN: Use Case */
1975
        $content = $this->createContentVersion1();
1976
1977
        // Creates a metadata update struct
1978
        $metadataUpdate = $this->contentService->newContentMetadataUpdateStruct();
1979
1980
        $metadataUpdate->remoteId = 'aaaabbbbccccddddeeeeffff11112222';
1981
        $metadataUpdate->mainLanguageCode = 'eng-GB';
1982
        $metadataUpdate->alwaysAvailable = false;
1983
        $metadataUpdate->publishedDate = $this->createDateTime(441759600); // 1984/01/01
1984
        $metadataUpdate->modificationDate = $this->createDateTime(441759600); // 1984/01/01
1985
1986
        // Update the metadata of the published content object
1987
        $content = $this->contentService->updateContentMetadata(
1988
            $content->contentInfo,
1989
            $metadataUpdate
1990
        );
1991
        /* END: Use Case */
1992
1993
        $this->assertInstanceOf(
1994
            Content::class,
1995
            $content
1996
        );
1997
1998
        return $content;
1999
    }
2000
2001
    /**
2002
     * Test for the updateContentMetadata() method.
2003
     *
2004
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
2005
     *
2006
     * @see \eZ\Publish\API\Repository\ContentService::updateContentMetadata()
2007
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContentMetadata
2008
     */
2009
    public function testUpdateContentMetadataSetsExpectedProperties($content)
2010
    {
2011
        $contentInfo = $content->contentInfo;
2012
2013
        $this->assertEquals(
2014
            [
2015
                'remoteId' => 'aaaabbbbccccddddeeeeffff11112222',
2016
                'sectionId' => $this->generateId('section', 1),
2017
                'alwaysAvailable' => false,
2018
                'currentVersionNo' => 1,
2019
                'mainLanguageCode' => 'eng-GB',
2020
                'modificationDate' => $this->createDateTime(441759600),
2021
                '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...
2022
                'published' => true,
2023
                'publishedDate' => $this->createDateTime(441759600),
2024
            ],
2025
            [
2026
                'remoteId' => $contentInfo->remoteId,
2027
                'sectionId' => $contentInfo->sectionId,
2028
                'alwaysAvailable' => $contentInfo->alwaysAvailable,
2029
                'currentVersionNo' => $contentInfo->currentVersionNo,
2030
                'mainLanguageCode' => $contentInfo->mainLanguageCode,
2031
                'modificationDate' => $contentInfo->modificationDate,
2032
                'ownerId' => $contentInfo->ownerId,
2033
                'published' => $contentInfo->published,
2034
                'publishedDate' => $contentInfo->publishedDate,
2035
            ]
2036
        );
2037
    }
2038
2039
    /**
2040
     * Test for the updateContentMetadata() method.
2041
     *
2042
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
2043
     *
2044
     * @see \eZ\Publish\API\Repository\ContentService::updateContentMetadata()
2045
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContentMetadata
2046
     */
2047
    public function testUpdateContentMetadataNotUpdatesContentVersion($content)
2048
    {
2049
        $this->assertEquals(1, $content->getVersionInfo()->versionNo);
2050
    }
2051
2052
    /**
2053
     * Test for the updateContentMetadata() method.
2054
     *
2055
     * @covers \eZ\Publish\API\Repository\ContentService::updateContentMetadata()
2056
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContentMetadata
2057
     */
2058
    public function testUpdateContentMetadataThrowsInvalidArgumentExceptionOnDuplicateRemoteId()
2059
    {
2060
        /* BEGIN: Use Case */
2061
        // RemoteId of the "Media" page of an eZ Publish demo installation
2062
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
2063
2064
        $content = $this->createContentVersion1();
2065
2066
        // Creates a metadata update struct
2067
        $metadataUpdate = $this->contentService->newContentMetadataUpdateStruct();
2068
        $metadataUpdate->remoteId = $mediaRemoteId;
2069
2070
        $this->expectException(APIInvalidArgumentException::class);
2071
        // specified remoteId is already used by the "Media" page.
2072
        $this->contentService->updateContentMetadata(
2073
            $content->contentInfo,
2074
            $metadataUpdate
2075
        );
2076
        /* END: Use Case */
2077
    }
2078
2079
    /**
2080
     * Test for the updateContentMetadata() method.
2081
     *
2082
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContentMetadata
2083
     */
2084
    public function testUpdateContentMetadataThrowsInvalidArgumentExceptionOnNoMetadataPropertiesSet()
2085
    {
2086
        $contentInfo = $this->contentService->loadContentInfo(4);
2087
        $contentMetadataUpdateStruct = $this->contentService->newContentMetadataUpdateStruct();
2088
2089
        $this->expectException(APIInvalidArgumentException::class);
2090
        $this->contentService->updateContentMetadata($contentInfo, $contentMetadataUpdateStruct);
2091
    }
2092
2093
    /**
2094
     * Test for the deleteContent() method.
2095
     *
2096
     * @see \eZ\Publish\API\Repository\ContentService::deleteContent()
2097
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
2098
     */
2099 View Code Duplication
    public function testDeleteContent()
2100
    {
2101
        /* BEGIN: Use Case */
2102
        $contentVersion2 = $this->createContentVersion2();
2103
2104
        // Load the locations for this content object
2105
        $locations = $this->locationService->loadLocations($contentVersion2->contentInfo);
2106
2107
        // This will delete the content, all versions and the associated locations
2108
        $this->contentService->deleteContent($contentVersion2->contentInfo);
2109
        /* END: Use Case */
2110
2111
        $this->expectException(NotFoundException::class);
2112
2113
        foreach ($locations as $location) {
2114
            $this->locationService->loadLocation($location->id);
2115
        }
2116
    }
2117
2118
    /**
2119
     * Test for the deleteContent() method.
2120
     *
2121
     * Test for issue EZP-21057:
2122
     * "contentService: Unable to delete a content with an empty file attribute"
2123
     *
2124
     * @see \eZ\Publish\API\Repository\ContentService::deleteContent()
2125
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
2126
     */
2127 View Code Duplication
    public function testDeleteContentWithEmptyBinaryField()
2128
    {
2129
        /* BEGIN: Use Case */
2130
        $contentVersion = $this->createContentVersion1EmptyBinaryField();
2131
2132
        // Load the locations for this content object
2133
        $locations = $this->locationService->loadLocations($contentVersion->contentInfo);
2134
2135
        // This will delete the content, all versions and the associated locations
2136
        $this->contentService->deleteContent($contentVersion->contentInfo);
2137
        /* END: Use Case */
2138
2139
        $this->expectException(NotFoundException::class);
2140
2141
        foreach ($locations as $location) {
2142
            $this->locationService->loadLocation($location->id);
2143
        }
2144
    }
2145
2146
    public function testCountContentDraftsReturnsZeroByDefault(): void
2147
    {
2148
        $this->assertSame(0, $this->contentService->countContentDrafts());
2149
        $this->assertSame(0, $this->contentService->countContentDrafts());
2150
    }
2151
2152
    public function testCountContentDrafts(): void
2153
    {
2154
        /* BEGIN: Use Case */
2155
        // Create 5 drafts
2156
        $this->createContentDrafts(5);
2157
        /* END: Use Case */
2158
2159
        $this->assertSame(5, $this->contentService->countContentDrafts());
2160
    }
2161
2162
    public function testCountContentDraftsForUsers(): void
2163
    {
2164
        /* BEGIN: Use Case */
2165
        $newUser = $this->createUserWithPolicies(
2166
            'new_user',
2167
            [
2168
                ['module' => 'content', 'function' => 'create'],
2169
                ['module' => 'content', 'function' => 'read'],
2170
                ['module' => 'content', 'function' => 'publish'],
2171
                ['module' => 'content', 'function' => 'edit'],
2172
            ]
2173
        );
2174
2175
        $previousUser = $this->permissionResolver->getCurrentUserReference();
2176
2177
        // Set new editor as user
2178
        $this->permissionResolver->setCurrentUserReference($newUser);
2179
2180
        // Create a content draft as newUser
2181
        $publishedContent = $this->createContentVersion1();
2182
        $this->contentService->createContentDraft($publishedContent->contentInfo);
2183
2184
        // Reset to previous current user
2185
        $this->permissionResolver->setCurrentUserReference($previousUser);
2186
2187
        // Now $contentDrafts for the previous current user and the new user
2188
        $newUserDrafts = $this->contentService->countContentDrafts($newUser);
2189
        $previousUserDrafts = $this->contentService->countContentDrafts();
2190
        /* END: Use Case */
2191
2192
        $this->assertSame(1, $newUserDrafts);
2193
        $this->assertSame(0, $previousUserDrafts);
2194
    }
2195
2196
    /**
2197
     * Test for the loadContentDrafts() method.
2198
     *
2199
     * @see \eZ\Publish\API\Repository\ContentService::loadContentDrafts()
2200
     */
2201
    public function testLoadContentDraftsReturnsEmptyArrayByDefault()
2202
    {
2203
        /* BEGIN: Use Case */
2204
        $contentDrafts = $this->contentService->loadContentDrafts();
2205
        /* END: Use Case */
2206
2207
        $this->assertSame([], $contentDrafts);
2208
    }
2209
2210
    /**
2211
     * Test for the loadContentDrafts() method.
2212
     *
2213
     * @see \eZ\Publish\API\Repository\ContentService::loadContentDrafts()
2214
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
2215
     */
2216
    public function testLoadContentDrafts()
2217
    {
2218
        /* BEGIN: Use Case */
2219
        // Remote ids of the "Media" and the "eZ Publish Demo Design ..." page
2220
        // of a eZ Publish demo installation.
2221
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
2222
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
2223
2224
        // "Media" content object
2225
        $mediaContentInfo = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
2226
2227
        // "eZ Publish Demo Design ..." content object
2228
        $demoDesignContentInfo = $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId);
2229
2230
        // Create some drafts
2231
        $this->contentService->createContentDraft($mediaContentInfo);
2232
        $this->contentService->createContentDraft($demoDesignContentInfo);
2233
2234
        // Now $contentDrafts should contain two drafted versions
2235
        $draftedVersions = $this->contentService->loadContentDrafts();
2236
        /* END: Use Case */
2237
2238
        $actual = [
2239
            $draftedVersions[0]->status,
2240
            $draftedVersions[0]->getContentInfo()->remoteId,
2241
            $draftedVersions[1]->status,
2242
            $draftedVersions[1]->getContentInfo()->remoteId,
2243
        ];
2244
        sort($actual, SORT_STRING);
2245
2246
        $this->assertEquals(
2247
            [
2248
                VersionInfo::STATUS_DRAFT,
2249
                VersionInfo::STATUS_DRAFT,
2250
                $demoDesignRemoteId,
2251
                $mediaRemoteId,
2252
            ],
2253
            $actual
2254
        );
2255
    }
2256
2257
    /**
2258
     * Test for the loadContentDrafts() method.
2259
     *
2260
     * @see \eZ\Publish\API\Repository\ContentService::loadContentDrafts($user)
2261
     */
2262
    public function testLoadContentDraftsWithFirstParameter()
2263
    {
2264
        /* BEGIN: Use Case */
2265
        $user = $this->createUserVersion1();
2266
2267
        // Get current user
2268
        $oldCurrentUser = $this->permissionResolver->getCurrentUserReference();
2269
2270
        // Set new editor as user
2271
        $this->permissionResolver->setCurrentUserReference($user);
2272
2273
        // Remote id of the "Media" content object in an eZ Publish demo installation.
2274
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
2275
2276
        // "Media" content object
2277
        $mediaContentInfo = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
2278
2279
        // Create a content draft
2280
        $this->contentService->createContentDraft($mediaContentInfo);
2281
2282
        // Reset to previous current user
2283
        $this->permissionResolver->setCurrentUserReference($oldCurrentUser);
2284
2285
        // Now $contentDrafts for the previous current user and the new user
2286
        $newCurrentUserDrafts = $this->contentService->loadContentDrafts($user);
2287
        $oldCurrentUserDrafts = $this->contentService->loadContentDrafts();
2288
        /* END: Use Case */
2289
2290
        $this->assertSame([], $oldCurrentUserDrafts);
2291
2292
        $this->assertEquals(
2293
            [
2294
                VersionInfo::STATUS_DRAFT,
2295
                $mediaRemoteId,
2296
            ],
2297
            [
2298
                $newCurrentUserDrafts[0]->status,
2299
                $newCurrentUserDrafts[0]->getContentInfo()->remoteId,
2300
            ]
2301
        );
2302
        $this->assertTrue($newCurrentUserDrafts[0]->isDraft());
2303
        $this->assertFalse($newCurrentUserDrafts[0]->isArchived());
2304
        $this->assertFalse($newCurrentUserDrafts[0]->isPublished());
2305
    }
2306
2307
    /**
2308
     * Test for the loadContentDraftList() method.
2309
     *
2310
     * @see \eZ\Publish\API\Repository\ContentService::loadContentDrafts()
2311
     */
2312
    public function testLoadContentDraftListWithPaginationParameters()
2313
    {
2314
        // Create some drafts
2315
        $publishedContent = $this->createContentVersion1();
2316
        $draftContentA = $this->contentService->createContentDraft($publishedContent->contentInfo);
2317
        $draftContentB = $this->contentService->createContentDraft($draftContentA->contentInfo);
2318
        $draftContentC = $this->contentService->createContentDraft($draftContentB->contentInfo);
2319
        $draftContentD = $this->contentService->createContentDraft($draftContentC->contentInfo);
2320
        $draftContentE = $this->contentService->createContentDraft($draftContentD->contentInfo);
2321
2322
        $draftsOnPage1 = $this->contentService->loadContentDraftList(null, 0, 2);
2323
        $draftsOnPage2 = $this->contentService->loadContentDraftList(null, 2, 2);
2324
        /* END: Use Case */
2325
        $this->assertSame(5, $draftsOnPage1->totalCount);
2326
        $this->assertSame(5, $draftsOnPage2->totalCount);
2327
        $this->assertEquals($draftContentE->getVersionInfo(), $draftsOnPage1->items[0]->getVersionInfo());
2328
        $this->assertEquals($draftContentD->getVersionInfo(), $draftsOnPage1->items[1]->getVersionInfo());
2329
        $this->assertEquals($draftContentC->getVersionInfo(), $draftsOnPage2->items[0]->getVersionInfo());
2330
        $this->assertEquals($draftContentB->getVersionInfo(), $draftsOnPage2->items[1]->getVersionInfo());
2331
    }
2332
2333
    /**
2334
     * Test for the loadContentDraftList() method.
2335
     *
2336
     * @see \eZ\Publish\API\Repository\ContentService::loadContentDrafts($user)
2337
     */
2338
    public function testLoadContentDraftListWithForUserWithLimitation()
2339
    {
2340
        /* BEGIN: Use Case */
2341
        $oldUser = $this->permissionResolver->getCurrentUserReference();
2342
2343
        $parentContent = $this->createFolder(['eng-US' => 'parentFolder'], 2);
2344
        $content = $this->createFolder(['eng-US' => 'parentFolder'], $parentContent->contentInfo->mainLocationId);
2345
2346
        // User has limitation to read versions only for `$content`, not for `$parentContent`
2347
        $newUser = $this->createUserWithVersionreadLimitations([$content->contentInfo->mainLocationId]);
2348
2349
        $this->permissionResolver->setCurrentUserReference($newUser);
2350
2351
        $contentDraftUnauthorized = $this->contentService->createContentDraft($parentContent->contentInfo);
2352
        $contentDraftA = $this->contentService->createContentDraft($content->contentInfo);
2353
        $contentDraftB = $this->contentService->createContentDraft($content->contentInfo);
2354
        /* END: Use Case */
2355
2356
        $newUserDraftList = $this->contentService->loadContentDraftList($newUser, 0);
2357
        $this->assertSame(3, $newUserDraftList->totalCount);
2358
        $this->assertEquals($contentDraftB->getVersionInfo(), $newUserDraftList->items[0]->getVersionInfo());
2359
        $this->assertEquals($contentDraftA->getVersionInfo(), $newUserDraftList->items[1]->getVersionInfo());
2360
        $this->assertEquals(
2361
            new UnauthorizedContentDraftListItem('content', 'versionread', ['contentId' => $contentDraftUnauthorized->id]),
2362
            $newUserDraftList->items[2]
2363
        );
2364
2365
        // Reset to previous user
2366
        $this->permissionResolver->setCurrentUserReference($oldUser);
2367
2368
        $oldUserDraftList = $this->contentService->loadContentDraftList();
2369
2370
        $this->assertSame(0, $oldUserDraftList->totalCount);
2371
        $this->assertSame([], $oldUserDraftList->items);
2372
    }
2373
2374
    /**
2375
     * Test for the loadContentDraftList() method.
2376
     *
2377
     * @see \eZ\Publish\API\Repository\ContentService::loadContentDrafts()
2378
     */
2379
    public function testLoadAllContentDrafts()
2380
    {
2381
        // Create more drafts then default pagination limit
2382
        $this->createContentDrafts(12);
2383
        /* END: Use Case */
2384
2385
        $this->assertCount(12, $this->contentService->loadContentDraftList());
2386
    }
2387
2388
    /**
2389
     * Test for the loadVersionInfo() method.
2390
     *
2391
     * @see \eZ\Publish\API\Repository\ContentService::loadVersionInfo($contentInfo, $versionNo)
2392
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
2393
     */
2394 View Code Duplication
    public function testLoadVersionInfoWithSecondParameter()
2395
    {
2396
        /* BEGIN: Use Case */
2397
        $publishedContent = $this->createContentVersion1();
2398
2399
        $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...
2400
2401
        // Will return the VersionInfo of the $draftContent
2402
        $versionInfo = $this->contentService->loadVersionInfoById($publishedContent->id, 2);
2403
        /* END: Use Case */
2404
2405
        $this->assertEquals(2, $versionInfo->versionNo);
2406
2407
        // Check that ContentInfo contained in VersionInfo has correct main Location id set
2408
        $this->assertEquals(
2409
            $publishedContent->getVersionInfo()->getContentInfo()->mainLocationId,
2410
            $versionInfo->getContentInfo()->mainLocationId
2411
        );
2412
    }
2413
2414
    /**
2415
     * Test for the loadVersionInfo() method.
2416
     *
2417
     * @see \eZ\Publish\API\Repository\ContentService::loadVersionInfo($contentInfo, $versionNo)
2418
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfoWithSecondParameter
2419
     */
2420
    public function testLoadVersionInfoThrowsNotFoundExceptionWithSecondParameter()
2421
    {
2422
        /* BEGIN: Use Case */
2423
        $draft = $this->createContentDraftVersion1();
2424
2425
        $this->expectException(NotFoundException::class);
2426
2427
        // This call will fail with a "NotFoundException", because not versionNo 2 exists for this content object.
2428
        $this->contentService->loadVersionInfo($draft->contentInfo, 2);
2429
        /* END: Use Case */
2430
    }
2431
2432
    /**
2433
     * Test for the loadVersionInfoById() method.
2434
     *
2435
     * @see \eZ\Publish\API\Repository\ContentService::loadVersionInfoById($contentId, $versionNo)
2436
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfoWithSecondParameter
2437
     */
2438
    public function testLoadVersionInfoByIdWithSecondParameter()
2439
    {
2440
        /* BEGIN: Use Case */
2441
        $publishedContent = $this->createContentVersion1();
2442
2443
        $draftContent = $this->contentService->createContentDraft($publishedContent->contentInfo);
2444
2445
        // Will return the VersionInfo of the $draftContent
2446
        $versionInfo = $this->contentService->loadVersionInfoById($publishedContent->id, 2);
2447
        /* END: Use Case */
2448
2449
        $this->assertEquals(2, $versionInfo->versionNo);
2450
2451
        // Check that ContentInfo contained in VersionInfo has correct main Location id set
2452
        $this->assertEquals(
2453
            $publishedContent->getVersionInfo()->getContentInfo()->mainLocationId,
2454
            $versionInfo->getContentInfo()->mainLocationId
2455
        );
2456
2457
        return [
2458
            'versionInfo' => $versionInfo,
2459
            'draftContent' => $draftContent,
2460
        ];
2461
    }
2462
2463
    /**
2464
     * Test for the returned value of the loadVersionInfoById() method.
2465
     *
2466
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfoByIdWithSecondParameter
2467
     * @covers \eZ\Publish\API\Repository\ContentService::loadVersionInfoById
2468
     *
2469
     * @param array $data
2470
     */
2471
    public function testLoadVersionInfoByIdWithSecondParameterSetsExpectedVersionInfo(array $data)
2472
    {
2473
        /** @var VersionInfo $versionInfo */
2474
        $versionInfo = $data['versionInfo'];
2475
        /** @var \eZ\Publish\API\Repository\Values\Content\Content $draftContent */
2476
        $draftContent = $data['draftContent'];
2477
2478
        $this->assertPropertiesCorrect(
2479
            [
2480
                'names' => [
2481
                    'eng-US' => 'An awesome forum',
2482
                ],
2483
                'contentInfo' => new ContentInfo([
2484
                    'id' => $draftContent->contentInfo->id,
2485
                    'contentTypeId' => 28,
2486
                    'name' => 'An awesome forum',
2487
                    'sectionId' => 1,
2488
                    'currentVersionNo' => 1,
2489
                    'published' => true,
2490
                    'ownerId' => 14,
2491
                    // this Content Object is created at the test runtime
2492
                    'modificationDate' => $versionInfo->contentInfo->modificationDate,
2493
                    'publishedDate' => $versionInfo->contentInfo->publishedDate,
2494
                    'alwaysAvailable' => 1,
2495
                    'remoteId' => 'abcdef0123456789abcdef0123456789',
2496
                    'mainLanguageCode' => 'eng-US',
2497
                    'mainLocationId' => $draftContent->contentInfo->mainLocationId,
2498
                    'status' => ContentInfo::STATUS_PUBLISHED,
2499
                ]),
2500
                'id' => $draftContent->versionInfo->id,
2501
                'versionNo' => 2,
2502
                'creatorId' => 14,
2503
                'status' => 0,
2504
                'initialLanguageCode' => 'eng-US',
2505
                'languageCodes' => [
2506
                    'eng-US',
2507
                ],
2508
            ],
2509
            $versionInfo
2510
        );
2511
    }
2512
2513
    /**
2514
     * Test for the loadVersionInfoById() method.
2515
     *
2516
     * @see \eZ\Publish\API\Repository\ContentService::loadVersionInfoById($contentId, $versionNo)
2517
     */
2518
    public function testLoadVersionInfoByIdThrowsNotFoundExceptionWithSecondParameter()
2519
    {
2520
        /* BEGIN: Use Case */
2521
        $content = $this->createContentVersion1();
2522
2523
        $this->expectException(NotFoundException::class);
2524
2525
        // This call will fail with a "NotFoundException", because not versionNo 2 exists for this content object.
2526
        $this->contentService->loadVersionInfoById($content->id, 2);
2527
        /* END: Use Case */
2528
    }
2529
2530
    /**
2531
     * Test for the loadContentByVersionInfo() method.
2532
     *
2533
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByVersionInfo($versionInfo, $languages)
2534
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
2535
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByVersionInfo
2536
     */
2537
    public function testLoadContentByVersionInfoWithSecondParameter()
2538
    {
2539
        $sectionId = $this->generateId('section', 1);
2540
        /* BEGIN: Use Case */
2541
        $contentTypeService = $this->getRepository()->getContentTypeService();
2542
2543
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
2544
2545
        $contentCreateStruct = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
2546
2547
        $contentCreateStruct->setField('name', 'Sindelfingen forum²');
2548
2549
        $contentCreateStruct->setField('name', 'Sindelfingen forum²³', 'eng-GB');
2550
2551
        $contentCreateStruct->remoteId = 'abcdef0123456789abcdef0123456789';
2552
        // $sectionId contains the ID of section 1
2553
        $contentCreateStruct->sectionId = $sectionId;
2554
        $contentCreateStruct->alwaysAvailable = true;
2555
2556
        // Create a new content draft
2557
        $content = $this->contentService->createContent($contentCreateStruct);
2558
2559
        // Now publish this draft
2560
        $publishedContent = $this->contentService->publishVersion($content->getVersionInfo());
2561
2562
        // Will return a content instance with fields in "eng-US"
2563
        $reloadedContent = $this->contentService->loadContentByVersionInfo(
2564
            $publishedContent->getVersionInfo(),
2565
            [
2566
                'eng-GB',
2567
            ],
2568
            false
2569
        );
2570
        /* END: Use Case */
2571
2572
        $actual = [];
2573
        foreach ($reloadedContent->getFields() as $field) {
2574
            $actual[] = new Field(
2575
                [
2576
                    'id' => 0,
2577
                    'value' => ($field->value !== null ? true : null), // Actual value tested by FieldType integration tests
2578
                    'languageCode' => $field->languageCode,
2579
                    'fieldDefIdentifier' => $field->fieldDefIdentifier,
2580
                ]
2581
            );
2582
        }
2583
        usort(
2584
            $actual,
2585 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...
2586
                if (0 === ($return = strcasecmp($field1->fieldDefIdentifier, $field2->fieldDefIdentifier))) {
2587
                    return strcasecmp($field1->languageCode, $field2->languageCode);
2588
                }
2589
2590
                return $return;
2591
            }
2592
        );
2593
2594
        $expected = [
2595
            new Field(
2596
                [
2597
                    'id' => 0,
2598
                    'value' => true,
2599
                    'languageCode' => 'eng-GB',
2600
                    'fieldDefIdentifier' => 'description',
2601
                ]
2602
            ),
2603
            new Field(
2604
                [
2605
                    'id' => 0,
2606
                    'value' => true,
2607
                    'languageCode' => 'eng-GB',
2608
                    'fieldDefIdentifier' => 'name',
2609
                ]
2610
            ),
2611
        ];
2612
2613
        $this->assertEquals($expected, $actual);
2614
    }
2615
2616
    /**
2617
     * Test for the loadContentByContentInfo() method.
2618
     *
2619
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByContentInfo($contentInfo, $languages)
2620
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByContentInfo
2621
     */
2622
    public function testLoadContentByContentInfoWithLanguageParameters()
2623
    {
2624
        $sectionId = $this->generateId('section', 1);
2625
        /* BEGIN: Use Case */
2626
        $contentTypeService = $this->getRepository()->getContentTypeService();
2627
2628
        $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
2629
2630
        $contentCreateStruct = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
2631
2632
        $contentCreateStruct->setField('name', 'Sindelfingen forum²');
2633
2634
        $contentCreateStruct->setField('name', 'Sindelfingen forum²³', 'eng-GB');
2635
2636
        $contentCreateStruct->remoteId = 'abcdef0123456789abcdef0123456789';
2637
        // $sectionId contains the ID of section 1
2638
        $contentCreateStruct->sectionId = $sectionId;
2639
        $contentCreateStruct->alwaysAvailable = true;
2640
2641
        // Create a new content draft
2642
        $content = $this->contentService->createContent($contentCreateStruct);
2643
2644
        // Now publish this draft
2645
        $publishedContent = $this->contentService->publishVersion($content->getVersionInfo());
2646
2647
        // Will return a content instance with fields in "eng-US"
2648
        $reloadedContent = $this->contentService->loadContentByContentInfo(
2649
            $publishedContent->contentInfo,
2650
            [
2651
                'eng-US',
2652
            ],
2653
            null,
2654
            false
2655
        );
2656
        /* END: Use Case */
2657
2658
        $actual = $this->normalizeFields($reloadedContent->getFields());
2659
2660
        $expected = [
2661
            new Field(
2662
                [
2663
                    'id' => 0,
2664
                    'value' => true,
2665
                    'languageCode' => 'eng-US',
2666
                    'fieldDefIdentifier' => 'description',
2667
                    'fieldTypeIdentifier' => 'ezrichtext',
2668
                ]
2669
            ),
2670
            new Field(
2671
                [
2672
                    'id' => 0,
2673
                    'value' => true,
2674
                    'languageCode' => 'eng-US',
2675
                    'fieldDefIdentifier' => 'name',
2676
                    'fieldTypeIdentifier' => 'ezstring',
2677
                ]
2678
            ),
2679
        ];
2680
2681
        $this->assertEquals($expected, $actual);
2682
2683
        // Will return a content instance with fields in "eng-GB" (versions prior to 6.0.0-beta9 returned "eng-US" also)
2684
        $reloadedContent = $this->contentService->loadContentByContentInfo(
2685
            $publishedContent->contentInfo,
2686
            [
2687
                'eng-GB',
2688
            ],
2689
            null,
2690
            true
2691
        );
2692
2693
        $actual = $this->normalizeFields($reloadedContent->getFields());
2694
2695
        $expected = [
2696
            new Field(
2697
                [
2698
                    'id' => 0,
2699
                    'value' => true,
2700
                    'languageCode' => 'eng-GB',
2701
                    'fieldDefIdentifier' => 'description',
2702
                    'fieldTypeIdentifier' => 'ezrichtext',
2703
                ]
2704
            ),
2705
            new Field(
2706
                [
2707
                    'id' => 0,
2708
                    'value' => true,
2709
                    'languageCode' => 'eng-GB',
2710
                    'fieldDefIdentifier' => 'name',
2711
                    'fieldTypeIdentifier' => 'ezstring',
2712
                ]
2713
            ),
2714
        ];
2715
2716
        $this->assertEquals($expected, $actual);
2717
2718
        // Will return a content instance with fields in main language "eng-US", as "fre-FR" does not exists
2719
        $reloadedContent = $this->contentService->loadContentByContentInfo(
2720
            $publishedContent->contentInfo,
2721
            [
2722
                'fre-FR',
2723
            ],
2724
            null,
2725
            true
2726
        );
2727
2728
        $actual = $this->normalizeFields($reloadedContent->getFields());
2729
2730
        $expected = [
2731
            new Field(
2732
                [
2733
                    'id' => 0,
2734
                    'value' => true,
2735
                    'languageCode' => 'eng-US',
2736
                    'fieldDefIdentifier' => 'description',
2737
                    'fieldTypeIdentifier' => 'ezrichtext',
2738
                ]
2739
            ),
2740
            new Field(
2741
                [
2742
                    'id' => 0,
2743
                    'value' => true,
2744
                    'languageCode' => 'eng-US',
2745
                    'fieldDefIdentifier' => 'name',
2746
                    'fieldTypeIdentifier' => 'ezstring',
2747
                ]
2748
            ),
2749
        ];
2750
2751
        $this->assertEquals($expected, $actual);
2752
    }
2753
2754
    /**
2755
     * Test for the loadContentByContentInfo() method.
2756
     *
2757
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByContentInfo($contentInfo, $languages, $versionNo)
2758
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByContentInfo
2759
     */
2760 View Code Duplication
    public function testLoadContentByContentInfoWithVersionNumberParameter()
2761
    {
2762
        /* BEGIN: Use Case */
2763
        $publishedContent = $this->createContentVersion1();
2764
2765
        $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...
2766
2767
        // This content instance is identical to $draftContent
2768
        $draftContentReloaded = $this->contentService->loadContentByContentInfo(
2769
            $publishedContent->contentInfo,
2770
            null,
2771
            2
2772
        );
2773
        /* END: Use Case */
2774
2775
        $this->assertEquals(
2776
            2,
2777
            $draftContentReloaded->getVersionInfo()->versionNo
2778
        );
2779
2780
        // Check that ContentInfo contained in reloaded draft Content has correct main Location id set
2781
        $this->assertEquals(
2782
            $publishedContent->versionInfo->contentInfo->mainLocationId,
2783
            $draftContentReloaded->versionInfo->contentInfo->mainLocationId
2784
        );
2785
    }
2786
2787
    /**
2788
     * Test for the loadContentByContentInfo() method.
2789
     *
2790
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByContentInfo($contentInfo, $languages, $versionNo)
2791
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByContentInfoWithVersionNumberParameter
2792
     */
2793
    public function testLoadContentByContentInfoThrowsNotFoundExceptionWithVersionNumberParameter()
2794
    {
2795
        /* BEGIN: Use Case */
2796
        $content = $this->createContentVersion1();
2797
2798
        $this->expectException(NotFoundException::class);
2799
2800
        // This call will fail with a "NotFoundException", because no content with versionNo = 2 exists.
2801
        $this->contentService->loadContentByContentInfo($content->contentInfo, null, 2);
2802
        /* END: Use Case */
2803
    }
2804
2805
    /**
2806
     * Test for the loadContent() method.
2807
     *
2808
     * @see \eZ\Publish\API\Repository\ContentService::loadContent($contentId, $languages)
2809
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
2810
     */
2811
    public function testLoadContentWithSecondParameter()
2812
    {
2813
        /* BEGIN: Use Case */
2814
        $draft = $this->createMultipleLanguageDraftVersion1();
2815
2816
        // This draft contains those fields localized with "eng-GB"
2817
        $draftLocalized = $this->contentService->loadContent($draft->id, ['eng-GB'], null, false);
2818
        /* END: Use Case */
2819
2820
        $this->assertLocaleFieldsEquals($draftLocalized->getFields(), 'eng-GB');
2821
2822
        return $draft;
2823
    }
2824
2825
    /**
2826
     * Test for the loadContent() method using undefined translation.
2827
     *
2828
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentWithSecondParameter
2829
     *
2830
     * @param \eZ\Publish\API\Repository\Values\Content\Content $contentDraft
2831
     */
2832
    public function testLoadContentWithSecondParameterThrowsNotFoundException(Content $contentDraft)
2833
    {
2834
        $this->expectException(NotFoundException::class);
2835
2836
        $this->contentService->loadContent($contentDraft->id, ['ger-DE'], null, false);
2837
    }
2838
2839
    /**
2840
     * Test for the loadContent() method.
2841
     *
2842
     * @see \eZ\Publish\API\Repository\ContentService::loadContent($contentId, $languages, $versionNo)
2843
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
2844
     */
2845 View Code Duplication
    public function testLoadContentWithThirdParameter()
2846
    {
2847
        /* BEGIN: Use Case */
2848
        $publishedContent = $this->createContentVersion1();
2849
2850
        $this->contentService->createContentDraft($publishedContent->contentInfo);
2851
2852
        // This content instance is identical to $draftContent
2853
        $draftContentReloaded = $this->contentService->loadContent($publishedContent->id, null, 2);
2854
        /* END: Use Case */
2855
2856
        $this->assertEquals(2, $draftContentReloaded->getVersionInfo()->versionNo);
2857
2858
        // Check that ContentInfo contained in reloaded draft Content has correct main Location id set
2859
        $this->assertEquals(
2860
            $publishedContent->versionInfo->contentInfo->mainLocationId,
2861
            $draftContentReloaded->versionInfo->contentInfo->mainLocationId
2862
        );
2863
    }
2864
2865
    /**
2866
     * Test for the loadContent() method.
2867
     *
2868
     * @see \eZ\Publish\API\Repository\ContentService::loadContent($contentId, $languages, $versionNo)
2869
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentWithThirdParameter
2870
     */
2871
    public function testLoadContentThrowsNotFoundExceptionWithThirdParameter()
2872
    {
2873
        /* BEGIN: Use Case */
2874
        $content = $this->createContentVersion1();
2875
2876
        $this->expectException(NotFoundException::class);
2877
2878
        // This call will fail with a "NotFoundException", because for this content object no versionNo=2 exists.
2879
        $this->contentService->loadContent($content->id, null, 2);
2880
        /* END: Use Case */
2881
    }
2882
2883
    /**
2884
     * Test for the loadContentByRemoteId() method.
2885
     *
2886
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByRemoteId($remoteId, $languages)
2887
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
2888
     */
2889
    public function testLoadContentByRemoteIdWithSecondParameter()
2890
    {
2891
        /* BEGIN: Use Case */
2892
        $draft = $this->createMultipleLanguageDraftVersion1();
2893
2894
        $this->contentService->publishVersion($draft->versionInfo);
2895
2896
        // This draft contains those fields localized with "eng-GB"
2897
        $draftLocalized = $this->contentService->loadContentByRemoteId(
2898
            $draft->contentInfo->remoteId,
2899
            ['eng-GB'],
2900
            null,
2901
            false
2902
        );
2903
        /* END: Use Case */
2904
2905
        $this->assertLocaleFieldsEquals($draftLocalized->getFields(), 'eng-GB');
2906
    }
2907
2908
    /**
2909
     * Test for the loadContentByRemoteId() method.
2910
     *
2911
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByRemoteId($remoteId, $languages, $versionNo)
2912
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
2913
     */
2914 View Code Duplication
    public function testLoadContentByRemoteIdWithThirdParameter()
2915
    {
2916
        /* BEGIN: Use Case */
2917
        $publishedContent = $this->createContentVersion1();
2918
2919
        $this->contentService->createContentDraft($publishedContent->contentInfo);
2920
2921
        // This content instance is identical to $draftContent
2922
        $draftContentReloaded = $this->contentService->loadContentByRemoteId(
2923
            $publishedContent->contentInfo->remoteId,
2924
            null,
2925
            2
2926
        );
2927
        /* END: Use Case */
2928
2929
        $this->assertEquals(2, $draftContentReloaded->getVersionInfo()->versionNo);
2930
2931
        // Check that ContentInfo contained in reloaded draft Content has correct main Location id set
2932
        $this->assertEquals(
2933
            $publishedContent->versionInfo->contentInfo->mainLocationId,
2934
            $draftContentReloaded->versionInfo->contentInfo->mainLocationId
2935
        );
2936
    }
2937
2938
    /**
2939
     * Test for the loadContentByRemoteId() method.
2940
     *
2941
     * @see \eZ\Publish\API\Repository\ContentService::loadContentByRemoteId($remoteId, $languages, $versionNo)
2942
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentByRemoteIdWithThirdParameter
2943
     */
2944
    public function testLoadContentByRemoteIdThrowsNotFoundExceptionWithThirdParameter()
2945
    {
2946
        /* BEGIN: Use Case */
2947
        $content = $this->createContentVersion1();
2948
2949
        $this->expectException(NotFoundException::class);
2950
2951
        // This call will fail with a "NotFoundException", because for this content object no versionNo=2 exists.
2952
        $this->contentService->loadContentByRemoteId(
2953
            $content->contentInfo->remoteId,
2954
            null,
2955
            2
2956
        );
2957
        /* END: Use Case */
2958
    }
2959
2960
    /**
2961
     * Test that retrieval of translated name field respects prioritized language list.
2962
     *
2963
     * @dataProvider getPrioritizedLanguageList
2964
     * @param string[]|null $languageCodes
2965
     */
2966
    public function testLoadContentWithPrioritizedLanguagesList($languageCodes)
2967
    {
2968
        $content = $this->createContentVersion2();
2969
2970
        $content = $this->contentService->loadContent($content->id, $languageCodes);
2971
2972
        $expectedName = $content->getVersionInfo()->getName(
2973
            isset($languageCodes[0]) ? $languageCodes[0] : null
2974
        );
2975
        $nameValue = $content->getFieldValue('name');
2976
        /** @var \eZ\Publish\Core\FieldType\TextLine\Value $nameValue */
2977
        self::assertEquals($expectedName, $nameValue->text);
2978
        self::assertEquals($expectedName, $content->getVersionInfo()->getName());
2979
        // Also check value on shortcut method on content
2980
        self::assertEquals($expectedName, $content->getName());
2981
    }
2982
2983
    /**
2984
     * @return array
2985
     */
2986
    public function getPrioritizedLanguageList()
2987
    {
2988
        return [
2989
            [['eng-US']],
2990
            [['eng-GB']],
2991
            [['eng-GB', 'eng-US']],
2992
            [['eng-US', 'eng-GB']],
2993
        ];
2994
    }
2995
2996
    /**
2997
     * Test for the deleteVersion() method.
2998
     *
2999
     * @see \eZ\Publish\API\Repository\ContentService::deleteVersion()
3000
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
3001
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
3002
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
3003
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
3004
     */
3005
    public function testDeleteVersion()
3006
    {
3007
        /* BEGIN: Use Case */
3008
        $content = $this->createContentVersion1();
3009
3010
        // Create new draft, because published or last version of the Content can't be deleted
3011
        $draft = $this->contentService->createContentDraft(
3012
            $content->getVersionInfo()->getContentInfo()
3013
        );
3014
3015
        // Delete the previously created draft
3016
        $this->contentService->deleteVersion($draft->getVersionInfo());
3017
        /* END: Use Case */
3018
3019
        $versions = $this->contentService->loadVersions($content->getVersionInfo()->getContentInfo());
3020
3021
        $this->assertCount(1, $versions);
3022
        $this->assertEquals(
3023
            $content->getVersionInfo()->id,
3024
            $versions[0]->id
3025
        );
3026
    }
3027
3028
    /**
3029
     * Test for the deleteVersion() method.
3030
     *
3031
     * @see \eZ\Publish\API\Repository\ContentService::deleteVersion()
3032
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
3033
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
3034
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
3035
     */
3036
    public function testDeleteVersionThrowsBadStateExceptionOnPublishedVersion()
3037
    {
3038
        /* BEGIN: Use Case */
3039
        $content = $this->createContentVersion1();
3040
3041
        $this->expectException(BadStateException::class);
3042
3043
        // This call will fail with a "BadStateException", because the content version is currently published.
3044
        $this->contentService->deleteVersion($content->getVersionInfo());
3045
        /* END: Use Case */
3046
    }
3047
3048
    /**
3049
     * Test for the deleteVersion() method.
3050
     *
3051
     * @see \eZ\Publish\API\Repository\ContentService::deleteVersion()
3052
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
3053
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
3054
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
3055
     */
3056
    public function testDeleteVersionWorksIfOnlyVersionIsDraft()
3057
    {
3058
        /* BEGIN: Use Case */
3059
        $draft = $this->createContentDraftVersion1();
3060
3061
        $this->contentService->deleteVersion($draft->getVersionInfo());
3062
3063
        $this->expectException(NotFoundException::class);
3064
3065
        // This call will fail with a "NotFound", because we allow to delete content if remaining version is draft.
3066
        // Can normally only happen if there where always only a draft to begin with, simplifies UI edit API usage.
3067
        $this->contentService->loadContent($draft->id);
3068
        /* END: Use Case */
3069
    }
3070
3071
    /**
3072
     * Test for the loadVersions() method.
3073
     *
3074
     * @see \eZ\Publish\API\Repository\ContentService::loadVersions()
3075
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
3076
     *
3077
     * @return VersionInfo[]
3078
     */
3079
    public function testLoadVersions()
3080
    {
3081
        /* BEGIN: Use Case */
3082
        $contentVersion2 = $this->createContentVersion2();
3083
3084
        // Load versions of this ContentInfo instance
3085
        $versions = $this->contentService->loadVersions($contentVersion2->contentInfo);
3086
        /* END: Use Case */
3087
3088
        $expectedVersionsOrder = [
3089
            $this->contentService->loadVersionInfo($contentVersion2->contentInfo, 1),
3090
            $this->contentService->loadVersionInfo($contentVersion2->contentInfo, 2),
3091
        ];
3092
3093
        $this->assertEquals($expectedVersionsOrder, $versions);
3094
3095
        return $versions;
3096
    }
3097
3098
    /**
3099
     * Test for the loadVersions() method.
3100
     *
3101
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersions
3102
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersions
3103
     *
3104
     * @param VersionInfo[] $versions
3105
     */
3106
    public function testLoadVersionsSetsExpectedVersionInfo(array $versions)
3107
    {
3108
        $this->assertCount(2, $versions);
3109
3110
        $expectedVersions = [
3111
            [
3112
                'versionNo' => 1,
3113
                'creatorId' => 14,
3114
                'status' => VersionInfo::STATUS_ARCHIVED,
3115
                'initialLanguageCode' => 'eng-US',
3116
                'languageCodes' => ['eng-US'],
3117
            ],
3118
            [
3119
                'versionNo' => 2,
3120
                'creatorId' => 10,
3121
                'status' => VersionInfo::STATUS_PUBLISHED,
3122
                'initialLanguageCode' => 'eng-US',
3123
                'languageCodes' => ['eng-US', 'eng-GB'],
3124
            ],
3125
        ];
3126
3127
        $this->assertPropertiesCorrect($expectedVersions[0], $versions[0]);
3128
        $this->assertPropertiesCorrect($expectedVersions[1], $versions[1]);
3129
        $this->assertEquals(
3130
            $versions[0]->creationDate->getTimestamp(),
3131
            $versions[1]->creationDate->getTimestamp(),
3132
            'Creation time did not match within delta of 2 seconds',
3133
            2
3134
        );
3135
        $this->assertEquals(
3136
            $versions[0]->modificationDate->getTimestamp(),
3137
            $versions[1]->modificationDate->getTimestamp(),
3138
            'Creation time did not match within delta of 2 seconds',
3139
            2
3140
        );
3141
        $this->assertTrue($versions[0]->isArchived());
3142
        $this->assertFalse($versions[0]->isDraft());
3143
        $this->assertFalse($versions[0]->isPublished());
3144
3145
        $this->assertTrue($versions[1]->isPublished());
3146
        $this->assertFalse($versions[1]->isDraft());
3147
        $this->assertFalse($versions[1]->isArchived());
3148
    }
3149
3150
    /**
3151
     * Test for the copyContent() method.
3152
     *
3153
     * @see \eZ\Publish\API\Repository\ContentService::copyContent()
3154
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
3155
     * @group field-type
3156
     */
3157 View Code Duplication
    public function testCopyContent()
3158
    {
3159
        $parentLocationId = $this->generateId('location', 56);
3160
3161
        /* BEGIN: Use Case */
3162
        $contentVersion2 = $this->createMultipleLanguageContentVersion2();
3163
3164
        // Configure new target location
3165
        $targetLocationCreate = $this->locationService->newLocationCreateStruct($parentLocationId);
3166
3167
        $targetLocationCreate->priority = 42;
3168
        $targetLocationCreate->hidden = true;
3169
        $targetLocationCreate->remoteId = '01234abcdef5678901234abcdef56789';
3170
        $targetLocationCreate->sortField = Location::SORT_FIELD_NODE_ID;
3171
        $targetLocationCreate->sortOrder = Location::SORT_ORDER_DESC;
3172
3173
        // Copy content with all versions and drafts
3174
        $contentCopied = $this->contentService->copyContent(
3175
            $contentVersion2->contentInfo,
3176
            $targetLocationCreate
3177
        );
3178
        /* END: Use Case */
3179
3180
        $this->assertInstanceOf(
3181
            Content::class,
3182
            $contentCopied
3183
        );
3184
3185
        $this->assertNotEquals(
3186
            $contentVersion2->contentInfo->remoteId,
3187
            $contentCopied->contentInfo->remoteId
3188
        );
3189
3190
        $this->assertNotEquals(
3191
            $contentVersion2->id,
3192
            $contentCopied->id
3193
        );
3194
3195
        $this->assertEquals(
3196
            2,
3197
            count($this->contentService->loadVersions($contentCopied->contentInfo))
3198
        );
3199
3200
        $this->assertEquals(2, $contentCopied->getVersionInfo()->versionNo);
3201
3202
        $this->assertAllFieldsEquals($contentCopied->getFields());
3203
3204
        $this->assertDefaultContentStates($contentCopied->contentInfo);
3205
3206
        $this->assertNotNull(
3207
            $contentCopied->contentInfo->mainLocationId,
3208
            'Expected main location to be set given we provided a LocationCreateStruct'
3209
        );
3210
    }
3211
3212
    /**
3213
     * Test for the copyContent() method with ezsettings.default.content.retain_owner_on_copy set to false
3214
     * See settings/test/integration_legacy.yml for service override.
3215
     *
3216
     * @see \eZ\Publish\API\Repository\ContentService::copyContent()
3217
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
3218
     * @group field-type
3219
     */
3220
    public function testCopyContentWithNewOwner()
3221
    {
3222
        $parentLocationId = $this->generateId('location', 56);
3223
3224
        $userService = $this->getRepository()->getUserService();
3225
3226
        $newOwner = $this->createUser('new_owner', 'foo', 'bar');
3227
        /* BEGIN: Use Case */
3228
        /** @var \eZ\Publish\API\Repository\Values\Content\Content $contentVersion2 */
3229
        $contentVersion2 = $this->createContentDraftVersion1(
3230
            $parentLocationId,
3231
            'forum',
3232
            'name',
3233
            $newOwner
3234
        );
3235
3236
        // Configure new target location
3237
        $targetLocationCreate = $this->locationService->newLocationCreateStruct($parentLocationId);
3238
3239
        $targetLocationCreate->priority = 42;
3240
        $targetLocationCreate->hidden = true;
3241
        $targetLocationCreate->remoteId = '01234abcdef5678901234abcdef56789';
3242
        $targetLocationCreate->sortField = Location::SORT_FIELD_NODE_ID;
3243
        $targetLocationCreate->sortOrder = Location::SORT_ORDER_DESC;
3244
3245
        // Copy content with all versions and drafts
3246
        $contentCopied = $this->contentService->copyContent(
3247
            $contentVersion2->contentInfo,
3248
            $targetLocationCreate
3249
        );
3250
        /* END: Use Case */
3251
3252
        $this->assertEquals(
3253
            $newOwner->id,
3254
            $contentVersion2->contentInfo->ownerId
3255
        );
3256
        $this->assertEquals(
3257
            $userService->loadUserByLogin('admin')->getUserId(),
3258
            $contentCopied->contentInfo->ownerId
3259
        );
3260
    }
3261
3262
    /**
3263
     * Test for the copyContent() method.
3264
     *
3265
     * @see \eZ\Publish\API\Repository\ContentService::copyContent($contentInfo, $destinationLocationCreateStruct, $versionInfo)
3266
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCopyContent
3267
     */
3268 View Code Duplication
    public function testCopyContentWithGivenVersion()
3269
    {
3270
        $parentLocationId = $this->generateId('location', 56);
3271
3272
        /* BEGIN: Use Case */
3273
        $contentVersion2 = $this->createContentVersion2();
3274
3275
        // Configure new target location
3276
        $targetLocationCreate = $this->locationService->newLocationCreateStruct($parentLocationId);
3277
3278
        $targetLocationCreate->priority = 42;
3279
        $targetLocationCreate->hidden = true;
3280
        $targetLocationCreate->remoteId = '01234abcdef5678901234abcdef56789';
3281
        $targetLocationCreate->sortField = Location::SORT_FIELD_NODE_ID;
3282
        $targetLocationCreate->sortOrder = Location::SORT_ORDER_DESC;
3283
3284
        // Copy only the initial version
3285
        $contentCopied = $this->contentService->copyContent(
3286
            $contentVersion2->contentInfo,
3287
            $targetLocationCreate,
3288
            $this->contentService->loadVersionInfo($contentVersion2->contentInfo, 1)
3289
        );
3290
        /* END: Use Case */
3291
3292
        $this->assertInstanceOf(
3293
            Content::class,
3294
            $contentCopied
3295
        );
3296
3297
        $this->assertNotEquals(
3298
            $contentVersion2->contentInfo->remoteId,
3299
            $contentCopied->contentInfo->remoteId
3300
        );
3301
3302
        $this->assertNotEquals(
3303
            $contentVersion2->id,
3304
            $contentCopied->id
3305
        );
3306
3307
        $this->assertEquals(
3308
            1,
3309
            count($this->contentService->loadVersions($contentCopied->contentInfo))
3310
        );
3311
3312
        $this->assertEquals(1, $contentCopied->getVersionInfo()->versionNo);
3313
3314
        $this->assertNotNull(
3315
            $contentCopied->contentInfo->mainLocationId,
3316
            'Expected main location to be set given we provided a LocationCreateStruct'
3317
        );
3318
    }
3319
3320
    /**
3321
     * Test for the addRelation() method.
3322
     *
3323
     * @return \eZ\Publish\API\Repository\Values\Content\Content
3324
     *
3325
     * @see \eZ\Publish\API\Repository\ContentService::addRelation()
3326
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersionFromContentDraft
3327
     */
3328 View Code Duplication
    public function testAddRelation()
3329
    {
3330
        /* BEGIN: Use Case */
3331
        // RemoteId of the "Media" content of an eZ Publish demo installation
3332
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3333
3334
        $draft = $this->createContentDraftVersion1();
3335
3336
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3337
3338
        // Create relation between new content object and "Media" page
3339
        $relation = $this->contentService->addRelation(
3340
            $draft->getVersionInfo(),
3341
            $media
3342
        );
3343
        /* END: Use Case */
3344
3345
        $this->assertInstanceOf(
3346
            '\\eZ\\Publish\\API\\Repository\\Values\\Content\\Relation',
3347
            $relation
3348
        );
3349
3350
        return $this->contentService->loadRelations($draft->getVersionInfo());
3351
    }
3352
3353
    /**
3354
     * Test for the addRelation() method.
3355
     *
3356
     * @param \eZ\Publish\API\Repository\Values\Content\Relation[] $relations
3357
     *
3358
     * @see \eZ\Publish\API\Repository\ContentService::addRelation()
3359
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3360
     */
3361
    public function testAddRelationAddsRelationToContent($relations)
3362
    {
3363
        $this->assertEquals(
3364
            1,
3365
            count($relations)
3366
        );
3367
    }
3368
3369
    /**
3370
     * @param \eZ\Publish\API\Repository\Values\Content\Relation[] $relations
3371
     */
3372
    protected function assertExpectedRelations($relations)
3373
    {
3374
        $this->assertEquals(
3375
            [
3376
                'type' => Relation::COMMON,
3377
                'sourceFieldDefinitionIdentifier' => null,
3378
                'sourceContentInfo' => 'abcdef0123456789abcdef0123456789',
3379
                'destinationContentInfo' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
3380
            ],
3381
            [
3382
                'type' => $relations[0]->type,
3383
                'sourceFieldDefinitionIdentifier' => $relations[0]->sourceFieldDefinitionIdentifier,
3384
                'sourceContentInfo' => $relations[0]->sourceContentInfo->remoteId,
3385
                'destinationContentInfo' => $relations[0]->destinationContentInfo->remoteId,
3386
            ]
3387
        );
3388
    }
3389
3390
    /**
3391
     * Test for the addRelation() method.
3392
     *
3393
     * @param \eZ\Publish\API\Repository\Values\Content\Relation[] $relations
3394
     *
3395
     * @see \eZ\Publish\API\Repository\ContentService::addRelation()
3396
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3397
     */
3398
    public function testAddRelationSetsExpectedRelations($relations)
3399
    {
3400
        $this->assertExpectedRelations($relations);
3401
    }
3402
3403
    /**
3404
     * Test for the createContentDraft() method.
3405
     *
3406
     * @return \eZ\Publish\API\Repository\Values\Content\Relation[]
3407
     *
3408
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
3409
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelationSetsExpectedRelations
3410
     */
3411 View Code Duplication
    public function testCreateContentDraftWithRelations()
3412
    {
3413
        // RemoteId of the "Media" content of an eZ Publish demo installation
3414
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3415
        $draft = $this->createContentDraftVersion1();
3416
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3417
3418
        // Create relation between new content object and "Media" page
3419
        $this->contentService->addRelation(
3420
            $draft->getVersionInfo(),
3421
            $media
3422
        );
3423
3424
        $content = $this->contentService->publishVersion($draft->versionInfo);
3425
        $newDraft = $this->contentService->createContentDraft($content->contentInfo);
3426
3427
        return $this->contentService->loadRelations($newDraft->getVersionInfo());
3428
    }
3429
3430
    /**
3431
     * Test for the createContentDraft() method.
3432
     *
3433
     * @param \eZ\Publish\API\Repository\Values\Content\Relation[] $relations
3434
     *
3435
     * @return \eZ\Publish\API\Repository\Values\Content\Relation[]
3436
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraftWithRelations
3437
     */
3438
    public function testCreateContentDraftWithRelationsCreatesRelations($relations)
3439
    {
3440
        $this->assertEquals(
3441
            1,
3442
            count($relations)
3443
        );
3444
3445
        return $relations;
3446
    }
3447
3448
    /**
3449
     * Test for the createContentDraft() method.
3450
     *
3451
     * @param \eZ\Publish\API\Repository\Values\Content\Relation[] $relations
3452
     *
3453
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraftWithRelationsCreatesRelations
3454
     */
3455
    public function testCreateContentDraftWithRelationsCreatesExpectedRelations($relations)
3456
    {
3457
        $this->assertExpectedRelations($relations);
3458
    }
3459
3460
    /**
3461
     * Test for the addRelation() method.
3462
     *
3463
     * @see \eZ\Publish\API\Repository\ContentService::addRelation()
3464
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3465
     */
3466
    public function testAddRelationThrowsBadStateException()
3467
    {
3468
        /* BEGIN: Use Case */
3469
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3470
3471
        $content = $this->createContentVersion1();
3472
3473
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3474
3475
        $this->expectException(BadStateException::class);
3476
3477
        // This call will fail with a "BadStateException", because content is published and not a draft.
3478
        $this->contentService->addRelation(
3479
            $content->getVersionInfo(),
3480
            $media
3481
        );
3482
        /* END: Use Case */
3483
    }
3484
3485
    /**
3486
     * Test for the loadRelations() method.
3487
     *
3488
     * @see \eZ\Publish\API\Repository\ContentService::loadRelations()
3489
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3490
     */
3491
    public function testLoadRelations()
3492
    {
3493
        /* BEGIN: Use Case */
3494
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3495
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
3496
3497
        $draft = $this->createContentDraftVersion1();
3498
3499
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3500
        $demoDesign = $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId);
3501
3502
        // Create relation between new content object and "Media" page
3503
        $this->contentService->addRelation(
3504
            $draft->getVersionInfo(),
3505
            $media
3506
        );
3507
3508
        // Create another relation with the "Demo Design" page
3509
        $this->contentService->addRelation(
3510
            $draft->getVersionInfo(),
3511
            $demoDesign
3512
        );
3513
3514
        $relations = $this->contentService->loadRelations($draft->getVersionInfo());
3515
        /* END: Use Case */
3516
3517
        usort(
3518
            $relations,
3519
            function ($rel1, $rel2) {
3520
                return strcasecmp(
3521
                    $rel2->getDestinationContentInfo()->remoteId,
3522
                    $rel1->getDestinationContentInfo()->remoteId
3523
                );
3524
            }
3525
        );
3526
3527
        $this->assertEquals(
3528
            [
3529
                [
3530
                    'sourceContentInfo' => 'abcdef0123456789abcdef0123456789',
3531
                    'destinationContentInfo' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
3532
                ],
3533
                [
3534
                    'sourceContentInfo' => 'abcdef0123456789abcdef0123456789',
3535
                    'destinationContentInfo' => '8b8b22fe3c6061ed500fbd2b377b885f',
3536
                ],
3537
            ],
3538
            [
3539
                [
3540
                    'sourceContentInfo' => $relations[0]->sourceContentInfo->remoteId,
3541
                    'destinationContentInfo' => $relations[0]->destinationContentInfo->remoteId,
3542
                ],
3543
                [
3544
                    'sourceContentInfo' => $relations[1]->sourceContentInfo->remoteId,
3545
                    'destinationContentInfo' => $relations[1]->destinationContentInfo->remoteId,
3546
                ],
3547
            ]
3548
        );
3549
    }
3550
3551
    /**
3552
     * Test for the loadRelations() method.
3553
     *
3554
     * @see \eZ\Publish\API\Repository\ContentService::loadRelations()
3555
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3556
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadRelations
3557
     */
3558
    public function testLoadRelationsSkipsArchivedContent()
3559
    {
3560
        /* BEGIN: Use Case */
3561
        $trashService = $this->getRepository()->getTrashService();
3562
        // Remote ids of the "Media" and the "eZ Publish Demo Design ..." page
3563
        // of a eZ Publish demo installation.
3564
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3565
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
3566
3567
        $draft = $this->createContentDraftVersion1();
3568
3569
        // Load other content objects
3570
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3571
        $demoDesign = $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId);
3572
3573
        // Create relation between new content object and "Media" page
3574
        $this->contentService->addRelation(
3575
            $draft->getVersionInfo(),
3576
            $media
3577
        );
3578
3579
        // Create another relation with the "Demo Design" page
3580
        $this->contentService->addRelation(
3581
            $draft->getVersionInfo(),
3582
            $demoDesign
3583
        );
3584
3585
        $demoDesignLocation = $this->locationService->loadLocation($demoDesign->mainLocationId);
3586
3587
        // Trashing Content's last Location will change its status to archived,
3588
        // in this case relation towards it will not be loaded.
3589
        $trashService->trash($demoDesignLocation);
3590
3591
        // Load all relations
3592
        $relations = $this->contentService->loadRelations($draft->getVersionInfo());
3593
        /* END: Use Case */
3594
3595
        $this->assertCount(1, $relations);
3596
        $this->assertEquals(
3597
            [
3598
                [
3599
                    'sourceContentInfo' => 'abcdef0123456789abcdef0123456789',
3600
                    'destinationContentInfo' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
3601
                ],
3602
            ],
3603
            [
3604
                [
3605
                    'sourceContentInfo' => $relations[0]->sourceContentInfo->remoteId,
3606
                    'destinationContentInfo' => $relations[0]->destinationContentInfo->remoteId,
3607
                ],
3608
            ]
3609
        );
3610
    }
3611
3612
    /**
3613
     * Test for the loadRelations() method.
3614
     *
3615
     * @see \eZ\Publish\API\Repository\ContentService::loadRelations()
3616
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3617
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadRelations
3618
     */
3619
    public function testLoadRelationsSkipsDraftContent()
3620
    {
3621
        /* BEGIN: Use Case */
3622
        // Remote ids of the "Media" and the "eZ Publish Demo Design ..." page
3623
        // of a eZ Publish demo installation.
3624
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3625
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
3626
3627
        $draft = $this->createContentDraftVersion1();
3628
3629
        // Load other content objects
3630
        $media = $this->contentService->loadContentByRemoteId($mediaRemoteId);
3631
        $demoDesign = $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId);
3632
3633
        // Create draft of "Media" page
3634
        $mediaDraft = $this->contentService->createContentDraft($media->contentInfo);
3635
3636
        // Create relation between "Media" page and new content object draft.
3637
        // This relation will not be loaded before the draft is published.
3638
        $this->contentService->addRelation(
3639
            $mediaDraft->getVersionInfo(),
3640
            $draft->getVersionInfo()->getContentInfo()
3641
        );
3642
3643
        // Create another relation with the "Demo Design" page
3644
        $this->contentService->addRelation(
3645
            $mediaDraft->getVersionInfo(),
3646
            $demoDesign
3647
        );
3648
3649
        // Load all relations
3650
        $relations = $this->contentService->loadRelations($mediaDraft->getVersionInfo());
3651
        /* END: Use Case */
3652
3653
        $this->assertCount(1, $relations);
3654
        $this->assertEquals(
3655
            [
3656
                [
3657
                    'sourceContentInfo' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
3658
                    'destinationContentInfo' => '8b8b22fe3c6061ed500fbd2b377b885f',
3659
                ],
3660
            ],
3661
            [
3662
                [
3663
                    'sourceContentInfo' => $relations[0]->sourceContentInfo->remoteId,
3664
                    'destinationContentInfo' => $relations[0]->destinationContentInfo->remoteId,
3665
                ],
3666
            ]
3667
        );
3668
    }
3669
3670
    /**
3671
     * Test for the loadReverseRelations() method.
3672
     *
3673
     * @see \eZ\Publish\API\Repository\ContentService::loadReverseRelations()
3674
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3675
     */
3676
    public function testLoadReverseRelations()
3677
    {
3678
        /* BEGIN: Use Case */
3679
        // Remote ids of the "Media" and the "eZ Publish Demo Design ..." page
3680
        // of a eZ Publish demo installation.
3681
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3682
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
3683
3684
        $versionInfo = $this->createContentVersion1()->getVersionInfo();
3685
        $contentInfo = $versionInfo->getContentInfo();
3686
3687
        // Create some drafts
3688
        $mediaDraft = $this->contentService->createContentDraft(
3689
            $this->contentService->loadContentInfoByRemoteId($mediaRemoteId)
3690
        );
3691
        $demoDesignDraft = $this->contentService->createContentDraft(
3692
            $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId)
3693
        );
3694
3695
        // Create relation between new content object and "Media" page
3696
        $relation1 = $this->contentService->addRelation(
3697
            $mediaDraft->getVersionInfo(),
3698
            $contentInfo
3699
        );
3700
3701
        // Create another relation with the "Demo Design" page
3702
        $relation2 = $this->contentService->addRelation(
3703
            $demoDesignDraft->getVersionInfo(),
3704
            $contentInfo
3705
        );
3706
3707
        // Publish drafts, so relations become active
3708
        $this->contentService->publishVersion($mediaDraft->getVersionInfo());
3709
        $this->contentService->publishVersion($demoDesignDraft->getVersionInfo());
3710
3711
        // Load all relations
3712
        $relations = $this->contentService->loadRelations($versionInfo);
3713
        $reverseRelations = $this->contentService->loadReverseRelations($contentInfo);
3714
        /* END: Use Case */
3715
3716
        $this->assertEquals($contentInfo->id, $relation1->getDestinationContentInfo()->id);
3717
        $this->assertEquals($mediaDraft->id, $relation1->getSourceContentInfo()->id);
3718
3719
        $this->assertEquals($contentInfo->id, $relation2->getDestinationContentInfo()->id);
3720
        $this->assertEquals($demoDesignDraft->id, $relation2->getSourceContentInfo()->id);
3721
3722
        $this->assertEquals(0, count($relations));
3723
        $this->assertEquals(2, count($reverseRelations));
3724
3725
        usort(
3726
            $reverseRelations,
3727
            function ($rel1, $rel2) {
3728
                return strcasecmp(
3729
                    $rel2->getSourceContentInfo()->remoteId,
3730
                    $rel1->getSourceContentInfo()->remoteId
3731
                );
3732
            }
3733
        );
3734
3735
        $this->assertEquals(
3736
            [
3737
                [
3738
                    'sourceContentInfo' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
3739
                    'destinationContentInfo' => 'abcdef0123456789abcdef0123456789',
3740
                ],
3741
                [
3742
                    'sourceContentInfo' => '8b8b22fe3c6061ed500fbd2b377b885f',
3743
                    'destinationContentInfo' => 'abcdef0123456789abcdef0123456789',
3744
                ],
3745
            ],
3746
            [
3747
                [
3748
                    'sourceContentInfo' => $reverseRelations[0]->sourceContentInfo->remoteId,
3749
                    'destinationContentInfo' => $reverseRelations[0]->destinationContentInfo->remoteId,
3750
                ],
3751
                [
3752
                    'sourceContentInfo' => $reverseRelations[1]->sourceContentInfo->remoteId,
3753
                    'destinationContentInfo' => $reverseRelations[1]->destinationContentInfo->remoteId,
3754
                ],
3755
            ]
3756
        );
3757
    }
3758
3759
    /**
3760
     * Test for the loadReverseRelations() method.
3761
     *
3762
     * @see \eZ\Publish\API\Repository\ContentService::loadReverseRelations()
3763
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3764
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadReverseRelations
3765
     */
3766
    public function testLoadReverseRelationsSkipsArchivedContent()
3767
    {
3768
        /* BEGIN: Use Case */
3769
        $trashService = $this->getRepository()->getTrashService();
3770
        // Remote ids of the "Media" and the "eZ Publish Demo Design ..." page
3771
        // of a eZ Publish demo installation.
3772
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3773
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
3774
3775
        $versionInfo = $this->createContentVersion1()->getVersionInfo();
3776
        $contentInfo = $versionInfo->getContentInfo();
3777
3778
        // Create some drafts
3779
        $mediaDraft = $this->contentService->createContentDraft(
3780
            $this->contentService->loadContentInfoByRemoteId($mediaRemoteId)
3781
        );
3782
        $demoDesignDraft = $this->contentService->createContentDraft(
3783
            $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId)
3784
        );
3785
3786
        // Create relation between new content object and "Media" page
3787
        $relation1 = $this->contentService->addRelation(
3788
            $mediaDraft->getVersionInfo(),
3789
            $contentInfo
3790
        );
3791
3792
        // Create another relation with the "Demo Design" page
3793
        $relation2 = $this->contentService->addRelation(
3794
            $demoDesignDraft->getVersionInfo(),
3795
            $contentInfo
3796
        );
3797
3798
        // Publish drafts, so relations become active
3799
        $this->contentService->publishVersion($mediaDraft->getVersionInfo());
3800
        $this->contentService->publishVersion($demoDesignDraft->getVersionInfo());
3801
3802
        $demoDesignLocation = $this->locationService->loadLocation($demoDesignDraft->contentInfo->mainLocationId);
3803
3804
        // Trashing Content's last Location will change its status to archived,
3805
        // in this case relation from it will not be loaded.
3806
        $trashService->trash($demoDesignLocation);
3807
3808
        // Load all relations
3809
        $relations = $this->contentService->loadRelations($versionInfo);
3810
        $reverseRelations = $this->contentService->loadReverseRelations($contentInfo);
3811
        /* END: Use Case */
3812
3813
        $this->assertEquals($contentInfo->id, $relation1->getDestinationContentInfo()->id);
3814
        $this->assertEquals($mediaDraft->id, $relation1->getSourceContentInfo()->id);
3815
3816
        $this->assertEquals($contentInfo->id, $relation2->getDestinationContentInfo()->id);
3817
        $this->assertEquals($demoDesignDraft->id, $relation2->getSourceContentInfo()->id);
3818
3819
        $this->assertEquals(0, count($relations));
3820
        $this->assertEquals(1, count($reverseRelations));
3821
3822
        $this->assertEquals(
3823
            [
3824
                [
3825
                    'sourceContentInfo' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
3826
                    'destinationContentInfo' => 'abcdef0123456789abcdef0123456789',
3827
                ],
3828
            ],
3829
            [
3830
                [
3831
                    'sourceContentInfo' => $reverseRelations[0]->sourceContentInfo->remoteId,
3832
                    'destinationContentInfo' => $reverseRelations[0]->destinationContentInfo->remoteId,
3833
                ],
3834
            ]
3835
        );
3836
    }
3837
3838
    /**
3839
     * Test for the loadReverseRelations() method.
3840
     *
3841
     * @see \eZ\Publish\API\Repository\ContentService::loadReverseRelations()
3842
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testAddRelation
3843
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadReverseRelations
3844
     */
3845
    public function testLoadReverseRelationsSkipsDraftContent()
3846
    {
3847
        /* BEGIN: Use Case */
3848
        // Remote ids of the "Media" and the "eZ Publish Demo Design ..." page
3849
        // of a eZ Publish demo installation.
3850
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3851
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
3852
3853
        // Load "Media" page Content
3854
        $media = $this->contentService->loadContentByRemoteId($mediaRemoteId);
3855
3856
        // Create some drafts
3857
        $newDraftVersionInfo = $this->createContentDraftVersion1()->getVersionInfo();
3858
        $demoDesignDraft = $this->contentService->createContentDraft(
3859
            $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId)
3860
        );
3861
3862
        // Create relation between "Media" page and new content object
3863
        $relation1 = $this->contentService->addRelation(
3864
            $newDraftVersionInfo,
3865
            $media->contentInfo
3866
        );
3867
3868
        // Create another relation with the "Demo Design" page
3869
        $relation2 = $this->contentService->addRelation(
3870
            $demoDesignDraft->getVersionInfo(),
3871
            $media->contentInfo
3872
        );
3873
3874
        // Publish drafts, so relations become active
3875
        $this->contentService->publishVersion($demoDesignDraft->getVersionInfo());
3876
        // We will not publish new Content draft, therefore relation from it
3877
        // will not be loaded as reverse relation for "Media" page
3878
        //$this->contentService->publishVersion( $newDraftVersionInfo );
3879
3880
        // Load all relations
3881
        $relations = $this->contentService->loadRelations($media->versionInfo);
3882
        $reverseRelations = $this->contentService->loadReverseRelations($media->contentInfo);
3883
        /* END: Use Case */
3884
3885
        $this->assertEquals($media->contentInfo->id, $relation1->getDestinationContentInfo()->id);
3886
        $this->assertEquals($newDraftVersionInfo->contentInfo->id, $relation1->getSourceContentInfo()->id);
3887
3888
        $this->assertEquals($media->contentInfo->id, $relation2->getDestinationContentInfo()->id);
3889
        $this->assertEquals($demoDesignDraft->id, $relation2->getSourceContentInfo()->id);
3890
3891
        $this->assertEquals(0, count($relations));
3892
        $this->assertEquals(1, count($reverseRelations));
3893
3894
        $this->assertEquals(
3895
            [
3896
                [
3897
                    'sourceContentInfo' => '8b8b22fe3c6061ed500fbd2b377b885f',
3898
                    'destinationContentInfo' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
3899
                ],
3900
            ],
3901
            [
3902
                [
3903
                    'sourceContentInfo' => $reverseRelations[0]->sourceContentInfo->remoteId,
3904
                    'destinationContentInfo' => $reverseRelations[0]->destinationContentInfo->remoteId,
3905
                ],
3906
            ]
3907
        );
3908
    }
3909
3910
    /**
3911
     * Test for the deleteRelation() method.
3912
     *
3913
     * @see \eZ\Publish\API\Repository\ContentService::deleteRelation()
3914
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadRelations
3915
     */
3916 View Code Duplication
    public function testDeleteRelation()
3917
    {
3918
        /* BEGIN: Use Case */
3919
        // Remote ids of the "Media" and the "Demo Design" page of a eZ Publish
3920
        // demo installation.
3921
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3922
        $demoDesignRemoteId = '8b8b22fe3c6061ed500fbd2b377b885f';
3923
3924
        $draft = $this->createContentDraftVersion1();
3925
3926
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3927
        $demoDesign = $this->contentService->loadContentInfoByRemoteId($demoDesignRemoteId);
3928
3929
        // Establish some relations
3930
        $this->contentService->addRelation($draft->getVersionInfo(), $media);
3931
        $this->contentService->addRelation($draft->getVersionInfo(), $demoDesign);
3932
3933
        // Delete one of the currently created relations
3934
        $this->contentService->deleteRelation($draft->getVersionInfo(), $media);
3935
3936
        // The relations array now contains only one element
3937
        $relations = $this->contentService->loadRelations($draft->getVersionInfo());
3938
        /* END: Use Case */
3939
3940
        $this->assertEquals(1, count($relations));
3941
    }
3942
3943
    /**
3944
     * Test for the deleteRelation() method.
3945
     *
3946
     * @see \eZ\Publish\API\Repository\ContentService::deleteRelation()
3947
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testDeleteRelation
3948
     */
3949
    public function testDeleteRelationThrowsBadStateException()
3950
    {
3951
        /* BEGIN: Use Case */
3952
        // RemoteId of the "Media" page of an eZ Publish demo installation
3953
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3954
3955
        $content = $this->createContentVersion1();
3956
3957
        // Load the destination object
3958
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3959
3960
        // Create a new draft
3961
        $draftVersion2 = $this->contentService->createContentDraft($content->contentInfo);
3962
3963
        // Add a relation
3964
        $this->contentService->addRelation($draftVersion2->getVersionInfo(), $media);
3965
3966
        // Publish new version
3967
        $contentVersion2 = $this->contentService->publishVersion(
3968
            $draftVersion2->getVersionInfo()
3969
        );
3970
3971
        $this->expectException(BadStateException::class);
3972
3973
        // This call will fail with a "BadStateException", because content is published and not a draft.
3974
        $this->contentService->deleteRelation(
3975
            $contentVersion2->getVersionInfo(),
3976
            $media
3977
        );
3978
        /* END: Use Case */
3979
    }
3980
3981
    /**
3982
     * Test for the deleteRelation() method.
3983
     *
3984
     * @see \eZ\Publish\API\Repository\ContentService::deleteRelation()
3985
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testDeleteRelation
3986
     */
3987 View Code Duplication
    public function testDeleteRelationThrowsInvalidArgumentException()
3988
    {
3989
        /* BEGIN: Use Case */
3990
        // RemoteId of the "Media" page of an eZ Publish demo installation
3991
        $mediaRemoteId = 'a6e35cbcb7cd6ae4b691f3eee30cd262';
3992
3993
        $draft = $this->createContentDraftVersion1();
3994
3995
        // Load the destination object
3996
        $media = $this->contentService->loadContentInfoByRemoteId($mediaRemoteId);
3997
3998
        // This call will fail with a "InvalidArgumentException", because no relation exists between $draft and $media.
3999
        $this->expectException(APIInvalidArgumentException::class);
4000
        $this->contentService->deleteRelation(
4001
            $draft->getVersionInfo(),
4002
            $media
4003
        );
4004
        /* END: Use Case */
4005
    }
4006
4007
    /**
4008
     * Test for the createContent() method.
4009
     *
4010
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
4011
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
4012
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
4013
     */
4014
    public function testCreateContentInTransactionWithRollback()
4015
    {
4016
        if ($this->isVersion4()) {
4017
            $this->markTestSkipped('This test requires eZ Publish 5');
4018
        }
4019
4020
        $repository = $this->getRepository();
4021
4022
        /* BEGIN: Use Case */
4023
        $contentTypeService = $this->getRepository()->getContentTypeService();
4024
4025
        // Start a transaction
4026
        $repository->beginTransaction();
4027
4028
        try {
4029
            $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
4030
4031
            // Get a content create struct and set mandatory properties
4032
            $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
4033
            $contentCreate->setField('name', 'Sindelfingen forum');
4034
4035
            $contentCreate->remoteId = 'abcdef0123456789abcdef0123456789';
4036
            $contentCreate->alwaysAvailable = true;
4037
4038
            // Create a new content object
4039
            $contentId = $this->contentService->createContent($contentCreate)->id;
4040
        } catch (Exception $e) {
4041
            // Cleanup hanging transaction on error
4042
            $repository->rollback();
4043
            throw $e;
4044
        }
4045
4046
        // Rollback all changes
4047
        $repository->rollback();
4048
4049
        try {
4050
            // This call will fail with a "NotFoundException"
4051
            $this->contentService->loadContent($contentId);
4052
        } catch (NotFoundException $e) {
4053
            // This is expected
4054
            return;
4055
        }
4056
        /* END: Use Case */
4057
4058
        $this->fail('Content object still exists after rollback.');
4059
    }
4060
4061
    /**
4062
     * Test for the createContent() method.
4063
     *
4064
     * @see \eZ\Publish\API\Repository\ContentService::createContent()
4065
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
4066
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
4067
     */
4068
    public function testCreateContentInTransactionWithCommit()
4069
    {
4070
        if ($this->isVersion4()) {
4071
            $this->markTestSkipped('This test requires eZ Publish 5');
4072
        }
4073
4074
        $repository = $this->getRepository();
4075
4076
        /* BEGIN: Use Case */
4077
        $contentTypeService = $repository->getContentTypeService();
4078
4079
        // Start a transaction
4080
        $repository->beginTransaction();
4081
4082
        try {
4083
            $contentType = $contentTypeService->loadContentTypeByIdentifier('forum');
4084
4085
            // Get a content create struct and set mandatory properties
4086
            $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
4087
            $contentCreate->setField('name', 'Sindelfingen forum');
4088
4089
            $contentCreate->remoteId = 'abcdef0123456789abcdef0123456789';
4090
            $contentCreate->alwaysAvailable = true;
4091
4092
            // Create a new content object
4093
            $contentId = $this->contentService->createContent($contentCreate)->id;
4094
4095
            // Commit changes
4096
            $repository->commit();
4097
        } catch (Exception $e) {
4098
            // Cleanup hanging transaction on error
4099
            $repository->rollback();
4100
            throw $e;
4101
        }
4102
4103
        // Load the new content object
4104
        $content = $this->contentService->loadContent($contentId);
4105
        /* END: Use Case */
4106
4107
        $this->assertEquals($contentId, $content->id);
4108
    }
4109
4110
    /**
4111
     * Test for the createContent() method.
4112
     *
4113
     * @see \eZ\Publish\API\Repository\ContentService::createContent($contentCreateStruct, $locationCreateStructs)
4114
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentWithLocationCreateParameterDoesNotCreateLocationImmediately
4115
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentThrowsNotFoundException
4116
     */
4117 View Code Duplication
    public function testCreateContentWithLocationCreateParameterInTransactionWithRollback()
4118
    {
4119
        $repository = $this->getRepository();
4120
4121
        /* BEGIN: Use Case */
4122
        // Start a transaction
4123
        $repository->beginTransaction();
4124
4125
        try {
4126
            $draft = $this->createContentDraftVersion1();
4127
        } catch (Exception $e) {
4128
            // Cleanup hanging transaction on error
4129
            $repository->rollback();
4130
            throw $e;
4131
        }
4132
4133
        $contentId = $draft->id;
4134
4135
        // Roleback the transaction
4136
        $repository->rollback();
4137
4138
        try {
4139
            // This call will fail with a "NotFoundException"
4140
            $this->contentService->loadContent($contentId);
4141
        } catch (NotFoundException $e) {
4142
            return;
4143
        }
4144
        /* END: Use Case */
4145
4146
        $this->fail('Can still load content object after rollback.');
4147
    }
4148
4149
    /**
4150
     * Test for the createContent() method.
4151
     *
4152
     * @see \eZ\Publish\API\Repository\ContentService::createContent($contentCreateStruct, $locationCreateStructs)
4153
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentWithLocationCreateParameterDoesNotCreateLocationImmediately
4154
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentThrowsNotFoundException
4155
     */
4156
    public function testCreateContentWithLocationCreateParameterInTransactionWithCommit()
4157
    {
4158
        $repository = $this->getRepository();
4159
4160
        /* BEGIN: Use Case */
4161
        // Start a transaction
4162
        $repository->beginTransaction();
4163
4164
        try {
4165
            $draft = $this->createContentDraftVersion1();
4166
4167
            $contentId = $draft->id;
4168
4169
            // Roleback the transaction
4170
            $repository->commit();
4171
        } catch (Exception $e) {
4172
            // Cleanup hanging transaction on error
4173
            $repository->rollback();
4174
            throw $e;
4175
        }
4176
4177
        // Load the new content object
4178
        $content = $this->contentService->loadContent($contentId);
4179
        /* END: Use Case */
4180
4181
        $this->assertEquals($contentId, $content->id);
4182
    }
4183
4184
    /**
4185
     * Test for the createContentDraft() method.
4186
     *
4187
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
4188
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
4189
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
4190
     */
4191
    public function testCreateContentDraftInTransactionWithRollback()
4192
    {
4193
        $repository = $this->getRepository();
4194
4195
        $contentId = $this->generateId('object', 12);
4196
        /* BEGIN: Use Case */
4197
        // $contentId is the ID of the "Administrator users" user group
4198
4199
        // Load the user group content object
4200
        $content = $this->contentService->loadContent($contentId);
4201
4202
        // Start a new transaction
4203
        $repository->beginTransaction();
4204
4205
        try {
4206
            // Create a new draft
4207
            $drafted = $this->contentService->createContentDraft($content->contentInfo);
4208
4209
            // Store version number for later reuse
4210
            $versionNo = $drafted->versionInfo->versionNo;
4211
        } catch (Exception $e) {
4212
            // Cleanup hanging transaction on error
4213
            $repository->rollback();
4214
            throw $e;
4215
        }
4216
4217
        // Rollback
4218
        $repository->rollback();
4219
4220
        try {
4221
            // This call will fail with a "NotFoundException"
4222
            $this->contentService->loadContent($contentId, null, $versionNo);
4223
        } catch (NotFoundException $e) {
4224
            return;
4225
        }
4226
        /* END: Use Case */
4227
4228
        $this->fail('Can still load content draft after rollback');
4229
    }
4230
4231
    /**
4232
     * Test for the createContentDraft() method.
4233
     *
4234
     * @see \eZ\Publish\API\Repository\ContentService::createContentDraft()
4235
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContentDraft
4236
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
4237
     */
4238 View Code Duplication
    public function testCreateContentDraftInTransactionWithCommit()
4239
    {
4240
        $repository = $this->getRepository();
4241
4242
        $contentId = $this->generateId('object', 12);
4243
        /* BEGIN: Use Case */
4244
        // $contentId is the ID of the "Administrator users" user group
4245
4246
        // Load the user group content object
4247
        $content = $this->contentService->loadContent($contentId);
4248
4249
        // Start a new transaction
4250
        $repository->beginTransaction();
4251
4252
        try {
4253
            // Create a new draft
4254
            $drafted = $this->contentService->createContentDraft($content->contentInfo);
4255
4256
            // Store version number for later reuse
4257
            $versionNo = $drafted->versionInfo->versionNo;
4258
4259
            // Commit all changes
4260
            $repository->commit();
4261
        } catch (Exception $e) {
4262
            // Cleanup hanging transaction on error
4263
            $repository->rollback();
4264
            throw $e;
4265
        }
4266
4267
        $content = $this->contentService->loadContent($contentId, null, $versionNo);
4268
        /* END: Use Case */
4269
4270
        $this->assertEquals(
4271
            $versionNo,
4272
            $content->getVersionInfo()->versionNo
4273
        );
4274
    }
4275
4276
    /**
4277
     * Test for the publishVersion() method.
4278
     *
4279
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
4280
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
4281
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
4282
     */
4283 View Code Duplication
    public function testPublishVersionInTransactionWithRollback()
4284
    {
4285
        $repository = $this->getRepository();
4286
4287
        $contentId = $this->generateId('object', 12);
4288
        /* BEGIN: Use Case */
4289
        // $contentId is the ID of the "Administrator users" user group
4290
4291
        // Load the user group content object
4292
        $content = $this->contentService->loadContent($contentId);
4293
4294
        // Start a new transaction
4295
        $repository->beginTransaction();
4296
4297
        try {
4298
            $draftVersion = $this->contentService->createContentDraft($content->contentInfo)->getVersionInfo();
4299
4300
            // Publish a new version
4301
            $content = $this->contentService->publishVersion($draftVersion);
4302
4303
            // Store version number for later reuse
4304
            $versionNo = $content->versionInfo->versionNo;
4305
        } catch (Exception $e) {
4306
            // Cleanup hanging transaction on error
4307
            $repository->rollback();
4308
            throw $e;
4309
        }
4310
4311
        // Rollback
4312
        $repository->rollback();
4313
4314
        try {
4315
            // This call will fail with a "NotFoundException"
4316
            $this->contentService->loadContent($contentId, null, $versionNo);
4317
        } catch (NotFoundException $e) {
4318
            return;
4319
        }
4320
        /* END: Use Case */
4321
4322
        $this->fail('Can still load content draft after rollback');
4323
    }
4324
4325
    /**
4326
     * Test for the publishVersion() method.
4327
     *
4328
     * @see \eZ\Publish\API\Repository\ContentService::publishVersion()
4329
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testPublishVersion
4330
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadVersionInfo
4331
     */
4332 View Code Duplication
    public function testPublishVersionInTransactionWithCommit()
4333
    {
4334
        $repository = $this->getRepository();
4335
4336
        /* BEGIN: Use Case */
4337
        // ID of the "Administrator users" user group
4338
        $contentId = 12;
4339
4340
        // Load the user group content object
4341
        $template = $this->contentService->loadContent($contentId);
4342
4343
        // Start a new transaction
4344
        $repository->beginTransaction();
4345
4346
        try {
4347
            // Publish a new version
4348
            $content = $this->contentService->publishVersion(
4349
                $this->contentService->createContentDraft($template->contentInfo)->getVersionInfo()
4350
            );
4351
4352
            // Store version number for later reuse
4353
            $versionNo = $content->versionInfo->versionNo;
4354
4355
            // Commit all changes
4356
            $repository->commit();
4357
        } catch (Exception $e) {
4358
            // Cleanup hanging transaction on error
4359
            $repository->rollback();
4360
            throw $e;
4361
        }
4362
4363
        // Load current version info
4364
        $versionInfo = $this->contentService->loadVersionInfo($content->contentInfo);
4365
        /* END: Use Case */
4366
4367
        $this->assertEquals($versionNo, $versionInfo->versionNo);
4368
    }
4369
4370
    /**
4371
     * Test for the updateContent() method.
4372
     *
4373
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
4374
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
4375
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
4376
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4377
     */
4378 View Code Duplication
    public function testUpdateContentInTransactionWithRollback()
4379
    {
4380
        $repository = $this->getRepository();
4381
4382
        $contentId = $this->generateId('object', 12);
4383
        /* BEGIN: Use Case */
4384
        // $contentId is the ID of the "Administrator users" user group
4385
4386
        // Create a new user group draft
4387
        $draft = $this->contentService->createContentDraft(
4388
            $this->contentService->loadContentInfo($contentId)
4389
        );
4390
4391
        // Get an update struct and change the group name
4392
        $contentUpdate = $this->contentService->newContentUpdateStruct();
4393
        $contentUpdate->setField('name', 'Administrators', 'eng-US');
4394
4395
        // Start a transaction
4396
        $repository->beginTransaction();
4397
4398
        try {
4399
            // Update the group name
4400
            $draft = $this->contentService->updateContent(
4401
                $draft->getVersionInfo(),
4402
                $contentUpdate
4403
            );
4404
4405
            // Publish updated version
4406
            $this->contentService->publishVersion($draft->getVersionInfo());
4407
        } catch (Exception $e) {
4408
            // Cleanup hanging transaction on error
4409
            $repository->rollback();
4410
            throw $e;
4411
        }
4412
4413
        // Rollback all changes.
4414
        $repository->rollback();
4415
4416
        // Name will still be "Administrator users"
4417
        $name = $this->contentService->loadContent($contentId)->getFieldValue('name');
4418
        /* END: Use Case */
4419
4420
        $this->assertEquals('Administrator users', $name);
4421
    }
4422
4423
    /**
4424
     * Test for the updateContent() method.
4425
     *
4426
     * @see \eZ\Publish\API\Repository\ContentService::updateContent()
4427
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
4428
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContent
4429
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4430
     */
4431 View Code Duplication
    public function testUpdateContentInTransactionWithCommit()
4432
    {
4433
        $repository = $this->getRepository();
4434
4435
        $contentId = $this->generateId('object', 12);
4436
        /* BEGIN: Use Case */
4437
        // $contentId is the ID of the "Administrator users" user group
4438
4439
        // Create a new user group draft
4440
        $draft = $this->contentService->createContentDraft(
4441
            $this->contentService->loadContentInfo($contentId)
4442
        );
4443
4444
        // Get an update struct and change the group name
4445
        $contentUpdate = $this->contentService->newContentUpdateStruct();
4446
        $contentUpdate->setField('name', 'Administrators', 'eng-US');
4447
4448
        // Start a transaction
4449
        $repository->beginTransaction();
4450
4451
        try {
4452
            // Update the group name
4453
            $draft = $this->contentService->updateContent(
4454
                $draft->getVersionInfo(),
4455
                $contentUpdate
4456
            );
4457
4458
            // Publish updated version
4459
            $this->contentService->publishVersion($draft->getVersionInfo());
4460
4461
            // Commit all changes.
4462
            $repository->commit();
4463
        } catch (Exception $e) {
4464
            // Cleanup hanging transaction on error
4465
            $repository->rollback();
4466
            throw $e;
4467
        }
4468
4469
        // Name is now "Administrators"
4470
        $name = $this->contentService->loadContent($contentId)->getFieldValue('name', 'eng-US');
4471
        /* END: Use Case */
4472
4473
        $this->assertEquals('Administrators', $name);
4474
    }
4475
4476
    /**
4477
     * Test for the updateContentMetadata() method.
4478
     *
4479
     * @see \eZ\Publish\API\Repository\ContentService::updateContentMetadata()
4480
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContentMetadata
4481
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4482
     */
4483 View Code Duplication
    public function testUpdateContentMetadataInTransactionWithRollback()
4484
    {
4485
        $repository = $this->getRepository();
4486
4487
        $contentId = $this->generateId('object', 12);
4488
        /* BEGIN: Use Case */
4489
        // $contentId is the ID of the "Administrator users" user group
4490
4491
        // Load a ContentInfo object
4492
        $contentInfo = $this->contentService->loadContentInfo($contentId);
4493
4494
        // Store remoteId for later testing
4495
        $remoteId = $contentInfo->remoteId;
4496
4497
        // Start a transaction
4498
        $repository->beginTransaction();
4499
4500
        try {
4501
            // Get metadata update struct and change remoteId
4502
            $metadataUpdate = $this->contentService->newContentMetadataUpdateStruct();
4503
            $metadataUpdate->remoteId = md5(microtime(true));
4504
4505
            // Update the metadata of the published content object
4506
            $this->contentService->updateContentMetadata(
4507
                $contentInfo,
4508
                $metadataUpdate
4509
            );
4510
        } catch (Exception $e) {
4511
            // Cleanup hanging transaction on error
4512
            $repository->rollback();
4513
            throw $e;
4514
        }
4515
4516
        // Rollback all changes.
4517
        $repository->rollback();
4518
4519
        // Load current remoteId
4520
        $remoteIdReloaded = $this->contentService->loadContentInfo($contentId)->remoteId;
4521
        /* END: Use Case */
4522
4523
        $this->assertEquals($remoteId, $remoteIdReloaded);
4524
    }
4525
4526
    /**
4527
     * Test for the updateContentMetadata() method.
4528
     *
4529
     * @see \eZ\Publish\API\Repository\ContentService::updateContentMetadata()
4530
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContentMetadata
4531
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4532
     */
4533 View Code Duplication
    public function testUpdateContentMetadataInTransactionWithCommit()
4534
    {
4535
        $repository = $this->getRepository();
4536
4537
        $contentId = $this->generateId('object', 12);
4538
        /* BEGIN: Use Case */
4539
        // $contentId is the ID of the "Administrator users" user group
4540
4541
        // Load a ContentInfo object
4542
        $contentInfo = $this->contentService->loadContentInfo($contentId);
4543
4544
        // Store remoteId for later testing
4545
        $remoteId = $contentInfo->remoteId;
4546
4547
        // Start a transaction
4548
        $repository->beginTransaction();
4549
4550
        try {
4551
            // Get metadata update struct and change remoteId
4552
            $metadataUpdate = $this->contentService->newContentMetadataUpdateStruct();
4553
            $metadataUpdate->remoteId = md5(microtime(true));
4554
4555
            // Update the metadata of the published content object
4556
            $this->contentService->updateContentMetadata(
4557
                $contentInfo,
4558
                $metadataUpdate
4559
            );
4560
4561
            // Commit all changes.
4562
            $repository->commit();
4563
        } catch (Exception $e) {
4564
            // Cleanup hanging transaction on error
4565
            $repository->rollback();
4566
            throw $e;
4567
        }
4568
4569
        // Load current remoteId
4570
        $remoteIdReloaded = $this->contentService->loadContentInfo($contentId)->remoteId;
4571
        /* END: Use Case */
4572
4573
        $this->assertNotEquals($remoteId, $remoteIdReloaded);
4574
    }
4575
4576
    /**
4577
     * Test for the deleteVersion() method.
4578
     *
4579
     * @see \eZ\Publish\API\Repository\ContentService::deleteVersion()
4580
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
4581
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4582
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentDrafts
4583
     */
4584 View Code Duplication
    public function testDeleteVersionInTransactionWithRollback()
4585
    {
4586
        $repository = $this->getRepository();
4587
4588
        $contentId = $this->generateId('object', 12);
4589
        /* BEGIN: Use Case */
4590
        // $contentId is the ID of the "Administrator users" user group
4591
4592
        // Start a new transaction
4593
        $repository->beginTransaction();
4594
4595
        try {
4596
            // Create a new draft
4597
            $draft = $this->contentService->createContentDraft(
4598
                $this->contentService->loadContentInfo($contentId)
4599
            );
4600
4601
            $this->contentService->deleteVersion($draft->getVersionInfo());
4602
        } catch (Exception $e) {
4603
            // Cleanup hanging transaction on error
4604
            $repository->rollback();
4605
            throw $e;
4606
        }
4607
4608
        // Rollback all changes.
4609
        $repository->rollback();
4610
4611
        // This array will be empty
4612
        $drafts = $this->contentService->loadContentDrafts();
4613
        /* END: Use Case */
4614
4615
        $this->assertSame([], $drafts);
4616
    }
4617
4618
    /**
4619
     * Test for the deleteVersion() method.
4620
     *
4621
     * @see \eZ\Publish\API\Repository\ContentService::deleteVersion()
4622
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCreateContent
4623
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4624
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentDrafts
4625
     */
4626 View Code Duplication
    public function testDeleteVersionInTransactionWithCommit()
4627
    {
4628
        $repository = $this->getRepository();
4629
4630
        $contentId = $this->generateId('object', 12);
4631
        /* BEGIN: Use Case */
4632
        // $contentId is the ID of the "Administrator users" user group
4633
4634
        // Start a new transaction
4635
        $repository->beginTransaction();
4636
4637
        try {
4638
            // Create a new draft
4639
            $draft = $this->contentService->createContentDraft(
4640
                $this->contentService->loadContentInfo($contentId)
4641
            );
4642
4643
            $this->contentService->deleteVersion($draft->getVersionInfo());
4644
4645
            // Commit all changes.
4646
            $repository->commit();
4647
        } catch (Exception $e) {
4648
            // Cleanup hanging transaction on error
4649
            $repository->rollback();
4650
            throw $e;
4651
        }
4652
4653
        // This array will contain no element
4654
        $drafts = $this->contentService->loadContentDrafts();
4655
        /* END: Use Case */
4656
4657
        $this->assertSame([], $drafts);
4658
    }
4659
4660
    /**
4661
     * Test for the deleteContent() method.
4662
     *
4663
     * @see \eZ\Publish\API\Repository\ContentService::deleteContent()
4664
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testDeleteContent
4665
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4666
     */
4667
    public function testDeleteContentInTransactionWithRollback()
4668
    {
4669
        $repository = $this->getRepository();
4670
4671
        $contentId = $this->generateId('object', 11);
4672
        /* BEGIN: Use Case */
4673
        // $contentId is the ID of the "Members" user group in an eZ Publish
4674
        // demo installation
4675
4676
        // Load a ContentInfo instance
4677
        $contentInfo = $this->contentService->loadContentInfo($contentId);
4678
4679
        // Start a new transaction
4680
        $repository->beginTransaction();
4681
4682
        try {
4683
            // Delete content object
4684
            $this->contentService->deleteContent($contentInfo);
4685
        } catch (Exception $e) {
4686
            // Cleanup hanging transaction on error
4687
            $repository->rollback();
4688
            throw $e;
4689
        }
4690
4691
        // Rollback all changes
4692
        $repository->rollback();
4693
4694
        // This call will return the original content object
4695
        $contentInfo = $this->contentService->loadContentInfo($contentId);
4696
        /* END: Use Case */
4697
4698
        $this->assertEquals($contentId, $contentInfo->id);
4699
    }
4700
4701
    /**
4702
     * Test for the deleteContent() method.
4703
     *
4704
     * @see \eZ\Publish\API\Repository\ContentService::deleteContent()
4705
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testDeleteContent
4706
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfo
4707
     */
4708
    public function testDeleteContentInTransactionWithCommit()
4709
    {
4710
        $repository = $this->getRepository();
4711
4712
        $contentId = $this->generateId('object', 11);
4713
        /* BEGIN: Use Case */
4714
        // $contentId is the ID of the "Members" user group in an eZ Publish
4715
        // demo installation
4716
4717
        // Load a ContentInfo instance
4718
        $contentInfo = $this->contentService->loadContentInfo($contentId);
4719
4720
        // Start a new transaction
4721
        $repository->beginTransaction();
4722
4723
        try {
4724
            // Delete content object
4725
            $this->contentService->deleteContent($contentInfo);
4726
4727
            // Commit all changes
4728
            $repository->commit();
4729
        } catch (Exception $e) {
4730
            // Cleanup hanging transaction on error
4731
            $repository->rollback();
4732
            throw $e;
4733
        }
4734
4735
        // Deleted content info is not found anymore
4736
        try {
4737
            $this->contentService->loadContentInfo($contentId);
4738
        } catch (NotFoundException $e) {
4739
            return;
4740
        }
4741
        /* END: Use Case */
4742
4743
        $this->fail('Can still load ContentInfo after commit.');
4744
    }
4745
4746
    /**
4747
     * Test for the copyContent() method.
4748
     *
4749
     * @see \eZ\Publish\API\Repository\ContentService::copyContent()
4750
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCopyContent
4751
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
4752
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
4753
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
4754
     */
4755 View Code Duplication
    public function testCopyContentInTransactionWithRollback()
4756
    {
4757
        $repository = $this->getRepository();
4758
4759
        $contentId = $this->generateId('object', 11);
4760
        $locationId = $this->generateId('location', 13);
4761
        /* BEGIN: Use Case */
4762
        // $contentId is the ID of the "Members" user group in an eZ Publish
4763
        // demo installation
4764
4765
        // $locationId is the ID of the "Administrator users" group location
4766
4767
        // Load content object to copy
4768
        $content = $this->contentService->loadContent($contentId);
4769
4770
        // Create new target location
4771
        $locationCreate = $this->locationService->newLocationCreateStruct($locationId);
4772
4773
        // Start a new transaction
4774
        $repository->beginTransaction();
4775
4776
        try {
4777
            // Copy content with all versions and drafts
4778
            $this->contentService->copyContent(
4779
                $content->contentInfo,
4780
                $locationCreate
4781
            );
4782
        } catch (Exception $e) {
4783
            // Cleanup hanging transaction on error
4784
            $repository->rollback();
4785
            throw $e;
4786
        }
4787
4788
        // Rollback all changes
4789
        $repository->rollback();
4790
4791
        $this->refreshSearch($repository);
4792
4793
        // This array will only contain a single admin user object
4794
        $locations = $this->locationService->loadLocationChildren(
4795
            $this->locationService->loadLocation($locationId)
4796
        )->locations;
4797
        /* END: Use Case */
4798
4799
        $this->assertEquals(1, count($locations));
4800
    }
4801
4802
    /**
4803
     * Test for the copyContent() method.
4804
     *
4805
     * @see \eZ\Publish\API\Repository\ContentService::copyContent()
4806
     * @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testCopyContent
4807
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testNewLocationCreateStruct
4808
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocationChildren
4809
     * @depend(s) eZ\Publish\API\Repository\Tests\LocationServiceTest::testLoadLocation
4810
     */
4811 View Code Duplication
    public function testCopyContentInTransactionWithCommit()
4812
    {
4813
        $repository = $this->getRepository();
4814
4815
        $contentId = $this->generateId('object', 11);
4816
        $locationId = $this->generateId('location', 13);
4817
        /* BEGIN: Use Case */
4818
        // $contentId is the ID of the "Members" user group in an eZ Publish
4819
        // demo installation
4820
4821
        // $locationId is the ID of the "Administrator users" group location
4822
4823
        // Load content object to copy
4824
        $content = $this->contentService->loadContent($contentId);
4825
4826
        // Create new target location
4827
        $locationCreate = $this->locationService->newLocationCreateStruct($locationId);
4828
4829
        // Start a new transaction
4830
        $repository->beginTransaction();
4831
4832
        try {
4833
            // Copy content with all versions and drafts
4834
            $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...
4835
                $content->contentInfo,
4836
                $locationCreate
4837
            );
4838
4839
            // Commit all changes
4840
            $repository->commit();
4841
        } catch (Exception $e) {
4842
            // Cleanup hanging transaction on error
4843
            $repository->rollback();
4844
            throw $e;
4845
        }
4846
4847
        $this->refreshSearch($repository);
4848
4849
        // This will contain the admin user and the new child location
4850
        $locations = $this->locationService->loadLocationChildren(
4851
            $this->locationService->loadLocation($locationId)
4852
        )->locations;
4853
        /* END: Use Case */
4854
4855
        $this->assertEquals(2, count($locations));
4856
    }
4857
4858
    public function testURLAliasesCreatedForNewContent()
4859
    {
4860
        $urlAliasService = $this->getRepository()->getURLAliasService();
4861
4862
        /* BEGIN: Use Case */
4863
        $draft = $this->createContentDraftVersion1();
4864
4865
        // Automatically creates a new URLAlias for the content
4866
        $liveContent = $this->contentService->publishVersion($draft->getVersionInfo());
4867
        /* END: Use Case */
4868
4869
        $location = $this->locationService->loadLocation(
4870
            $liveContent->getVersionInfo()->getContentInfo()->mainLocationId
4871
        );
4872
4873
        $aliases = $urlAliasService->listLocationAliases($location, false);
4874
4875
        $this->assertAliasesCorrect(
4876
            [
4877
                '/Design/Plain-site/An-awesome-forum' => [
4878
                    'type' => URLAlias::LOCATION,
4879
                    'destination' => $location->id,
4880
                    'path' => '/Design/Plain-site/An-awesome-forum',
4881
                    'languageCodes' => ['eng-US'],
4882
                    'isHistory' => false,
4883
                    'isCustom' => false,
4884
                    'forward' => false,
4885
                ],
4886
            ],
4887
            $aliases
4888
        );
4889
    }
4890
4891
    public function testURLAliasesCreatedForUpdatedContent()
4892
    {
4893
        $urlAliasService = $this->getRepository()->getURLAliasService();
4894
4895
        /* BEGIN: Use Case */
4896
        $draft = $this->createUpdatedDraftVersion2();
4897
4898
        $location = $this->locationService->loadLocation(
4899
            $draft->getVersionInfo()->getContentInfo()->mainLocationId
4900
        );
4901
4902
        // Load and assert URL aliases before publishing updated Content, so that
4903
        // SPI cache is warmed up and cache invalidation is also tested.
4904
        $aliases = $urlAliasService->listLocationAliases($location, false);
4905
4906
        $this->assertAliasesCorrect(
4907
            [
4908
                '/Design/Plain-site/An-awesome-forum' => [
4909
                    'type' => URLAlias::LOCATION,
4910
                    'destination' => $location->id,
4911
                    'path' => '/Design/Plain-site/An-awesome-forum',
4912
                    'languageCodes' => ['eng-US'],
4913
                    'alwaysAvailable' => true,
4914
                    'isHistory' => false,
4915
                    'isCustom' => false,
4916
                    'forward' => false,
4917
                ],
4918
            ],
4919
            $aliases
4920
        );
4921
4922
        // Automatically marks old aliases for the content as history
4923
        // and creates new aliases, based on the changes
4924
        $liveContent = $this->contentService->publishVersion($draft->getVersionInfo());
4925
        /* END: Use Case */
4926
4927
        $location = $this->locationService->loadLocation(
4928
            $liveContent->getVersionInfo()->getContentInfo()->mainLocationId
4929
        );
4930
4931
        $aliases = $urlAliasService->listLocationAliases($location, false);
4932
4933
        $this->assertAliasesCorrect(
4934
            [
4935
                '/Design/Plain-site/An-awesome-forum2' => [
4936
                    'type' => URLAlias::LOCATION,
4937
                    'destination' => $location->id,
4938
                    'path' => '/Design/Plain-site/An-awesome-forum2',
4939
                    'languageCodes' => ['eng-US'],
4940
                    'alwaysAvailable' => true,
4941
                    'isHistory' => false,
4942
                    'isCustom' => false,
4943
                    'forward' => false,
4944
                ],
4945
                '/Design/Plain-site/An-awesome-forum23' => [
4946
                    'type' => URLAlias::LOCATION,
4947
                    'destination' => $location->id,
4948
                    'path' => '/Design/Plain-site/An-awesome-forum23',
4949
                    'languageCodes' => ['eng-GB'],
4950
                    'alwaysAvailable' => true,
4951
                    'isHistory' => false,
4952
                    'isCustom' => false,
4953
                    'forward' => false,
4954
                ],
4955
            ],
4956
            $aliases
4957
        );
4958
    }
4959
4960
    public function testCustomURLAliasesNotHistorizedOnUpdatedContent()
4961
    {
4962
        /* BEGIN: Use Case */
4963
        $urlAliasService = $this->getRepository()->getURLAliasService();
4964
4965
        $content = $this->createContentVersion1();
4966
4967
        // Create a custom URL alias
4968
        $urlAliasService->createUrlAlias(
4969
            $this->locationService->loadLocation(
4970
                $content->getVersionInfo()->getContentInfo()->mainLocationId
4971
            ),
4972
            '/my/fancy/story-about-ez-publish',
4973
            'eng-US'
4974
        );
4975
4976
        $draftVersion2 = $this->contentService->createContentDraft($content->contentInfo);
4977
4978
        $contentUpdate = $this->contentService->newContentUpdateStruct();
4979
        $contentUpdate->initialLanguageCode = 'eng-US';
4980
        $contentUpdate->setField('name', 'Amazing Bielefeld forum');
4981
4982
        $draftVersion2 = $this->contentService->updateContent(
4983
            $draftVersion2->getVersionInfo(),
4984
            $contentUpdate
4985
        );
4986
4987
        // Only marks auto-generated aliases as history
4988
        // the custom one is left untouched
4989
        $liveContent = $this->contentService->publishVersion($draftVersion2->getVersionInfo());
4990
        /* END: Use Case */
4991
4992
        $location = $this->locationService->loadLocation(
4993
            $liveContent->getVersionInfo()->getContentInfo()->mainLocationId
4994
        );
4995
4996
        $aliases = $urlAliasService->listLocationAliases($location);
4997
4998
        $this->assertAliasesCorrect(
4999
            [
5000
                '/my/fancy/story-about-ez-publish' => [
5001
                    'type' => URLAlias::LOCATION,
5002
                    'destination' => $location->id,
5003
                    'path' => '/my/fancy/story-about-ez-publish',
5004
                    'languageCodes' => ['eng-US'],
5005
                    'isHistory' => false,
5006
                    'isCustom' => true,
5007
                    'forward' => false,
5008
                    'alwaysAvailable' => false,
5009
                ],
5010
            ],
5011
            $aliases
5012
        );
5013
    }
5014
5015
    /**
5016
     * Test to ensure that old versions are not affected by updates to newer
5017
     * drafts.
5018
     */
5019
    public function testUpdatingDraftDoesNotUpdateOldVersions()
5020
    {
5021
        $contentVersion2 = $this->createContentVersion2();
5022
5023
        $loadedContent1 = $this->contentService->loadContent($contentVersion2->id, null, 1);
5024
        $loadedContent2 = $this->contentService->loadContent($contentVersion2->id, null, 2);
5025
5026
        $this->assertNotEquals(
5027
            $loadedContent1->getFieldValue('name', 'eng-US'),
5028
            $loadedContent2->getFieldValue('name', 'eng-US')
5029
        );
5030
    }
5031
5032
    /**
5033
     * Test scenario with writer and publisher users.
5034
     * Writer can only create content. Publisher can publish this content.
5035
     */
5036
    public function testPublishWorkflow()
5037
    {
5038
        $this->createRoleWithPolicies('Publisher', [
5039
            ['module' => 'content', 'function' => 'read'],
5040
            ['module' => 'content', 'function' => 'create'],
5041
            ['module' => 'content', 'function' => 'publish'],
5042
        ]);
5043
5044
        $this->createRoleWithPolicies('Writer', [
5045
            ['module' => 'content', 'function' => 'read'],
5046
            ['module' => 'content', 'function' => 'create'],
5047
        ]);
5048
5049
        $writerUser = $this->createCustomUserWithLogin(
5050
            'writer',
5051
            '[email protected]',
5052
            'Writers',
5053
            'Writer'
5054
        );
5055
5056
        $publisherUser = $this->createCustomUserWithLogin(
5057
            'publisher',
5058
            '[email protected]',
5059
            'Publishers',
5060
            'Publisher'
5061
        );
5062
5063
        $this->permissionResolver->setCurrentUserReference($writerUser);
5064
        $draft = $this->createContentDraftVersion1();
5065
5066
        $this->permissionResolver->setCurrentUserReference($publisherUser);
5067
        $content = $this->contentService->publishVersion($draft->versionInfo);
5068
5069
        $this->contentService->loadContent($content->id);
5070
    }
5071
5072
    /**
5073
     * Test publish / content policy is required to be able to publish content.
5074
     */
5075
    public function testPublishContentWithoutPublishPolicyThrowsException()
5076
    {
5077
        $this->createRoleWithPolicies('Writer', [
5078
            ['module' => 'content', 'function' => 'read'],
5079
            ['module' => 'content', 'function' => 'create'],
5080
            ['module' => 'content', 'function' => 'edit'],
5081
        ]);
5082
        $writerUser = $this->createCustomUserWithLogin(
5083
            'writer',
5084
            '[email protected]',
5085
            'Writers',
5086
            'Writer'
5087
        );
5088
        $this->permissionResolver->setCurrentUserReference($writerUser);
5089
5090
        $this->expectException(CoreUnauthorizedException::class);
5091
        $this->expectExceptionMessageRegExp('/User does not have access to \'publish\' \'content\'/');
5092
5093
        $this->createContentVersion1();
5094
    }
5095
5096
    /**
5097
     * Test removal of the specific translation from all the Versions of a Content Object.
5098
     *
5099
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslation
5100
     */
5101
    public function testDeleteTranslation()
5102
    {
5103
        $content = $this->createContentVersion2();
5104
5105
        // create multiple versions to exceed archive limit
5106
        for ($i = 0; $i < 5; ++$i) {
5107
            $contentDraft = $this->contentService->createContentDraft($content->contentInfo);
5108
            $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
5109
            $contentDraft = $this->contentService->updateContent(
5110
                $contentDraft->versionInfo,
5111
                $contentUpdateStruct
5112
            );
5113
            $this->contentService->publishVersion($contentDraft->versionInfo);
5114
        }
5115
5116
        $this->contentService->deleteTranslation($content->contentInfo, 'eng-GB');
5117
5118
        $this->assertTranslationDoesNotExist('eng-GB', $content->id);
5119
    }
5120
5121
    /**
5122
     * Test deleting a Translation which is initial for some Version, updates initialLanguageCode
5123
     * with mainLanguageCode (assuming they are different).
5124
     */
5125
    public function testDeleteTranslationUpdatesInitialLanguageCodeVersion()
5126
    {
5127
        $content = $this->createContentVersion2();
5128
        // create another, copied, version
5129
        $contentDraft = $this->contentService->updateContent(
5130
            $this->contentService->createContentDraft($content->contentInfo)->versionInfo,
5131
            $this->contentService->newContentUpdateStruct()
5132
        );
5133
        $publishedContent = $this->contentService->publishVersion($contentDraft->versionInfo);
5134
5135
        // remove first version with only one translation as it is not the subject of this test
5136
        $this->contentService->deleteVersion(
5137
            $this->contentService->loadVersionInfo($publishedContent->contentInfo, 1)
5138
        );
5139
5140
        // sanity check
5141
        self::assertEquals('eng-US', $content->contentInfo->mainLanguageCode);
5142
        self::assertEquals('eng-US', $content->versionInfo->initialLanguageCode);
5143
5144
        // update mainLanguageCode so it is different than initialLanguageCode for Version
5145
        $contentMetadataUpdateStruct = $this->contentService->newContentMetadataUpdateStruct();
5146
        $contentMetadataUpdateStruct->mainLanguageCode = 'eng-GB';
5147
        $content = $this->contentService->updateContentMetadata($publishedContent->contentInfo, $contentMetadataUpdateStruct);
5148
5149
        $this->contentService->deleteTranslation($content->contentInfo, 'eng-US');
5150
5151
        $this->assertTranslationDoesNotExist('eng-US', $content->id);
5152
    }
5153
5154
    /**
5155
     * Test removal of the specific translation properly updates languages of the URL alias.
5156
     *
5157
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslation
5158
     */
5159
    public function testDeleteTranslationUpdatesUrlAlias()
5160
    {
5161
        $urlAliasService = $this->getRepository()->getURLAliasService();
5162
5163
        $content = $this->createContentVersion2();
5164
        $mainLocation = $this->locationService->loadLocation($content->contentInfo->mainLocationId);
5165
5166
        // create custom URL alias for Content main Location
5167
        $urlAliasService->createUrlAlias($mainLocation, '/my-custom-url', 'eng-GB');
5168
5169
        // create secondary Location for Content
5170
        $secondaryLocation = $this->locationService->createLocation(
5171
            $content->contentInfo,
5172
            $this->locationService->newLocationCreateStruct(2)
5173
        );
5174
5175
        // create custom URL alias for Content secondary Location
5176
        $urlAliasService->createUrlAlias($secondaryLocation, '/my-secondary-url', 'eng-GB');
5177
5178
        // delete Translation
5179
        $this->contentService->deleteTranslation($content->contentInfo, 'eng-GB');
5180
5181
        foreach ([$mainLocation, $secondaryLocation] as $location) {
5182
            // check auto-generated URL aliases
5183
            foreach ($urlAliasService->listLocationAliases($location, false) as $alias) {
5184
                self::assertNotContains('eng-GB', $alias->languageCodes);
5185
            }
5186
5187
            // check custom URL aliases
5188
            foreach ($urlAliasService->listLocationAliases($location) as $alias) {
5189
                self::assertNotContains('eng-GB', $alias->languageCodes);
5190
            }
5191
        }
5192
    }
5193
5194
    /**
5195
     * Test removal of a main translation throws BadStateException.
5196
     *
5197
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslation
5198
     */
5199
    public function testDeleteTranslationMainLanguageThrowsBadStateException()
5200
    {
5201
        $content = $this->createContentVersion2();
5202
5203
        // delete first version which has only one translation
5204
        $this->contentService->deleteVersion($this->contentService->loadVersionInfo($content->contentInfo, 1));
5205
5206
        // try to delete main translation
5207
        $this->expectException(BadStateException::class);
5208
        $this->expectExceptionMessage('Specified translation is the main translation of the Content Object');
5209
5210
        $this->contentService->deleteTranslation($content->contentInfo, $content->contentInfo->mainLanguageCode);
5211
    }
5212
5213
    /**
5214
     * Test removal of a Translation is possible when some archived Versions have only this Translation.
5215
     *
5216
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslation
5217
     */
5218
    public function testDeleteTranslationDeletesSingleTranslationVersions()
5219
    {
5220
        // content created by the createContentVersion1 method has eng-US translation only.
5221
        $content = $this->createContentVersion1();
5222
5223
        // create new version and add eng-GB translation
5224
        $contentDraft = $this->contentService->createContentDraft($content->contentInfo);
5225
        $contentUpdateStruct = $this->contentService->newContentUpdateStruct();
5226
        $contentUpdateStruct->setField('name', 'Awesome Board', 'eng-GB');
5227
        $contentDraft = $this->contentService->updateContent($contentDraft->versionInfo, $contentUpdateStruct);
5228
        $publishedContent = $this->contentService->publishVersion($contentDraft->versionInfo);
5229
5230
        // update mainLanguageCode to avoid exception related to that
5231
        $contentMetadataUpdateStruct = $this->contentService->newContentMetadataUpdateStruct();
5232
        $contentMetadataUpdateStruct->mainLanguageCode = 'eng-GB';
5233
5234
        $content = $this->contentService->updateContentMetadata($publishedContent->contentInfo, $contentMetadataUpdateStruct);
5235
5236
        $this->contentService->deleteTranslation($content->contentInfo, 'eng-US');
5237
5238
        $this->assertTranslationDoesNotExist('eng-US', $content->id);
5239
    }
5240
5241
    /**
5242
     * Test removal of the translation by the user who is not allowed to delete a content
5243
     * throws UnauthorizedException.
5244
     *
5245
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslation
5246
     */
5247
    public function testDeleteTranslationThrowsUnauthorizedException()
5248
    {
5249
        $content = $this->createContentVersion2();
5250
5251
        // create user that can read/create/edit but cannot delete content
5252
        $this->createRoleWithPolicies('Writer', [
5253
            ['module' => 'content', 'function' => 'read'],
5254
            ['module' => 'content', 'function' => 'versionread'],
5255
            ['module' => 'content', 'function' => 'create'],
5256
            ['module' => 'content', 'function' => 'edit'],
5257
        ]);
5258
        $writerUser = $this->createCustomUserWithLogin(
5259
            'writer',
5260
            '[email protected]',
5261
            'Writers',
5262
            'Writer'
5263
        );
5264
        $this->permissionResolver->setCurrentUserReference($writerUser);
5265
5266
        $this->expectException(UnauthorizedException::class);
5267
        $this->expectExceptionMessage('User does not have access to \'remove\' \'content\'');
5268
5269
        $this->contentService->deleteTranslation($content->contentInfo, 'eng-GB');
5270
    }
5271
5272
    /**
5273
     * Test removal of a non-existent translation throws InvalidArgumentException.
5274
     *
5275
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslation
5276
     */
5277
    public function testDeleteTranslationThrowsInvalidArgumentException()
5278
    {
5279
        // content created by the createContentVersion1 method has eng-US translation only.
5280
        $content = $this->createContentVersion1();
5281
5282
        $this->expectException(APIInvalidArgumentException::class);
5283
        $this->expectExceptionMessage('Argument \'$languageCode\' is invalid: ger-DE does not exist in the Content item');
5284
5285
        $this->contentService->deleteTranslation($content->contentInfo, 'ger-DE');
5286
    }
5287
5288
    /**
5289
     * Test deleting a Translation from Draft.
5290
     *
5291
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslationFromDraft
5292
     */
5293
    public function testDeleteTranslationFromDraft()
5294
    {
5295
        $languageCode = 'eng-GB';
5296
        $content = $this->createMultipleLanguageContentVersion2();
5297
        $draft = $this->contentService->createContentDraft($content->contentInfo);
5298
        $draft = $this->contentService->deleteTranslationFromDraft($draft->versionInfo, $languageCode);
5299
        $content = $this->contentService->publishVersion($draft->versionInfo);
5300
5301
        $loadedContent = $this->contentService->loadContent($content->id);
5302
        self::assertNotContains($languageCode, $loadedContent->versionInfo->languageCodes);
5303
        self::assertEmpty($loadedContent->getFieldsByLanguage($languageCode));
5304
    }
5305
5306
    /**
5307
     * Get values for multilingual field.
5308
     *
5309
     * @return array
5310
     */
5311
    public function providerForDeleteTranslationFromDraftRemovesUrlAliasOnPublishing()
5312
    {
5313
        return [
5314
            [
5315
                ['eng-US' => 'US Name', 'eng-GB' => 'GB Name'],
5316
            ],
5317
            [
5318
                ['eng-US' => 'Same Name', 'eng-GB' => 'Same Name'],
5319
            ],
5320
        ];
5321
    }
5322
5323
    /**
5324
     * Test deleting a Translation from Draft removes previously stored URL aliases for published Content.
5325
     *
5326
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslationFromDraft
5327
     *
5328
     * @dataProvider providerForDeleteTranslationFromDraftRemovesUrlAliasOnPublishing
5329
     *
5330
     * @param string[] $fieldValues translated field values
5331
     *
5332
     * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
5333
     * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
5334
     * @throws NotFoundException
5335
     * @throws UnauthorizedException
5336
     */
5337
    public function testDeleteTranslationFromDraftRemovesUrlAliasOnPublishing(array $fieldValues)
5338
    {
5339
        $urlAliasService = $this->getRepository()->getURLAliasService();
5340
5341
        // set language code to be removed
5342
        $languageCode = 'eng-GB';
5343
        $draft = $this->createMultilingualContentDraft(
5344
            'folder',
5345
            2,
5346
            'eng-US',
5347
            [
5348
                'name' => [
5349
                    'eng-GB' => $fieldValues['eng-GB'],
5350
                    'eng-US' => $fieldValues['eng-US'],
5351
                ],
5352
            ]
5353
        );
5354
        $content = $this->contentService->publishVersion($draft->versionInfo);
5355
5356
        // create secondary location
5357
        $this->locationService->createLocation(
5358
            $content->contentInfo,
5359
            $this->locationService->newLocationCreateStruct(5)
5360
        );
5361
5362
        // sanity check
5363
        $locations = $this->locationService->loadLocations($content->contentInfo);
5364
        self::assertCount(2, $locations, 'Sanity check: Expected to find 2 Locations');
5365
        foreach ($locations as $location) {
5366
            $urlAliasService->createUrlAlias($location, '/us-custom_' . $location->id, 'eng-US');
5367
            $urlAliasService->createUrlAlias($location, '/gb-custom_' . $location->id, 'eng-GB');
5368
5369
            // check default URL aliases
5370
            $aliases = $urlAliasService->listLocationAliases($location, false, $languageCode);
5371
            self::assertNotEmpty($aliases, 'Sanity check: URL alias for the translation does not exist');
5372
5373
            // check custom URL aliases
5374
            $aliases = $urlAliasService->listLocationAliases($location, true, $languageCode);
5375
            self::assertNotEmpty($aliases, 'Sanity check: Custom URL alias for the translation does not exist');
5376
        }
5377
5378
        // delete translation and publish new version
5379
        $draft = $this->contentService->createContentDraft($content->contentInfo);
5380
        $draft = $this->contentService->deleteTranslationFromDraft($draft->versionInfo, $languageCode);
5381
        $this->contentService->publishVersion($draft->versionInfo);
5382
5383
        // check that aliases does not exist
5384
        foreach ($locations as $location) {
5385
            // check default URL aliases
5386
            $aliases = $urlAliasService->listLocationAliases($location, false, $languageCode);
5387
            self::assertEmpty($aliases, 'URL alias for the deleted translation still exists');
5388
5389
            // check custom URL aliases
5390
            $aliases = $urlAliasService->listLocationAliases($location, true, $languageCode);
5391
            self::assertEmpty($aliases, 'Custom URL alias for the deleted translation still exists');
5392
        }
5393
    }
5394
5395
    /**
5396
     * Test that URL aliases for deleted Translations are properly archived.
5397
     */
5398
    public function testDeleteTranslationFromDraftArchivesUrlAliasOnPublishing()
5399
    {
5400
        $urlAliasService = $this->getRepository()->getURLAliasService();
5401
5402
        $content = $this->contentService->publishVersion(
5403
            $this->createMultilingualContentDraft(
5404
                'folder',
5405
                2,
5406
                'eng-US',
5407
                [
5408
                    'name' => [
5409
                        'eng-GB' => 'BritishEnglishContent',
5410
                        'eng-US' => 'AmericanEnglishContent',
5411
                    ],
5412
                ]
5413
            )->versionInfo
5414
        );
5415
5416
        $unrelatedContent = $this->contentService->publishVersion(
5417
            $this->createMultilingualContentDraft(
5418
                'folder',
5419
                2,
5420
                'eng-US',
5421
                [
5422
                    'name' => [
5423
                        'eng-GB' => 'AnotherBritishContent',
5424
                        'eng-US' => 'AnotherAmericanContent',
5425
                    ],
5426
                ]
5427
            )->versionInfo
5428
        );
5429
5430
        $urlAlias = $urlAliasService->lookup('/BritishEnglishContent');
5431
        self::assertFalse($urlAlias->isHistory);
5432
        self::assertEquals($urlAlias->path, '/BritishEnglishContent');
5433
        self::assertEquals($urlAlias->destination, $content->contentInfo->mainLocationId);
5434
5435
        $draft = $this->contentService->deleteTranslationFromDraft(
5436
            $this->contentService->createContentDraft($content->contentInfo)->versionInfo,
5437
            'eng-GB'
5438
        );
5439
        $content = $this->contentService->publishVersion($draft->versionInfo);
5440
5441
        $urlAlias = $urlAliasService->lookup('/BritishEnglishContent');
5442
        self::assertTrue($urlAlias->isHistory);
5443
        self::assertEquals($urlAlias->path, '/BritishEnglishContent');
5444
        self::assertEquals($urlAlias->destination, $content->contentInfo->mainLocationId);
5445
5446
        $unrelatedUrlAlias = $urlAliasService->lookup('/AnotherBritishContent');
5447
        self::assertFalse($unrelatedUrlAlias->isHistory);
5448
        self::assertEquals($unrelatedUrlAlias->path, '/AnotherBritishContent');
5449
        self::assertEquals($unrelatedUrlAlias->destination, $unrelatedContent->contentInfo->mainLocationId);
5450
    }
5451
5452
    /**
5453
     * Test deleting a Translation from Draft which has single Translation throws BadStateException.
5454
     *
5455
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslationFromDraft
5456
     */
5457
    public function testDeleteTranslationFromDraftThrowsBadStateExceptionOnSingleTranslation()
5458
    {
5459
        // create Content with single Translation
5460
        $publishedContent = $this->contentService->publishVersion(
5461
            $this->createContentDraft(
5462
                'forum',
5463
                2,
5464
                ['name' => 'Eng-US Version name']
5465
            )->versionInfo
5466
        );
5467
5468
        // update mainLanguageCode to avoid exception related to trying to delete main Translation
5469
        $contentMetadataUpdateStruct = $this->contentService->newContentMetadataUpdateStruct();
5470
        $contentMetadataUpdateStruct->mainLanguageCode = 'eng-GB';
5471
        $publishedContent = $this->contentService->updateContentMetadata(
5472
            $publishedContent->contentInfo,
5473
            $contentMetadataUpdateStruct
5474
        );
5475
5476
        // create single Translation Version from the first one
5477
        $draft = $this->contentService->createContentDraft(
5478
            $publishedContent->contentInfo,
5479
            $publishedContent->versionInfo
5480
        );
5481
5482
        $this->expectException(BadStateException::class);
5483
        $this->expectExceptionMessage('Specified Translation is the only one Content Object Version has');
5484
5485
        // attempt to delete Translation
5486
        $this->contentService->deleteTranslationFromDraft($draft->versionInfo, 'eng-US');
5487
    }
5488
5489
    /**
5490
     * Test deleting the Main Translation from Draft throws BadStateException.
5491
     *
5492
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslationFromDraft
5493
     */
5494
    public function testDeleteTranslationFromDraftThrowsBadStateExceptionOnMainTranslation()
5495
    {
5496
        $mainLanguageCode = 'eng-US';
5497
        $draft = $this->createMultilingualContentDraft(
5498
            'forum',
5499
            2,
5500
            $mainLanguageCode,
5501
            [
5502
                'name' => [
5503
                    'eng-US' => 'An awesome eng-US forum',
5504
                    'eng-GB' => 'An awesome eng-GB forum',
5505
                ],
5506
            ]
5507
        );
5508
5509
        $this->expectException(BadStateException::class);
5510
        $this->expectExceptionMessage('Specified Translation is the main Translation of the Content Object');
5511
5512
        $this->contentService->deleteTranslationFromDraft($draft->versionInfo, $mainLanguageCode);
5513
    }
5514
5515
    /**
5516
     * Test deleting the Translation from Published Version throws BadStateException.
5517
     *
5518
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslationFromDraft
5519
     */
5520
    public function testDeleteTranslationFromDraftThrowsBadStateExceptionOnPublishedVersion()
5521
    {
5522
        $languageCode = 'eng-US';
5523
        $content = $this->createMultipleLanguageContentVersion2();
5524
        $draft = $this->contentService->createContentDraft($content->contentInfo);
5525
        $publishedContent = $this->contentService->publishVersion($draft->versionInfo);
5526
5527
        $this->expectException(BadStateException::class);
5528
        $this->expectExceptionMessage('Version is not a draft');
5529
5530
        $this->contentService->deleteTranslationFromDraft($publishedContent->versionInfo, $languageCode);
5531
    }
5532
5533
    /**
5534
     * Test deleting a Translation from Draft throws UnauthorizedException if user cannot edit Content.
5535
     *
5536
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslationFromDraft
5537
     */
5538
    public function testDeleteTranslationFromDraftThrowsUnauthorizedException()
5539
    {
5540
        $languageCode = 'eng-GB';
5541
        $content = $this->createMultipleLanguageContentVersion2();
5542
        $draft = $this->contentService->createContentDraft($content->contentInfo);
5543
5544
        // create user that can read/create/delete but cannot edit or content
5545
        $this->createRoleWithPolicies('Writer', [
5546
            ['module' => 'content', 'function' => 'read'],
5547
            ['module' => 'content', 'function' => 'versionread'],
5548
            ['module' => 'content', 'function' => 'create'],
5549
            ['module' => 'content', 'function' => 'delete'],
5550
        ]);
5551
        $writerUser = $this->createCustomUserWithLogin(
5552
            'user',
5553
            '[email protected]',
5554
            'Writers',
5555
            'Writer'
5556
        );
5557
        $this->permissionResolver->setCurrentUserReference($writerUser);
5558
5559
        $this->expectException(UnauthorizedException::class);
5560
        $this->expectExceptionMessage('User does not have access to \'edit\' \'content\'');
5561
5562
        $this->contentService->deleteTranslationFromDraft($draft->versionInfo, $languageCode);
5563
    }
5564
5565
    /**
5566
     * Test deleting a non-existent Translation from Draft throws InvalidArgumentException.
5567
     *
5568
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteTranslationFromDraft
5569
     */
5570
    public function testDeleteTranslationFromDraftThrowsInvalidArgumentException()
5571
    {
5572
        $languageCode = 'ger-DE';
5573
        $content = $this->createMultipleLanguageContentVersion2();
5574
        $draft = $this->contentService->createContentDraft($content->contentInfo);
5575
        $this->expectException(APIInvalidArgumentException::class);
5576
        $this->expectExceptionMessageRegExp('/The Version \(ContentId=\d+, VersionNo=\d+\) is not translated into ger-DE/');
5577
        $this->contentService->deleteTranslationFromDraft($draft->versionInfo, $languageCode);
5578
    }
5579
5580
    /**
5581
     * Test loading list of Content items.
5582
     */
5583
    public function testLoadContentListByContentInfo()
5584
    {
5585
        $allLocationsCount = $this->locationService->getAllLocationsCount();
5586
        $contentInfoList = array_map(
5587
            function (Location $location) {
5588
                return $location->contentInfo;
5589
            },
5590
            $this->locationService->loadAllLocations(0, $allLocationsCount)
5591
        );
5592
5593
        $contentList = $this->contentService->loadContentListByContentInfo($contentInfoList);
5594
        self::assertCount(count($contentInfoList), $contentList);
5595
        foreach ($contentList as $content) {
5596
            try {
5597
                $loadedContent = $this->contentService->loadContent($content->id);
5598
                self::assertEquals($loadedContent, $content, "Failed to properly bulk-load Content {$content->id}");
5599
            } catch (NotFoundException $e) {
5600
                self::fail("Failed to load Content {$content->id}: {$e->getMessage()}");
5601
            } catch (UnauthorizedException $e) {
5602
                self::fail("Failed to load Content {$content->id}: {$e->getMessage()}");
5603
            }
5604
        }
5605
    }
5606
5607
    /**
5608
     * Test loading content versions after removing exactly two drafts.
5609
     *
5610
     * @see https://jira.ez.no/browse/EZP-30271
5611
     *
5612
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteVersion
5613
     */
5614
    public function testLoadVersionsAfterDeletingTwoDrafts()
5615
    {
5616
        $content = $this->createFolder(['eng-GB' => 'Foo'], 2);
5617
5618
        // First update and publish
5619
        $modifiedContent = $this->updateFolder($content, ['eng-GB' => 'Foo1']);
5620
        $content = $this->contentService->publishVersion($modifiedContent->versionInfo);
5621
5622
        // Second update and publish
5623
        $modifiedContent = $this->updateFolder($content, ['eng-GB' => 'Foo2']);
5624
        $content = $this->contentService->publishVersion($modifiedContent->versionInfo);
5625
5626
        // Create drafts
5627
        $this->updateFolder($content, ['eng-GB' => 'Foo3']);
5628
        $this->updateFolder($content, ['eng-GB' => 'Foo4']);
5629
5630
        $versions = $this->contentService->loadVersions($content->contentInfo);
5631
5632
        foreach ($versions as $key => $version) {
5633
            if ($version->isDraft()) {
5634
                $this->contentService->deleteVersion($version);
5635
                unset($versions[$key]);
5636
            }
5637
        }
5638
5639
        $this->assertEquals($versions, $this->contentService->loadVersions($content->contentInfo));
5640
    }
5641
5642
    /**
5643
     * Tests loading list of content versions of status draft.
5644
     */
5645
    public function testLoadVersionsOfStatusDraft()
5646
    {
5647
        $content = $this->createContentVersion1();
5648
5649
        $this->contentService->createContentDraft($content->contentInfo);
5650
        $this->contentService->createContentDraft($content->contentInfo);
5651
        $this->contentService->createContentDraft($content->contentInfo);
5652
5653
        $versions = $this->contentService->loadVersions($content->contentInfo, VersionInfo::STATUS_DRAFT);
5654
5655
        $this->assertSame(\count($versions), 3);
5656
    }
5657
5658
    /**
5659
     * Tests loading list of content versions of status archived.
5660
     */
5661
    public function testLoadVersionsOfStatusArchived()
5662
    {
5663
        $content = $this->createContentVersion1();
5664
5665
        $draft1 = $this->contentService->createContentDraft($content->contentInfo);
5666
        $this->contentService->publishVersion($draft1->versionInfo);
5667
5668
        $draft2 = $this->contentService->createContentDraft($content->contentInfo);
5669
        $this->contentService->publishVersion($draft2->versionInfo);
5670
5671
        $versions = $this->contentService->loadVersions($content->contentInfo, VersionInfo::STATUS_ARCHIVED);
5672
5673
        $this->assertSame(\count($versions), 2);
5674
    }
5675
5676
    /**
5677
     * Asserts that all aliases defined in $expectedAliasProperties with the
5678
     * given properties are available in $actualAliases and not more.
5679
     *
5680
     * @param array $expectedAliasProperties
5681
     * @param array $actualAliases
5682
     */
5683
    private function assertAliasesCorrect(array $expectedAliasProperties, array $actualAliases)
5684
    {
5685
        foreach ($actualAliases as $actualAlias) {
5686
            if (!isset($expectedAliasProperties[$actualAlias->path])) {
5687
                $this->fail(
5688
                    sprintf(
5689
                        'Alias with path "%s" in languages "%s" not expected.',
5690
                        $actualAlias->path,
5691
                        implode(', ', $actualAlias->languageCodes)
5692
                    )
5693
                );
5694
            }
5695
5696
            foreach ($expectedAliasProperties[$actualAlias->path] as $propertyName => $propertyValue) {
5697
                $this->assertEquals(
5698
                    $propertyValue,
5699
                    $actualAlias->$propertyName,
5700
                    sprintf(
5701
                        'Property $%s incorrect on alias with path "%s" in languages "%s".',
5702
                        $propertyName,
5703
                        $actualAlias->path,
5704
                        implode(', ', $actualAlias->languageCodes)
5705
                    )
5706
                );
5707
            }
5708
5709
            unset($expectedAliasProperties[$actualAlias->path]);
5710
        }
5711
5712
        if (!empty($expectedAliasProperties)) {
5713
            $this->fail(
5714
                sprintf(
5715
                    'Missing expected aliases with paths "%s".',
5716
                    implode('", "', array_keys($expectedAliasProperties))
5717
                )
5718
            );
5719
        }
5720
    }
5721
5722
    /**
5723
     * Asserts that the given fields are equal to the default fields fixture.
5724
     *
5725
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $fields
5726
     */
5727
    private function assertAllFieldsEquals(array $fields)
5728
    {
5729
        $actual = $this->normalizeFields($fields);
5730
        $expected = $this->normalizeFields($this->createFieldsFixture());
5731
5732
        $this->assertEquals($expected, $actual);
5733
    }
5734
5735
    /**
5736
     * Asserts that the given fields are equal to a language filtered set of the
5737
     * default fields fixture.
5738
     *
5739
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $fields
5740
     * @param string $languageCode
5741
     */
5742
    private function assertLocaleFieldsEquals(array $fields, $languageCode)
5743
    {
5744
        $actual = $this->normalizeFields($fields);
5745
5746
        $expected = [];
5747
        foreach ($this->normalizeFields($this->createFieldsFixture()) as $field) {
5748
            if ($field->languageCode !== $languageCode) {
5749
                continue;
5750
            }
5751
            $expected[] = $field;
5752
        }
5753
5754
        $this->assertEquals($expected, $actual);
5755
    }
5756
5757
    /**
5758
     * This method normalizes a set of fields and returns a normalized set.
5759
     *
5760
     * Normalization means it resets the storage specific field id to zero and
5761
     * it sorts the field by their identifier and their language code. In
5762
     * addition, the field value is removed, since this one depends on the
5763
     * specific FieldType, which is tested in a dedicated integration test.
5764
     *
5765
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $fields
5766
     *
5767
     * @return \eZ\Publish\API\Repository\Values\Content\Field[]
5768
     */
5769
    private function normalizeFields(array $fields)
5770
    {
5771
        $normalized = [];
5772
        foreach ($fields as $field) {
5773
            $normalized[] = new Field(
5774
                [
5775
                    'id' => 0,
5776
                    'value' => ($field->value !== null ? true : null),
5777
                    'languageCode' => $field->languageCode,
5778
                    'fieldDefIdentifier' => $field->fieldDefIdentifier,
5779
                    'fieldTypeIdentifier' => $field->fieldTypeIdentifier,
5780
                ]
5781
            );
5782
        }
5783
        usort(
5784
            $normalized,
5785 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...
5786
                if (0 === ($return = strcasecmp($field1->fieldDefIdentifier, $field2->fieldDefIdentifier))) {
5787
                    return strcasecmp($field1->languageCode, $field2->languageCode);
5788
                }
5789
5790
                return $return;
5791
            }
5792
        );
5793
5794
        return $normalized;
5795
    }
5796
5797
    /**
5798
     * Returns a filtered set of the default fields fixture.
5799
     *
5800
     * @param string $languageCode
5801
     *
5802
     * @return \eZ\Publish\API\Repository\Values\Content\Field[]
5803
     */
5804
    private function createLocaleFieldsFixture($languageCode)
5805
    {
5806
        $fields = [];
5807
        foreach ($this->createFieldsFixture() as $field) {
5808
            if (null === $field->languageCode || $languageCode === $field->languageCode) {
5809
                $fields[] = $field;
5810
            }
5811
        }
5812
5813
        return $fields;
5814
    }
5815
5816
    /**
5817
     * Asserts that given Content has default ContentStates.
5818
     *
5819
     * @param ContentInfo $contentInfo
5820
     */
5821 View Code Duplication
    private function assertDefaultContentStates(ContentInfo $contentInfo)
5822
    {
5823
        $objectStateService = $this->getRepository()->getObjectStateService();
5824
5825
        $objectStateGroups = $objectStateService->loadObjectStateGroups();
5826
5827
        foreach ($objectStateGroups as $objectStateGroup) {
5828
            $contentState = $objectStateService->getContentState($contentInfo, $objectStateGroup);
5829
            foreach ($objectStateService->loadObjectStates($objectStateGroup) as $objectState) {
5830
                // Only check the first object state which is the default one.
5831
                $this->assertEquals(
5832
                    $objectState,
5833
                    $contentState
5834
                );
5835
                break;
5836
            }
5837
        }
5838
    }
5839
5840
    /**
5841
     * Assert that given Content has no references to a translation specified by the $languageCode.
5842
     *
5843
     * @param string $languageCode
5844
     * @param int $contentId
5845
     */
5846
    private function assertTranslationDoesNotExist($languageCode, $contentId)
5847
    {
5848
        $content = $this->contentService->loadContent($contentId);
5849
5850
        foreach ($content->fields as $fieldIdentifier => $field) {
5851
            /** @var array $field */
5852
            self::assertArrayNotHasKey($languageCode, $field);
5853
            self::assertNotEquals($languageCode, $content->contentInfo->mainLanguageCode);
5854
            self::assertArrayNotHasKey($languageCode, $content->versionInfo->getNames());
5855
            self::assertNotEquals($languageCode, $content->versionInfo->initialLanguageCode);
5856
            self::assertNotContains($languageCode, $content->versionInfo->languageCodes);
5857
        }
5858
        foreach ($this->contentService->loadVersions($content->contentInfo) as $versionInfo) {
5859
            self::assertArrayNotHasKey($languageCode, $versionInfo->getNames());
5860
            self::assertNotEquals($languageCode, $versionInfo->contentInfo->mainLanguageCode);
5861
            self::assertNotEquals($languageCode, $versionInfo->initialLanguageCode);
5862
            self::assertNotContains($languageCode, $versionInfo->languageCodes);
5863
        }
5864
    }
5865
5866
    /**
5867
     * Returns the default fixture of fields used in most tests.
5868
     *
5869
     * @return \eZ\Publish\API\Repository\Values\Content\Field[]
5870
     */
5871
    private function createFieldsFixture()
5872
    {
5873
        return [
5874
            new Field(
5875
                [
5876
                    'id' => 0,
5877
                    'value' => 'Foo',
5878
                    'languageCode' => 'eng-US',
5879
                    'fieldDefIdentifier' => 'description',
5880
                    'fieldTypeIdentifier' => 'ezrichtext',
5881
                ]
5882
            ),
5883
            new Field(
5884
                [
5885
                    'id' => 0,
5886
                    'value' => 'Bar',
5887
                    'languageCode' => 'eng-GB',
5888
                    'fieldDefIdentifier' => 'description',
5889
                    'fieldTypeIdentifier' => 'ezrichtext',
5890
                ]
5891
            ),
5892
            new Field(
5893
                [
5894
                    'id' => 0,
5895
                    'value' => 'An awesome multi-lang forum²',
5896
                    'languageCode' => 'eng-US',
5897
                    'fieldDefIdentifier' => 'name',
5898
                    'fieldTypeIdentifier' => 'ezstring',
5899
                ]
5900
            ),
5901
            new Field(
5902
                [
5903
                    'id' => 0,
5904
                    'value' => 'An awesome multi-lang forum²³',
5905
                    'languageCode' => 'eng-GB',
5906
                    'fieldDefIdentifier' => 'name',
5907
                    'fieldTypeIdentifier' => 'ezstring',
5908
                ]
5909
            ),
5910
        ];
5911
    }
5912
5913
    /**
5914
     * Gets expected property values for the "Media" ContentInfo ValueObject.
5915
     *
5916
     * @return array
5917
     */
5918 View Code Duplication
    private function getExpectedMediaContentInfoProperties()
5919
    {
5920
        return [
5921
            'id' => 41,
5922
            'contentTypeId' => 1,
5923
            'name' => 'Media',
5924
            'sectionId' => 3,
5925
            'currentVersionNo' => 1,
5926
            'published' => true,
5927
            'ownerId' => 14,
5928
            'modificationDate' => $this->createDateTime(1060695457),
5929
            'publishedDate' => $this->createDateTime(1060695457),
5930
            'alwaysAvailable' => 1,
5931
            'remoteId' => 'a6e35cbcb7cd6ae4b691f3eee30cd262',
5932
            'mainLanguageCode' => 'eng-US',
5933
            'mainLocationId' => 43,
5934
            'status' => ContentInfo::STATUS_PUBLISHED,
5935
        ];
5936
    }
5937
5938
    /**
5939
     * @covers \eZ\Publish\API\Repository\ContentService::hideContent
5940
     *
5941
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
5942
     * @throws NotFoundException
5943
     * @throws UnauthorizedException
5944
     */
5945
    public function testHideContent(): void
5946
    {
5947
        $contentTypeService = $this->getRepository()->getContentTypeService();
5948
5949
        $locationCreateStructs = array_map(
5950
            function (Location $parentLocation) {
5951
                return $this->locationService->newLocationCreateStruct($parentLocation->id);
5952
            },
5953
            $this->createParentLocationsForHideReveal(2)
5954
        );
5955
5956
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
5957
5958
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
5959
        $contentCreate->setField('name', 'Folder to hide');
5960
5961
        $content = $this->contentService->createContent(
5962
            $contentCreate,
5963
            $locationCreateStructs
5964
        );
5965
5966
        $publishedContent = $this->contentService->publishVersion($content->versionInfo);
5967
        $locations = $this->locationService->loadLocations($publishedContent->contentInfo);
5968
5969
        // Sanity check
5970
        $this->assertCount(3, $locations);
5971
        $this->assertCount(0, $this->filterHiddenLocations($locations));
5972
5973
        /* BEGIN: Use Case */
5974
        $this->contentService->hideContent($publishedContent->contentInfo);
5975
        /* END: Use Case */
5976
5977
        $locations = $this->locationService->loadLocations($publishedContent->contentInfo);
5978
        $this->assertCount(3, $locations);
5979
        $this->assertCount(3, $this->filterHiddenLocations($locations));
5980
    }
5981
5982
    /**
5983
     * @covers \eZ\Publish\API\Repository\ContentService::revealContent
5984
     *
5985
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
5986
     * @throws NotFoundException
5987
     * @throws UnauthorizedException
5988
     */
5989
    public function testRevealContent()
5990
    {
5991
        $contentTypeService = $this->getRepository()->getContentTypeService();
5992
5993
        $locationCreateStructs = array_map(
5994
            function (Location $parentLocation) {
5995
                return $this->locationService->newLocationCreateStruct($parentLocation->id);
5996
            },
5997
            $this->createParentLocationsForHideReveal(2)
5998
        );
5999
6000
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
6001
6002
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
6003
        $contentCreate->setField('name', 'Folder to hide');
6004
6005
        $locationCreateStructs[0]->hidden = true;
6006
6007
        $content = $this->contentService->createContent(
6008
            $contentCreate,
6009
            $locationCreateStructs
6010
        );
6011
6012
        $publishedContent = $this->contentService->publishVersion($content->versionInfo);
6013
        $locations = $this->locationService->loadLocations($publishedContent->contentInfo);
6014
6015
        // Sanity check
6016
        $hiddenLocations = $this->filterHiddenLocations($locations);
6017
        $this->assertCount(3, $locations);
6018
        $this->assertCount(1, $hiddenLocations);
6019
6020
        // BEGIN: Use Case
6021
        $this->contentService->hideContent($publishedContent->contentInfo);
6022
        $this->assertCount(
6023
            3,
6024
            $this->filterHiddenLocations(
6025
                $this->locationService->loadLocations($publishedContent->contentInfo)
6026
            )
6027
        );
6028
6029
        $this->contentService->revealContent($publishedContent->contentInfo);
6030
        // END: Use Case
6031
6032
        $locations = $this->locationService->loadLocations($publishedContent->contentInfo);
6033
        $hiddenLocationsAfterReveal = $this->filterHiddenLocations($locations);
6034
        $this->assertCount(3, $locations);
6035
        $this->assertCount(1, $hiddenLocationsAfterReveal);
6036
        $this->assertEquals($hiddenLocations, $hiddenLocationsAfterReveal);
6037
    }
6038
6039
    /**
6040
     * @depends testRevealContent
6041
     */
6042
    public function testRevealContentWithHiddenParent()
6043
    {
6044
        $contentTypeService = $this->getRepository()->getContentTypeService();
6045
6046
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
6047
6048
        $contentNames = [
6049
            'Parent Content',
6050
            'Child (Nesting 1)',
6051
            'Child (Nesting 2)',
6052
            'Child (Nesting 3)',
6053
            'Child (Nesting 4)',
6054
        ];
6055
6056
        $parentLocation = $this->locationService->newLocationCreateStruct(
6057
            $this->generateId('location', 2)
6058
        );
6059
6060
        /** @var Content[] $contents */
6061
        $contents = [];
6062
6063 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...
6064
            $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
6065
            $contentCreate->setField('name', $contentName);
6066
6067
            $content = $this->contentService->createContent($contentCreate, [$parentLocation]);
6068
            $contents[] = $publishedContent = $this->contentService->publishVersion($content->versionInfo);
6069
6070
            $parentLocation = $this->locationService->newLocationCreateStruct(
6071
                $this->generateId('location', $publishedContent->contentInfo->mainLocationId)
6072
            );
6073
        }
6074
6075
        $this->contentService->hideContent($contents[0]->contentInfo);
6076
        $this->contentService->hideContent($contents[2]->contentInfo);
6077
        $this->contentService->revealContent($contents[2]->contentInfo);
6078
6079
        $parentContent = $this->contentService->loadContent($contents[0]->id);
6080
        $parentLocation = $this->locationService->loadLocation($parentContent->contentInfo->mainLocationId);
6081
        $parentSublocations = $this->locationService->loadLocationList([
6082
            $contents[1]->contentInfo->mainLocationId,
6083
            $contents[2]->contentInfo->mainLocationId,
6084
            $contents[3]->contentInfo->mainLocationId,
6085
            $contents[4]->contentInfo->mainLocationId,
6086
        ]);
6087
6088
        // Parent remains invisible
6089
        self::assertTrue($parentLocation->invisible);
6090
6091
        // All parent sublocations remain invisible as well
6092
        foreach ($parentSublocations as $parentSublocation) {
6093
            self::assertTrue($parentSublocation->invisible);
6094
        }
6095
    }
6096
6097
    /**
6098
     * @depends testRevealContent
6099
     */
6100
    public function testRevealContentWithHiddenChildren()
6101
    {
6102
        $contentTypeService = $this->getRepository()->getContentTypeService();
6103
6104
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
6105
6106
        $contentNames = [
6107
            'Parent Content',
6108
            'Child (Nesting 1)',
6109
            'Child (Nesting 2)',
6110
            'Child (Nesting 3)',
6111
            'Child (Nesting 4)',
6112
        ];
6113
6114
        $parentLocation = $this->locationService->newLocationCreateStruct(
6115
            $this->generateId('location', 2)
6116
        );
6117
6118
        /** @var Content[] $contents */
6119
        $contents = [];
6120
6121 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...
6122
            $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
6123
            $contentCreate->setField('name', $contentName);
6124
6125
            $content = $this->contentService->createContent($contentCreate, [$parentLocation]);
6126
            $contents[] = $publishedContent = $this->contentService->publishVersion($content->versionInfo);
6127
6128
            $parentLocation = $this->locationService->newLocationCreateStruct(
6129
                $this->generateId('location', $publishedContent->contentInfo->mainLocationId)
6130
            );
6131
        }
6132
6133
        $this->contentService->hideContent($contents[0]->contentInfo);
6134
        $this->contentService->hideContent($contents[2]->contentInfo);
6135
        $this->contentService->revealContent($contents[0]->contentInfo);
6136
6137
        $directChildContent = $this->contentService->loadContent($contents[1]->id);
6138
        $directChildLocation = $this->locationService->loadLocation($directChildContent->contentInfo->mainLocationId);
6139
6140
        $childContent = $this->contentService->loadContent($contents[2]->id);
6141
        $childLocation = $this->locationService->loadLocation($childContent->contentInfo->mainLocationId);
6142
        $childSublocations = $this->locationService->loadLocationList([
6143
            $contents[3]->contentInfo->mainLocationId,
6144
            $contents[4]->contentInfo->mainLocationId,
6145
        ]);
6146
6147
        // Direct child content is not hidden
6148
        self::assertFalse($directChildContent->contentInfo->isHidden);
6149
6150
        // Direct child content location is still invisible
6151
        self::assertFalse($directChildLocation->invisible);
6152
6153
        // Child content is still hidden
6154
        self::assertTrue($childContent->contentInfo->isHidden);
6155
6156
        // Child content location is still invisible
6157
        self::assertTrue($childLocation->invisible);
6158
6159
        // All childs sublocations remain invisible as well
6160
        foreach ($childSublocations as $childSublocation) {
6161
            self::assertTrue($childSublocation->invisible);
6162
        }
6163
    }
6164
6165
    public function testHideContentWithParentLocation()
6166
    {
6167
        $contentTypeService = $this->getRepository()->getContentTypeService();
6168
6169
        $contentType = $contentTypeService->loadContentTypeByIdentifier('folder');
6170
6171
        $contentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
6172
        $contentCreate->setField('name', 'Parent');
6173
6174
        $content = $this->contentService->createContent(
6175
            $contentCreate,
6176
            [
6177
                $this->locationService->newLocationCreateStruct(
6178
                    $this->generateId('location', 2)
6179
                ),
6180
            ]
6181
        );
6182
6183
        $publishedContent = $this->contentService->publishVersion($content->versionInfo);
6184
6185
        /* BEGIN: Use Case */
6186
        $this->contentService->hideContent($publishedContent->contentInfo);
6187
        /* END: Use Case */
6188
6189
        $locations = $this->locationService->loadLocations($publishedContent->contentInfo);
6190
6191
        $childContentCreate = $this->contentService->newContentCreateStruct($contentType, 'eng-US');
6192
        $childContentCreate->setField('name', 'Child');
6193
6194
        $childContent = $this->contentService->createContent(
6195
            $childContentCreate,
6196
            [
6197
                $this->locationService->newLocationCreateStruct(
6198
                    $locations[0]->id
6199
                ),
6200
            ]
6201
        );
6202
6203
        $publishedChildContent = $this->contentService->publishVersion($childContent->versionInfo);
6204
6205
        $childLocations = $this->locationService->loadLocations($publishedChildContent->contentInfo);
6206
6207
        $this->assertTrue($locations[0]->hidden);
6208
        $this->assertTrue($locations[0]->invisible);
6209
6210
        $this->assertFalse($childLocations[0]->hidden);
6211
        $this->assertTrue($childLocations[0]->invisible);
6212
    }
6213
6214
    public function testChangeContentName()
6215
    {
6216
        $contentDraft = $this->createContentDraft(
6217
            'folder',
6218
            $this->generateId('location', 2),
6219
            [
6220
                'name' => 'Marco',
6221
            ]
6222
        );
6223
6224
        $publishedContent = $this->contentService->publishVersion($contentDraft->versionInfo);
6225
        $contentMetadataUpdateStruct = new ContentMetadataUpdateStruct([
6226
            'name' => 'Polo',
6227
        ]);
6228
        $this->contentService->updateContentMetadata($publishedContent->contentInfo, $contentMetadataUpdateStruct);
6229
6230
        $updatedContent = $this->contentService->loadContent($publishedContent->id);
6231
6232
        $this->assertEquals('Marco', $publishedContent->contentInfo->name);
6233
        $this->assertEquals('Polo', $updatedContent->contentInfo->name);
6234
    }
6235
6236
    public function testCopyTranslationsFromPublishedToDraft()
6237
    {
6238
        $contentDraft = $this->createContentDraft(
6239
            'folder',
6240
            $this->generateId('location', 2),
6241
            [
6242
                'name' => 'Folder US',
6243
            ]
6244
        );
6245
6246
        $publishedContent = $this->contentService->publishVersion($contentDraft->versionInfo);
6247
6248
        $deDraft = $this->contentService->createContentDraft($publishedContent->contentInfo);
6249
6250
        $contentUpdateStruct = new ContentUpdateStruct([
6251
            'initialLanguageCode' => 'ger-DE',
6252
            'fields' => $contentDraft->getFields(),
6253
        ]);
6254
6255
        $contentUpdateStruct->setField('name', 'Folder GER', 'ger-DE');
6256
6257
        $deContent = $this->contentService->updateContent($deDraft->versionInfo, $contentUpdateStruct);
6258
6259
        $updatedContent = $this->contentService->loadContent($deContent->id, null, $deContent->versionInfo->versionNo);
6260
        $this->assertEquals(
6261
            [
6262
                'eng-US' => 'Folder US',
6263
                'ger-DE' => 'Folder GER',
6264
            ],
6265
            $updatedContent->fields['name']
6266
        );
6267
6268
        $gbDraft = $this->contentService->createContentDraft($publishedContent->contentInfo);
6269
6270
        $contentUpdateStruct = new ContentUpdateStruct([
6271
            'initialLanguageCode' => 'eng-GB',
6272
            'fields' => $contentDraft->getFields(),
6273
        ]);
6274
6275
        $contentUpdateStruct->setField('name', 'Folder GB', 'eng-GB');
6276
6277
        $gbContent = $this->contentService->updateContent($gbDraft->versionInfo, $contentUpdateStruct);
6278
        $this->contentService->publishVersion($gbDraft->versionInfo);
6279
        $updatedContent = $this->contentService->loadContent($gbContent->id, null, $gbContent->versionInfo->versionNo);
6280
        $this->assertEquals(
6281
            [
6282
                'eng-US' => 'Folder US',
6283
                'eng-GB' => 'Folder GB',
6284
            ],
6285
            $updatedContent->fields['name']
6286
        );
6287
6288
        $dePublished = $this->contentService->publishVersion($deDraft->versionInfo);
6289
        $this->assertEquals(
6290
            [
6291
                'eng-US' => 'Folder US',
6292
                'ger-DE' => 'Folder GER',
6293
                'eng-GB' => 'Folder GB',
6294
            ],
6295
            $dePublished->fields['name']
6296
        );
6297
    }
6298
6299
    /**
6300
     * Create structure of parent folders with Locations to be used for Content hide/reveal tests.
6301
     *
6302
     * @param int $parentLocationId
6303
     *
6304
     * @return \eZ\Publish\API\Repository\Values\Content\Location[] A list of Locations aimed to be parents
6305
     *
6306
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
6307
     * @throws NotFoundException
6308
     * @throws UnauthorizedException
6309
     */
6310
    private function createParentLocationsForHideReveal(int $parentLocationId): array
6311
    {
6312
        $parentFoldersLocationsIds = [
6313
            $this->createFolder(['eng-US' => 'P1'], $parentLocationId)->contentInfo->mainLocationId,
6314
            $this->createFolder(['eng-US' => 'P2'], $parentLocationId)->contentInfo->mainLocationId,
6315
            $this->createFolder(['eng-US' => 'P3'], $parentLocationId)->contentInfo->mainLocationId,
6316
        ];
6317
6318
        return array_values($this->locationService->loadLocationList($parentFoldersLocationsIds));
6319
    }
6320
6321
    /**
6322
     * Filter Locations list by hidden only.
6323
     *
6324
     * @param \eZ\Publish\API\Repository\Values\Content\Location[] $locations
6325
     *
6326
     * @return array
6327
     */
6328
    private function filterHiddenLocations(array $locations): array
6329
    {
6330
        return array_values(
6331
            array_filter(
6332
                $locations,
6333
                function (Location $location) {
6334
                    return $location->hidden;
6335
                }
6336
            )
6337
        );
6338
    }
6339
6340
    public function testPublishVersionWithSelectedLanguages()
6341
    {
6342
        $publishedContent = $this->createFolder(
6343
            [
6344
                'eng-US' => 'Published US',
6345
                'ger-DE' => 'Published DE',
6346
            ],
6347
            $this->generateId('location', 2)
6348
        );
6349
6350
        $draft = $this->contentService->createContentDraft($publishedContent->contentInfo);
6351
        $contentUpdateStruct = new ContentUpdateStruct([
6352
            'initialLanguageCode' => 'eng-US',
6353
        ]);
6354
        $contentUpdateStruct->setField('name', 'Draft 1 US', 'eng-US');
6355
        $contentUpdateStruct->setField('name', 'Draft 1 DE', 'ger-DE');
6356
6357
        $this->contentService->updateContent($draft->versionInfo, $contentUpdateStruct);
6358
6359
        $this->contentService->publishVersion($draft->versionInfo, ['ger-DE']);
6360
        $content = $this->contentService->loadContent($draft->contentInfo->id);
6361
        $this->assertEquals(
6362
            [
6363
                'eng-US' => 'Published US',
6364
                'ger-DE' => 'Draft 1 DE',
6365
            ],
6366
            $content->fields['name']
6367
        );
6368
    }
6369
6370
    public function testCreateContentWithRomanianSpecialCharsInTitle()
6371
    {
6372
        $baseName = 'ȘșțȚdfdf';
6373
        $expectedPath = '/SstTdfdf';
6374
6375
        $this->createFolder(['eng-US' => $baseName], 2);
6376
6377
        $urlAliasService = $this->getRepository()->getURLAliasService();
6378
        $urlAlias = $urlAliasService->lookup($expectedPath);
6379
        $this->assertSame($expectedPath, $urlAlias->path);
6380
    }
6381
6382
    /**
6383
     * @param int $amountOfDrafts
6384
     *
6385
     * @throws UnauthorizedException
6386
     */
6387
    private function createContentDrafts(int $amountOfDrafts): void
6388
    {
6389
        if (0 >= $amountOfDrafts) {
6390
            throw new InvalidArgumentException('$amountOfDrafts', 'Must be greater then 0');
6391
        }
6392
6393
        $publishedContent = $this->createContentVersion1();
6394
6395
        $i = 1;
6396
        while ($i <= $amountOfDrafts) {
6397
            $this->contentService->createContentDraft($publishedContent->contentInfo);
6398
            ++$i;
6399
        }
6400
    }
6401
6402
    /**
6403
     * @param array $limitationValues
6404
     *
6405
     * @return \eZ\Publish\API\Repository\Values\User\User
6406
     *
6407
     * @throws \eZ\Publish\API\Repository\Exceptions\ForbiddenException
6408
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
6409
     * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
6410
     */
6411
    private function createUserWithVersionreadLimitations(array $limitationValues = [2]): User
6412
    {
6413
        $limitations = [
6414
            new LocationLimitation(['limitationValues' => $limitationValues]),
6415
        ];
6416
6417
        return $this->createUserWithPolicies(
6418
            'user',
6419
            [
6420
                ['module' => 'content', 'function' => 'versionread', 'limitations' => $limitations],
6421
                ['module' => 'content', 'function' => 'create'],
6422
                ['module' => 'content', 'function' => 'read'],
6423
                ['module' => 'content', 'function' => 'edit'],
6424
            ]
6425
        );
6426
    }
6427
}
6428