Completed
Push — EZP-30427 ( 34539c )
by
unknown
22:09
created

ContentServiceTest::testCopyContent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 54

Duplication

Lines 54
Ratio 100 %

Importance

Changes 0
Metric Value
dl 54
loc 54
c 0
b 0
f 0
cc 1
nc 1
nop 0
rs 9.0036

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

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