Completed
Push — 6.13 ( b26b7e...09bc2f )
by André
25:42 queued 08:54
created

testLoadVersionInfoByIdAndVersionNumber()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 41
rs 9.264
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File contains: eZ\Publish\Core\Repository\Tests\Service\Mock\ContentTest class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\Core\Repository\Tests\Service\Mock;
10
11
use eZ\Publish\API\Repository\Values\Content\Language;
12
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
13
use eZ\Publish\Core\Base\Exceptions\ContentFieldValidationException;
14
use eZ\Publish\Core\Base\Exceptions\ContentValidationException;
15
use eZ\Publish\Core\Repository\Tests\Service\Mock\Base as BaseServiceMockTest;
16
use eZ\Publish\Core\Repository\ContentService;
17
use eZ\Publish\Core\Repository\Values\Content\Location;
18
use eZ\Publish\Core\Repository\Values\Content\Content;
19
use eZ\Publish\Core\Repository\Values\Content\ContentCreateStruct;
20
use eZ\Publish\Core\Repository\Values\Content\ContentUpdateStruct;
21
use eZ\Publish\API\Repository\Values\Content\Content as APIContent;
22
use eZ\Publish\Core\Repository\Values\Content\VersionInfo;
23
use eZ\Publish\API\Repository\Values\Content\Field;
24
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
25
use eZ\Publish\API\Repository\Values\Content\VersionInfo as APIVersionInfo;
26
use eZ\Publish\Core\Repository\Values\ContentType\ContentType;
27
use eZ\Publish\Core\Repository\Values\ContentType\FieldDefinition;
28
use eZ\Publish\SPI\Persistence\Content\Location as SPILocation;
29
use eZ\Publish\SPI\Persistence\Content as SPIContent;
30
use eZ\Publish\SPI\Persistence\Content\UpdateStruct as SPIContentUpdateStruct;
31
use eZ\Publish\SPI\Persistence\Content\CreateStruct as SPIContentCreateStruct;
32
use eZ\Publish\SPI\Persistence\Content\Field as SPIField;
33
use eZ\Publish\SPI\Persistence\Content\ObjectState\Group as SPIObjectStateGroup;
34
use eZ\Publish\SPI\Persistence\Content\ObjectState as SPIObjectState;
35
use eZ\Publish\SPI\Persistence\Content\VersionInfo as SPIVersionInfo;
36
use eZ\Publish\SPI\Persistence\Content\ContentInfo as SPIContentInfo;
37
use eZ\Publish\SPI\Persistence\Content\MetadataUpdateStruct as SPIMetadataUpdateStruct;
38
use eZ\Publish\Core\Base\Exceptions\NotFoundException;
39
use eZ\Publish\Core\Repository\Values\User\UserReference;
40
use Exception;
41
42
/**
43
 * Mock test case for Content service.
44
 */
45
class ContentTest extends BaseServiceMockTest
46
{
47
    /**
48
     * Represents empty Field Value.
49
     */
50
    const EMPTY_FIELD_VALUE = 'empty';
51
52
    /**
53
     * Test for the __construct() method.
54
     *
55
     * @covers \eZ\Publish\Core\Repository\ContentService::__construct
56
     */
57
    public function testConstructor()
58
    {
59
        $repositoryMock = $this->getRepositoryMock();
60
        /** @var \eZ\Publish\SPI\Persistence\Handler $persistenceHandlerMock */
61
        $persistenceHandlerMock = $this->getPersistenceMockHandler('Handler');
62
        $domainMapperMock = $this->getDomainMapperMock();
63
        $relationProcessorMock = $this->getRelationProcessorMock();
64
        $nameSchemaServiceMock = $this->getNameSchemaServiceMock();
65
        $fieldTypeRegistryMock = $this->getFieldTypeRegistryMock();
66
        $settings = ['default_version_archive_limit' => 10];
67
68
        $service = new ContentService(
69
            $repositoryMock,
0 ignored issues
show
Bug introduced by
It seems like $repositoryMock defined by $this->getRepositoryMock() on line 59 can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, eZ\Publish\Core\Reposito...tService::__construct() does only seem to accept object<eZ\Publish\API\Repository\Repository>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
70
            $persistenceHandlerMock,
71
            $domainMapperMock,
0 ignored issues
show
Bug introduced by
It seems like $domainMapperMock defined by $this->getDomainMapperMock() on line 62 can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, eZ\Publish\Core\Reposito...tService::__construct() does only seem to accept object<eZ\Publish\Core\R...ry\Helper\DomainMapper>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
72
            $relationProcessorMock,
0 ignored issues
show
Bug introduced by
It seems like $relationProcessorMock defined by $this->getRelationProcessorMock() on line 63 can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, eZ\Publish\Core\Reposito...tService::__construct() does only seem to accept object<eZ\Publish\Core\R...lper\RelationProcessor>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
73
            $nameSchemaServiceMock,
0 ignored issues
show
Bug introduced by
It seems like $nameSchemaServiceMock defined by $this->getNameSchemaServiceMock() on line 64 can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, eZ\Publish\Core\Reposito...tService::__construct() does only seem to accept object<eZ\Publish\Core\R...lper\NameSchemaService>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
74
            $fieldTypeRegistryMock,
0 ignored issues
show
Bug introduced by
It seems like $fieldTypeRegistryMock defined by $this->getFieldTypeRegistryMock() on line 65 can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, eZ\Publish\Core\Reposito...tService::__construct() does only seem to accept object<eZ\Publish\Core\R...lper\FieldTypeRegistry>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
75
            $settings
76
        );
77
78
        $this->assertAttributeSame(
79
            $repositoryMock,
80
            'repository',
81
            $service
82
        );
83
84
        $this->assertAttributeSame(
85
            $persistenceHandlerMock,
86
            'persistenceHandler',
87
            $service
88
        );
89
90
        $this->assertAttributeSame(
91
            $domainMapperMock,
92
            'domainMapper',
93
            $service
94
        );
95
96
        $this->assertAttributeSame(
97
            $relationProcessorMock,
98
            'relationProcessor',
99
            $service
100
        );
101
102
        $this->assertAttributeSame(
103
            $nameSchemaServiceMock,
104
            'nameSchemaService',
105
            $service
106
        );
107
108
        $this->assertAttributeSame(
109
            $fieldTypeRegistryMock,
110
            'fieldTypeRegistry',
111
            $service
112
        );
113
114
        $this->assertAttributeSame(
115
            $settings,
116
            'settings',
117
            $service
118
        );
119
    }
120
121
    /**
122
     * Test for the loadVersionInfo() method, of published version.
123
     *
124
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById
125
     */
126
    public function testLoadVersionInfoById()
127
    {
128
        $repository = $this->getRepositoryMock();
129
        $contentServiceMock = $this->getPartlyMockedContentService(['loadContentInfo']);
130
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
131
        $contentHandler = $this->getPersistenceMock()->contentHandler();
132
        $domainMapperMock = $this->getDomainMapperMock();
133
        $versionInfoMock = $this->createMock(APIVersionInfo::class);
134
135
        $versionInfoMock->expects($this->once())
136
            ->method('isPublished')
137
            ->willReturn(true);
138
139
        $contentServiceMock->expects($this->never())
140
            ->method('loadContentInfo');
141
142
        $contentHandler->expects($this->once())
143
            ->method('loadVersionInfo')
144
            ->with(
145
                $this->equalTo(42),
146
                $this->equalTo(null)
147
            )->will(
148
                $this->returnValue(new SPIVersionInfo())
149
            );
150
151
        $domainMapperMock->expects($this->once())
152
            ->method('buildVersionInfoDomainObject')
153
            ->with(new SPIVersionInfo())
154
            ->will($this->returnValue($versionInfoMock));
155
156
        $repository->expects($this->once())
157
            ->method('canUser')
158
            ->with(
159
                $this->equalTo('content'),
160
                $this->equalTo('read'),
161
                $this->equalTo($versionInfoMock)
162
            )->will($this->returnValue(true));
163
164
        $result = $contentServiceMock->loadVersionInfoById(42);
165
166
        $this->assertEquals($versionInfoMock, $result);
167
    }
168
169
    /**
170
     * Test for the loadVersionInfo() method, of a draft.
171
     *
172
     * @depends testLoadVersionInfoById
173
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById
174
     */
175
    public function testLoadVersionInfoByIdAndVersionNumber()
176
    {
177
        $repository = $this->getRepositoryMock();
178
        $contentServiceMock = $this->getPartlyMockedContentService(['loadContentInfo']);
179
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
180
        $contentHandler = $this->getPersistenceMock()->contentHandler();
181
        $domainMapperMock = $this->getDomainMapperMock();
182
        $versionInfoMock = $this->createMock(APIVersionInfo::class);
183
184
        $versionInfoMock->expects($this->any())
185
            ->method('__get')
186
            ->with('status')
187
            ->willReturn(APIVersionInfo::STATUS_DRAFT);
188
189
        $contentServiceMock->expects($this->never())
190
            ->method('loadContentInfo');
191
192
        $contentHandler->expects($this->once())
193
            ->method('loadVersionInfo')
194
            ->with(
195
                $this->equalTo(42),
196
                $this->equalTo(2)
197
            )->willReturn(new SPIVersionInfo());
198
199
        $domainMapperMock->expects($this->once())
200
            ->method('buildVersionInfoDomainObject')
201
            ->with(new SPIVersionInfo())
202
            ->willReturn($versionInfoMock);
203
204
        $repository->expects($this->once())
205
            ->method('canUser')
206
            ->with(
207
                $this->equalTo('content'),
208
                $this->equalTo('versionread'),
209
                $this->equalTo($versionInfoMock)
210
            )->willReturn(true);
211
212
        $result = $contentServiceMock->loadVersionInfoById(42, 2);
213
214
        $this->assertEquals($versionInfoMock, $result);
215
    }
216
217
    /**
218
     * Test for the loadVersionInfo() method.
219
     *
220
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById
221
     * @expectedException \eZ\Publish\Core\Base\Exceptions\NotFoundException
222
     */
223
    public function testLoadVersionInfoByIdThrowsNotFoundException()
224
    {
225
        $contentServiceMock = $this->getPartlyMockedContentService(['loadContentInfo']);
226
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
227
        $contentHandler = $this->getPersistenceMock()->contentHandler();
228
229
        $contentHandler->expects($this->once())
230
            ->method('loadVersionInfo')
231
            ->with(
232
                $this->equalTo(42),
233
                $this->equalTo(24)
234
            )->will(
235
                $this->throwException(
236
                    new NotFoundException(
237
                        'Content',
238
                        [
239
                            'contentId' => 42,
240
                            'versionNo' => 24,
241
                        ]
242
                    )
243
                )
244
            );
245
246
        $contentServiceMock->loadVersionInfoById(42, 24);
247
    }
248
249
    /**
250
     * Test for the loadVersionInfo() method.
251
     *
252
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById
253
     * @expectedException \eZ\Publish\Core\Base\Exceptions\UnauthorizedException
254
     */
255
    public function testLoadVersionInfoByIdThrowsUnauthorizedExceptionNonPublishedVersion()
256
    {
257
        $repository = $this->getRepositoryMock();
258
        $contentServiceMock = $this->getPartlyMockedContentService();
259
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
260
        $contentHandler = $this->getPersistenceMock()->contentHandler();
261
        $domainMapperMock = $this->getDomainMapperMock();
262
        $versionInfoMock = $this->createMock(APIVersionInfo::class);
263
264
        $versionInfoMock->expects($this->any())
265
            ->method('isPublished')
266
            ->willReturn(false);
267
268
        $contentHandler->expects($this->once())
269
            ->method('loadVersionInfo')
270
            ->with(
271
                $this->equalTo(42),
272
                $this->equalTo(24)
273
            )->will(
274
                $this->returnValue(new SPIVersionInfo())
275
            );
276
277
        $domainMapperMock->expects($this->once())
278
            ->method('buildVersionInfoDomainObject')
279
            ->with(new SPIVersionInfo())
280
            ->will($this->returnValue($versionInfoMock));
281
282
        $repository->expects($this->once())
283
            ->method('canUser')
284
            ->with(
285
                $this->equalTo('content'),
286
                $this->equalTo('versionread'),
287
                $this->equalTo($versionInfoMock)
288
            )->will($this->returnValue(false));
289
290
        $contentServiceMock->loadVersionInfoById(42, 24);
291
    }
292
293
    /**
294
     * Test for the loadVersionInfo() method.
295
     *
296
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById
297
     */
298 View Code Duplication
    public function testLoadVersionInfoByIdPublishedVersion()
299
    {
300
        $repository = $this->getRepositoryMock();
301
        $contentServiceMock = $this->getPartlyMockedContentService();
302
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
303
        $contentHandler = $this->getPersistenceMock()->contentHandler();
304
        $domainMapperMock = $this->getDomainMapperMock();
305
        $versionInfoMock = $this->createMock(APIVersionInfo::class);
306
307
        $versionInfoMock->expects($this->once())
308
            ->method('isPublished')
309
            ->willReturn(true);
310
311
        $contentHandler->expects($this->once())
312
            ->method('loadVersionInfo')
313
            ->with(
314
                $this->equalTo(42),
315
                $this->equalTo(24)
316
            )->will(
317
                $this->returnValue(new SPIVersionInfo())
318
            );
319
320
        $domainMapperMock->expects($this->once())
321
            ->method('buildVersionInfoDomainObject')
322
            ->with(new SPIVersionInfo())
323
            ->will($this->returnValue($versionInfoMock));
324
325
        $repository->expects($this->once())
326
            ->method('canUser')
327
            ->with(
328
                $this->equalTo('content'),
329
                $this->equalTo('read'),
330
                $this->equalTo($versionInfoMock)
331
            )->will($this->returnValue(true));
332
333
        $result = $contentServiceMock->loadVersionInfoById(42, 24);
334
335
        $this->assertEquals($versionInfoMock, $result);
336
    }
337
338
    /**
339
     * Test for the loadVersionInfo() method.
340
     *
341
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById
342
     */
343 View Code Duplication
    public function testLoadVersionInfoByIdNonPublishedVersion()
344
    {
345
        $repository = $this->getRepositoryMock();
346
        $contentServiceMock = $this->getPartlyMockedContentService();
347
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
348
        $contentHandler = $this->getPersistenceMock()->contentHandler();
349
        $domainMapperMock = $this->getDomainMapperMock();
350
        $versionInfoMock = $this->createMock(APIVersionInfo::class);
351
352
        $versionInfoMock->expects($this->once())
353
            ->method('isPublished')
354
            ->willReturn(false);
355
356
        $contentHandler->expects($this->once())
357
            ->method('loadVersionInfo')
358
            ->with(
359
                $this->equalTo(42),
360
                $this->equalTo(24)
361
            )->will(
362
                $this->returnValue(new SPIVersionInfo())
363
            );
364
365
        $domainMapperMock->expects($this->once())
366
            ->method('buildVersionInfoDomainObject')
367
            ->with(new SPIVersionInfo())
368
            ->will($this->returnValue($versionInfoMock));
369
370
        $repository->expects($this->once())
371
            ->method('canUser')
372
            ->with(
373
                $this->equalTo('content'),
374
                $this->equalTo('versionread'),
375
                $this->equalTo($versionInfoMock)
376
            )->will($this->returnValue(true));
377
378
        $result = $contentServiceMock->loadVersionInfoById(42, 24);
379
380
        $this->assertEquals($versionInfoMock, $result);
381
    }
382
383
    /**
384
     * Test for the loadVersionInfo() method.
385
     *
386
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfo
387
     * @depends eZ\Publish\Core\Repository\Tests\Service\Mock\ContentTest::testLoadVersionInfoById
388
     * @depends eZ\Publish\Core\Repository\Tests\Service\Mock\ContentTest::testLoadVersionInfoByIdThrowsNotFoundException
389
     * @depends eZ\Publish\Core\Repository\Tests\Service\Mock\ContentTest::testLoadVersionInfoByIdThrowsUnauthorizedExceptionNonPublishedVersion
390
     * @depends eZ\Publish\Core\Repository\Tests\Service\Mock\ContentTest::testLoadVersionInfoByIdPublishedVersion
391
     * @depends eZ\Publish\Core\Repository\Tests\Service\Mock\ContentTest::testLoadVersionInfoByIdNonPublishedVersion
392
     */
393
    public function testLoadVersionInfo()
394
    {
395
        $contentServiceMock = $this->getPartlyMockedContentService(
396
            ['loadVersionInfoById']
397
        );
398
        $contentServiceMock->expects(
399
            $this->once()
400
        )->method(
401
            'loadVersionInfoById'
402
        )->with(
403
            $this->equalTo(42),
404
            $this->equalTo(7)
405
        )->will(
406
            $this->returnValue('result')
407
        );
408
409
        $result = $contentServiceMock->loadVersionInfo(
410
            new ContentInfo(['id' => 42]),
411
            7
412
        );
413
414
        $this->assertEquals('result', $result);
415
    }
416
417
    public function testLoadContent()
418
    {
419
        $repository = $this->getRepositoryMock();
420
        $contentService = $this->getPartlyMockedContentService(['internalLoadContent']);
421
        $content = $this->createMock('eZ\Publish\API\Repository\Values\Content\Content');
422
        $versionInfo = $this->createMock(APIVersionInfo::class);
423
        $content
424
            ->expects($this->once())
425
            ->method('getVersionInfo')
426
            ->will($this->returnValue($versionInfo));
427
        $versionInfo
428
            ->expects($this->once())
429
            ->method('isPublished')
430
            ->willReturn(true);
431
        $contentId = 123;
432
        $contentService
433
            ->expects($this->once())
434
            ->method('internalLoadContent')
435
            ->with($contentId)
436
            ->will($this->returnValue($content));
437
438
        $repository
439
            ->expects($this->once())
440
            ->method('canUser')
441
            ->with('content', 'read', $content)
442
            ->will($this->returnValue(true));
443
444
        $this->assertSame($content, $contentService->loadContent($contentId));
445
    }
446
447 View Code Duplication
    public function testLoadContentNonPublished()
448
    {
449
        $repository = $this->getRepositoryMock();
450
        $contentService = $this->getPartlyMockedContentService(['internalLoadContent']);
451
        $content = $this->createMock('eZ\Publish\API\Repository\Values\Content\Content');
452
        $versionInfo = $this
453
            ->getMockBuilder('eZ\Publish\API\Repository\Values\Content\VersionInfo')
454
            ->getMockForAbstractClass();
455
        $content
456
            ->expects($this->once())
457
            ->method('getVersionInfo')
458
            ->will($this->returnValue($versionInfo));
459
        $contentId = 123;
460
        $contentService
461
            ->expects($this->once())
462
            ->method('internalLoadContent')
463
            ->with($contentId)
464
            ->will($this->returnValue($content));
465
466
        $repository
467
            ->expects($this->exactly(2))
468
            ->method('canUser')
469
            ->will(
470
                $this->returnValueMap(
471
                    [
472
                        ['content', 'read', $content, null, true],
473
                        ['content', 'versionread', $content, null, true],
474
                    ]
475
                )
476
            );
477
478
        $this->assertSame($content, $contentService->loadContent($contentId));
479
    }
480
481
    /**
482
     * @expectedException \eZ\Publish\Core\Base\Exceptions\UnauthorizedException
483
     */
484
    public function testLoadContentUnauthorized()
485
    {
486
        $repository = $this->getRepositoryMock();
487
        $contentService = $this->getPartlyMockedContentService(['internalLoadContent']);
488
        $content = $this->createMock('eZ\Publish\API\Repository\Values\Content\Content');
489
        $contentId = 123;
490
        $contentService
491
            ->expects($this->once())
492
            ->method('internalLoadContent')
493
            ->with($contentId)
494
            ->will($this->returnValue($content));
495
496
        $repository
497
            ->expects($this->once())
498
            ->method('canUser')
499
            ->with('content', 'read', $content)
500
            ->will($this->returnValue(false));
501
502
        $contentService->loadContent($contentId);
503
    }
504
505
    /**
506
     * @expectedException \eZ\Publish\Core\Base\Exceptions\UnauthorizedException
507
     */
508 View Code Duplication
    public function testLoadContentNotPublishedStatusUnauthorized()
509
    {
510
        $repository = $this->getRepositoryMock();
511
        $contentService = $this->getPartlyMockedContentService(['internalLoadContent']);
512
        $content = $this->createMock('eZ\Publish\API\Repository\Values\Content\Content');
513
        $versionInfo = $this
514
            ->getMockBuilder('eZ\Publish\API\Repository\Values\Content\VersionInfo')
515
            ->getMockForAbstractClass();
516
        $content
517
            ->expects($this->once())
518
            ->method('getVersionInfo')
519
            ->will($this->returnValue($versionInfo));
520
        $contentId = 123;
521
        $contentService
522
            ->expects($this->once())
523
            ->method('internalLoadContent')
524
            ->with($contentId)
525
            ->will($this->returnValue($content));
526
527
        $repository
528
            ->expects($this->exactly(2))
529
            ->method('canUser')
530
            ->will(
531
                $this->returnValueMap(
532
                    [
533
                        ['content', 'read', $content, null, true],
534
                        ['content', 'versionread', $content, null, false],
535
                    ]
536
                )
537
            );
538
539
        $contentService->loadContent($contentId);
540
    }
541
542
    /**
543
     * @dataProvider internalLoadContentProvider
544
     */
545
    public function testInternalLoadContent($id, $languages, $versionNo, $isRemoteId, $useAlwaysAvailable)
546
    {
547
        $contentService = $this->getPartlyMockedContentService();
548
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
549
        $contentHandler = $this->getPersistenceMock()->contentHandler();
550
        $realId = $id;
551
552
        if ($isRemoteId) {
553
            $realId = 123;
554
            $spiContentInfo = new SPIContentInfo(['currentVersionNo' => $versionNo ?: 7, 'id' => $realId]);
555
            $contentHandler
556
                ->expects($this->once())
557
                ->method('loadContentInfoByRemoteId')
558
                ->with($id)
559
                ->will($this->returnValue($spiContentInfo));
560
        } elseif (!empty($languages) && $useAlwaysAvailable) {
561
            $spiContentInfo = new SPIContentInfo(['alwaysAvailable' => false]);
562
            $contentHandler
563
                ->expects($this->once())
564
                ->method('loadContentInfo')
565
                ->with($id)
566
                ->will($this->returnValue($spiContentInfo));
567
        }
568
569
        $spiContent = new SPIContent();
570
        $contentHandler
571
            ->expects($this->once())
572
            ->method('load')
573
            ->with($realId, $versionNo, $languages)
574
            ->will($this->returnValue($spiContent));
575
        $content = $this->createMock('eZ\Publish\API\Repository\Values\Content\Content');
576
        $this->getDomainMapperMock()
577
            ->expects($this->once())
578
            ->method('buildContentDomainObject')
579
            ->with($spiContent)
580
            ->will($this->returnValue($content));
581
582
        $this->assertSame(
583
            $content,
584
            $contentService->internalLoadContent($id, $languages, $versionNo, $isRemoteId, $useAlwaysAvailable)
585
        );
586
    }
587
588
    public function internalLoadContentProvider()
589
    {
590
        return [
591
            [123, null, null, false, false],
592
            [123, null, 456, false, false],
593
            [456, null, 123, false, true],
594
            [456, null, 2, false, false],
595
            [456, ['eng-GB'], 2, false, true],
596
            [456, ['eng-GB', 'fre-FR'], null, false, false],
597
            [456, ['eng-GB', 'fre-FR', 'nor-NO'], 2, false, false],
598
            // With remoteId
599
            [123, null, null, true, false],
600
            ['someRemoteId', null, 456, true, false],
601
            [456, null, 123, true, false],
602
            ['someRemoteId', null, 2, true, false],
603
            ['someRemoteId', ['eng-GB'], 2, true, false],
604
            [456, ['eng-GB', 'fre-FR'], null, true, false],
605
            ['someRemoteId', ['eng-GB', 'fre-FR', 'nor-NO'], 2, true, false],
606
        ];
607
    }
608
609
    /**
610
     * @expectedException \eZ\Publish\Core\Base\Exceptions\NotFoundException
611
     */
612
    public function testInternalLoadContentNotFound()
613
    {
614
        $contentService = $this->getPartlyMockedContentService();
615
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
616
        $contentHandler = $this->getPersistenceMock()->contentHandler();
617
        $id = 123;
618
        $versionNo = 7;
619
        $languages = null;
620
        $contentHandler
621
            ->expects($this->once())
622
            ->method('load')
623
            ->with($id, $versionNo, $languages)
624
            ->will(
625
                $this->throwException(
626
                    $this->createMock('eZ\Publish\API\Repository\Exceptions\NotFoundException')
627
                )
628
            );
629
630
        $contentService->internalLoadContent($id, $languages, $versionNo);
631
    }
632
633
    /**
634
     * Test for the loadContentByContentInfo() method.
635
     *
636
     * @covers \eZ\Publish\Core\Repository\ContentService::loadContentByContentInfo
637
     */
638
    public function testLoadContentByContentInfo()
639
    {
640
        $contentServiceMock = $this->getPartlyMockedContentService(
641
            ['loadContent']
642
        );
643
        $contentServiceMock->expects(
644
            $this->once()
645
        )->method(
646
            'loadContent'
647
        )->with(
648
            $this->equalTo(42),
649
            $this->equalTo(['cro-HR']),
650
            $this->equalTo(7),
651
            $this->equalTo(false)
652
        )->will(
653
            $this->returnValue('result')
654
        );
655
656
        $result = $contentServiceMock->loadContentByContentInfo(
657
            new ContentInfo(['id' => 42]),
658
            ['cro-HR'],
659
            7
660
        );
661
662
        $this->assertEquals('result', $result);
663
    }
664
665
    /**
666
     * Test for the loadContentByVersionInfo() method.
667
     *
668
     * @covers \eZ\Publish\Core\Repository\ContentService::loadContentByVersionInfo
669
     */
670
    public function testLoadContentByVersionInfo()
671
    {
672
        $contentServiceMock = $this->getPartlyMockedContentService(
673
            ['loadContent']
674
        );
675
        $contentServiceMock->expects(
676
            $this->once()
677
        )->method(
678
            'loadContent'
679
        )->with(
680
            $this->equalTo(42),
681
            $this->equalTo(['cro-HR']),
682
            $this->equalTo(7),
683
            $this->equalTo(false)
684
        )->will(
685
            $this->returnValue('result')
686
        );
687
688
        $result = $contentServiceMock->loadContentByVersionInfo(
689
            new VersionInfo(
690
                [
691
                    'contentInfo' => new ContentInfo(['id' => 42]),
692
                    'versionNo' => 7,
693
                ]
694
            ),
695
            ['cro-HR']
696
        );
697
698
        $this->assertEquals('result', $result);
699
    }
700
701
    /**
702
     * Test for the deleteContent() method.
703
     *
704
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteContent
705
     * @expectedException \eZ\Publish\Core\Base\Exceptions\UnauthorizedException
706
     */
707
    public function testDeleteContentThrowsUnauthorizedException()
708
    {
709
        $repository = $this->getRepositoryMock();
710
        $contentService = $this->getPartlyMockedContentService(['internalLoadContentInfo']);
711
        $contentInfo = $this->createMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
712
713
        $contentInfo->expects($this->any())
714
            ->method('__get')
715
            ->with('id')
716
            ->will($this->returnValue(42));
717
718
        $contentService->expects($this->once())
719
            ->method('internalLoadContentInfo')
720
            ->with(42)
721
            ->will($this->returnValue($contentInfo));
722
723
        $repository->expects($this->once())
724
            ->method('canUser')
725
            ->with('content', 'remove')
726
            ->will($this->returnValue(false));
727
728
        /* @var \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo */
729
        $contentService->deleteContent($contentInfo);
730
    }
731
732
    /**
733
     * Test for the deleteContent() method.
734
     *
735
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteContent
736
     */
737
    public function testDeleteContent()
738
    {
739
        $repository = $this->getRepositoryMock();
740
741
        $repository->expects($this->once())
742
            ->method('canUser')
743
            ->with('content', 'remove')
744
            ->will($this->returnValue(true));
745
746
        $contentService = $this->getPartlyMockedContentService(['internalLoadContentInfo']);
747
        /** @var \PHPUnit_Framework_MockObject_MockObject $urlAliasHandler */
748
        $urlAliasHandler = $this->getPersistenceMock()->urlAliasHandler();
749
        /** @var \PHPUnit_Framework_MockObject_MockObject $locationHandler */
750
        $locationHandler = $this->getPersistenceMock()->locationHandler();
751
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
752
        $contentHandler = $this->getPersistenceMock()->contentHandler();
753
754
        $contentInfo = $this->createMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
755
756
        $contentService->expects($this->once())
757
            ->method('internalLoadContentInfo')
758
            ->with(42)
759
            ->will($this->returnValue($contentInfo));
760
761
        $contentInfo->expects($this->any())
762
            ->method('__get')
763
            ->with('id')
764
            ->will($this->returnValue(42));
765
766
        $repository->expects($this->once())->method('beginTransaction');
767
768
        $spiLocations = [
769
            new SPILocation(['id' => 1]),
770
            new SPILocation(['id' => 2]),
771
        ];
772
        $locationHandler->expects($this->once())
773
            ->method('loadLocationsByContent')
774
            ->with(42)
775
            ->will($this->returnValue($spiLocations));
776
777
        $contentHandler->expects($this->once())
778
            ->method('deleteContent')
779
            ->with(42);
780
781
        foreach ($spiLocations as $index => $spiLocation) {
782
            $urlAliasHandler->expects($this->at($index))
783
                ->method('locationDeleted')
784
                ->with($spiLocation->id);
785
        }
786
787
        $repository->expects($this->once())->method('commit');
788
789
        /* @var \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo */
790
        $contentService->deleteContent($contentInfo);
791
    }
792
793
    /**
794
     * Test for the deleteContent() method.
795
     *
796
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteContent
797
     * @expectedException \Exception
798
     */
799
    public function testDeleteContentWithRollback()
800
    {
801
        $repository = $this->getRepositoryMock();
802
803
        $repository->expects($this->once())
804
            ->method('canUser')
805
            ->with('content', 'remove')
806
            ->will($this->returnValue(true));
807
808
        $contentService = $this->getPartlyMockedContentService(['internalLoadContentInfo']);
809
        /** @var \PHPUnit_Framework_MockObject_MockObject $locationHandler */
810
        $locationHandler = $this->getPersistenceMock()->locationHandler();
811
812
        $contentInfo = $this->createMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
813
814
        $contentService->expects($this->once())
815
            ->method('internalLoadContentInfo')
816
            ->with(42)
817
            ->will($this->returnValue($contentInfo));
818
819
        $contentInfo->expects($this->any())
820
            ->method('__get')
821
            ->with('id')
822
            ->will($this->returnValue(42));
823
824
        $repository->expects($this->once())->method('beginTransaction');
825
826
        $locationHandler->expects($this->once())
827
            ->method('loadLocationsByContent')
828
            ->with(42)
829
            ->will($this->throwException(new \Exception()));
830
831
        $repository->expects($this->once())->method('rollback');
832
833
        /* @var \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo */
834
        $contentService->deleteContent($contentInfo);
835
    }
836
837
    /**
838
     * Test for the deleteVersion() method.
839
     *
840
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteVersion
841
     * @expectedException \eZ\Publish\API\Repository\Exceptions\BadStateException
842
     */
843
    public function testDeleteVersionThrowsBadStateExceptionLastVersion()
844
    {
845
        $repository = $this->getRepositoryMock();
846
        $repository
847
            ->expects($this->once())
848
            ->method('canUser')
849
            ->with('content', 'versionremove')
850
            ->will($this->returnValue(true));
851
        $repository
852
            ->expects($this->never())
853
            ->method('beginTransaction');
854
855
        $contentService = $this->getPartlyMockedContentService();
856
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
857
        $contentHandler = $this->getPersistenceMock()->contentHandler();
858
        $contentInfo = $this->createMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
859
        $versionInfo = $this->createMock(APIVersionInfo::class);
860
861
        $contentInfo
862
            ->expects($this->any())
863
            ->method('__get')
864
            ->with('id')
865
            ->will($this->returnValue(42));
866
867
        $versionInfo
868
            ->expects($this->any())
869
            ->method('__get')
870
            ->will(
871
                $this->returnValueMap(
872
                    [
873
                        ['versionNo', 123],
874
                        ['contentInfo', $contentInfo],
875
                    ]
876
                )
877
            );
878
        $versionInfo
879
            ->expects($this->once())
880
            ->method('isPublished')
881
            ->willReturn(false);
882
883
        $contentHandler
884
            ->expects($this->once())
885
            ->method('listVersions')
886
            ->with(42)
887
            ->will($this->returnValue(['version']));
888
889
        /* @var \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo */
890
        $contentService->deleteVersion($versionInfo);
891
    }
892
893
    /**
894
     * Test for the createContent() method.
895
     *
896
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
897
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
898
     * @expectedExceptionMessage Argument '$contentCreateStruct' is invalid: 'mainLanguageCode' property must be set
899
     */
900
    public function testCreateContentThrowsInvalidArgumentExceptionMainLanguageCodeNotSet()
901
    {
902
        $mockedService = $this->getPartlyMockedContentService();
903
        $mockedService->createContent(new ContentCreateStruct(), []);
904
    }
905
906
    /**
907
     * Test for the createContent() method.
908
     *
909
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
910
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
911
     * @expectedExceptionMessage Argument '$contentCreateStruct' is invalid: 'contentType' property must be set
912
     */
913
    public function testCreateContentThrowsInvalidArgumentExceptionContentTypeNotSet()
914
    {
915
        $mockedService = $this->getPartlyMockedContentService();
916
        $mockedService->createContent(
917
            new ContentCreateStruct(['mainLanguageCode' => 'eng-US']),
918
            []
919
        );
920
    }
921
922
    /**
923
     * Test for the createContent() method.
924
     *
925
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
926
     * @expectedException \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
927
     */
928
    public function testCreateContentThrowsUnauthorizedException()
929
    {
930
        $repositoryMock = $this->getRepositoryMock();
931
        $mockedService = $this->getPartlyMockedContentService();
932
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
933
        $contentType = new ContentType(
934
            [
935
                'id' => 123,
936
                'fieldDefinitions' => [],
937
            ]
938
        );
939
        $contentCreateStruct = new ContentCreateStruct(
940
            [
941
                'ownerId' => 169,
942
                'alwaysAvailable' => false,
943
                'mainLanguageCode' => 'eng-US',
944
                'contentType' => $contentType,
945
            ]
946
        );
947
948
        $repositoryMock->expects($this->once())
949
            ->method('getCurrentUserReference')
950
            ->will($this->returnValue(new UserReference(169)));
951
952
        $contentTypeServiceMock->expects($this->once())
953
            ->method('loadContentType')
954
            ->with($this->equalTo(123))
955
            ->will($this->returnValue($contentType));
956
957
        $repositoryMock->expects($this->once())
958
            ->method('getContentTypeService')
959
            ->will($this->returnValue($contentTypeServiceMock));
960
961
        $repositoryMock->expects($this->once())
962
            ->method('canUser')
963
            ->with(
964
                $this->equalTo('content'),
965
                $this->equalTo('create'),
966
                $this->isInstanceOf($contentCreateStruct),
967
                $this->equalTo([])
968
            )->will($this->returnValue(false));
969
970
        $mockedService->createContent(
971
            new ContentCreateStruct(
972
                [
973
                    'mainLanguageCode' => 'eng-US',
974
                    'contentType' => $contentType,
975
                ]
976
            ),
977
            []
978
        );
979
    }
980
981
    /**
982
     * Test for the createContent() method.
983
     *
984
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
985
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
986
     * @exceptionMessage Argument '$contentCreateStruct' is invalid: Another content with remoteId 'faraday' exists
987
     */
988
    public function testCreateContentThrowsInvalidArgumentExceptionDuplicateRemoteId()
989
    {
990
        $repositoryMock = $this->getRepositoryMock();
991
        $mockedService = $this->getPartlyMockedContentService(['loadContentByRemoteId']);
992
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
993
        $contentType = new ContentType(
994
            [
995
                'id' => 123,
996
                'fieldDefinitions' => [],
997
            ]
998
        );
999
        $contentCreateStruct = new ContentCreateStruct(
1000
            [
1001
                'ownerId' => 169,
1002
                'alwaysAvailable' => false,
1003
                'remoteId' => 'faraday',
1004
                'mainLanguageCode' => 'eng-US',
1005
                'contentType' => $contentType,
1006
            ]
1007
        );
1008
1009
        $repositoryMock->expects($this->once())
1010
            ->method('getCurrentUserReference')
1011
            ->will($this->returnValue(new UserReference(169)));
1012
1013
        $contentTypeServiceMock->expects($this->once())
1014
            ->method('loadContentType')
1015
            ->with($this->equalTo(123))
1016
            ->will($this->returnValue($contentType));
1017
1018
        $repositoryMock->expects($this->once())
1019
            ->method('getContentTypeService')
1020
            ->will($this->returnValue($contentTypeServiceMock));
1021
1022
        $repositoryMock->expects($this->once())
1023
            ->method('canUser')
1024
            ->with(
1025
                $this->equalTo('content'),
1026
                $this->equalTo('create'),
1027
                $this->isInstanceOf($contentCreateStruct),
1028
                $this->equalTo([])
1029
            )->will($this->returnValue(true));
1030
1031
        $mockedService->expects($this->once())
1032
            ->method('loadContentByRemoteId')
1033
            ->with($contentCreateStruct->remoteId)
1034
            ->will($this->returnValue('Hello...'));
1035
1036
        $mockedService->createContent(
1037
            new ContentCreateStruct(
1038
                [
1039
                    'remoteId' => 'faraday',
1040
                    'mainLanguageCode' => 'eng-US',
1041
                    'contentType' => $contentType,
1042
                ]
1043
            ),
1044
            []
1045
        );
1046
    }
1047
1048
    /**
1049
     * @param string $mainLanguageCode
1050
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
1051
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
1052
     *
1053
     * @return array
1054
     */
1055
    protected function mapStructFieldsForCreate($mainLanguageCode, $structFields, $fieldDefinitions)
1056
    {
1057
        $mappedFieldDefinitions = [];
1058
        foreach ($fieldDefinitions as $fieldDefinition) {
1059
            $mappedFieldDefinitions[$fieldDefinition->identifier] = $fieldDefinition;
1060
        }
1061
1062
        $mappedStructFields = [];
1063
        foreach ($structFields as $structField) {
1064
            if ($structField->languageCode === null) {
1065
                $languageCode = $mainLanguageCode;
1066
            } else {
1067
                $languageCode = $structField->languageCode;
1068
            }
1069
1070
            $mappedStructFields[$structField->fieldDefIdentifier][$languageCode] = (string)$structField->value;
1071
        }
1072
1073
        return $mappedStructFields;
1074
    }
1075
1076
    /**
1077
     * Returns full, possibly redundant array of field values, indexed by field definition
1078
     * identifier and language code.
1079
     *
1080
     * @throws \RuntimeException Method is intended to be used only with consistent fixtures
1081
     *
1082
     * @param string $mainLanguageCode
1083
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
1084
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
1085
     * @param array $languageCodes
1086
     *
1087
     * @return array
1088
     */
1089
    protected function determineValuesForCreate(
1090
        $mainLanguageCode,
1091
        array $structFields,
1092
        array $fieldDefinitions,
1093
        array $languageCodes
1094
    ) {
1095
        $mappedStructFields = $this->mapStructFieldsForCreate(
1096
            $mainLanguageCode,
1097
            $structFields,
1098
            $fieldDefinitions
1099
        );
1100
1101
        $values = [];
1102
1103
        foreach ($fieldDefinitions as $fieldDefinition) {
1104
            $identifier = $fieldDefinition->identifier;
1105
            foreach ($languageCodes as $languageCode) {
1106 View Code Duplication
                if (!$fieldDefinition->isTranslatable) {
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...
1107
                    if (isset($mappedStructFields[$identifier][$mainLanguageCode])) {
1108
                        $values[$identifier][$languageCode] = $mappedStructFields[$identifier][$mainLanguageCode];
1109
                    } else {
1110
                        $values[$identifier][$languageCode] = (string)$fieldDefinition->defaultValue;
1111
                    }
1112
                    continue;
1113
                }
1114
1115 View Code Duplication
                if (isset($mappedStructFields[$identifier][$languageCode])) {
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...
1116
                    $values[$identifier][$languageCode] = $mappedStructFields[$identifier][$languageCode];
1117
                    continue;
1118
                }
1119
1120
                $values[$identifier][$languageCode] = (string)$fieldDefinition->defaultValue;
1121
            }
1122
        }
1123
1124
        return $this->stubValues($values);
1125
    }
1126
1127
    /**
1128
     * @param string $mainLanguageCode
1129
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
1130
     *
1131
     * @return string[]
1132
     */
1133 View Code Duplication
    protected function determineLanguageCodesForCreate($mainLanguageCode, array $structFields)
1134
    {
1135
        $languageCodes = [];
1136
1137
        foreach ($structFields as $field) {
1138
            if ($field->languageCode === null || isset($languageCodes[$field->languageCode])) {
1139
                continue;
1140
            }
1141
1142
            $languageCodes[$field->languageCode] = true;
1143
        }
1144
1145
        $languageCodes[$mainLanguageCode] = true;
1146
1147
        return array_keys($languageCodes);
1148
    }
1149
1150
    /**
1151
     * Asserts that calling createContent() with given API field set causes calling
1152
     * Handler::createContent() with given SPI field set.
1153
     *
1154
     * @param string $mainLanguageCode
1155
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
1156
     * @param \eZ\Publish\SPI\Persistence\Content\Field[] $spiFields
1157
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
1158
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct[] $locationCreateStructs
1159
     * @param \eZ\Publish\SPI\Persistence\Content\ObjectState\Group[] $objectStateGroups
0 ignored issues
show
Bug introduced by
There is no parameter named $objectStateGroups. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1160
     * @param bool $execute
1161
     *
1162
     * @return mixed
1163
     */
1164
    protected function assertForTestCreateContentNonRedundantFieldSet(
1165
        $mainLanguageCode,
1166
        array $structFields,
1167
        array $spiFields,
1168
        array $fieldDefinitions,
1169
        array $locationCreateStructs = [],
1170
        $withObjectStates = false,
1171
        $execute = true
1172
    ) {
1173
        $repositoryMock = $this->getRepositoryMock();
1174
        $mockedService = $this->getPartlyMockedContentService();
1175
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
1176
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
1177
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
1178
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
1179
        /** @var \PHPUnit_Framework_MockObject_MockObject $objectStateHandlerMock */
1180
        $objectStateHandlerMock = $this->getPersistenceMock()->objectStateHandler();
1181
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
1182
        $fieldTypeServiceMock = $this->getFieldTypeServiceMock();
0 ignored issues
show
Unused Code introduced by
$fieldTypeServiceMock 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...
1183
        $domainMapperMock = $this->getDomainMapperMock();
1184
        $relationProcessorMock = $this->getRelationProcessorMock();
1185
        $nameSchemaServiceMock = $this->getNameSchemaServiceMock();
1186
        $fieldTypeMock = $this->createMock('eZ\\Publish\\SPI\\FieldType\\FieldType');
1187
        $languageCodes = $this->determineLanguageCodesForCreate($mainLanguageCode, $structFields);
1188
        $contentType = new ContentType(
1189
            [
1190
                'id' => 123,
1191
                'fieldDefinitions' => $fieldDefinitions,
1192
                'nameSchema' => '<nameSchema>',
1193
            ]
1194
        );
1195
        $contentCreateStruct = new ContentCreateStruct(
1196
            [
1197
                'fields' => $structFields,
1198
                'mainLanguageCode' => $mainLanguageCode,
1199
                'contentType' => $contentType,
1200
                'alwaysAvailable' => false,
1201
                'ownerId' => 169,
1202
                'sectionId' => 1,
1203
            ]
1204
        );
1205
1206
        $languageHandlerMock->expects($this->any())
1207
            ->method('loadByLanguageCode')
1208
            ->with($this->isType('string'))
1209
            ->will(
1210
                $this->returnCallback(
1211
                    function () {
1212
                        return new Language(['id' => 4242]);
1213
                    }
1214
                )
1215
            );
1216
1217
        $repositoryMock->expects($this->once())->method('beginTransaction');
1218
1219
        $contentTypeServiceMock->expects($this->once())
1220
            ->method('loadContentType')
1221
            ->with($this->equalTo($contentType->id))
1222
            ->will($this->returnValue($contentType));
1223
1224
        $repositoryMock->expects($this->once())
1225
            ->method('getContentTypeService')
1226
            ->will($this->returnValue($contentTypeServiceMock));
1227
1228
        $that = $this;
1229
        $repositoryMock->expects($this->once())
1230
            ->method('canUser')
1231
            ->with(
1232
                $this->equalTo('content'),
1233
                $this->equalTo('create'),
1234
                $this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'),
1235
                $this->equalTo($locationCreateStructs)
1236
            )->will(
1237
                $this->returnCallback(
1238
                    function () use ($that, $contentCreateStruct) {
1239
                        $that->assertEquals($contentCreateStruct, func_get_arg(2));
1240
1241
                        return true;
1242
                    }
1243
                )
1244
            );
1245
1246
        $domainMapperMock->expects($this->once())
1247
            ->method('getUniqueHash')
1248
            ->with($this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'))
1249
            ->will(
1250
                $this->returnCallback(
1251
                    function ($object) use ($that, $contentCreateStruct) {
1252
                        $that->assertEquals($contentCreateStruct, $object);
1253
1254
                        return 'hash';
1255
                    }
1256
                )
1257
            );
1258
1259
        $fieldTypeMock->expects($this->any())
1260
            ->method('acceptValue')
1261
            ->will(
1262
                $this->returnCallback(
1263
                    function ($valueString) {
1264
                        return new ValueStub($valueString);
1265
                    }
1266
                )
1267
            );
1268
1269
        $fieldTypeMock->expects($this->any())
1270
            ->method('toPersistenceValue')
1271
            ->will(
1272
                $this->returnCallback(
1273
                    function (ValueStub $value) {
1274
                        return (string)$value;
1275
                    }
1276
                )
1277
            );
1278
1279
        $emptyValue = self::EMPTY_FIELD_VALUE;
1280
        $fieldTypeMock->expects($this->any())
1281
            ->method('isEmptyValue')
1282
            ->will(
1283
                $this->returnCallback(
1284
                    function (ValueStub $value) use ($emptyValue) {
1285
                        return $emptyValue === (string)$value;
1286
                    }
1287
                )
1288
            );
1289
1290
        $fieldTypeMock->expects($this->any())
1291
            ->method('validate')
1292
            ->will($this->returnValue([]));
1293
1294
        $this->getFieldTypeRegistryMock()->expects($this->any())
1295
            ->method('getFieldType')
1296
            ->will($this->returnValue($fieldTypeMock));
1297
1298
        $relationProcessorMock
1299
            ->expects($this->exactly(count($fieldDefinitions) * count($languageCodes)))
1300
            ->method('appendFieldRelations')
1301
            ->with(
1302
                $this->isType('array'),
1303
                $this->isType('array'),
1304
                $this->isInstanceOf('eZ\\Publish\\SPI\\FieldType\\FieldType'),
1305
                $this->isInstanceOf('eZ\\Publish\\Core\\FieldType\\Value'),
1306
                $this->anything()
1307
            );
1308
1309
        $values = $this->determineValuesForCreate(
1310
            $mainLanguageCode,
1311
            $structFields,
1312
            $fieldDefinitions,
1313
            $languageCodes
1314
        );
1315
        $nameSchemaServiceMock->expects($this->once())
1316
            ->method('resolve')
1317
            ->with(
1318
                $this->equalTo($contentType->nameSchema),
1319
                $this->equalTo($contentType),
1320
                $this->equalTo($values),
1321
                $this->equalTo($languageCodes)
1322
            )->will($this->returnValue([]));
1323
1324
        $relationProcessorMock->expects($this->any())
1325
            ->method('processFieldRelations')
1326
            ->with(
1327
                $this->isType('array'),
1328
                $this->equalTo(42),
1329
                $this->isType('int'),
1330
                $this->equalTo($contentType),
1331
                $this->equalTo([])
1332
            );
1333
1334
        if (!$withObjectStates) {
1335
            $objectStateHandlerMock->expects($this->once())
1336
                ->method('loadAllGroups')
1337
                ->will($this->returnValue([]));
1338
        }
1339
1340
        if ($execute) {
1341
            $spiContentCreateStruct = new SPIContentCreateStruct(
1342
                [
1343
                    'name' => [],
1344
                    'typeId' => 123,
1345
                    'sectionId' => 1,
1346
                    'ownerId' => 169,
1347
                    'remoteId' => 'hash',
1348
                    'fields' => $spiFields,
1349
                    'modified' => time(),
1350
                    'initialLanguageId' => 4242,
1351
                ]
1352
            );
1353
            $spiContentCreateStruct2 = clone $spiContentCreateStruct;
1354
            ++$spiContentCreateStruct2->modified;
1355
1356
            $spiContent = new SPIContent(
1357
                [
1358
                    'versionInfo' => new SPIContent\VersionInfo(
1359
                        [
1360
                            'contentInfo' => new SPIContent\ContentInfo(['id' => 42]),
1361
                            'versionNo' => 7,
1362
                        ]
1363
                    ),
1364
                ]
1365
            );
1366
1367
            $contentHandlerMock->expects($this->once())
1368
                ->method('create')
1369
                ->with($this->logicalOr($spiContentCreateStruct, $spiContentCreateStruct2))
1370
                ->will($this->returnValue($spiContent));
1371
1372
            $repositoryMock->expects($this->once())->method('commit');
1373
            $domainMapperMock->expects($this->once())
1374
                ->method('buildContentDomainObject')
1375
                ->with(
1376
                    $this->isInstanceOf('eZ\\Publish\\SPI\\Persistence\\Content'),
1377
                    $this->equalTo(null)
1378
                );
1379
1380
            $mockedService->createContent($contentCreateStruct, []);
1381
        }
1382
1383
        return $contentCreateStruct;
1384
    }
1385
1386
    public function providerForTestCreateContentNonRedundantFieldSet1()
1387
    {
1388
        $spiFields = [
1389
            new SPIField(
1390
                [
1391
                    'fieldDefinitionId' => 'fieldDefinitionId',
1392
                    'type' => 'fieldTypeIdentifier',
1393
                    'value' => 'newValue',
1394
                    'languageCode' => 'eng-US',
1395
                ]
1396
            ),
1397
        ];
1398
1399
        return [
1400
            // 0. Without language set
1401
            [
1402
                'eng-US',
1403
                [
1404
                    new Field(
1405
                        [
1406
                            'fieldDefIdentifier' => 'identifier',
1407
                            'value' => 'newValue',
1408
                            'languageCode' => 'eng-US',
1409
                        ]
1410
                    ),
1411
                ],
1412
                $spiFields,
1413
            ],
1414
            // 1. Without language set
1415
            [
1416
                'eng-US',
1417
                [
1418
                    new Field(
1419
                        [
1420
                            'fieldDefIdentifier' => 'identifier',
1421
                            'value' => 'newValue',
1422
                            'languageCode' => null,
1423
                        ]
1424
                    ),
1425
                ],
1426
                $spiFields,
1427
            ],
1428
        ];
1429
    }
1430
1431
    /**
1432
     * Test for the createContent() method.
1433
     *
1434
     * Testing the simplest use case.
1435
     *
1436
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
1437
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
1438
     * @covers \eZ\Publish\Core\Repository\ContentService::cloneField
1439
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
1440
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
1441
     * @dataProvider providerForTestCreateContentNonRedundantFieldSet1
1442
     */
1443 View Code Duplication
    public function testCreateContentNonRedundantFieldSet1($mainLanguageCode, $structFields, $spiFields)
1444
    {
1445
        $fieldDefinitions = [
1446
            new FieldDefinition(
1447
                [
1448
                    'id' => 'fieldDefinitionId',
1449
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1450
                    'isTranslatable' => false,
1451
                    'identifier' => 'identifier',
1452
                    'isRequired' => false,
1453
                    'defaultValue' => 'defaultValue',
1454
                ]
1455
            ),
1456
        ];
1457
1458
        $this->assertForTestCreateContentNonRedundantFieldSet(
1459
            $mainLanguageCode,
1460
            $structFields,
1461
            $spiFields,
1462
            $fieldDefinitions
1463
        );
1464
    }
1465
1466
    public function providerForTestCreateContentNonRedundantFieldSet2()
1467
    {
1468
        $spiFields = [
1469
            new SPIField(
1470
                [
1471
                    'fieldDefinitionId' => 'fieldDefinitionId1',
1472
                    'type' => 'fieldTypeIdentifier',
1473
                    'value' => 'newValue1',
1474
                    'languageCode' => 'eng-US',
1475
                ]
1476
            ),
1477
            new SPIField(
1478
                [
1479
                    'fieldDefinitionId' => 'fieldDefinitionId2',
1480
                    'type' => 'fieldTypeIdentifier',
1481
                    'value' => 'newValue2',
1482
                    'languageCode' => 'ger-DE',
1483
                ]
1484
            ),
1485
        ];
1486
1487
        return [
1488
            // 0. With language set
1489
            [
1490
                'eng-US',
1491
                [
1492
                    new Field(
1493
                        [
1494
                            'fieldDefIdentifier' => 'identifier1',
1495
                            'value' => 'newValue1',
1496
                            'languageCode' => 'eng-US',
1497
                        ]
1498
                    ),
1499
                    new Field(
1500
                        [
1501
                            'fieldDefIdentifier' => 'identifier2',
1502
                            'value' => 'newValue2',
1503
                            'languageCode' => 'ger-DE',
1504
                        ]
1505
                    ),
1506
                ],
1507
                $spiFields,
1508
            ],
1509
            // 1. Without language set
1510
            [
1511
                'eng-US',
1512
                [
1513
                    new Field(
1514
                        [
1515
                            'fieldDefIdentifier' => 'identifier1',
1516
                            'value' => 'newValue1',
1517
                            'languageCode' => null,
1518
                        ]
1519
                    ),
1520
                    new Field(
1521
                        [
1522
                            'fieldDefIdentifier' => 'identifier2',
1523
                            'value' => 'newValue2',
1524
                            'languageCode' => 'ger-DE',
1525
                        ]
1526
                    ),
1527
                ],
1528
                $spiFields,
1529
            ],
1530
        ];
1531
    }
1532
1533
    /**
1534
     * Test for the createContent() method.
1535
     *
1536
     * Testing multiple languages with multiple translatable fields with empty default value.
1537
     *
1538
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
1539
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
1540
     * @covers \eZ\Publish\Core\Repository\ContentService::cloneField
1541
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
1542
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
1543
     * @dataProvider providerForTestCreateContentNonRedundantFieldSet2
1544
     */
1545
    public function testCreateContentNonRedundantFieldSet2($mainLanguageCode, $structFields, $spiFields)
1546
    {
1547
        $fieldDefinitions = [
1548
            new FieldDefinition(
1549
                [
1550
                    'id' => 'fieldDefinitionId1',
1551
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1552
                    'isTranslatable' => true,
1553
                    'identifier' => 'identifier1',
1554
                    'isRequired' => false,
1555
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
1556
                ]
1557
            ),
1558
            new FieldDefinition(
1559
                [
1560
                    'id' => 'fieldDefinitionId2',
1561
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1562
                    'isTranslatable' => true,
1563
                    'identifier' => 'identifier2',
1564
                    'isRequired' => false,
1565
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
1566
                ]
1567
            ),
1568
        ];
1569
1570
        $this->assertForTestCreateContentNonRedundantFieldSet(
1571
            $mainLanguageCode,
1572
            $structFields,
1573
            $spiFields,
1574
            $fieldDefinitions
1575
        );
1576
    }
1577
1578
    public function providerForTestCreateContentNonRedundantFieldSetComplex()
1579
    {
1580
        $spiFields0 = [
1581
            new SPIField(
1582
                [
1583
                    'fieldDefinitionId' => 'fieldDefinitionId2',
1584
                    'type' => 'fieldTypeIdentifier',
1585
                    'value' => 'defaultValue2',
1586
                    'languageCode' => 'eng-US',
1587
                ]
1588
            ),
1589
            new SPIField(
1590
                [
1591
                    'fieldDefinitionId' => 'fieldDefinitionId4',
1592
                    'type' => 'fieldTypeIdentifier',
1593
                    'value' => 'defaultValue4',
1594
                    'languageCode' => 'eng-US',
1595
                ]
1596
            ),
1597
        ];
1598
        $spiFields1 = [
1599
            new SPIField(
1600
                [
1601
                    'fieldDefinitionId' => 'fieldDefinitionId1',
1602
                    'type' => 'fieldTypeIdentifier',
1603
                    'value' => 'newValue1',
1604
                    'languageCode' => 'ger-DE',
1605
                ]
1606
            ),
1607
            new SPIField(
1608
                [
1609
                    'fieldDefinitionId' => 'fieldDefinitionId2',
1610
                    'type' => 'fieldTypeIdentifier',
1611
                    'value' => 'defaultValue2',
1612
                    'languageCode' => 'ger-DE',
1613
                ]
1614
            ),
1615
            new SPIField(
1616
                [
1617
                    'fieldDefinitionId' => 'fieldDefinitionId2',
1618
                    'type' => 'fieldTypeIdentifier',
1619
                    'value' => 'newValue2',
1620
                    'languageCode' => 'eng-US',
1621
                ]
1622
            ),
1623
            new SPIField(
1624
                [
1625
                    'fieldDefinitionId' => 'fieldDefinitionId4',
1626
                    'type' => 'fieldTypeIdentifier',
1627
                    'value' => 'newValue4',
1628
                    'languageCode' => 'eng-US',
1629
                ]
1630
            ),
1631
        ];
1632
1633
        return [
1634
            // 0. Creating by default values only
1635
            [
1636
                'eng-US',
1637
                [],
1638
                $spiFields0,
1639
            ],
1640
            // 1. Multiple languages with language set
1641
            [
1642
                'eng-US',
1643
                [
1644
                    new Field(
1645
                        [
1646
                            'fieldDefIdentifier' => 'identifier1',
1647
                            'value' => 'newValue1',
1648
                            'languageCode' => 'ger-DE',
1649
                        ]
1650
                    ),
1651
                    new Field(
1652
                        [
1653
                            'fieldDefIdentifier' => 'identifier2',
1654
                            'value' => 'newValue2',
1655
                            'languageCode' => 'eng-US',
1656
                        ]
1657
                    ),
1658
                    new Field(
1659
                        [
1660
                            'fieldDefIdentifier' => 'identifier4',
1661
                            'value' => 'newValue4',
1662
                            'languageCode' => 'eng-US',
1663
                        ]
1664
                    ),
1665
                ],
1666
                $spiFields1,
1667
            ],
1668
            // 2. Multiple languages without language set
1669
            [
1670
                'eng-US',
1671
                [
1672
                    new Field(
1673
                        [
1674
                            'fieldDefIdentifier' => 'identifier1',
1675
                            'value' => 'newValue1',
1676
                            'languageCode' => 'ger-DE',
1677
                        ]
1678
                    ),
1679
                    new Field(
1680
                        [
1681
                            'fieldDefIdentifier' => 'identifier2',
1682
                            'value' => 'newValue2',
1683
                            'languageCode' => null,
1684
                        ]
1685
                    ),
1686
                    new Field(
1687
                        [
1688
                            'fieldDefIdentifier' => 'identifier4',
1689
                            'value' => 'newValue4',
1690
                            'languageCode' => null,
1691
                        ]
1692
                    ),
1693
                ],
1694
                $spiFields1,
1695
            ],
1696
        ];
1697
    }
1698
1699
    protected function fixturesForTestCreateContentNonRedundantFieldSetComplex()
1700
    {
1701
        return [
1702
            new FieldDefinition(
1703
                [
1704
                    'id' => 'fieldDefinitionId1',
1705
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1706
                    'isTranslatable' => true,
1707
                    'identifier' => 'identifier1',
1708
                    'isRequired' => false,
1709
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
1710
                ]
1711
            ),
1712
            new FieldDefinition(
1713
                [
1714
                    'id' => 'fieldDefinitionId2',
1715
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1716
                    'isTranslatable' => true,
1717
                    'identifier' => 'identifier2',
1718
                    'isRequired' => false,
1719
                    'defaultValue' => 'defaultValue2',
1720
                ]
1721
            ),
1722
            new FieldDefinition(
1723
                [
1724
                    'id' => 'fieldDefinitionId3',
1725
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1726
                    'isTranslatable' => false,
1727
                    'identifier' => 'identifier3',
1728
                    'isRequired' => false,
1729
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
1730
                ]
1731
            ),
1732
            new FieldDefinition(
1733
                [
1734
                    'id' => 'fieldDefinitionId4',
1735
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1736
                    'isTranslatable' => false,
1737
                    'identifier' => 'identifier4',
1738
                    'isRequired' => false,
1739
                    'defaultValue' => 'defaultValue4',
1740
                ]
1741
            ),
1742
        ];
1743
    }
1744
1745
    /**
1746
     * Test for the createContent() method.
1747
     *
1748
     * Testing multiple languages with multiple translatable fields with empty default value.
1749
     *
1750
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
1751
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
1752
     * @covers \eZ\Publish\Core\Repository\ContentService::cloneField
1753
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
1754
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
1755
     * @dataProvider providerForTestCreateContentNonRedundantFieldSetComplex
1756
     */
1757
    public function testCreateContentNonRedundantFieldSetComplex($mainLanguageCode, $structFields, $spiFields)
1758
    {
1759
        $fieldDefinitions = $this->fixturesForTestCreateContentNonRedundantFieldSetComplex();
1760
1761
        $this->assertForTestCreateContentNonRedundantFieldSet(
1762
            $mainLanguageCode,
1763
            $structFields,
1764
            $spiFields,
1765
            $fieldDefinitions
1766
        );
1767
    }
1768
1769 View Code Duplication
    public function providerForTestCreateContentWithInvalidLanguage()
1770
    {
1771
        return [
1772
            [
1773
                'eng-GB',
1774
                [
1775
                    new Field(
1776
                        [
1777
                            'fieldDefIdentifier' => 'identifier',
1778
                            'value' => 'newValue',
1779
                            'languageCode' => 'Klingon',
1780
                        ]
1781
                    ),
1782
                ],
1783
            ],
1784
            [
1785
                'Klingon',
1786
                [
1787
                    new Field(
1788
                        [
1789
                            'fieldDefIdentifier' => 'identifier',
1790
                            'value' => 'newValue',
1791
                            'languageCode' => 'eng-GB',
1792
                        ]
1793
                    ),
1794
                ],
1795
            ],
1796
        ];
1797
    }
1798
1799
    /**
1800
     * Test for the updateContent() method.
1801
     *
1802
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
1803
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
1804
     * @dataProvider providerForTestCreateContentWithInvalidLanguage
1805
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
1806
     * @expectedExceptionMessage Could not find 'Language' with identifier 'Klingon'
1807
     */
1808
    public function testCreateContentWithInvalidLanguage($mainLanguageCode, $structFields)
1809
    {
1810
        $repositoryMock = $this->getRepositoryMock();
1811
        $mockedService = $this->getPartlyMockedContentService();
1812
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
1813
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
1814
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
1815
        $domainMapperMock = $this->getDomainMapperMock();
1816
        $contentType = new ContentType(
1817
            [
1818
                'id' => 123,
1819
                'fieldDefinitions' => [],
1820
            ]
1821
        );
1822
        $contentCreateStruct = new ContentCreateStruct(
1823
            [
1824
                'fields' => $structFields,
1825
                'mainLanguageCode' => $mainLanguageCode,
1826
                'contentType' => $contentType,
1827
                'alwaysAvailable' => false,
1828
                'ownerId' => 169,
1829
                'sectionId' => 1,
1830
            ]
1831
        );
1832
1833
        $languageHandlerMock->expects($this->any())
1834
            ->method('loadByLanguageCode')
1835
            ->with($this->isType('string'))
1836
            ->will(
1837
                $this->returnCallback(
1838 View Code Duplication
                    function ($languageCode) {
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...
1839
                        if ($languageCode === 'Klingon') {
1840
                            throw new NotFoundException('Language', 'Klingon');
1841
                        }
1842
1843
                        return new Language(['id' => 4242]);
1844
                    }
1845
                )
1846
            );
1847
1848
        $contentTypeServiceMock->expects($this->once())
1849
            ->method('loadContentType')
1850
            ->with($this->equalTo($contentType->id))
1851
            ->will($this->returnValue($contentType));
1852
1853
        $repositoryMock->expects($this->once())
1854
            ->method('getContentTypeService')
1855
            ->will($this->returnValue($contentTypeServiceMock));
1856
1857
        $that = $this;
1858
        $repositoryMock->expects($this->once())
1859
            ->method('canUser')
1860
            ->with(
1861
                $this->equalTo('content'),
1862
                $this->equalTo('create'),
1863
                $this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'),
1864
                $this->equalTo([])
1865
            )->will(
1866
                $this->returnCallback(
1867
                    function () use ($that, $contentCreateStruct) {
1868
                        $that->assertEquals($contentCreateStruct, func_get_arg(2));
1869
1870
                        return true;
1871
                    }
1872
                )
1873
            );
1874
1875
        $domainMapperMock->expects($this->once())
1876
            ->method('getUniqueHash')
1877
            ->with($this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'))
1878
            ->will(
1879
                $this->returnCallback(
1880
                    function ($object) use ($that, $contentCreateStruct) {
1881
                        $that->assertEquals($contentCreateStruct, $object);
1882
1883
                        return 'hash';
1884
                    }
1885
                )
1886
            );
1887
1888
        $mockedService->createContent($contentCreateStruct, []);
1889
    }
1890
1891
    protected function assertForCreateContentContentValidationException(
1892
        $mainLanguageCode,
1893
        $structFields,
1894
        $fieldDefinitions = []
1895
    ) {
1896
        $repositoryMock = $this->getRepositoryMock();
1897
        $mockedService = $this->getPartlyMockedContentService(['loadContentByRemoteId']);
1898
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
1899
        $contentType = new ContentType(
1900
            [
1901
                'id' => 123,
1902
                'fieldDefinitions' => $fieldDefinitions,
1903
            ]
1904
        );
1905
        $contentCreateStruct = new ContentCreateStruct(
1906
            [
1907
                'ownerId' => 169,
1908
                'alwaysAvailable' => false,
1909
                'remoteId' => 'faraday',
1910
                'mainLanguageCode' => $mainLanguageCode,
1911
                'fields' => $structFields,
1912
                'contentType' => $contentType,
1913
            ]
1914
        );
1915
1916
        $contentTypeServiceMock->expects($this->once())
1917
            ->method('loadContentType')
1918
            ->with($this->equalTo(123))
1919
            ->will($this->returnValue($contentType));
1920
1921
        $repositoryMock->expects($this->once())
1922
            ->method('getContentTypeService')
1923
            ->will($this->returnValue($contentTypeServiceMock));
1924
1925
        $repositoryMock->expects($this->once())
1926
            ->method('canUser')
1927
            ->with(
1928
                $this->equalTo('content'),
1929
                $this->equalTo('create'),
1930
                $this->isInstanceOf($contentCreateStruct),
1931
                $this->equalTo([])
1932
            )->will($this->returnValue(true));
1933
1934
        $mockedService->expects($this->once())
1935
            ->method('loadContentByRemoteId')
1936
            ->with($contentCreateStruct->remoteId)
1937
            ->will(
1938
                $this->throwException(new NotFoundException('Content', 'faraday'))
1939
            );
1940
1941
        $mockedService->createContent($contentCreateStruct, []);
1942
    }
1943
1944 View Code Duplication
    public function providerForTestCreateContentThrowsContentValidationExceptionFieldDefinition()
1945
    {
1946
        return [
1947
            [
1948
                'eng-GB',
1949
                [
1950
                    new Field(
1951
                        [
1952
                            'fieldDefIdentifier' => 'identifier',
1953
                            'value' => 'newValue',
1954
                            'languageCode' => 'eng-GB',
1955
                        ]
1956
                    ),
1957
                ],
1958
            ],
1959
        ];
1960
    }
1961
1962
    /**
1963
     * Test for the createContent() method.
1964
     *
1965
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
1966
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
1967
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
1968
     * @dataProvider providerForTestCreateContentThrowsContentValidationExceptionFieldDefinition
1969
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentValidationException
1970
     * @expectedExceptionMessage Field definition 'identifier' does not exist in given ContentType
1971
     */
1972
    public function testCreateContentThrowsContentValidationExceptionFieldDefinition($mainLanguageCode, $structFields)
1973
    {
1974
        $this->assertForCreateContentContentValidationException(
1975
            $mainLanguageCode,
1976
            $structFields,
1977
            []
1978
        );
1979
    }
1980
1981 View Code Duplication
    public function providerForTestCreateContentThrowsContentValidationExceptionTranslation()
1982
    {
1983
        return [
1984
            [
1985
                'eng-GB',
1986
                [
1987
                    new Field(
1988
                        [
1989
                            'fieldDefIdentifier' => 'identifier',
1990
                            'value' => 'newValue',
1991
                            'languageCode' => 'eng-US',
1992
                        ]
1993
                    ),
1994
                ],
1995
            ],
1996
        ];
1997
    }
1998
1999
    /**
2000
     * Test for the createContent() method.
2001
     *
2002
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
2003
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
2004
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
2005
     * @dataProvider providerForTestCreateContentThrowsContentValidationExceptionTranslation
2006
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentValidationException
2007
     * @expectedExceptionMessage A value is set for non translatable field definition 'identifier' with language 'eng-US'
2008
     */
2009 View Code Duplication
    public function testCreateContentThrowsContentValidationExceptionTranslation($mainLanguageCode, $structFields)
2010
    {
2011
        $fieldDefinitions = [
2012
            new FieldDefinition(
2013
                [
2014
                    'id' => 'fieldDefinitionId1',
2015
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
2016
                    'isTranslatable' => false,
2017
                    'identifier' => 'identifier',
2018
                    'isRequired' => false,
2019
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
2020
                ]
2021
            ),
2022
        ];
2023
2024
        $this->assertForCreateContentContentValidationException(
2025
            $mainLanguageCode,
2026
            $structFields,
2027
            $fieldDefinitions
2028
        );
2029
    }
2030
2031
    /**
2032
     * Asserts behaviour necessary for testing ContentFieldValidationException because of required
2033
     * field being empty.
2034
     *
2035
     * @param string $mainLanguageCode
2036
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
2037
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
2038
     *
2039
     * @return mixed
2040
     */
2041
    protected function assertForTestCreateContentRequiredField(
2042
        $mainLanguageCode,
2043
        array $structFields,
2044
        array $fieldDefinitions
2045
    ) {
2046
        $repositoryMock = $this->getRepositoryMock();
2047
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
2048
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
2049
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
2050
        $fieldTypeServiceMock = $this->getFieldTypeServiceMock();
0 ignored issues
show
Unused Code introduced by
$fieldTypeServiceMock 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...
2051
        $domainMapperMock = $this->getDomainMapperMock();
2052
        $fieldTypeMock = $this->createMock('eZ\\Publish\\SPI\\FieldType\\FieldType');
2053
        $contentType = new ContentType(
2054
            [
2055
                'id' => 123,
2056
                'fieldDefinitions' => $fieldDefinitions,
2057
                'nameSchema' => '<nameSchema>',
2058
            ]
2059
        );
2060
        $contentCreateStruct = new ContentCreateStruct(
2061
            [
2062
                'fields' => $structFields,
2063
                'mainLanguageCode' => $mainLanguageCode,
2064
                'contentType' => $contentType,
2065
                'alwaysAvailable' => false,
2066
                'ownerId' => 169,
2067
                'sectionId' => 1,
2068
            ]
2069
        );
2070
2071
        $languageHandlerMock->expects($this->any())
2072
            ->method('loadByLanguageCode')
2073
            ->with($this->isType('string'))
2074
            ->will(
2075
                $this->returnCallback(
2076
                    function () {
2077
                        return new Language(['id' => 4242]);
2078
                    }
2079
                )
2080
            );
2081
2082
        $contentTypeServiceMock->expects($this->once())
2083
            ->method('loadContentType')
2084
            ->with($this->equalTo($contentType->id))
2085
            ->will($this->returnValue($contentType));
2086
2087
        $repositoryMock->expects($this->once())
2088
            ->method('getContentTypeService')
2089
            ->will($this->returnValue($contentTypeServiceMock));
2090
2091
        $that = $this;
2092
        $repositoryMock->expects($this->once())
2093
            ->method('canUser')
2094
            ->with(
2095
                $this->equalTo('content'),
2096
                $this->equalTo('create'),
2097
                $this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'),
2098
                $this->equalTo([])
2099
            )->will(
2100
                $this->returnCallback(
2101
                    function () use ($that, $contentCreateStruct) {
2102
                        $that->assertEquals($contentCreateStruct, func_get_arg(2));
2103
2104
                        return true;
2105
                    }
2106
                )
2107
            );
2108
2109
        $domainMapperMock->expects($this->once())
2110
            ->method('getUniqueHash')
2111
            ->with($this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'))
2112
            ->will(
2113
                $this->returnCallback(
2114
                    function ($object) use ($that, $contentCreateStruct) {
2115
                        $that->assertEquals($contentCreateStruct, $object);
2116
2117
                        return 'hash';
2118
                    }
2119
                )
2120
            );
2121
2122
        $fieldTypeMock->expects($this->any())
2123
            ->method('acceptValue')
2124
            ->will(
2125
                $this->returnCallback(
2126
                    function ($valueString) {
2127
                        return new ValueStub($valueString);
2128
                    }
2129
                )
2130
            );
2131
2132
        $emptyValue = self::EMPTY_FIELD_VALUE;
2133
        $fieldTypeMock->expects($this->any())
2134
            ->method('isEmptyValue')
2135
            ->will(
2136
                $this->returnCallback(
2137
                    function (ValueStub $value) use ($emptyValue) {
2138
                        return $emptyValue === (string)$value;
2139
                    }
2140
                )
2141
            );
2142
2143
        $fieldTypeMock->expects($this->any())
2144
            ->method('validate')
2145
            ->will($this->returnValue([]));
2146
2147
        $this->getFieldTypeRegistryMock()->expects($this->any())
2148
            ->method('getFieldType')
2149
            ->will($this->returnValue($fieldTypeMock));
2150
2151
        return $contentCreateStruct;
2152
    }
2153
2154 View Code Duplication
    public function providerForTestCreateContentThrowsContentValidationExceptionRequiredField()
2155
    {
2156
        return [
2157
            [
2158
                'eng-US',
2159
                [
2160
                    new Field(
2161
                        [
2162
                            'fieldDefIdentifier' => 'identifier',
2163
                            'value' => self::EMPTY_FIELD_VALUE,
2164
                            'languageCode' => null,
2165
                        ]
2166
                    ),
2167
                ],
2168
                'identifier',
2169
                'eng-US',
2170
            ],
2171
        ];
2172
    }
2173
2174
    /**
2175
     * Test for the createContent() method.
2176
     *
2177
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
2178
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
2179
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
2180
     * @dataProvider providerForTestCreateContentThrowsContentValidationExceptionRequiredField
2181
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
2182
     */
2183
    public function testCreateContentRequiredField(
2184
        $mainLanguageCode,
2185
        $structFields,
2186
        $identifier,
2187
        $languageCode
2188
    ) {
2189
        $fieldDefinitions = [
2190
            new FieldDefinition(
2191
                [
2192
                    'id' => 'fieldDefinitionId',
2193
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
2194
                    'isTranslatable' => true,
2195
                    'identifier' => 'identifier',
2196
                    'isRequired' => true,
2197
                    'defaultValue' => 'defaultValue',
2198
                ]
2199
            ),
2200
        ];
2201
        $contentCreateStruct = $this->assertForTestCreateContentRequiredField(
2202
            $mainLanguageCode,
2203
            $structFields,
2204
            $fieldDefinitions
2205
        );
2206
2207
        $mockedService = $this->getPartlyMockedContentService();
2208
2209
        try {
2210
            $mockedService->createContent($contentCreateStruct, []);
2211
        } catch (ContentValidationException $e) {
2212
            $this->assertEquals(
2213
                "Value for required field definition '{$identifier}' with language '{$languageCode}' is empty",
2214
                $e->getMessage()
2215
            );
2216
2217
            throw $e;
2218
        }
2219
    }
2220
2221
    /**
2222
     * Asserts behaviour necessary for testing ContentFieldValidationException because of
2223
     * field not being valid.
2224
     *
2225
     * @param string $mainLanguageCode
2226
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
2227
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
2228
     *
2229
     * @return mixed
2230
     */
2231
    protected function assertForTestCreateContentThrowsContentFieldValidationException(
2232
        $mainLanguageCode,
2233
        array $structFields,
2234
        array $fieldDefinitions
2235
    ) {
2236
        $repositoryMock = $this->getRepositoryMock();
2237
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
2238
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
2239
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
2240
        $fieldTypeServiceMock = $this->getFieldTypeServiceMock();
0 ignored issues
show
Unused Code introduced by
$fieldTypeServiceMock 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...
2241
        $domainMapperMock = $this->getDomainMapperMock();
2242
        $relationProcessorMock = $this->getRelationProcessorMock();
2243
        $fieldTypeMock = $this->createMock('eZ\\Publish\\SPI\\FieldType\\FieldType');
2244
        $languageCodes = $this->determineLanguageCodesForCreate($mainLanguageCode, $structFields);
2245
        $contentType = new ContentType(
2246
            [
2247
                'id' => 123,
2248
                'fieldDefinitions' => $fieldDefinitions,
2249
                'nameSchema' => '<nameSchema>',
2250
            ]
2251
        );
2252
        $contentCreateStruct = new ContentCreateStruct(
2253
            [
2254
                'fields' => $structFields,
2255
                'mainLanguageCode' => $mainLanguageCode,
2256
                'contentType' => $contentType,
2257
                'alwaysAvailable' => false,
2258
                'ownerId' => 169,
2259
                'sectionId' => 1,
2260
            ]
2261
        );
2262
2263
        $languageHandlerMock->expects($this->any())
2264
            ->method('loadByLanguageCode')
2265
            ->with($this->isType('string'))
2266
            ->will(
2267
                $this->returnCallback(
2268
                    function () {
2269
                        return new Language(['id' => 4242]);
2270
                    }
2271
                )
2272
            );
2273
2274
        $contentTypeServiceMock->expects($this->once())
2275
            ->method('loadContentType')
2276
            ->with($this->equalTo($contentType->id))
2277
            ->will($this->returnValue($contentType));
2278
2279
        $repositoryMock->expects($this->once())
2280
            ->method('getContentTypeService')
2281
            ->will($this->returnValue($contentTypeServiceMock));
2282
2283
        $that = $this;
2284
        $repositoryMock->expects($this->once())
2285
            ->method('canUser')
2286
            ->with(
2287
                $this->equalTo('content'),
2288
                $this->equalTo('create'),
2289
                $this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'),
2290
                $this->equalTo([])
2291
            )->will(
2292
                $this->returnCallback(
2293
                    function () use ($that, $contentCreateStruct) {
2294
                        $that->assertEquals($contentCreateStruct, func_get_arg(2));
2295
2296
                        return true;
2297
                    }
2298
                )
2299
            );
2300
2301
        $domainMapperMock->expects($this->once())
2302
            ->method('getUniqueHash')
2303
            ->with($this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'))
2304
            ->will(
2305
                $this->returnCallback(
2306
                    function ($object) use ($that, $contentCreateStruct) {
2307
                        $that->assertEquals($contentCreateStruct, $object);
2308
2309
                        return 'hash';
2310
                    }
2311
                )
2312
            );
2313
2314
        $this->getFieldTypeRegistryMock()->expects($this->any())
2315
            ->method('getFieldType')
2316
            ->will($this->returnValue($fieldTypeMock));
2317
2318
        $relationProcessorMock
2319
            ->expects($this->any())
2320
            ->method('appendFieldRelations')
2321
            ->with(
2322
                $this->isType('array'),
2323
                $this->isType('array'),
2324
                $this->isInstanceOf('eZ\\Publish\\SPI\\FieldType\\FieldType'),
2325
                $this->isInstanceOf('eZ\\Publish\\Core\\FieldType\\Value'),
2326
                $this->anything()
2327
            );
2328
2329
        $fieldValues = $this->determineValuesForCreate(
2330
            $mainLanguageCode,
2331
            $structFields,
2332
            $fieldDefinitions,
2333
            $languageCodes
2334
        );
2335
        $allFieldErrors = [];
2336
        $validateCount = 0;
2337
        $emptyValue = self::EMPTY_FIELD_VALUE;
2338
        foreach ($contentType->getFieldDefinitions() as $fieldDefinition) {
2339
            foreach ($fieldValues[$fieldDefinition->identifier] as $languageCode => $value) {
2340
                $fieldTypeMock->expects($this->at($validateCount++))
2341
                    ->method('acceptValue')
2342
                    ->will(
2343
                        $this->returnCallback(
2344
                            function ($valueString) {
2345
                                return new ValueStub($valueString);
2346
                            }
2347
                        )
2348
                    );
2349
2350
                $fieldTypeMock->expects($this->at($validateCount++))
2351
                    ->method('isEmptyValue')
2352
                    ->will(
2353
                        $this->returnCallback(
2354
                            function (ValueStub $value) use ($emptyValue) {
2355
                                return $emptyValue === (string)$value;
2356
                            }
2357
                        )
2358
                    );
2359
2360
                if (self::EMPTY_FIELD_VALUE === (string)$value) {
2361
                    continue;
2362
                }
2363
2364
                $fieldTypeMock->expects($this->at($validateCount++))
2365
                    ->method('validate')
2366
                    ->with(
2367
                        $this->equalTo($fieldDefinition),
2368
                        $this->equalTo($value)
2369
                    )->will($this->returnArgument(1));
2370
2371
                $allFieldErrors[$fieldDefinition->id][$languageCode] = $value;
2372
            }
2373
        }
2374
2375
        return [$contentCreateStruct, $allFieldErrors];
2376
    }
2377
2378
    public function providerForTestCreateContentThrowsContentFieldValidationException()
2379
    {
2380
        return $this->providerForTestCreateContentNonRedundantFieldSetComplex();
2381
    }
2382
2383
    /**
2384
     * Test for the createContent() method.
2385
     *
2386
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
2387
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
2388
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
2389
     * @dataProvider providerForTestCreateContentThrowsContentFieldValidationException
2390
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
2391
     * @expectedExceptionMessage Content fields did not validate
2392
     */
2393
    public function testCreateContentThrowsContentFieldValidationException($mainLanguageCode, $structFields)
2394
    {
2395
        $fieldDefinitions = $this->fixturesForTestCreateContentNonRedundantFieldSetComplex();
2396
        list($contentCreateStruct, $allFieldErrors) =
2397
            $this->assertForTestCreateContentThrowsContentFieldValidationException(
2398
                $mainLanguageCode,
2399
                $structFields,
2400
                $fieldDefinitions
2401
            );
2402
2403
        $mockedService = $this->getPartlyMockedContentService();
2404
2405
        try {
2406
            $mockedService->createContent($contentCreateStruct);
2407
        } catch (ContentFieldValidationException $e) {
2408
            $this->assertEquals($allFieldErrors, $e->getFieldErrors());
2409
            throw $e;
2410
        }
2411
    }
2412
2413
    /**
2414
     * Test for the createContent() method.
2415
     *
2416
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
2417
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
2418
     * @covers \eZ\Publish\Core\Repository\ContentService::buildSPILocationCreateStructs
2419
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
2420
     */
2421
    public function testCreateContentWithLocations()
2422
    {
2423
        $spiFields = [
2424
            new SPIField(
2425
                [
2426
                    'fieldDefinitionId' => 'fieldDefinitionId',
2427
                    'type' => 'fieldTypeIdentifier',
2428
                    'value' => 'defaultValue',
2429
                    'languageCode' => 'eng-US',
2430
                ]
2431
            ),
2432
        ];
2433
        $fieldDefinitions = [
2434
            new FieldDefinition(
2435
                [
2436
                    'id' => 'fieldDefinitionId',
2437
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
2438
                    'isTranslatable' => false,
2439
                    'identifier' => 'identifier',
2440
                    'isRequired' => false,
2441
                    'defaultValue' => 'defaultValue',
2442
                ]
2443
            ),
2444
        ];
2445
2446
        // Set up a simple case that will pass
2447
        $locationCreateStruct1 = new LocationCreateStruct(['parentLocationId' => 321]);
2448
        $locationCreateStruct2 = new LocationCreateStruct(['parentLocationId' => 654]);
2449
        $locationCreateStructs = [$locationCreateStruct1, $locationCreateStruct2];
2450
        $contentCreateStruct = $this->assertForTestCreateContentNonRedundantFieldSet(
2451
            'eng-US',
2452
            [],
2453
            $spiFields,
2454
            $fieldDefinitions,
2455
            $locationCreateStructs,
2456
            false,
2457
            // Do not execute
2458
            false
2459
        );
2460
2461
        $repositoryMock = $this->getRepositoryMock();
2462
        $mockedService = $this->getPartlyMockedContentService();
2463
        $locationServiceMock = $this->getLocationServiceMock();
2464
        /** @var \PHPUnit_Framework_MockObject_MockObject $handlerMock */
2465
        $handlerMock = $this->getPersistenceMock()->contentHandler();
2466
        $domainMapperMock = $this->getDomainMapperMock();
2467
        $spiLocationCreateStruct = new SPILocation\CreateStruct();
2468
        $parentLocation = new Location(['contentInfo' => new ContentInfo(['sectionId' => 1])]);
2469
2470
        $locationServiceMock->expects($this->at(0))
2471
            ->method('loadLocation')
2472
            ->with($this->equalTo(321))
2473
            ->will($this->returnValue($parentLocation));
2474
2475
        $locationServiceMock->expects($this->at(1))
2476
            ->method('loadLocation')
2477
            ->with($this->equalTo(654))
2478
            ->will($this->returnValue($parentLocation));
2479
2480
        $repositoryMock->expects($this->atLeastOnce())
2481
            ->method('getLocationService')
2482
            ->will($this->returnValue($locationServiceMock));
2483
2484
        $domainMapperMock->expects($this->at(1))
2485
            ->method('buildSPILocationCreateStruct')
2486
            ->with(
2487
                $this->equalTo($locationCreateStruct1),
2488
                $this->equalTo($parentLocation),
2489
                $this->equalTo(true),
2490
                $this->equalTo(null),
2491
                $this->equalTo(null)
2492
            )->will($this->returnValue($spiLocationCreateStruct));
2493
2494
        $domainMapperMock->expects($this->at(2))
2495
            ->method('buildSPILocationCreateStruct')
2496
            ->with(
2497
                $this->equalTo($locationCreateStruct2),
2498
                $this->equalTo($parentLocation),
2499
                $this->equalTo(false),
2500
                $this->equalTo(null),
2501
                $this->equalTo(null)
2502
            )->will($this->returnValue($spiLocationCreateStruct));
2503
2504
        $spiContentCreateStruct = new SPIContentCreateStruct(
2505
            [
2506
                'name' => [],
2507
                'typeId' => 123,
2508
                'sectionId' => 1,
2509
                'ownerId' => 169,
2510
                'remoteId' => 'hash',
2511
                'fields' => $spiFields,
2512
                'modified' => time(),
2513
                'initialLanguageId' => 4242,
2514
                'locations' => [$spiLocationCreateStruct, $spiLocationCreateStruct],
2515
            ]
2516
        );
2517
        $spiContentCreateStruct2 = clone $spiContentCreateStruct;
2518
        ++$spiContentCreateStruct2->modified;
2519
2520
        $spiContent = new SPIContent(
2521
            [
2522
                'versionInfo' => new SPIContent\VersionInfo(
2523
                    [
2524
                        'contentInfo' => new SPIContent\ContentInfo(['id' => 42]),
2525
                        'versionNo' => 7,
2526
                    ]
2527
                ),
2528
            ]
2529
        );
2530
2531
        $handlerMock->expects($this->once())
2532
            ->method('create')
2533
            ->with($this->logicalOr($spiContentCreateStruct, $spiContentCreateStruct2))
2534
            ->will($this->returnValue($spiContent));
2535
2536
        $domainMapperMock->expects($this->once())
2537
            ->method('buildContentDomainObject')
2538
            ->with(
2539
                $this->isInstanceOf('eZ\\Publish\\SPI\\Persistence\\Content'),
2540
                $this->equalTo(null)
2541
            );
2542
2543
        $repositoryMock->expects($this->once())->method('commit');
2544
2545
        // Execute
2546
        $mockedService->createContent($contentCreateStruct, $locationCreateStructs);
2547
    }
2548
2549
    /**
2550
     * Test for the createContent() method.
2551
     *
2552
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
2553
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
2554
     * @covers \eZ\Publish\Core\Repository\ContentService::buildSPILocationCreateStructs
2555
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
2556
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
2557
     * @expectedExceptionMessage Multiple LocationCreateStructs with the same parent Location '321' are given
2558
     */
2559
    public function testCreateContentWithLocationsDuplicateUnderParent()
2560
    {
2561
        $fieldDefinitions = [
2562
            new FieldDefinition(
2563
                [
2564
                    'id' => 'fieldDefinitionId',
2565
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
2566
                    'isTranslatable' => false,
2567
                    'identifier' => 'identifier',
2568
                    'isRequired' => false,
2569
                    'defaultValue' => 'defaultValue',
2570
                ]
2571
            ),
2572
        ];
2573
2574
        $repositoryMock = $this->getRepositoryMock();
2575
        $mockedService = $this->getPartlyMockedContentService();
2576
        $locationServiceMock = $this->getLocationServiceMock();
2577
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
2578
        $domainMapperMock = $this->getDomainMapperMock();
2579
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
2580
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
2581
        $spiLocationCreateStruct = new SPILocation\CreateStruct();
2582
        $parentLocation = new Location(['id' => 321]);
2583
        $locationCreateStruct = new LocationCreateStruct(['parentLocationId' => 321]);
2584
        $locationCreateStructs = [$locationCreateStruct, clone $locationCreateStruct];
2585
        $contentType = new ContentType(
2586
            [
2587
                'id' => 123,
2588
                'fieldDefinitions' => $fieldDefinitions,
2589
                'nameSchema' => '<nameSchema>',
2590
            ]
2591
        );
2592
        $contentCreateStruct = new ContentCreateStruct(
2593
            [
2594
                'fields' => [],
2595
                'mainLanguageCode' => 'eng-US',
2596
                'contentType' => $contentType,
2597
                'alwaysAvailable' => false,
2598
                'ownerId' => 169,
2599
                'sectionId' => 1,
2600
            ]
2601
        );
2602
2603
        $languageHandlerMock->expects($this->any())
2604
            ->method('loadByLanguageCode')
2605
            ->with($this->isType('string'))
2606
            ->will(
2607
                $this->returnCallback(
2608
                    function () {
2609
                        return new Language(['id' => 4242]);
2610
                    }
2611
                )
2612
            );
2613
2614
        $contentTypeServiceMock->expects($this->once())
2615
            ->method('loadContentType')
2616
            ->with($this->equalTo($contentType->id))
2617
            ->will($this->returnValue($contentType));
2618
2619
        $repositoryMock->expects($this->once())
2620
            ->method('getContentTypeService')
2621
            ->will($this->returnValue($contentTypeServiceMock));
2622
2623
        $that = $this;
2624
        $repositoryMock->expects($this->once())
2625
            ->method('canUser')
2626
            ->with(
2627
                $this->equalTo('content'),
2628
                $this->equalTo('create'),
2629
                $this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'),
2630
                $this->equalTo($locationCreateStructs)
2631
            )->will(
2632
                $this->returnCallback(
2633
                    function () use ($that, $contentCreateStruct) {
2634
                        $that->assertEquals($contentCreateStruct, func_get_arg(2));
2635
2636
                        return true;
2637
                    }
2638
                )
2639
            );
2640
2641
        $domainMapperMock->expects($this->once())
2642
            ->method('getUniqueHash')
2643
            ->with($this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'))
2644
            ->will(
2645
                $this->returnCallback(
2646
                    function ($object) use ($that, $contentCreateStruct) {
2647
                        $that->assertEquals($contentCreateStruct, $object);
2648
2649
                        return 'hash';
2650
                    }
2651
                )
2652
            );
2653
2654
        $locationServiceMock->expects($this->once())
2655
            ->method('loadLocation')
2656
            ->with($this->equalTo(321))
2657
            ->will($this->returnValue($parentLocation));
2658
2659
        $repositoryMock->expects($this->any())
2660
            ->method('getLocationService')
2661
            ->will($this->returnValue($locationServiceMock));
2662
2663
        $domainMapperMock->expects($this->any())
2664
            ->method('buildSPILocationCreateStruct')
2665
            ->with(
2666
                $this->equalTo($locationCreateStruct),
2667
                $this->equalTo($parentLocation),
2668
                $this->equalTo(true),
2669
                $this->equalTo(null),
2670
                $this->equalTo(null)
2671
            )->will($this->returnValue($spiLocationCreateStruct));
2672
2673
        $mockedService->createContent(
2674
            $contentCreateStruct,
2675
            $locationCreateStructs
2676
        );
2677
    }
2678
2679
    /**
2680
     * Test for the createContent() method.
2681
     *
2682
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
2683
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
2684
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
2685
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
2686
     */
2687
    public function testCreateContentObjectStates()
2688
    {
2689
        $spiFields = [
2690
            new SPIField(
2691
                [
2692
                    'fieldDefinitionId' => 'fieldDefinitionId',
2693
                    'type' => 'fieldTypeIdentifier',
2694
                    'value' => 'defaultValue',
2695
                    'languageCode' => 'eng-US',
2696
                ]
2697
            ),
2698
        ];
2699
        $fieldDefinitions = [
2700
            new FieldDefinition(
2701
                [
2702
                    'id' => 'fieldDefinitionId',
2703
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
2704
                    'isTranslatable' => false,
2705
                    'identifier' => 'identifier',
2706
                    'isRequired' => false,
2707
                    'defaultValue' => 'defaultValue',
2708
                ]
2709
            ),
2710
        ];
2711
        $objectStateGroups = [
0 ignored issues
show
Unused Code introduced by
$objectStateGroups 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...
2712
            new SPIObjectStateGroup(['id' => 10]),
2713
            new SPIObjectStateGroup(['id' => 20]),
2714
        ];
2715
2716
        // Set up a simple case that will pass
2717
        $contentCreateStruct = $this->assertForTestCreateContentNonRedundantFieldSet(
2718
            'eng-US',
2719
            [],
2720
            $spiFields,
2721
            $fieldDefinitions,
2722
            [],
2723
            true,
2724
            // Do not execute
2725
            false
2726
        );
2727
        $timestamp = time();
2728
        $contentCreateStruct->modificationDate = new \DateTime("@{$timestamp}");
2729
2730
        $repositoryMock = $this->getRepositoryMock();
2731
        $mockedService = $this->getPartlyMockedContentService();
2732
        /** @var \PHPUnit_Framework_MockObject_MockObject $handlerMock */
2733
        $handlerMock = $this->getPersistenceMock()->contentHandler();
2734
        $domainMapperMock = $this->getDomainMapperMock();
2735
2736
        $this->mockGetDefaultObjectStates();
2737
        $this->mockSetDefaultObjectStates();
2738
2739
        $spiContentCreateStruct = new SPIContentCreateStruct(
2740
            [
2741
                'name' => [],
2742
                'typeId' => 123,
2743
                'sectionId' => 1,
2744
                'ownerId' => 169,
2745
                'remoteId' => 'hash',
2746
                'fields' => $spiFields,
2747
                'modified' => $timestamp,
2748
                'initialLanguageId' => 4242,
2749
                'locations' => [],
2750
            ]
2751
        );
2752
        $spiContentCreateStruct2 = clone $spiContentCreateStruct;
2753
        ++$spiContentCreateStruct2->modified;
2754
2755
        $spiContent = new SPIContent(
2756
            [
2757
                'versionInfo' => new SPIContent\VersionInfo(
2758
                    [
2759
                        'contentInfo' => new SPIContent\ContentInfo(['id' => 42]),
2760
                        'versionNo' => 7,
2761
                    ]
2762
                ),
2763
            ]
2764
        );
2765
2766
        $handlerMock->expects($this->once())
2767
            ->method('create')
2768
            ->with($this->equalTo($spiContentCreateStruct))
2769
            ->will($this->returnValue($spiContent));
2770
2771
        $domainMapperMock->expects($this->once())
2772
            ->method('buildContentDomainObject')
2773
            ->with(
2774
                $this->isInstanceOf('eZ\\Publish\\SPI\\Persistence\\Content'),
2775
                $this->equalTo(null)
2776
            );
2777
2778
        $repositoryMock->expects($this->once())->method('commit');
2779
2780
        // Execute
2781
        $mockedService->createContent($contentCreateStruct, []);
2782
    }
2783
2784
    /**
2785
     * Test for the createContent() method.
2786
     *
2787
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
2788
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
2789
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
2790
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
2791
     * @dataProvider providerForTestCreateContentThrowsContentValidationExceptionTranslation
2792
     * @expectedException \Exception
2793
     * @expectedExceptionMessage Store failed
2794
     */
2795
    public function testCreateContentWithRollback()
2796
    {
2797
        $fieldDefinitions = [
2798
            new FieldDefinition(
2799
                [
2800
                    'id' => 'fieldDefinitionId',
2801
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
2802
                    'isTranslatable' => false,
2803
                    'identifier' => 'identifier',
2804
                    'isRequired' => false,
2805
                    'defaultValue' => 'defaultValue',
2806
                ]
2807
            ),
2808
        ];
2809
2810
        // Setup a simple case that will pass
2811
        $contentCreateStruct = $this->assertForTestCreateContentNonRedundantFieldSet(
2812
            'eng-US',
2813
            [],
2814
            [],
2815
            $fieldDefinitions,
2816
            [],
2817
            false,
2818
            // Do not execute test
2819
            false
2820
        );
2821
2822
        $repositoryMock = $this->getRepositoryMock();
2823
        $repositoryMock->expects($this->never())->method('commit');
2824
        $repositoryMock->expects($this->once())->method('rollback');
2825
2826
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
2827
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
2828
        $contentHandlerMock->expects($this->once())
2829
            ->method('create')
2830
            ->with($this->anything())
2831
            ->will($this->throwException(new \Exception('Store failed')));
2832
2833
        // Execute
2834
        $this->partlyMockedContentService->createContent($contentCreateStruct, []);
2835
    }
2836
2837
    public function providerForTestUpdateContentThrowsBadStateException()
2838
    {
2839
        return [
2840
            [VersionInfo::STATUS_PUBLISHED],
2841
            [VersionInfo::STATUS_ARCHIVED],
2842
        ];
2843
    }
2844
2845
    /**
2846
     * Test for the updateContent() method.
2847
     *
2848
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
2849
     * @expectedException \eZ\Publish\API\Repository\Exceptions\BadStateException
2850
     * @dataProvider providerForTestUpdateContentThrowsBadStateException
2851
     */
2852
    public function testUpdateContentThrowsBadStateException($status)
2853
    {
2854
        $mockedService = $this->getPartlyMockedContentService(['loadContent']);
2855
        $contentUpdateStruct = new ContentUpdateStruct();
2856
        $versionInfo = new VersionInfo(
2857
            [
2858
                'contentInfo' => new ContentInfo(['id' => 42]),
2859
                'versionNo' => 7,
2860
                'status' => $status,
2861
            ]
2862
        );
2863
        $content = new Content(
2864
            [
2865
                'versionInfo' => $versionInfo,
2866
                'internalFields' => [],
2867
            ]
2868
        );
2869
2870
        $mockedService->expects($this->once())
2871
            ->method('loadContent')
2872
            ->with(
2873
                $this->equalTo(42),
2874
                $this->equalTo(null),
2875
                $this->equalTo(7)
2876
            )->will(
2877
                $this->returnValue($content)
2878
            );
2879
2880
        $mockedService->updateContent($versionInfo, $contentUpdateStruct);
2881
    }
2882
2883
    /**
2884
     * Test for the updateContent() method.
2885
     *
2886
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
2887
     * @expectedException \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
2888
     */
2889
    public function testUpdateContentThrowsUnauthorizedException()
2890
    {
2891
        $repositoryMock = $this->getRepositoryMock();
2892
        $mockedService = $this->getPartlyMockedContentService(['loadContent']);
2893
        $contentUpdateStruct = new ContentUpdateStruct();
2894
        $versionInfo = new VersionInfo(
2895
            [
2896
                'contentInfo' => new ContentInfo(['id' => 42]),
2897
                'versionNo' => 7,
2898
                'status' => VersionInfo::STATUS_DRAFT,
2899
            ]
2900
        );
2901
        $content = new Content(
2902
            [
2903
                'versionInfo' => $versionInfo,
2904
                'internalFields' => [],
2905
            ]
2906
        );
2907
2908
        $mockedService->expects($this->once())
2909
            ->method('loadContent')
2910
            ->with(
2911
                $this->equalTo(42),
2912
                $this->equalTo(null),
2913
                $this->equalTo(7)
2914
            )->will(
2915
                $this->returnValue($content)
2916
            );
2917
2918
        $repositoryMock->expects($this->once())
2919
            ->method('canUser')
2920
            ->with(
2921
                $this->equalTo('content'),
2922
                $this->equalTo('edit'),
2923
                $this->equalTo($content)
2924
            )->will($this->returnValue(false));
2925
2926
        $mockedService->updateContent($versionInfo, $contentUpdateStruct);
2927
    }
2928
2929
    /**
2930
     * @param string $initialLanguageCode
2931
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
2932
     * @param string[] $existingLanguages
2933
     *
2934
     * @return string[]
2935
     */
2936
    protected function determineLanguageCodesForUpdate($initialLanguageCode, array $structFields, $existingLanguages)
2937
    {
2938
        $languageCodes = array_fill_keys($existingLanguages, true);
2939
        if ($initialLanguageCode !== null) {
2940
            $languageCodes[$initialLanguageCode] = true;
2941
        }
2942
2943
        foreach ($structFields as $field) {
2944
            if ($field->languageCode === null || isset($languageCodes[$field->languageCode])) {
2945
                continue;
2946
            }
2947
2948
            $languageCodes[$field->languageCode] = true;
2949
        }
2950
2951
        return array_keys($languageCodes);
2952
    }
2953
2954
    /**
2955
     * @param string $initialLanguageCode
2956
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
2957
     * @param string $mainLanguageCode
2958
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
2959
     *
2960
     * @return array
2961
     */
2962
    protected function mapStructFieldsForUpdate($initialLanguageCode, $structFields, $mainLanguageCode, $fieldDefinitions)
2963
    {
2964
        $initialLanguageCode = $initialLanguageCode ?: $mainLanguageCode;
2965
2966
        $mappedFieldDefinitions = [];
2967
        foreach ($fieldDefinitions as $fieldDefinition) {
2968
            $mappedFieldDefinitions[$fieldDefinition->identifier] = $fieldDefinition;
2969
        }
2970
2971
        $mappedStructFields = [];
2972
        foreach ($structFields as $structField) {
2973
            $identifier = $structField->fieldDefIdentifier;
2974
2975
            if ($structField->languageCode !== null) {
2976
                $languageCode = $structField->languageCode;
2977
            } elseif ($mappedFieldDefinitions[$identifier]->isTranslatable) {
2978
                $languageCode = $initialLanguageCode;
2979
            } else {
2980
                $languageCode = $mainLanguageCode;
2981
            }
2982
2983
            $mappedStructFields[$identifier][$languageCode] = (string)$structField->value;
2984
        }
2985
2986
        return $mappedStructFields;
2987
    }
2988
2989
    /**
2990
     * Returns full, possibly redundant array of field values, indexed by field definition
2991
     * identifier and language code.
2992
     *
2993
     * @param string $initialLanguageCode
2994
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
2995
     * @param \eZ\Publish\Core\Repository\Values\Content\Content $content
2996
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
2997
     * @param array $languageCodes
2998
     *
2999
     * @return array
3000
     */
3001
    protected function determineValuesForUpdate(
3002
        $initialLanguageCode,
3003
        array $structFields,
3004
        Content $content,
3005
        array $fieldDefinitions,
3006
        array $languageCodes
3007
    ) {
3008
        $mainLanguageCode = $content->versionInfo->contentInfo->mainLanguageCode;
3009
3010
        $mappedStructFields = $this->mapStructFieldsForUpdate(
3011
            $initialLanguageCode,
3012
            $structFields,
3013
            $mainLanguageCode,
3014
            $fieldDefinitions
3015
        );
3016
3017
        $values = [];
3018
3019
        foreach ($fieldDefinitions as $fieldDefinition) {
3020
            $identifier = $fieldDefinition->identifier;
3021
            foreach ($languageCodes as $languageCode) {
3022 View Code Duplication
                if (!$fieldDefinition->isTranslatable) {
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...
3023
                    if (isset($mappedStructFields[$identifier][$mainLanguageCode])) {
3024
                        $values[$identifier][$languageCode] = $mappedStructFields[$identifier][$mainLanguageCode];
3025
                    } else {
3026
                        $values[$identifier][$languageCode] = (string)$content->fields[$identifier][$mainLanguageCode];
3027
                    }
3028
                    continue;
3029
                }
3030
3031 View Code Duplication
                if (isset($mappedStructFields[$identifier][$languageCode])) {
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...
3032
                    $values[$identifier][$languageCode] = $mappedStructFields[$identifier][$languageCode];
3033
                    continue;
3034
                }
3035
3036
                if (isset($content->fields[$identifier][$languageCode])) {
3037
                    $values[$identifier][$languageCode] = (string)$content->fields[$identifier][$languageCode];
3038
                    continue;
3039
                }
3040
3041
                $values[$identifier][$languageCode] = (string)$fieldDefinition->defaultValue;
3042
            }
3043
        }
3044
3045
        return $this->stubValues($values);
3046
    }
3047
3048
    protected function stubValues(array $fieldValues)
3049
    {
3050
        foreach ($fieldValues as &$languageValues) {
3051
            foreach ($languageValues as &$value) {
3052
                $value = new ValueStub($value);
3053
            }
3054
        }
3055
3056
        return $fieldValues;
3057
    }
3058
3059
    /**
3060
     * Asserts that calling updateContent() with given API field set causes calling
3061
     * Handler::updateContent() with given SPI field set.
3062
     *
3063
     * @param string $initialLanguageCode
3064
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
3065
     * @param \eZ\Publish\SPI\Persistence\Content\Field[] $spiFields
3066
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $existingFields
3067
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
3068
     * @param bool $execute
3069
     *
3070
     * @return mixed
3071
     */
3072
    protected function assertForTestUpdateContentNonRedundantFieldSet(
3073
        $initialLanguageCode,
3074
        array $structFields,
3075
        array $spiFields,
3076
        array $existingFields,
3077
        array $fieldDefinitions,
3078
        $execute = true
3079
    ) {
3080
        $repositoryMock = $this->getRepositoryMock();
3081
        $mockedService = $this->getPartlyMockedContentService(['loadContent', 'loadRelations']);
3082
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
3083
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
3084
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
3085
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
3086
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
3087
        $fieldTypeServiceMock = $this->getFieldTypeServiceMock();
0 ignored issues
show
Unused Code introduced by
$fieldTypeServiceMock 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...
3088
        $domainMapperMock = $this->getDomainMapperMock();
3089
        $relationProcessorMock = $this->getRelationProcessorMock();
3090
        $nameSchemaServiceMock = $this->getNameSchemaServiceMock();
3091
        $fieldTypeMock = $this->createMock('eZ\\Publish\\SPI\\FieldType\\FieldType');
3092
        $existingLanguageCodes = array_map(
3093
            function (Field $field) {
3094
                return $field->languageCode;
3095
            },
3096
            $existingFields
3097
        );
3098
        $languageCodes = $this->determineLanguageCodesForUpdate(
3099
            $initialLanguageCode,
3100
            $structFields,
3101
            $existingLanguageCodes
3102
        );
3103
        $versionInfo = new VersionInfo(
3104
            [
3105
                'contentInfo' => new ContentInfo(
3106
                    [
3107
                        'id' => 42,
3108
                        'contentTypeId' => 24,
3109
                        'mainLanguageCode' => 'eng-GB',
3110
                    ]
3111
                ),
3112
                'versionNo' => 7,
3113
                'languageCodes' => $existingLanguageCodes,
3114
                'status' => VersionInfo::STATUS_DRAFT,
3115
            ]
3116
        );
3117
        $content = new Content(
3118
            [
3119
                'versionInfo' => $versionInfo,
3120
                'internalFields' => $existingFields,
3121
            ]
3122
        );
3123
        $contentType = new ContentType(['fieldDefinitions' => $fieldDefinitions]);
3124
3125
        $languageHandlerMock->expects($this->any())
3126
            ->method('loadByLanguageCode')
3127
            ->with($this->isType('string'))
3128
            ->will(
3129
                $this->returnCallback(
3130
                    function () {
3131
                        return new Language(['id' => 4242]);
3132
                    }
3133
                )
3134
            );
3135
3136
        $mockedService->expects($this->once())
3137
            ->method('loadContent')
3138
            ->with(
3139
                $this->equalTo(42),
3140
                $this->equalTo(null),
3141
                $this->equalTo(7)
3142
            )->will(
3143
                $this->returnValue($content)
3144
            );
3145
3146
        $repositoryMock->expects($this->once())->method('beginTransaction');
3147
3148
        $repositoryMock->expects($this->once())
3149
            ->method('canUser')
3150
            ->with(
3151
                $this->equalTo('content'),
3152
                $this->equalTo('edit'),
3153
                $this->equalTo($content)
3154
            )->will($this->returnValue(true));
3155
3156
        $contentTypeServiceMock->expects($this->once())
3157
            ->method('loadContentType')
3158
            ->with($this->equalTo(24))
3159
            ->will($this->returnValue($contentType));
3160
3161
        $repositoryMock->expects($this->once())
3162
            ->method('getContentTypeService')
3163
            ->will($this->returnValue($contentTypeServiceMock));
3164
3165
        $repositoryMock->expects($this->once())
3166
            ->method('getCurrentUserReference')
3167
            ->will($this->returnValue(new UserReference(169)));
3168
3169
        $fieldTypeMock->expects($this->any())
3170
            ->method('acceptValue')
3171
            ->will(
3172
                $this->returnCallback(
3173
                    function ($valueString) {
3174
                        return new ValueStub($valueString);
3175
                    }
3176
                )
3177
            );
3178
3179
        $emptyValue = self::EMPTY_FIELD_VALUE;
3180
        $fieldTypeMock->expects($this->any())
3181
            ->method('toPersistenceValue')
3182
            ->will(
3183
                $this->returnCallback(
3184
                    function (ValueStub $value) {
3185
                        return (string)$value;
3186
                    }
3187
                )
3188
            );
3189
3190
        $fieldTypeMock->expects($this->any())
3191
            ->method('isEmptyValue')
3192
            ->will(
3193
                $this->returnCallback(
3194
                    function (ValueStub $value) use ($emptyValue) {
3195
                        return $emptyValue === (string)$value;
3196
                    }
3197
                )
3198
            );
3199
3200
        $fieldTypeMock->expects($this->any())
3201
            ->method('validate')
3202
            ->will($this->returnValue([]));
3203
3204
        $this->getFieldTypeRegistryMock()->expects($this->any())
3205
            ->method('getFieldType')
3206
            ->will($this->returnValue($fieldTypeMock));
3207
3208
        $relationProcessorMock
3209
            ->expects($this->exactly(count($fieldDefinitions) * count($languageCodes)))
3210
            ->method('appendFieldRelations')
3211
            ->with(
3212
                $this->isType('array'),
3213
                $this->isType('array'),
3214
                $this->isInstanceOf('eZ\\Publish\\SPI\\FieldType\\FieldType'),
3215
                $this->isInstanceOf('eZ\\Publish\\Core\\FieldType\\Value'),
3216
                $this->anything()
3217
            );
3218
3219
        $values = $this->determineValuesForUpdate(
3220
            $initialLanguageCode,
3221
            $structFields,
3222
            $content,
3223
            $fieldDefinitions,
3224
            $languageCodes
3225
        );
3226
        $nameSchemaServiceMock->expects($this->once())
3227
            ->method('resolveNameSchema')
3228
            ->with(
3229
                $this->equalTo($content),
3230
                $this->equalTo($values),
3231
                $this->equalTo($languageCodes)
3232
            )->will($this->returnValue([]));
3233
3234
        $existingRelations = ['RELATIONS!!!'];
3235
        $mockedService->expects($this->once())
3236
            ->method('loadRelations')
3237
            ->with($content->versionInfo)
3238
            ->will($this->returnValue($existingRelations));
3239
        $relationProcessorMock->expects($this->any())
3240
            ->method('processFieldRelations')
3241
            ->with(
3242
                $this->isType('array'),
3243
                $this->equalTo(42),
3244
                $this->isType('int'),
3245
                $this->equalTo($contentType),
3246
                $this->equalTo($existingRelations)
3247
            );
3248
3249
        $contentUpdateStruct = new ContentUpdateStruct(
3250
            [
3251
                'fields' => $structFields,
3252
                'initialLanguageCode' => $initialLanguageCode,
3253
            ]
3254
        );
3255
3256
        if ($execute) {
3257
            $spiContentUpdateStruct = new SPIContentUpdateStruct(
3258
                [
3259
                    'creatorId' => 169,
3260
                    'fields' => $spiFields,
3261
                    'modificationDate' => time(),
3262
                    'initialLanguageId' => 4242,
3263
                ]
3264
            );
3265
3266
            // During code coverage runs, timestamp might differ 1-3 seconds
3267
            $spiContentUpdateStructTs1 = clone $spiContentUpdateStruct;
3268
            ++$spiContentUpdateStructTs1->modificationDate;
3269
3270
            $spiContentUpdateStructTs2 = clone $spiContentUpdateStructTs1;
3271
            ++$spiContentUpdateStructTs2->modificationDate;
3272
3273
            $spiContentUpdateStructTs3 = clone $spiContentUpdateStructTs2;
3274
            ++$spiContentUpdateStructTs3->modificationDate;
3275
3276
            $spiContent = new SPIContent(
3277
                [
3278
                    'versionInfo' => new SPIContent\VersionInfo(
3279
                        [
3280
                            'contentInfo' => new SPIContent\ContentInfo(['id' => 42]),
3281
                            'versionNo' => 7,
3282
                        ]
3283
                    ),
3284
                ]
3285
            );
3286
3287
            $contentHandlerMock->expects($this->once())
3288
                ->method('updateContent')
3289
                ->with(
3290
                    42,
3291
                    7,
3292
                    $this->logicalOr($spiContentUpdateStruct, $spiContentUpdateStructTs1, $spiContentUpdateStructTs2, $spiContentUpdateStructTs3)
3293
                )
3294
                ->will($this->returnValue($spiContent));
3295
3296
            $repositoryMock->expects($this->once())->method('commit');
3297
            $domainMapperMock->expects($this->once())
3298
                ->method('buildContentDomainObject')
3299
                ->with(
3300
                    $this->isInstanceOf('eZ\\Publish\\SPI\\Persistence\\Content'),
3301
                    $this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\ContentType\\ContentType')
3302
                );
3303
3304
            $mockedService->updateContent($content->versionInfo, $contentUpdateStruct);
3305
        }
3306
3307
        return [$content->versionInfo, $contentUpdateStruct];
3308
    }
3309
3310
    public function providerForTestUpdateContentNonRedundantFieldSet1()
3311
    {
3312
        $spiFields = [
3313
            new SPIField(
3314
                [
3315
                    'id' => '100',
3316
                    'fieldDefinitionId' => 'fieldDefinitionId',
3317
                    'type' => 'fieldTypeIdentifier',
3318
                    'value' => 'newValue',
3319
                    'languageCode' => 'eng-GB',
3320
                    'versionNo' => 7,
3321
                ]
3322
            ),
3323
        ];
3324
3325
        return [
3326
            // With languages set
3327
            [
3328
                'eng-GB',
3329
                [
3330
                    new Field(
3331
                        [
3332
                            'fieldDefIdentifier' => 'identifier',
3333
                            'value' => 'newValue',
3334
                            'languageCode' => 'eng-GB',
3335
                        ]
3336
                    ),
3337
                ],
3338
                $spiFields,
3339
            ],
3340
            // Without languages set
3341
            [
3342
                null,
3343
                [
3344
                    new Field(
3345
                        [
3346
                            'fieldDefIdentifier' => 'identifier',
3347
                            'value' => 'newValue',
3348
                            'languageCode' => null,
3349
                        ]
3350
                    ),
3351
                ],
3352
                $spiFields,
3353
            ],
3354
            // Adding new language without fields
3355
            [
3356
                'eng-US',
3357
                [],
3358
                [],
3359
            ],
3360
        ];
3361
    }
3362
3363
    /**
3364
     * Test for the updateContent() method.
3365
     *
3366
     * Testing the simplest use case.
3367
     *
3368
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
3369
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
3370
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
3371
     * @dataProvider providerForTestUpdateContentNonRedundantFieldSet1
3372
     */
3373 View Code Duplication
    public function testUpdateContentNonRedundantFieldSet1($initialLanguageCode, $structFields, $spiFields)
3374
    {
3375
        $existingFields = [
3376
            new Field(
3377
                [
3378
                    'id' => '100',
3379
                    'fieldDefIdentifier' => 'identifier',
3380
                    'value' => 'initialValue',
3381
                    'languageCode' => 'eng-GB',
3382
                ]
3383
            ),
3384
        ];
3385
3386
        $fieldDefinitions = [
3387
            new FieldDefinition(
3388
                [
3389
                    'id' => 'fieldDefinitionId',
3390
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
3391
                    'isTranslatable' => false,
3392
                    'identifier' => 'identifier',
3393
                    'isRequired' => false,
3394
                    'defaultValue' => 'defaultValue',
3395
                ]
3396
            ),
3397
        ];
3398
3399
        $this->assertForTestUpdateContentNonRedundantFieldSet(
3400
            $initialLanguageCode,
3401
            $structFields,
3402
            $spiFields,
3403
            $existingFields,
3404
            $fieldDefinitions
3405
        );
3406
    }
3407
3408
    public function providerForTestUpdateContentNonRedundantFieldSet2()
3409
    {
3410
        $spiFields0 = [
3411
            new SPIField(
3412
                [
3413
                    'id' => '100',
3414
                    'fieldDefinitionId' => 'fieldDefinitionId',
3415
                    'type' => 'fieldTypeIdentifier',
3416
                    'value' => 'newValue',
3417
                    'languageCode' => 'eng-GB',
3418
                    'versionNo' => 7,
3419
                ]
3420
            ),
3421
        ];
3422
        $spiFields1 = [
3423
            new SPIField(
3424
                [
3425
                    'id' => null,
3426
                    'fieldDefinitionId' => 'fieldDefinitionId',
3427
                    'type' => 'fieldTypeIdentifier',
3428
                    'value' => 'newValue',
3429
                    'languageCode' => 'eng-US',
3430
                    'versionNo' => 7,
3431
                ]
3432
            ),
3433
        ];
3434
        $spiFields2 = [
3435
            new SPIField(
3436
                [
3437
                    'id' => 100,
3438
                    'fieldDefinitionId' => 'fieldDefinitionId',
3439
                    'type' => 'fieldTypeIdentifier',
3440
                    'value' => 'newValue2',
3441
                    'languageCode' => 'eng-GB',
3442
                    'versionNo' => 7,
3443
                ]
3444
            ),
3445
            new SPIField(
3446
                [
3447
                    'id' => null,
3448
                    'fieldDefinitionId' => 'fieldDefinitionId',
3449
                    'type' => 'fieldTypeIdentifier',
3450
                    'value' => 'newValue1',
3451
                    'languageCode' => 'eng-US',
3452
                    'versionNo' => 7,
3453
                ]
3454
            ),
3455
        ];
3456
3457
        return [
3458
            // 0. With languages set
3459
            [
3460
                'eng-GB',
3461
                [
3462
                    new Field(
3463
                        [
3464
                            'fieldDefIdentifier' => 'identifier',
3465
                            'value' => 'newValue',
3466
                            'languageCode' => 'eng-GB',
3467
                        ]
3468
                    ),
3469
                ],
3470
                $spiFields0,
3471
            ],
3472
            // 1. Without languages set
3473
            [
3474
                null,
3475
                [
3476
                    new Field(
3477
                        [
3478
                            'fieldDefIdentifier' => 'identifier',
3479
                            'value' => 'newValue',
3480
                            'languageCode' => null,
3481
                        ]
3482
                    ),
3483
                ],
3484
                $spiFields0,
3485
            ],
3486
            // 2. New language with language set
3487
            [
3488
                'eng-GB',
3489
                [
3490
                    new Field(
3491
                        [
3492
                            'fieldDefIdentifier' => 'identifier',
3493
                            'value' => 'newValue',
3494
                            'languageCode' => 'eng-US',
3495
                        ]
3496
                    ),
3497
                ],
3498
                $spiFields1,
3499
            ],
3500
            // 3. New language without language set
3501
            [
3502
                'eng-US',
3503
                [
3504
                    new Field(
3505
                        [
3506
                            'fieldDefIdentifier' => 'identifier',
3507
                            'value' => 'newValue',
3508
                            'languageCode' => null,
3509
                        ]
3510
                    ),
3511
                ],
3512
                $spiFields1,
3513
            ],
3514
            // 4. New language and existing language with language set
3515
            [
3516
                'eng-GB',
3517
                [
3518
                    new Field(
3519
                        [
3520
                            'fieldDefIdentifier' => 'identifier',
3521
                            'value' => 'newValue1',
3522
                            'languageCode' => 'eng-US',
3523
                        ]
3524
                    ),
3525
                    new Field(
3526
                        [
3527
                            'fieldDefIdentifier' => 'identifier',
3528
                            'value' => 'newValue2',
3529
                            'languageCode' => 'eng-GB',
3530
                        ]
3531
                    ),
3532
                ],
3533
                $spiFields2,
3534
            ],
3535
            // 5. New language and existing language without language set
3536
            [
3537
                'eng-US',
3538
                [
3539
                    new Field(
3540
                        [
3541
                            'fieldDefIdentifier' => 'identifier',
3542
                            'value' => 'newValue1',
3543
                            'languageCode' => null,
3544
                        ]
3545
                    ),
3546
                    new Field(
3547
                        [
3548
                            'fieldDefIdentifier' => 'identifier',
3549
                            'value' => 'newValue2',
3550
                            'languageCode' => 'eng-GB',
3551
                        ]
3552
                    ),
3553
                ],
3554
                $spiFields2,
3555
            ],
3556
            // 6. Adding new language without fields
3557
            [
3558
                'eng-US',
3559
                [],
3560
                [
3561
                    new SPIField(
3562
                        [
3563
                            'id' => null,
3564
                            'fieldDefinitionId' => 'fieldDefinitionId',
3565
                            'type' => 'fieldTypeIdentifier',
3566
                            'value' => 'defaultValue',
3567
                            'languageCode' => 'eng-US',
3568
                            'versionNo' => 7,
3569
                        ]
3570
                    ),
3571
                ],
3572
            ],
3573
        ];
3574
    }
3575
3576
    /**
3577
     * Test for the updateContent() method.
3578
     *
3579
     * Testing with translatable field.
3580
     *
3581
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
3582
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
3583
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
3584
     * @dataProvider providerForTestUpdateContentNonRedundantFieldSet2
3585
     */
3586 View Code Duplication
    public function testUpdateContentNonRedundantFieldSet2($initialLanguageCode, $structFields, $spiFields)
3587
    {
3588
        $existingFields = [
3589
            new Field(
3590
                [
3591
                    'id' => '100',
3592
                    'fieldDefIdentifier' => 'identifier',
3593
                    'value' => 'initialValue',
3594
                    'languageCode' => 'eng-GB',
3595
                ]
3596
            ),
3597
        ];
3598
3599
        $fieldDefinitions = [
3600
            new FieldDefinition(
3601
                [
3602
                    'id' => 'fieldDefinitionId',
3603
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
3604
                    'isTranslatable' => true,
3605
                    'identifier' => 'identifier',
3606
                    'isRequired' => false,
3607
                    'defaultValue' => 'defaultValue',
3608
                ]
3609
            ),
3610
        ];
3611
3612
        $this->assertForTestUpdateContentNonRedundantFieldSet(
3613
            $initialLanguageCode,
3614
            $structFields,
3615
            $spiFields,
3616
            $existingFields,
3617
            $fieldDefinitions
3618
        );
3619
    }
3620
3621
    public function providerForTestUpdateContentNonRedundantFieldSet3()
3622
    {
3623
        $spiFields0 = [
3624
            new SPIField(
3625
                [
3626
                    'id' => null,
3627
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3628
                    'type' => 'fieldTypeIdentifier',
3629
                    'value' => 'newValue1',
3630
                    'languageCode' => 'eng-US',
3631
                    'versionNo' => 7,
3632
                ]
3633
            ),
3634
        ];
3635
        $spiFields1 = [
3636
            new SPIField(
3637
                [
3638
                    'id' => 100,
3639
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3640
                    'type' => 'fieldTypeIdentifier',
3641
                    'value' => 'newValue2',
3642
                    'languageCode' => 'eng-GB',
3643
                    'versionNo' => 7,
3644
                ]
3645
            ),
3646
            new SPIField(
3647
                [
3648
                    'id' => null,
3649
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3650
                    'type' => 'fieldTypeIdentifier',
3651
                    'value' => 'newValue1',
3652
                    'languageCode' => 'eng-US',
3653
                    'versionNo' => 7,
3654
                ]
3655
            ),
3656
        ];
3657
        $spiFields2 = [
3658
            new SPIField(
3659
                [
3660
                    'id' => 100,
3661
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3662
                    'type' => 'fieldTypeIdentifier',
3663
                    'value' => 'newValue2',
3664
                    'languageCode' => 'eng-GB',
3665
                    'versionNo' => 7,
3666
                ]
3667
            ),
3668
            new SPIField(
3669
                [
3670
                    'id' => null,
3671
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3672
                    'type' => 'fieldTypeIdentifier',
3673
                    'value' => 'newValue1',
3674
                    'languageCode' => 'eng-US',
3675
                    'versionNo' => 7,
3676
                ]
3677
            ),
3678
            new SPIField(
3679
                [
3680
                    'id' => 101,
3681
                    'fieldDefinitionId' => 'fieldDefinitionId2',
3682
                    'type' => 'fieldTypeIdentifier',
3683
                    'value' => 'newValue3',
3684
                    'languageCode' => 'eng-GB',
3685
                    'versionNo' => 7,
3686
                ]
3687
            ),
3688
        ];
3689
        $spiFields3 = [
3690
            new SPIField(
3691
                [
3692
                    'id' => null,
3693
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3694
                    'type' => 'fieldTypeIdentifier',
3695
                    'value' => 'defaultValue1',
3696
                    'languageCode' => 'eng-US',
3697
                    'versionNo' => 7,
3698
                ]
3699
            ),
3700
        ];
3701
3702
        return [
3703
            // 0. ew language with language set
3704
            [
3705
                'eng-US',
3706
                [
3707
                    new Field(
3708
                        [
3709
                            'fieldDefIdentifier' => 'identifier1',
3710
                            'value' => 'newValue1',
3711
                            'languageCode' => 'eng-US',
3712
                        ]
3713
                    ),
3714
                ],
3715
                $spiFields0,
3716
            ],
3717
            // 1. New language without language set
3718
            [
3719
                'eng-US',
3720
                [
3721
                    new Field(
3722
                        [
3723
                            'fieldDefIdentifier' => 'identifier1',
3724
                            'value' => 'newValue1',
3725
                            'languageCode' => null,
3726
                        ]
3727
                    ),
3728
                ],
3729
                $spiFields0,
3730
            ],
3731
            // 2. New language and existing language with language set
3732
            [
3733
                'eng-US',
3734
                [
3735
                    new Field(
3736
                        [
3737
                            'fieldDefIdentifier' => 'identifier1',
3738
                            'value' => 'newValue1',
3739
                            'languageCode' => 'eng-US',
3740
                        ]
3741
                    ),
3742
                    new Field(
3743
                        [
3744
                            'fieldDefIdentifier' => 'identifier1',
3745
                            'value' => 'newValue2',
3746
                            'languageCode' => 'eng-GB',
3747
                        ]
3748
                    ),
3749
                ],
3750
                $spiFields1,
3751
            ],
3752
            // 3. New language and existing language without language set
3753
            [
3754
                'eng-US',
3755
                [
3756
                    new Field(
3757
                        [
3758
                            'fieldDefIdentifier' => 'identifier1',
3759
                            'value' => 'newValue1',
3760
                            'languageCode' => null,
3761
                        ]
3762
                    ),
3763
                    new Field(
3764
                        [
3765
                            'fieldDefIdentifier' => 'identifier1',
3766
                            'value' => 'newValue2',
3767
                            'languageCode' => 'eng-GB',
3768
                        ]
3769
                    ),
3770
                ],
3771
                $spiFields1,
3772
            ],
3773
            // 4. New language and existing language with untranslatable field, with language set
3774
            [
3775
                'eng-US',
3776
                [
3777
                    new Field(
3778
                        [
3779
                            'fieldDefIdentifier' => 'identifier1',
3780
                            'value' => 'newValue1',
3781
                            'languageCode' => 'eng-US',
3782
                        ]
3783
                    ),
3784
                    new Field(
3785
                        [
3786
                            'fieldDefIdentifier' => 'identifier1',
3787
                            'value' => 'newValue2',
3788
                            'languageCode' => 'eng-GB',
3789
                        ]
3790
                    ),
3791
                    new Field(
3792
                        [
3793
                            'fieldDefIdentifier' => 'identifier2',
3794
                            'value' => 'newValue3',
3795
                            'languageCode' => 'eng-GB',
3796
                        ]
3797
                    ),
3798
                ],
3799
                $spiFields2,
3800
            ],
3801
            // 5. New language and existing language with untranslatable field, without language set
3802
            [
3803
                'eng-US',
3804
                [
3805
                    new Field(
3806
                        [
3807
                            'fieldDefIdentifier' => 'identifier1',
3808
                            'value' => 'newValue1',
3809
                            'languageCode' => null,
3810
                        ]
3811
                    ),
3812
                    new Field(
3813
                        [
3814
                            'fieldDefIdentifier' => 'identifier1',
3815
                            'value' => 'newValue2',
3816
                            'languageCode' => 'eng-GB',
3817
                        ]
3818
                    ),
3819
                    new Field(
3820
                        [
3821
                            'fieldDefIdentifier' => 'identifier2',
3822
                            'value' => 'newValue3',
3823
                            'languageCode' => null,
3824
                        ]
3825
                    ),
3826
                ],
3827
                $spiFields2,
3828
            ],
3829
            // 6. Adding new language without fields
3830
            [
3831
                'eng-US',
3832
                [],
3833
                $spiFields3,
3834
            ],
3835
        ];
3836
    }
3837
3838
    /**
3839
     * Test for the updateContent() method.
3840
     *
3841
     * Testing with new language and untranslatable field.
3842
     *
3843
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
3844
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
3845
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
3846
     * @dataProvider providerForTestUpdateContentNonRedundantFieldSet3
3847
     */
3848
    public function testUpdateContentNonRedundantFieldSet3($initialLanguageCode, $structFields, $spiFields)
3849
    {
3850
        $existingFields = [
3851
            new Field(
3852
                [
3853
                    'id' => '100',
3854
                    'fieldDefIdentifier' => 'identifier1',
3855
                    'value' => 'initialValue1',
3856
                    'languageCode' => 'eng-GB',
3857
                ]
3858
            ),
3859
            new Field(
3860
                [
3861
                    'id' => '101',
3862
                    'fieldDefIdentifier' => 'identifier2',
3863
                    'value' => 'initialValue2',
3864
                    'languageCode' => 'eng-GB',
3865
                ]
3866
            ),
3867
        ];
3868
3869
        $fieldDefinitions = [
3870
            new FieldDefinition(
3871
                [
3872
                    'id' => 'fieldDefinitionId1',
3873
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
3874
                    'isTranslatable' => true,
3875
                    'identifier' => 'identifier1',
3876
                    'isRequired' => false,
3877
                    'defaultValue' => 'defaultValue1',
3878
                ]
3879
            ),
3880
            new FieldDefinition(
3881
                [
3882
                    'id' => 'fieldDefinitionId2',
3883
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
3884
                    'isTranslatable' => false,
3885
                    'identifier' => 'identifier2',
3886
                    'isRequired' => false,
3887
                    'defaultValue' => 'defaultValue2',
3888
                ]
3889
            ),
3890
        ];
3891
3892
        $this->assertForTestUpdateContentNonRedundantFieldSet(
3893
            $initialLanguageCode,
3894
            $structFields,
3895
            $spiFields,
3896
            $existingFields,
3897
            $fieldDefinitions
3898
        );
3899
    }
3900
3901
    public function providerForTestUpdateContentNonRedundantFieldSet4()
3902
    {
3903
        $spiFields0 = [
3904
            new SPIField(
3905
                [
3906
                    'id' => null,
3907
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3908
                    'type' => 'fieldTypeIdentifier',
3909
                    'value' => 'newValue1',
3910
                    'languageCode' => 'eng-US',
3911
                    'versionNo' => 7,
3912
                ]
3913
            ),
3914
        ];
3915
        $spiFields1 = [
3916
            new SPIField(
3917
                [
3918
                    'id' => 100,
3919
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3920
                    'type' => 'fieldTypeIdentifier',
3921
                    'value' => self::EMPTY_FIELD_VALUE,
3922
                    'languageCode' => 'eng-GB',
3923
                    'versionNo' => 7,
3924
                ]
3925
            ),
3926
            new SPIField(
3927
                [
3928
                    'id' => null,
3929
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3930
                    'type' => 'fieldTypeIdentifier',
3931
                    'value' => 'newValue1',
3932
                    'languageCode' => 'eng-US',
3933
                    'versionNo' => 7,
3934
                ]
3935
            ),
3936
        ];
3937
        $spiFields2 = [
3938
            new SPIField(
3939
                [
3940
                    'id' => 100,
3941
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3942
                    'type' => 'fieldTypeIdentifier',
3943
                    'value' => self::EMPTY_FIELD_VALUE,
3944
                    'languageCode' => 'eng-GB',
3945
                    'versionNo' => 7,
3946
                ]
3947
            ),
3948
        ];
3949
3950
        return [
3951
            // 0. New translation with empty field by default
3952
            [
3953
                'eng-US',
3954
                [
3955
                    new Field(
3956
                        [
3957
                            'fieldDefIdentifier' => 'identifier1',
3958
                            'value' => 'newValue1',
3959
                            'languageCode' => 'eng-US',
3960
                        ]
3961
                    ),
3962
                ],
3963
                $spiFields0,
3964
            ],
3965
            // 1. New translation with empty field by default, without language set
3966
            [
3967
                'eng-US',
3968
                [
3969
                    new Field(
3970
                        [
3971
                            'fieldDefIdentifier' => 'identifier1',
3972
                            'value' => 'newValue1',
3973
                            'languageCode' => null,
3974
                        ]
3975
                    ),
3976
                ],
3977
                $spiFields0,
3978
            ],
3979
            // 2. New translation with empty field given
3980
            [
3981
                'eng-US',
3982
                [
3983
                    new Field(
3984
                        [
3985
                            'fieldDefIdentifier' => 'identifier1',
3986
                            'value' => 'newValue1',
3987
                            'languageCode' => 'eng-US',
3988
                        ]
3989
                    ),
3990
                    new Field(
3991
                        [
3992
                            'fieldDefIdentifier' => 'identifier2',
3993
                            'value' => self::EMPTY_FIELD_VALUE,
3994
                            'languageCode' => 'eng-US',
3995
                        ]
3996
                    ),
3997
                ],
3998
                $spiFields0,
3999
            ],
4000
            // 3. New translation with empty field given, without language set
4001
            [
4002
                'eng-US',
4003
                [
4004
                    new Field(
4005
                        [
4006
                            'fieldDefIdentifier' => 'identifier1',
4007
                            'value' => 'newValue1',
4008
                            'languageCode' => null,
4009
                        ]
4010
                    ),
4011
                    new Field(
4012
                        [
4013
                            'fieldDefIdentifier' => 'identifier2',
4014
                            'value' => self::EMPTY_FIELD_VALUE,
4015
                            'languageCode' => null,
4016
                        ]
4017
                    ),
4018
                ],
4019
                $spiFields0,
4020
            ],
4021
            // 4. Updating existing language with empty value
4022
            [
4023
                'eng-US',
4024
                [
4025
                    new Field(
4026
                        [
4027
                            'fieldDefIdentifier' => 'identifier1',
4028
                            'value' => 'newValue1',
4029
                            'languageCode' => 'eng-US',
4030
                        ]
4031
                    ),
4032
                    new Field(
4033
                        [
4034
                            'fieldDefIdentifier' => 'identifier1',
4035
                            'value' => self::EMPTY_FIELD_VALUE,
4036
                            'languageCode' => 'eng-GB',
4037
                        ]
4038
                    ),
4039
                ],
4040
                $spiFields1,
4041
            ],
4042
            // 5. Updating existing language with empty value, without language set
4043
            [
4044
                'eng-US',
4045
                [
4046
                    new Field(
4047
                        [
4048
                            'fieldDefIdentifier' => 'identifier1',
4049
                            'value' => 'newValue1',
4050
                            'languageCode' => null,
4051
                        ]
4052
                    ),
4053
                    new Field(
4054
                        [
4055
                            'fieldDefIdentifier' => 'identifier1',
4056
                            'value' => self::EMPTY_FIELD_VALUE,
4057
                            'languageCode' => 'eng-GB',
4058
                        ]
4059
                    ),
4060
                ],
4061
                $spiFields1,
4062
            ],
4063
            // 6. Updating existing language with empty value and adding new language with empty value
4064
            [
4065
                'eng-US',
4066
                [
4067
                    new Field(
4068
                        [
4069
                            'fieldDefIdentifier' => 'identifier1',
4070
                            'value' => self::EMPTY_FIELD_VALUE,
4071
                            'languageCode' => 'eng-US',
4072
                        ]
4073
                    ),
4074
                    new Field(
4075
                        [
4076
                            'fieldDefIdentifier' => 'identifier1',
4077
                            'value' => self::EMPTY_FIELD_VALUE,
4078
                            'languageCode' => 'eng-GB',
4079
                        ]
4080
                    ),
4081
                ],
4082
                $spiFields2,
4083
            ],
4084
            // 7. Updating existing language with empty value and adding new language with empty value,
4085
            // without language set
4086
            [
4087
                'eng-US',
4088
                [
4089
                    new Field(
4090
                        [
4091
                            'fieldDefIdentifier' => 'identifier1',
4092
                            'value' => self::EMPTY_FIELD_VALUE,
4093
                            'languageCode' => null,
4094
                        ]
4095
                    ),
4096
                    new Field(
4097
                        [
4098
                            'fieldDefIdentifier' => 'identifier1',
4099
                            'value' => self::EMPTY_FIELD_VALUE,
4100
                            'languageCode' => 'eng-GB',
4101
                        ]
4102
                    ),
4103
                ],
4104
                $spiFields2,
4105
            ],
4106
            // 8. Adding new language with no fields given
4107
            [
4108
                'eng-US',
4109
                [],
4110
                [],
4111
            ],
4112
            // 9. Adding new language with fields
4113
            [
4114
                'eng-US',
4115
                [
4116
                    new Field(
4117
                        [
4118
                            'fieldDefIdentifier' => 'identifier1',
4119
                            'value' => self::EMPTY_FIELD_VALUE,
4120
                            'languageCode' => 'eng-US',
4121
                        ]
4122
                    ),
4123
                ],
4124
                [],
4125
            ],
4126
            // 10. Adding new language with fields, without language set
4127
            [
4128
                'eng-US',
4129
                [
4130
                    new Field(
4131
                        [
4132
                            'fieldDefIdentifier' => 'identifier1',
4133
                            'value' => self::EMPTY_FIELD_VALUE,
4134
                            'languageCode' => null,
4135
                        ]
4136
                    ),
4137
                ],
4138
                [],
4139
            ],
4140
        ];
4141
    }
4142
4143
    /**
4144
     * Test for the updateContent() method.
4145
     *
4146
     * Testing with empty values.
4147
     *
4148
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
4149
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
4150
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
4151
     * @dataProvider providerForTestUpdateContentNonRedundantFieldSet4
4152
     */
4153
    public function testUpdateContentNonRedundantFieldSet4($initialLanguageCode, $structFields, $spiFields)
4154
    {
4155
        $existingFields = [
4156
            new Field(
4157
                [
4158
                    'id' => '100',
4159
                    'fieldDefIdentifier' => 'identifier1',
4160
                    'value' => 'initialValue1',
4161
                    'languageCode' => 'eng-GB',
4162
                ]
4163
            ),
4164
            new Field(
4165
                [
4166
                    'id' => '101',
4167
                    'fieldDefIdentifier' => 'identifier2',
4168
                    'value' => 'initialValue2',
4169
                    'languageCode' => 'eng-GB',
4170
                ]
4171
            ),
4172
        ];
4173
4174
        $fieldDefinitions = [
4175
            new FieldDefinition(
4176
                [
4177
                    'id' => 'fieldDefinitionId1',
4178
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4179
                    'isTranslatable' => true,
4180
                    'identifier' => 'identifier1',
4181
                    'isRequired' => false,
4182
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
4183
                ]
4184
            ),
4185
            new FieldDefinition(
4186
                [
4187
                    'id' => 'fieldDefinitionId2',
4188
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4189
                    'isTranslatable' => true,
4190
                    'identifier' => 'identifier2',
4191
                    'isRequired' => false,
4192
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
4193
                ]
4194
            ),
4195
        ];
4196
4197
        $this->assertForTestUpdateContentNonRedundantFieldSet(
4198
            $initialLanguageCode,
4199
            $structFields,
4200
            $spiFields,
4201
            $existingFields,
4202
            $fieldDefinitions
4203
        );
4204
    }
4205
4206
    /**
4207
     * @todo add first field empty
4208
     *
4209
     * @return array
4210
     */
4211
    public function providerForTestUpdateContentNonRedundantFieldSetComplex()
4212
    {
4213
        $spiFields0 = [
4214
            new SPIField(
4215
                [
4216
                    'id' => 100,
4217
                    'fieldDefinitionId' => 'fieldDefinitionId1',
4218
                    'type' => 'fieldTypeIdentifier',
4219
                    'value' => 'newValue1-eng-GB',
4220
                    'languageCode' => 'eng-GB',
4221
                    'versionNo' => 7,
4222
                ]
4223
            ),
4224
            new SPIField(
4225
                [
4226
                    'id' => null,
4227
                    'fieldDefinitionId' => 'fieldDefinitionId4',
4228
                    'type' => 'fieldTypeIdentifier',
4229
                    'value' => 'newValue4',
4230
                    'languageCode' => 'eng-US',
4231
                    'versionNo' => 7,
4232
                ]
4233
            ),
4234
        ];
4235
        $spiFields1 = [
4236
            new SPIField(
4237
                [
4238
                    'id' => 100,
4239
                    'fieldDefinitionId' => 'fieldDefinitionId1',
4240
                    'type' => 'fieldTypeIdentifier',
4241
                    'value' => 'newValue1-eng-GB',
4242
                    'languageCode' => 'eng-GB',
4243
                    'versionNo' => 7,
4244
                ]
4245
            ),
4246
            new SPIField(
4247
                [
4248
                    'id' => null,
4249
                    'fieldDefinitionId' => 'fieldDefinitionId2',
4250
                    'type' => 'fieldTypeIdentifier',
4251
                    'value' => 'newValue2',
4252
                    'languageCode' => 'eng-US',
4253
                    'versionNo' => 7,
4254
                ]
4255
            ),
4256
            new SPIField(
4257
                [
4258
                    'id' => null,
4259
                    'fieldDefinitionId' => 'fieldDefinitionId4',
4260
                    'type' => 'fieldTypeIdentifier',
4261
                    'value' => 'defaultValue4',
4262
                    'languageCode' => 'eng-US',
4263
                    'versionNo' => 7,
4264
                ]
4265
            ),
4266
        ];
4267
        $spiFields2 = [
4268
            new SPIField(
4269
                [
4270
                    'id' => 100,
4271
                    'fieldDefinitionId' => 'fieldDefinitionId1',
4272
                    'type' => 'fieldTypeIdentifier',
4273
                    'value' => 'newValue1-eng-GB',
4274
                    'languageCode' => 'eng-GB',
4275
                    'versionNo' => 7,
4276
                ]
4277
            ),
4278
            new SPIField(
4279
                [
4280
                    'id' => null,
4281
                    'fieldDefinitionId' => 'fieldDefinitionId2',
4282
                    'type' => 'fieldTypeIdentifier',
4283
                    'value' => 'newValue2',
4284
                    'languageCode' => 'eng-US',
4285
                    'versionNo' => 7,
4286
                ]
4287
            ),
4288
            new SPIField(
4289
                [
4290
                    'id' => null,
4291
                    'fieldDefinitionId' => 'fieldDefinitionId4',
4292
                    'type' => 'fieldTypeIdentifier',
4293
                    'value' => 'defaultValue4',
4294
                    'languageCode' => 'ger-DE',
4295
                    'versionNo' => 7,
4296
                ]
4297
            ),
4298
            new SPIField(
4299
                [
4300
                    'id' => null,
4301
                    'fieldDefinitionId' => 'fieldDefinitionId4',
4302
                    'type' => 'fieldTypeIdentifier',
4303
                    'value' => 'defaultValue4',
4304
                    'languageCode' => 'eng-US',
4305
                    'versionNo' => 7,
4306
                ]
4307
            ),
4308
        ];
4309
4310
        return [
4311
            // 0. Add new language and update existing
4312
            [
4313
                'eng-US',
4314
                [
4315
                    new Field(
4316
                        [
4317
                            'fieldDefIdentifier' => 'identifier4',
4318
                            'value' => 'newValue4',
4319
                            'languageCode' => 'eng-US',
4320
                        ]
4321
                    ),
4322
                    new Field(
4323
                        [
4324
                            'fieldDefIdentifier' => 'identifier1',
4325
                            'value' => 'newValue1-eng-GB',
4326
                            'languageCode' => 'eng-GB',
4327
                        ]
4328
                    ),
4329
                ],
4330
                $spiFields0,
4331
            ],
4332
            // 1. Add new language and update existing, without language set
4333
            [
4334
                'eng-US',
4335
                [
4336
                    new Field(
4337
                        [
4338
                            'fieldDefIdentifier' => 'identifier4',
4339
                            'value' => 'newValue4',
4340
                            'languageCode' => null,
4341
                        ]
4342
                    ),
4343
                    new Field(
4344
                        [
4345
                            'fieldDefIdentifier' => 'identifier1',
4346
                            'value' => 'newValue1-eng-GB',
4347
                            'languageCode' => 'eng-GB',
4348
                        ]
4349
                    ),
4350
                ],
4351
                $spiFields0,
4352
            ],
4353
            // 2. Add new language and update existing variant
4354
            [
4355
                'eng-US',
4356
                [
4357
                    new Field(
4358
                        [
4359
                            'fieldDefIdentifier' => 'identifier2',
4360
                            'value' => 'newValue2',
4361
                            'languageCode' => 'eng-US',
4362
                        ]
4363
                    ),
4364
                    new Field(
4365
                        [
4366
                            'fieldDefIdentifier' => 'identifier1',
4367
                            'value' => 'newValue1-eng-GB',
4368
                            'languageCode' => 'eng-GB',
4369
                        ]
4370
                    ),
4371
                ],
4372
                $spiFields1,
4373
            ],
4374
            // 3. Add new language and update existing variant, without language set
4375
            [
4376
                'eng-US',
4377
                [
4378
                    new Field(
4379
                        [
4380
                            'fieldDefIdentifier' => 'identifier2',
4381
                            'value' => 'newValue2',
4382
                            'languageCode' => null,
4383
                        ]
4384
                    ),
4385
                    new Field(
4386
                        [
4387
                            'fieldDefIdentifier' => 'identifier1',
4388
                            'value' => 'newValue1-eng-GB',
4389
                            'languageCode' => 'eng-GB',
4390
                        ]
4391
                    ),
4392
                ],
4393
                $spiFields1,
4394
            ],
4395
            // 4. Update with multiple languages
4396
            [
4397
                'ger-DE',
4398
                [
4399
                    new Field(
4400
                        [
4401
                            'fieldDefIdentifier' => 'identifier2',
4402
                            'value' => 'newValue2',
4403
                            'languageCode' => 'eng-US',
4404
                        ]
4405
                    ),
4406
                    new Field(
4407
                        [
4408
                            'fieldDefIdentifier' => 'identifier1',
4409
                            'value' => 'newValue1-eng-GB',
4410
                            'languageCode' => 'eng-GB',
4411
                        ]
4412
                    ),
4413
                ],
4414
                $spiFields2,
4415
            ],
4416
            // 5. Update with multiple languages without language set
4417
            [
4418
                'ger-DE',
4419
                [
4420
                    new Field(
4421
                        [
4422
                            'fieldDefIdentifier' => 'identifier2',
4423
                            'value' => 'newValue2',
4424
                            'languageCode' => 'eng-US',
4425
                        ]
4426
                    ),
4427
                    new Field(
4428
                        [
4429
                            'fieldDefIdentifier' => 'identifier1',
4430
                            'value' => 'newValue1-eng-GB',
4431
                            'languageCode' => null,
4432
                        ]
4433
                    ),
4434
                ],
4435
                $spiFields2,
4436
            ],
4437
        ];
4438
    }
4439
4440
    protected function fixturesForTestUpdateContentNonRedundantFieldSetComplex()
4441
    {
4442
        $existingFields = [
4443
            new Field(
4444
                [
4445
                    'id' => '100',
4446
                    'fieldDefIdentifier' => 'identifier1',
4447
                    'value' => 'initialValue1',
4448
                    'languageCode' => 'eng-GB',
4449
                ]
4450
            ),
4451
            new Field(
4452
                [
4453
                    'id' => '101',
4454
                    'fieldDefIdentifier' => 'identifier2',
4455
                    'value' => 'initialValue2',
4456
                    'languageCode' => 'eng-GB',
4457
                ]
4458
            ),
4459
            new Field(
4460
                [
4461
                    'id' => '102',
4462
                    'fieldDefIdentifier' => 'identifier3',
4463
                    'value' => 'initialValue3',
4464
                    'languageCode' => 'eng-GB',
4465
                ]
4466
            ),
4467
            new Field(
4468
                [
4469
                    'id' => '103',
4470
                    'fieldDefIdentifier' => 'identifier4',
4471
                    'value' => 'initialValue4',
4472
                    'languageCode' => 'eng-GB',
4473
                ]
4474
            ),
4475
        ];
4476
4477
        $fieldDefinitions = [
4478
            new FieldDefinition(
4479
                [
4480
                    'id' => 'fieldDefinitionId1',
4481
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4482
                    'isTranslatable' => false,
4483
                    'identifier' => 'identifier1',
4484
                    'isRequired' => false,
4485
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
4486
                ]
4487
            ),
4488
            new FieldDefinition(
4489
                [
4490
                    'id' => 'fieldDefinitionId2',
4491
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4492
                    'isTranslatable' => true,
4493
                    'identifier' => 'identifier2',
4494
                    'isRequired' => false,
4495
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
4496
                ]
4497
            ),
4498
            new FieldDefinition(
4499
                [
4500
                    'id' => 'fieldDefinitionId3',
4501
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4502
                    'isTranslatable' => false,
4503
                    'identifier' => 'identifier3',
4504
                    'isRequired' => false,
4505
                    'defaultValue' => 'defaultValue3',
4506
                ]
4507
            ),
4508
            new FieldDefinition(
4509
                [
4510
                    'id' => 'fieldDefinitionId4',
4511
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4512
                    'isTranslatable' => true,
4513
                    'identifier' => 'identifier4',
4514
                    'isRequired' => false,
4515
                    'defaultValue' => 'defaultValue4',
4516
                ]
4517
            ),
4518
        ];
4519
4520
        return [$existingFields, $fieldDefinitions];
4521
    }
4522
4523
    /**
4524
     * Test for the updateContent() method.
4525
     *
4526
     * Testing more complex cases.
4527
     *
4528
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
4529
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
4530
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
4531
     * @dataProvider providerForTestUpdateContentNonRedundantFieldSetComplex
4532
     */
4533
    public function testUpdateContentNonRedundantFieldSetComplex($initialLanguageCode, $structFields, $spiFields)
4534
    {
4535
        list($existingFields, $fieldDefinitions) = $this->fixturesForTestUpdateContentNonRedundantFieldSetComplex();
4536
4537
        $this->assertForTestUpdateContentNonRedundantFieldSet(
4538
            $initialLanguageCode,
4539
            $structFields,
4540
            $spiFields,
4541
            $existingFields,
4542
            $fieldDefinitions
4543
        );
4544
    }
4545
4546 View Code Duplication
    public function providerForTestUpdateContentWithInvalidLanguage()
4547
    {
4548
        return [
4549
            [
4550
                'eng-GB',
4551
                [
4552
                    new Field(
4553
                        [
4554
                            'fieldDefIdentifier' => 'identifier',
4555
                            'value' => 'newValue',
4556
                            'languageCode' => 'Klingon',
4557
                        ]
4558
                    ),
4559
                ],
4560
            ],
4561
            [
4562
                'Klingon',
4563
                [
4564
                    new Field(
4565
                        [
4566
                            'fieldDefIdentifier' => 'identifier',
4567
                            'value' => 'newValue',
4568
                            'languageCode' => 'eng-GB',
4569
                        ]
4570
                    ),
4571
                ],
4572
            ],
4573
        ];
4574
    }
4575
4576
    /**
4577
     * Test for the updateContent() method.
4578
     *
4579
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
4580
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
4581
     * @dataProvider providerForTestUpdateContentWithInvalidLanguage
4582
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
4583
     * @expectedExceptionMessage Could not find 'Language' with identifier 'Klingon'
4584
     */
4585
    public function testUpdateContentWithInvalidLanguage($initialLanguageCode, $structFields)
4586
    {
4587
        $repositoryMock = $this->getRepositoryMock();
4588
        $mockedService = $this->getPartlyMockedContentService(['loadContent']);
4589
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
4590
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
4591
        $versionInfo = new VersionInfo(
4592
            [
4593
                'contentInfo' => new ContentInfo(
4594
                    [
4595
                        'id' => 42,
4596
                        'contentTypeId' => 24,
4597
                        'mainLanguageCode' => 'eng-GB',
4598
                    ]
4599
                ),
4600
                'versionNo' => 7,
4601
                'languageCodes' => ['eng-GB'],
4602
                'status' => VersionInfo::STATUS_DRAFT,
4603
            ]
4604
        );
4605
        $content = new Content(
4606
            [
4607
                'versionInfo' => $versionInfo,
4608
                'internalFields' => [],
4609
            ]
4610
        );
4611
4612
        $languageHandlerMock->expects($this->any())
4613
            ->method('loadByLanguageCode')
4614
            ->with($this->isType('string'))
4615
            ->will(
4616
                $this->returnCallback(
4617 View Code Duplication
                    function ($languageCode) {
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...
4618
                        if ($languageCode === 'Klingon') {
4619
                            throw new NotFoundException('Language', 'Klingon');
4620
                        }
4621
4622
                        return new Language(['id' => 4242]);
4623
                    }
4624
                )
4625
            );
4626
4627
        $mockedService->expects($this->once())
4628
            ->method('loadContent')
4629
            ->with(
4630
                $this->equalTo(42),
4631
                $this->equalTo(null),
4632
                $this->equalTo(7)
4633
            )->will(
4634
                $this->returnValue($content)
4635
            );
4636
4637
        $repositoryMock->expects($this->once())
4638
            ->method('canUser')
4639
            ->with(
4640
                $this->equalTo('content'),
4641
                $this->equalTo('edit'),
4642
                $this->equalTo($content)
4643
            )->will($this->returnValue(true));
4644
4645
        $contentUpdateStruct = new ContentUpdateStruct(
4646
            [
4647
                'fields' => $structFields,
4648
                'initialLanguageCode' => $initialLanguageCode,
4649
            ]
4650
        );
4651
4652
        $mockedService->updateContent($content->versionInfo, $contentUpdateStruct);
4653
    }
4654
4655
    protected function assertForUpdateContentContentValidationException(
4656
        $initialLanguageCode,
4657
        $structFields,
4658
        $fieldDefinitions = []
4659
    ) {
4660
        $repositoryMock = $this->getRepositoryMock();
4661
        $mockedService = $this->getPartlyMockedContentService(['loadContent']);
4662
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
4663
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
4664
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
4665
        $versionInfo = new VersionInfo(
4666
            [
4667
                'contentInfo' => new ContentInfo(
4668
                    [
4669
                        'id' => 42,
4670
                        'contentTypeId' => 24,
4671
                        'mainLanguageCode' => 'eng-GB',
4672
                    ]
4673
                ),
4674
                'versionNo' => 7,
4675
                'languageCodes' => ['eng-GB'],
4676
                'status' => VersionInfo::STATUS_DRAFT,
4677
            ]
4678
        );
4679
        $content = new Content(
4680
            [
4681
                'versionInfo' => $versionInfo,
4682
                'internalFields' => [],
4683
            ]
4684
        );
4685
        $contentType = new ContentType(['fieldDefinitions' => $fieldDefinitions]);
4686
4687
        $languageHandlerMock->expects($this->any())
4688
            ->method('loadByLanguageCode')
4689
            ->with($this->isType('string'))
4690
            ->will(
4691
                $this->returnCallback(
4692 View Code Duplication
                    function ($languageCode) {
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...
4693
                        if ($languageCode === 'Klingon') {
4694
                            throw new NotFoundException('Language', 'Klingon');
4695
                        }
4696
4697
                        return new Language(['id' => 4242]);
4698
                    }
4699
                )
4700
            );
4701
4702
        $mockedService->expects($this->once())
4703
            ->method('loadContent')
4704
            ->with(
4705
                $this->equalTo(42),
4706
                $this->equalTo(null),
4707
                $this->equalTo(7)
4708
            )->will(
4709
                $this->returnValue($content)
4710
            );
4711
4712
        $repositoryMock->expects($this->once())
4713
            ->method('canUser')
4714
            ->with(
4715
                $this->equalTo('content'),
4716
                $this->equalTo('edit'),
4717
                $this->equalTo($content)
4718
            )->will($this->returnValue(true));
4719
4720
        $contentTypeServiceMock->expects($this->once())
4721
            ->method('loadContentType')
4722
            ->with($this->equalTo(24))
4723
            ->will($this->returnValue($contentType));
4724
4725
        $repositoryMock->expects($this->once())
4726
            ->method('getContentTypeService')
4727
            ->will($this->returnValue($contentTypeServiceMock));
4728
4729
        $contentUpdateStruct = new ContentUpdateStruct(
4730
            [
4731
                'fields' => $structFields,
4732
                'initialLanguageCode' => $initialLanguageCode,
4733
            ]
4734
        );
4735
4736
        $mockedService->updateContent($content->versionInfo, $contentUpdateStruct);
4737
    }
4738
4739 View Code Duplication
    public function providerForTestUpdateContentThrowsContentValidationExceptionFieldDefinition()
4740
    {
4741
        return [
4742
            [
4743
                'eng-GB',
4744
                [
4745
                    new Field(
4746
                        [
4747
                            'fieldDefIdentifier' => 'identifier',
4748
                            'value' => 'newValue',
4749
                            'languageCode' => 'eng-GB',
4750
                        ]
4751
                    ),
4752
                ],
4753
            ],
4754
        ];
4755
    }
4756
4757
    /**
4758
     * Test for the updateContent() method.
4759
     *
4760
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
4761
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
4762
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
4763
     * @dataProvider providerForTestUpdateContentThrowsContentValidationExceptionFieldDefinition
4764
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentValidationException
4765
     * @expectedExceptionMessage Field definition 'identifier' does not exist in given ContentType
4766
     */
4767
    public function testUpdateContentThrowsContentValidationExceptionFieldDefinition($initialLanguageCode, $structFields)
4768
    {
4769
        $this->assertForUpdateContentContentValidationException(
4770
            $initialLanguageCode,
4771
            $structFields,
4772
            []
4773
        );
4774
    }
4775
4776 View Code Duplication
    public function providerForTestUpdateContentThrowsContentValidationExceptionTranslation()
4777
    {
4778
        return [
4779
            [
4780
                'eng-US',
4781
                [
4782
                    new Field(
4783
                        [
4784
                            'fieldDefIdentifier' => 'identifier',
4785
                            'value' => 'newValue',
4786
                            'languageCode' => 'eng-US',
4787
                        ]
4788
                    ),
4789
                ],
4790
            ],
4791
        ];
4792
    }
4793
4794
    /**
4795
     * Test for the updateContent() method.
4796
     *
4797
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
4798
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
4799
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
4800
     * @dataProvider providerForTestUpdateContentThrowsContentValidationExceptionTranslation
4801
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentValidationException
4802
     * @expectedExceptionMessage A value is set for non translatable field definition 'identifier' with language 'eng-US'
4803
     */
4804 View Code Duplication
    public function testUpdateContentThrowsContentValidationExceptionTranslation($initialLanguageCode, $structFields)
4805
    {
4806
        $fieldDefinitions = [
4807
            new FieldDefinition(
4808
                [
4809
                    'id' => 'fieldDefinitionId1',
4810
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4811
                    'isTranslatable' => false,
4812
                    'identifier' => 'identifier',
4813
                    'isRequired' => false,
4814
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
4815
                ]
4816
            ),
4817
        ];
4818
4819
        $this->assertForUpdateContentContentValidationException(
4820
            $initialLanguageCode,
4821
            $structFields,
4822
            $fieldDefinitions
4823
        );
4824
    }
4825
4826
    public function assertForTestUpdateContentRequiredField(
4827
        $initialLanguageCode,
4828
        $structFields,
4829
        $existingFields,
4830
        $fieldDefinitions
4831
    ) {
4832
        $repositoryMock = $this->getRepositoryMock();
4833
        $mockedService = $this->getPartlyMockedContentService(['loadContent']);
4834
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
4835
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
4836
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
4837
        $fieldTypeServiceMock = $this->getFieldTypeServiceMock();
0 ignored issues
show
Unused Code introduced by
$fieldTypeServiceMock 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...
4838
        $fieldTypeMock = $this->createMock('eZ\\Publish\\SPI\\FieldType\\FieldType');
4839
        $existingLanguageCodes = array_map(
4840
            function (Field $field) {
4841
                return $field->languageCode;
4842
            },
4843
            $existingFields
4844
        );
4845
        $versionInfo = new VersionInfo(
4846
            [
4847
                'contentInfo' => new ContentInfo(
4848
                    [
4849
                        'id' => 42,
4850
                        'contentTypeId' => 24,
4851
                        'mainLanguageCode' => 'eng-GB',
4852
                    ]
4853
                ),
4854
                'versionNo' => 7,
4855
                'languageCodes' => $existingLanguageCodes,
4856
                'status' => VersionInfo::STATUS_DRAFT,
4857
            ]
4858
        );
4859
        $content = new Content(
4860
            [
4861
                'versionInfo' => $versionInfo,
4862
                'internalFields' => $existingFields,
4863
            ]
4864
        );
4865
        $contentType = new ContentType(['fieldDefinitions' => $fieldDefinitions]);
4866
4867
        $languageHandlerMock->expects($this->any())
4868
            ->method('loadByLanguageCode')
4869
            ->with($this->isType('string'))
4870
            ->will(
4871
                $this->returnCallback(
4872
                    function () {
4873
                        return new Language(['id' => 4242]);
4874
                    }
4875
                )
4876
            );
4877
4878
        $mockedService->expects($this->once())
4879
            ->method('loadContent')
4880
            ->with(
4881
                $this->equalTo(42),
4882
                $this->equalTo(null),
4883
                $this->equalTo(7)
4884
            )->will(
4885
                $this->returnValue($content)
4886
            );
4887
4888
        $repositoryMock->expects($this->once())
4889
            ->method('canUser')
4890
            ->with(
4891
                $this->equalTo('content'),
4892
                $this->equalTo('edit'),
4893
                $this->equalTo($content)
4894
            )->will($this->returnValue(true));
4895
4896
        $contentTypeServiceMock->expects($this->once())
4897
            ->method('loadContentType')
4898
            ->with($this->equalTo(24))
4899
            ->will($this->returnValue($contentType));
4900
4901
        $repositoryMock->expects($this->once())
4902
            ->method('getContentTypeService')
4903
            ->will($this->returnValue($contentTypeServiceMock));
4904
4905
        $fieldTypeMock->expects($this->any())
4906
            ->method('acceptValue')
4907
            ->will(
4908
                $this->returnCallback(
4909
                    function ($valueString) {
4910
                        return new ValueStub($valueString);
4911
                    }
4912
                )
4913
            );
4914
4915
        $emptyValue = self::EMPTY_FIELD_VALUE;
4916
        $fieldTypeMock->expects($this->any())
4917
            ->method('isEmptyValue')
4918
            ->will(
4919
                $this->returnCallback(
4920
                    function (ValueStub $value) use ($emptyValue) {
4921
                        return $emptyValue === (string)$value;
4922
                    }
4923
                )
4924
            );
4925
4926
        $fieldTypeMock->expects($this->any())
4927
            ->method('validate')
4928
            ->with(
4929
                $this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\ContentType\\FieldDefinition'),
4930
                $this->isInstanceOf('eZ\\Publish\\Core\\FieldType\\Value')
4931
            );
4932
4933
        $this->getFieldTypeRegistryMock()->expects($this->any())
4934
            ->method('getFieldType')
4935
            ->will($this->returnValue($fieldTypeMock));
4936
4937
        $contentUpdateStruct = new ContentUpdateStruct(
4938
            [
4939
                'fields' => $structFields,
4940
                'initialLanguageCode' => $initialLanguageCode,
4941
            ]
4942
        );
4943
4944
        return [$content->versionInfo, $contentUpdateStruct];
4945
    }
4946
4947 View Code Duplication
    public function providerForTestUpdateContentRequiredField()
4948
    {
4949
        return [
4950
            [
4951
                'eng-US',
4952
                [
4953
                    new Field(
4954
                        [
4955
                            'fieldDefIdentifier' => 'identifier',
4956
                            'value' => self::EMPTY_FIELD_VALUE,
4957
                            'languageCode' => null,
4958
                        ]
4959
                    ),
4960
                ],
4961
                'identifier',
4962
                'eng-US',
4963
            ],
4964
        ];
4965
    }
4966
4967
    /**
4968
     * Test for the updateContent() method.
4969
     *
4970
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
4971
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
4972
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
4973
     * @dataProvider providerForTestUpdateContentRequiredField
4974
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
4975
     */
4976
    public function testUpdateContentRequiredField(
4977
        $initialLanguageCode,
4978
        $structFields,
4979
        $identifier,
4980
        $languageCode
4981
    ) {
4982
        $existingFields = [
4983
            new Field(
4984
                [
4985
                    'id' => '100',
4986
                    'fieldDefIdentifier' => 'identifier',
4987
                    'value' => 'initialValue',
4988
                    'languageCode' => 'eng-GB',
4989
                ]
4990
            ),
4991
        ];
4992
        $fieldDefinitions = [
4993
            new FieldDefinition(
4994
                [
4995
                    'id' => 'fieldDefinitionId',
4996
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4997
                    'isTranslatable' => true,
4998
                    'identifier' => 'identifier',
4999
                    'isRequired' => true,
5000
                    'defaultValue' => 'defaultValue',
5001
                ]
5002
            ),
5003
        ];
5004
        list($versionInfo, $contentUpdateStruct) =
5005
            $this->assertForTestUpdateContentRequiredField(
5006
                $initialLanguageCode,
5007
                $structFields,
5008
                $existingFields,
5009
                $fieldDefinitions
5010
            );
5011
5012
        try {
5013
            $this->partlyMockedContentService->updateContent($versionInfo, $contentUpdateStruct);
5014
        } catch (ContentValidationException $e) {
5015
            $this->assertEquals(
5016
                "Value for required field definition '{$identifier}' with language '{$languageCode}' is empty",
5017
                $e->getMessage()
5018
            );
5019
5020
            throw $e;
5021
        }
5022
    }
5023
5024
    public function assertForTestUpdateContentThrowsContentFieldValidationException(
5025
        $initialLanguageCode,
5026
        $structFields,
5027
        $existingFields,
5028
        $fieldDefinitions
5029
    ) {
5030
        $repositoryMock = $this->getRepositoryMock();
5031
        $mockedService = $this->getPartlyMockedContentService(['loadContent']);
5032
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
5033
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
5034
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
5035
        $fieldTypeMock = $this->createMock('eZ\\Publish\\SPI\\FieldType\\FieldType');
5036
        $existingLanguageCodes = array_map(
5037
            function (Field $field) {
5038
                return $field->languageCode;
5039
            },
5040
            $existingFields
5041
        );
5042
        $languageCodes = $this->determineLanguageCodesForUpdate(
5043
            $initialLanguageCode,
5044
            $structFields,
5045
            $existingLanguageCodes
5046
        );
5047
        $versionInfo = new VersionInfo(
5048
            [
5049
                'contentInfo' => new ContentInfo(
5050
                    [
5051
                        'id' => 42,
5052
                        'contentTypeId' => 24,
5053
                        'mainLanguageCode' => 'eng-GB',
5054
                    ]
5055
                ),
5056
                'versionNo' => 7,
5057
                'languageCodes' => $existingLanguageCodes,
5058
                'status' => VersionInfo::STATUS_DRAFT,
5059
            ]
5060
        );
5061
        $content = new Content(
5062
            [
5063
                'versionInfo' => $versionInfo,
5064
                'internalFields' => $existingFields,
5065
            ]
5066
        );
5067
        $contentType = new ContentType(['fieldDefinitions' => $fieldDefinitions]);
5068
5069
        $languageHandlerMock->expects($this->any())
5070
            ->method('loadByLanguageCode')
5071
            ->with($this->isType('string'))
5072
            ->will(
5073
                $this->returnCallback(
5074
                    function () {
5075
                        return new Language(['id' => 4242]);
5076
                    }
5077
                )
5078
            );
5079
5080
        $mockedService->expects($this->once())
5081
            ->method('loadContent')
5082
            ->with(
5083
                $this->equalTo(42),
5084
                $this->equalTo(null),
5085
                $this->equalTo(7)
5086
            )->will(
5087
                $this->returnValue($content)
5088
            );
5089
5090
        $repositoryMock->expects($this->once())
5091
            ->method('canUser')
5092
            ->with(
5093
                $this->equalTo('content'),
5094
                $this->equalTo('edit'),
5095
                $this->equalTo($content)
5096
            )->will($this->returnValue(true));
5097
5098
        $contentTypeServiceMock->expects($this->once())
5099
            ->method('loadContentType')
5100
            ->with($this->equalTo(24))
5101
            ->will($this->returnValue($contentType));
5102
5103
        $repositoryMock->expects($this->once())
5104
            ->method('getContentTypeService')
5105
            ->will($this->returnValue($contentTypeServiceMock));
5106
5107
        $fieldValues = $this->determineValuesForUpdate(
5108
            $initialLanguageCode,
5109
            $structFields,
5110
            $content,
5111
            $fieldDefinitions,
5112
            $languageCodes
5113
        );
5114
        $allFieldErrors = [];
5115
        $emptyValue = self::EMPTY_FIELD_VALUE;
5116
5117
        $fieldTypeMock->expects($this->exactly(count($fieldValues) * count($languageCodes)))
5118
            ->method('acceptValue')
5119
            ->will(
5120
                $this->returnCallback(
5121
                    function ($valueString) {
5122
                        return new ValueStub($valueString);
5123
                    }
5124
                )
5125
            );
5126
5127
        $fieldTypeMock->expects($this->exactly(count($fieldValues) * count($languageCodes)))
5128
            ->method('isEmptyValue')
5129
            ->will(
5130
                $this->returnCallback(
5131
                    function (ValueStub $value) use ($emptyValue) {
5132
                        return $emptyValue === (string)$value;
5133
                    }
5134
                )
5135
            );
5136
5137
        $fieldTypeMock
5138
            ->expects($this->any())
5139
            ->method('validate')
5140
            ->willReturnArgument(1);
5141
5142
        $this->getFieldTypeRegistryMock()->expects($this->any())
5143
            ->method('getFieldType')
5144
            ->will($this->returnValue($fieldTypeMock));
5145
5146
        $contentUpdateStruct = new ContentUpdateStruct(
5147
            [
5148
                'fields' => $structFields,
5149
                'initialLanguageCode' => $initialLanguageCode,
5150
            ]
5151
        );
5152
5153
        return [$content->versionInfo, $contentUpdateStruct, $allFieldErrors];
5154
    }
5155
5156
    public function providerForTestUpdateContentThrowsContentFieldValidationException()
5157
    {
5158
        $allFieldErrors = [
5159
            [
5160
                'fieldDefinitionId1' => [
5161
                    'eng-GB' => 'newValue1-eng-GB',
5162
                    'eng-US' => 'newValue1-eng-GB',
5163
                ],
5164
                'fieldDefinitionId2' => [
5165
                    'eng-GB' => 'initialValue2',
5166
                ],
5167
                'fieldDefinitionId3' => [
5168
                    'eng-GB' => 'initialValue3',
5169
                    'eng-US' => 'initialValue3',
5170
                ],
5171
                'fieldDefinitionId4' => [
5172
                    'eng-GB' => 'initialValue4',
5173
                    'eng-US' => 'newValue4',
5174
                ],
5175
            ],
5176
            [
5177
                'fieldDefinitionId1' => [
5178
                    'eng-GB' => 'newValue1-eng-GB',
5179
                    'eng-US' => 'newValue1-eng-GB',
5180
                ],
5181
                'fieldDefinitionId2' => [
5182
                    'eng-GB' => 'initialValue2',
5183
                ],
5184
                'fieldDefinitionId3' => [
5185
                    'eng-GB' => 'initialValue3',
5186
                    'eng-US' => 'initialValue3',
5187
                ],
5188
                'fieldDefinitionId4' => [
5189
                    'eng-GB' => 'initialValue4',
5190
                    'eng-US' => 'newValue4',
5191
                ],
5192
            ],
5193
            [
5194
                'fieldDefinitionId1' => [
5195
                    'eng-GB' => 'newValue1-eng-GB',
5196
                    'eng-US' => 'newValue1-eng-GB',
5197
                ],
5198
                'fieldDefinitionId2' => [
5199
                    'eng-GB' => 'initialValue2',
5200
                    'eng-US' => 'newValue2',
5201
                ],
5202
                'fieldDefinitionId3' => [
5203
                    'eng-GB' => 'initialValue3',
5204
                    'eng-US' => 'initialValue3',
5205
                ],
5206
                'fieldDefinitionId4' => [
5207
                    'eng-GB' => 'initialValue4',
5208
                    'eng-US' => 'defaultValue4',
5209
                ],
5210
            ],
5211
            [
5212
                'fieldDefinitionId1' => [
5213
                    'eng-GB' => 'newValue1-eng-GB',
5214
                    'eng-US' => 'newValue1-eng-GB',
5215
                ],
5216
                'fieldDefinitionId2' => [
5217
                    'eng-GB' => 'initialValue2',
5218
                    'eng-US' => 'newValue2',
5219
                ],
5220
                'fieldDefinitionId3' => [
5221
                    'eng-GB' => 'initialValue3',
5222
                    'eng-US' => 'initialValue3',
5223
                ],
5224
                'fieldDefinitionId4' => [
5225
                    'eng-GB' => 'initialValue4',
5226
                    'eng-US' => 'defaultValue4',
5227
                ],
5228
            ],
5229
            [
5230
                'fieldDefinitionId1' => [
5231
                    'eng-GB' => 'newValue1-eng-GB',
5232
                    'ger-DE' => 'newValue1-eng-GB',
5233
                    'eng-US' => 'newValue1-eng-GB',
5234
                ],
5235
                'fieldDefinitionId2' => [
5236
                    'eng-GB' => 'initialValue2',
5237
                    'eng-US' => 'newValue2',
5238
                ],
5239
                'fieldDefinitionId3' => [
5240
                    'eng-GB' => 'initialValue3',
5241
                    'ger-DE' => 'initialValue3',
5242
                    'eng-US' => 'initialValue3',
5243
                ],
5244
                'fieldDefinitionId4' => [
5245
                    'eng-GB' => 'initialValue4',
5246
                    'eng-US' => 'defaultValue4',
5247
                    'ger-DE' => 'defaultValue4',
5248
                ],
5249
            ],
5250
            [
5251
                'fieldDefinitionId1' => [
5252
                    'eng-US' => 'newValue1-eng-GB',
5253
                    'ger-DE' => 'newValue1-eng-GB',
5254
                ],
5255
                'fieldDefinitionId2' => [
5256
                    'eng-US' => 'newValue2',
5257
                ],
5258
                'fieldDefinitionId3' => [
5259
                    'ger-DE' => 'initialValue3',
5260
                    'eng-US' => 'initialValue3',
5261
                ],
5262
                'fieldDefinitionId4' => [
5263
                    'ger-DE' => 'defaultValue4',
5264
                    'eng-US' => 'defaultValue4',
5265
                ],
5266
            ],
5267
        ];
5268
5269
        $data = $this->providerForTestUpdateContentNonRedundantFieldSetComplex();
5270
        $count = count($data);
5271
        for ($i = 0; $i < $count; ++$i) {
5272
            $data[$i][] = $allFieldErrors[$i];
5273
        }
5274
5275
        return $data;
5276
    }
5277
5278
    /**
5279
     * Test for the updateContent() method.
5280
     *
5281
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
5282
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
5283
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
5284
     * @dataProvider providerForTestUpdateContentThrowsContentFieldValidationException
5285
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
5286
     * @expectedExceptionMessage Content fields did not validate
5287
     */
5288
    public function testUpdateContentThrowsContentFieldValidationException($initialLanguageCode, $structFields, $spiField, $allFieldErrors)
0 ignored issues
show
Unused Code introduced by
The parameter $spiField 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...
5289
    {
5290
        list($existingFields, $fieldDefinitions) = $this->fixturesForTestUpdateContentNonRedundantFieldSetComplex();
5291
        list($versionInfo, $contentUpdateStruct) =
5292
            $this->assertForTestUpdateContentThrowsContentFieldValidationException(
5293
                $initialLanguageCode,
5294
                $structFields,
5295
                $existingFields,
5296
                $fieldDefinitions
5297
            );
5298
5299
        try {
5300
            $this->partlyMockedContentService->updateContent($versionInfo, $contentUpdateStruct);
5301
        } catch (ContentFieldValidationException $e) {
5302
            $this->assertEquals($allFieldErrors, $e->getFieldErrors());
5303
            throw $e;
5304
        }
5305
    }
5306
5307
    /**
5308
     * Test for the updateContent() method.
5309
     *
5310
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
5311
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
5312
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
5313
     * @expectedException \Exception
5314
     * @expectedExceptionMessage Store failed
5315
     */
5316
    public function testUpdateContentTransactionRollback()
5317
    {
5318
        $existingFields = [
5319
            new Field(
5320
                [
5321
                    'id' => '100',
5322
                    'fieldDefIdentifier' => 'identifier',
5323
                    'value' => 'initialValue',
5324
                    'languageCode' => 'eng-GB',
5325
                ]
5326
            ),
5327
        ];
5328
5329
        $fieldDefinitions = [
5330
            new FieldDefinition(
5331
                [
5332
                    'id' => 'fieldDefinitionId',
5333
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
5334
                    'isTranslatable' => false,
5335
                    'identifier' => 'identifier',
5336
                    'isRequired' => false,
5337
                    'defaultValue' => 'defaultValue',
5338
                ]
5339
            ),
5340
        ];
5341
5342
        // Setup a simple case that will pass
5343
        list($versionInfo, $contentUpdateStruct) = $this->assertForTestUpdateContentNonRedundantFieldSet(
5344
            'eng-US',
5345
            [],
5346
            [],
5347
            $existingFields,
5348
            $fieldDefinitions,
5349
            // Do not execute test
5350
            false
5351
        );
5352
5353
        $repositoryMock = $this->getRepositoryMock();
5354
        $repositoryMock->expects($this->never())->method('commit');
5355
        $repositoryMock->expects($this->once())->method('rollback');
5356
5357
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
5358
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
5359
        $contentHandlerMock->expects($this->once())
5360
            ->method('updateContent')
5361
            ->with(
5362
                $this->anything(),
5363
                $this->anything(),
5364
                $this->anything()
5365
            )->will($this->throwException(new \Exception('Store failed')));
5366
5367
        // Execute
5368
        $this->partlyMockedContentService->updateContent($versionInfo, $contentUpdateStruct);
5369
    }
5370
5371
    /**
5372
     * Test for the copyContent() method.
5373
     *
5374
     * @covers \eZ\Publish\Core\Repository\ContentService::copyContent
5375
     * @expectedException \eZ\Publish\Core\Base\Exceptions\UnauthorizedException
5376
     */
5377
    public function testCopyContentThrowsUnauthorizedException()
5378
    {
5379
        $repository = $this->getRepositoryMock();
5380
        $contentService = $this->getPartlyMockedContentService(['internalLoadContentInfo']);
5381
        $contentInfo = $this->createMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
5382
        $locationCreateStruct = new LocationCreateStruct();
5383
        $location = new Location(['id' => $locationCreateStruct->parentLocationId]);
5384
        $locationServiceMock = $this->getLocationServiceMock();
5385
5386
        $repository->expects($this->once())
5387
            ->method('getLocationService')
5388
            ->will($this->returnValue($locationServiceMock))
5389
        ;
5390
5391
        $locationServiceMock->expects($this->once())
5392
            ->method('loadLocation')
5393
            ->with(
5394
                $locationCreateStruct->parentLocationId
5395
            )
5396
            ->will($this->returnValue($location))
5397
        ;
5398
5399
        $contentInfo->expects($this->any())
5400
            ->method('__get')
5401
            ->with('sectionId')
5402
            ->will($this->returnValue(42));
5403
5404
        $repository->expects($this->once())
5405
            ->method('canUser')
5406
            ->with(
5407
                'content',
5408
                'create',
5409
                $contentInfo,
5410
                [$location]
5411
            )
5412
            ->will($this->returnValue(false));
5413
5414
        /* @var \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo */
5415
        $contentService->copyContent($contentInfo, $locationCreateStruct);
5416
    }
5417
5418
    /**
5419
     * Test for the copyContent() method.
5420
     *
5421
     * @covers \eZ\Publish\Core\Repository\ContentService::copyContent
5422
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
5423
     * @covers \eZ\Publish\Core\Repository\ContentService::internalPublishVersion
5424
     */
5425
    public function testCopyContent()
5426
    {
5427
        $repositoryMock = $this->getRepositoryMock();
5428
        $contentService = $this->getPartlyMockedContentService(['internalLoadContentInfo', 'internalLoadContent']);
5429
        $locationServiceMock = $this->getLocationServiceMock();
5430
        $contentInfoMock = $this->createMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
5431
        $locationCreateStruct = new LocationCreateStruct();
5432
        $location = new Location(['id' => $locationCreateStruct->parentLocationId]);
5433
        $user = $this->getStubbedUser(14);
5434
5435
        $permissionResolverMock = $this
5436
            ->getMockBuilder('eZ\\Publish\\API\\Repository\\PermissionResolver')
5437
            ->disableOriginalConstructor()
5438
            ->getMock();
5439
5440
        $permissionResolverMock
5441
            ->method('getCurrentUserReference')
5442
            ->willReturn($user);
5443
5444
        $repositoryMock
5445
            ->method('getPermissionResolver')
5446
            ->willReturn($permissionResolverMock);
5447
5448
        $repositoryMock->expects($this->exactly(3))
5449
            ->method('getLocationService')
5450
            ->will($this->returnValue($locationServiceMock));
5451
5452
        $locationServiceMock->expects($this->once())
5453
            ->method('loadLocation')
5454
            ->with($locationCreateStruct->parentLocationId)
5455
            ->will($this->returnValue($location))
5456
        ;
5457
5458
        $contentInfoMock->expects($this->any())
5459
            ->method('__get')
5460
            ->with('id')
5461
            ->will($this->returnValue(42));
5462
        $versionInfoMock = $this->createMock(APIVersionInfo::class);
5463
5464
        $versionInfoMock->expects($this->any())
5465
            ->method('__get')
5466
            ->will(
5467
                $this->returnValueMap(
5468
                    [
5469
                        ['versionNo', 123],
5470
                    ]
5471
                )
5472
            );
5473
5474
        $versionInfoMock->expects($this->once())
5475
            ->method('isDraft')
5476
            ->willReturn(true);
5477
5478
        $versionInfoMock->expects($this->once())
5479
            ->method('getContentInfo')
5480
            ->will($this->returnValue($contentInfoMock));
5481
5482
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
5483
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
5484
        $domainMapperMock = $this->getDomainMapperMock();
5485
5486
        $repositoryMock->expects($this->once())->method('beginTransaction');
5487
        $repositoryMock->expects($this->once())->method('commit');
5488
        $repositoryMock->expects($this->once())
5489
            ->method('canUser')
5490
            ->with(
5491
                'content',
5492
                'create',
5493
                $contentInfoMock,
5494
                [$location]
5495
            )
5496
            ->will($this->returnValue(true));
5497
5498
        $spiContentInfo = new SPIContentInfo(['id' => 42]);
5499
        $spiVersionInfo = new SPIVersionInfo(
5500
            [
5501
                'contentInfo' => $spiContentInfo,
5502
                'creationDate' => 123456,
5503
            ]
5504
        );
5505
        $spiContent = new SPIContent(['versionInfo' => $spiVersionInfo]);
5506
        $contentHandlerMock->expects($this->once())
5507
            ->method('copy')
5508
            ->with(42, null)
5509
            ->will($this->returnValue($spiContent));
5510
5511
        $this->mockGetDefaultObjectStates();
5512
        $this->mockSetDefaultObjectStates();
5513
5514
        $domainMapperMock->expects($this->once())
5515
            ->method('buildVersionInfoDomainObject')
5516
            ->with($spiVersionInfo)
5517
            ->will($this->returnValue($versionInfoMock));
5518
5519
        /* @var \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfoMock */
5520
        $content = $this->mockPublishVersion(123456);
5521
        $locationServiceMock->expects($this->once())
5522
            ->method('createLocation')
5523
            ->with(
5524
                $content->getVersionInfo()->getContentInfo(),
5525
                $locationCreateStruct
5526
            );
5527
5528
        $contentService->expects($this->once())
5529
            ->method('internalLoadContent')
5530
            ->with(
5531
                $content->id
5532
            )
5533
            ->will($this->returnValue($content));
5534
5535
        /* @var \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfoMock */
5536
        $contentService->copyContent($contentInfoMock, $locationCreateStruct, null);
5537
    }
5538
5539
    /**
5540
     * Test for the copyContent() method.
5541
     *
5542
     * @covers \eZ\Publish\Core\Repository\ContentService::copyContent
5543
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
5544
     * @covers \eZ\Publish\Core\Repository\ContentService::internalPublishVersion
5545
     */
5546
    public function testCopyContentWithVersionInfo()
5547
    {
5548
        $repositoryMock = $this->getRepositoryMock();
5549
        $contentService = $this->getPartlyMockedContentService(['internalLoadContentInfo', 'internalLoadContent']);
5550
        $locationServiceMock = $this->getLocationServiceMock();
5551
        $contentInfoMock = $this->createMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
5552
        $locationCreateStruct = new LocationCreateStruct();
5553
        $location = new Location(['id' => $locationCreateStruct->parentLocationId]);
5554
        $user = $this->getStubbedUser(14);
5555
5556
        $permissionResolverMock = $this
5557
            ->getMockBuilder('eZ\\Publish\\API\\Repository\\PermissionResolver')
5558
            ->disableOriginalConstructor()
5559
            ->getMock();
5560
5561
        $permissionResolverMock
5562
            ->method('getCurrentUserReference')
5563
            ->willReturn($user);
5564
5565
        $repositoryMock
5566
            ->method('getPermissionResolver')
5567
            ->willReturn($permissionResolverMock);
5568
5569
        $repositoryMock->expects($this->exactly(3))
5570
            ->method('getLocationService')
5571
            ->will($this->returnValue($locationServiceMock));
5572
5573
        $locationServiceMock->expects($this->once())
5574
            ->method('loadLocation')
5575
            ->with($locationCreateStruct->parentLocationId)
5576
            ->will($this->returnValue($location))
5577
        ;
5578
5579
        $contentInfoMock->expects($this->any())
5580
            ->method('__get')
5581
            ->with('id')
5582
            ->will($this->returnValue(42));
5583
        $versionInfoMock = $this->createMock(APIVersionInfo::class);
5584
5585
        $versionInfoMock->expects($this->any())
5586
            ->method('__get')
5587
            ->will(
5588
                $this->returnValueMap(
5589
                    [
5590
                        ['versionNo', 123],
5591
                    ]
5592
                )
5593
            );
5594
        $versionInfoMock->expects($this->once())
5595
            ->method('isDraft')
5596
            ->willReturn(true);
5597
        $versionInfoMock->expects($this->once())
5598
            ->method('getContentInfo')
5599
            ->will($this->returnValue($contentInfoMock));
5600
5601
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
5602
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
5603
        $domainMapperMock = $this->getDomainMapperMock();
5604
5605
        $repositoryMock->expects($this->once())->method('beginTransaction');
5606
        $repositoryMock->expects($this->once())->method('commit');
5607
        $repositoryMock->expects($this->once())
5608
            ->method('canUser')
5609
            ->with(
5610
                'content',
5611
                'create',
5612
                $contentInfoMock,
5613
                [$location]
5614
            )
5615
            ->will($this->returnValue(true));
5616
5617
        $spiContentInfo = new SPIContentInfo(['id' => 42]);
5618
        $spiVersionInfo = new SPIVersionInfo(
5619
            [
5620
                'contentInfo' => $spiContentInfo,
5621
                'creationDate' => 123456,
5622
            ]
5623
        );
5624
        $spiContent = new SPIContent(['versionInfo' => $spiVersionInfo]);
5625
        $contentHandlerMock->expects($this->once())
5626
            ->method('copy')
5627
            ->with(42, 123)
5628
            ->will($this->returnValue($spiContent));
5629
5630
        $this->mockGetDefaultObjectStates();
5631
        $this->mockSetDefaultObjectStates();
5632
5633
        $domainMapperMock->expects($this->once())
5634
            ->method('buildVersionInfoDomainObject')
5635
            ->with($spiVersionInfo)
5636
            ->will($this->returnValue($versionInfoMock));
5637
5638
        /* @var \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfoMock */
5639
        $content = $this->mockPublishVersion(123456);
5640
        $locationServiceMock->expects($this->once())
5641
            ->method('createLocation')
5642
            ->with(
5643
                $content->getVersionInfo()->getContentInfo(),
5644
                $locationCreateStruct
5645
            );
5646
5647
        $contentService->expects($this->once())
5648
            ->method('internalLoadContent')
5649
            ->with(
5650
                $content->id
5651
            )
5652
            ->will($this->returnValue($content));
5653
5654
        /* @var \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfoMock */
5655
        $contentService->copyContent($contentInfoMock, $locationCreateStruct, $versionInfoMock);
5656
    }
5657
5658
    /**
5659
     * Test for the copyContent() method.
5660
     *
5661
     * @covers \eZ\Publish\Core\Repository\ContentService::copyContent
5662
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
5663
     * @covers \eZ\Publish\Core\Repository\ContentService::internalPublishVersion
5664
     * @expectedException \Exception
5665
     * @expectedExceptionMessage Handler threw an exception
5666
     */
5667
    public function testCopyContentWithRollback()
5668
    {
5669
        $repositoryMock = $this->getRepositoryMock();
5670
        $contentService = $this->getPartlyMockedContentService();
5671
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
5672
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
5673
        $locationCreateStruct = new LocationCreateStruct();
5674
        $location = new Location(['id' => $locationCreateStruct->parentLocationId]);
5675
        $locationServiceMock = $this->getLocationServiceMock();
5676
        $user = $this->getStubbedUser(14);
5677
5678
        $permissionResolverMock = $this
5679
            ->getMockBuilder('eZ\\Publish\\API\\Repository\\PermissionResolver')
5680
            ->disableOriginalConstructor()
5681
            ->getMock();
5682
5683
        $permissionResolverMock
5684
            ->method('getCurrentUserReference')
5685
            ->willReturn($user);
5686
5687
        $repositoryMock
5688
            ->method('getPermissionResolver')
5689
            ->willReturn($permissionResolverMock);
5690
5691
        $repositoryMock->expects($this->once())
5692
            ->method('getLocationService')
5693
            ->will($this->returnValue($locationServiceMock))
5694
        ;
5695
5696
        $locationServiceMock->expects($this->once())
5697
            ->method('loadLocation')
5698
            ->with($locationCreateStruct->parentLocationId)
5699
            ->will($this->returnValue($location))
5700
        ;
5701
5702
        $contentInfoMock = $this->createMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
5703
        $contentInfoMock->expects($this->any())
5704
            ->method('__get')
5705
            ->with('id')
5706
            ->will($this->returnValue(42));
5707
5708
        $this->mockGetDefaultObjectStates();
5709
5710
        $repositoryMock->expects($this->once())->method('beginTransaction');
5711
        $repositoryMock->expects($this->once())->method('rollback');
5712
        $repositoryMock->expects($this->once())
5713
            ->method('canUser')
5714
            ->with(
5715
                'content',
5716
                'create',
5717
                $contentInfoMock,
5718
                [$location]
5719
            )
5720
            ->will($this->returnValue(true));
5721
5722
        $contentHandlerMock->expects($this->once())
5723
            ->method('copy')
5724
            ->with(42, null)
5725
            ->will($this->throwException(new Exception('Handler threw an exception')));
5726
5727
        /* @var \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfoMock */
5728
        $contentService->copyContent($contentInfoMock, $locationCreateStruct, null);
5729
    }
5730
5731
    protected function mockGetDefaultObjectStates()
5732
    {
5733
        /** @var \PHPUnit_Framework_MockObject_MockObject $objectStateHandlerMock */
5734
        $objectStateHandlerMock = $this->getPersistenceMock()->objectStateHandler();
5735
5736
        $objectStateGroups = [
5737
            new SPIObjectStateGroup(['id' => 10]),
5738
            new SPIObjectStateGroup(['id' => 20]),
5739
        ];
5740
5741
        /* @var \PHPUnit_Framework_MockObject_MockObject $objectStateHandlerMock */
5742
        $objectStateHandlerMock->expects($this->once())
5743
            ->method('loadAllGroups')
5744
            ->will($this->returnValue($objectStateGroups));
5745
5746
        $objectStateHandlerMock->expects($this->at(1))
5747
            ->method('loadObjectStates')
5748
            ->with($this->equalTo(10))
5749
            ->will(
5750
                $this->returnValue(
5751
                    [
5752
                        new SPIObjectState(['id' => 11, 'groupId' => 10]),
5753
                        new SPIObjectState(['id' => 12, 'groupId' => 10]),
5754
                    ]
5755
                )
5756
            );
5757
5758
        $objectStateHandlerMock->expects($this->at(2))
5759
            ->method('loadObjectStates')
5760
            ->with($this->equalTo(20))
5761
            ->will(
5762
                $this->returnValue(
5763
                    [
5764
                        new SPIObjectState(['id' => 21, 'groupId' => 20]),
5765
                        new SPIObjectState(['id' => 22, 'groupId' => 20]),
5766
                    ]
5767
                )
5768
            );
5769
    }
5770
5771
    protected function mockSetDefaultObjectStates()
5772
    {
5773
        /** @var \PHPUnit_Framework_MockObject_MockObject $objectStateHandlerMock */
5774
        $objectStateHandlerMock = $this->getPersistenceMock()->objectStateHandler();
5775
5776
        $defaultObjectStates = [
5777
            new SPIObjectState(['id' => 11, 'groupId' => 10]),
5778
            new SPIObjectState(['id' => 21, 'groupId' => 20]),
5779
        ];
5780
        foreach ($defaultObjectStates as $index => $objectState) {
5781
            $objectStateHandlerMock->expects($this->at($index + 3))
5782
                ->method('setContentState')
5783
                ->with(
5784
                    42,
5785
                    $objectState->groupId,
5786
                    $objectState->id
5787
                );
5788
        }
5789
    }
5790
5791
    /**
5792
     * @param int|null $publicationDate
5793
     *
5794
     * @return \eZ\Publish\API\Repository\Values\Content\Content
5795
     */
5796
    protected function mockPublishVersion($publicationDate = null)
5797
    {
5798
        $domainMapperMock = $this->getDomainMapperMock();
5799
        $contentMock = $this->createMock('eZ\\Publish\\API\\Repository\\Values\\Content\\Content');
5800
        /* @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
5801
        $versionInfoMock = $this->createMock(APIVersionInfo::class);
5802
        $contentInfoMock = $this->createMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
5803
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
5804
        $metadataUpdateStruct = new SPIMetadataUpdateStruct();
5805
5806
        $contentMock->expects($this->any())
5807
            ->method('__get')
5808
            ->will(
5809
                $this->returnValueMap(
5810
                    [
5811
                        ['id', 42],
5812
                        ['contentInfo', $contentInfoMock],
5813
                        ['versionInfo', $versionInfoMock],
5814
                    ]
5815
                )
5816
            );
5817
        $contentMock->expects($this->any())
5818
            ->method('getVersionInfo')
5819
            ->will($this->returnValue($versionInfoMock));
5820
        $versionInfoMock->expects($this->any())
5821
            ->method('getContentInfo')
5822
            ->will($this->returnValue($contentInfoMock));
5823
        $versionInfoMock->expects($this->any())
5824
            ->method('__get')
5825
            ->will(
5826
                $this->returnValueMap(
5827
                    [
5828
                        ['languageCodes', ['eng-GB']],
5829
                    ]
5830
                )
5831
            );
5832
        $contentInfoMock->expects($this->any())
5833
            ->method('__get')
5834
            ->will(
5835
                $this->returnValueMap(
5836
                    [
5837
                        ['alwaysAvailable', true],
5838
                        ['mainLanguageCode', 'eng-GB'],
5839
                    ]
5840
                )
5841
            );
5842
5843
        $currentTime = time();
5844
        if ($publicationDate === null && $versionInfoMock->versionNo === 1) {
5845
            $publicationDate = $currentTime;
5846
        }
5847
5848
        // Account for 1 second of test execution time
5849
        $metadataUpdateStruct->publicationDate = $publicationDate;
5850
        $metadataUpdateStruct->modificationDate = $currentTime;
5851
        $metadataUpdateStruct2 = clone $metadataUpdateStruct;
5852
        ++$metadataUpdateStruct2->publicationDate;
5853
        ++$metadataUpdateStruct2->modificationDate;
5854
5855
        $spiContent = new SPIContent();
5856
        $contentHandlerMock->expects($this->once())
5857
            ->method('publish')
5858
            ->with(
5859
                42,
5860
                123,
5861
                $this->logicalOr($metadataUpdateStruct, $metadataUpdateStruct2)
5862
            )
5863
            ->will($this->returnValue($spiContent));
5864
5865
        $domainMapperMock->expects($this->once())
5866
            ->method('buildContentDomainObject')
5867
            ->with($spiContent)
5868
            ->will($this->returnValue($contentMock));
5869
5870
        /* @var \eZ\Publish\API\Repository\Values\Content\Content $contentMock */
5871
        $this->mockPublishUrlAliasesForContent($contentMock);
5872
5873
        return $contentMock;
5874
    }
5875
5876
    /**
5877
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
5878
     */
5879
    protected function mockPublishUrlAliasesForContent(APIContent $content)
5880
    {
5881
        $nameSchemaServiceMock = $this->getNameSchemaServiceMock();
5882
        /** @var \PHPUnit_Framework_MockObject_MockObject $urlAliasHandlerMock */
5883
        $urlAliasHandlerMock = $this->getPersistenceMock()->urlAliasHandler();
5884
        $locationServiceMock = $this->getLocationServiceMock();
5885
        $location = $this->createMock('eZ\\Publish\\API\\Repository\\Values\\Content\\Location');
5886
5887
        $location->expects($this->at(0))
5888
            ->method('__get')
5889
            ->with('id')
5890
            ->will($this->returnValue(123));
5891
        $location->expects($this->at(1))
5892
            ->method('__get')
5893
            ->with('parentLocationId')
5894
            ->will($this->returnValue(456));
5895
5896
        $urlAliasNames = ['eng-GB' => 'hello'];
5897
        $nameSchemaServiceMock->expects($this->once())
5898
            ->method('resolveUrlAliasSchema')
5899
            ->with($content)
5900
            ->will($this->returnValue($urlAliasNames));
5901
5902
        $locationServiceMock->expects($this->once())
5903
            ->method('loadLocations')
5904
            ->with($content->getVersionInfo()->getContentInfo())
5905
            ->will($this->returnValue([$location]));
5906
5907
        $urlAliasHandlerMock->expects($this->once())
5908
            ->method('publishUrlAliasForLocation')
5909
            ->with(123, 456, 'hello', 'eng-GB', true, true);
5910
5911
        $location->expects($this->at(2))
5912
            ->method('__get')
5913
            ->with('id')
5914
            ->will($this->returnValue(123));
5915
5916
        $location->expects($this->at(3))
5917
            ->method('__get')
5918
            ->with('parentLocationId')
5919
            ->will($this->returnValue(456));
5920
5921
        $urlAliasHandlerMock->expects($this->once())
5922
            ->method('archiveUrlAliasesForDeletedTranslations')
5923
            ->with(123, 456, ['eng-GB']);
5924
    }
5925
5926
    protected $domainMapperMock;
5927
5928
    /**
5929
     * @return \PHPUnit_Framework_MockObject_MockObject|\eZ\Publish\Core\Repository\Helper\DomainMapper
5930
     */
5931 View Code Duplication
    protected function getDomainMapperMock()
5932
    {
5933
        if (!isset($this->domainMapperMock)) {
5934
            $this->domainMapperMock = $this
5935
                ->getMockBuilder('eZ\\Publish\\Core\\Repository\\Helper\\DomainMapper')
5936
                ->disableOriginalConstructor()
5937
                ->getMock();
5938
        }
5939
5940
        return $this->domainMapperMock;
5941
    }
5942
5943
    protected $relationProcessorMock;
5944
5945
    /**
5946
     * @return \PHPUnit_Framework_MockObject_MockObject|\eZ\Publish\Core\Repository\Helper\RelationProcessor
5947
     */
5948
    protected function getRelationProcessorMock()
5949
    {
5950
        if (!isset($this->relationProcessorMock)) {
5951
            $this->relationProcessorMock = $this
5952
                ->getMockBuilder('eZ\\Publish\\Core\\Repository\\Helper\\RelationProcessor')
5953
                ->disableOriginalConstructor()
5954
                ->getMock();
5955
        }
5956
5957
        return $this->relationProcessorMock;
5958
    }
5959
5960
    protected $nameSchemaServiceMock;
5961
5962
    /**
5963
     * @return \PHPUnit_Framework_MockObject_MockObject|\eZ\Publish\Core\Repository\Helper\NameSchemaService
5964
     */
5965
    protected function getNameSchemaServiceMock()
5966
    {
5967
        if (!isset($this->nameSchemaServiceMock)) {
5968
            $this->nameSchemaServiceMock = $this
5969
                ->getMockBuilder('eZ\\Publish\\Core\\Repository\\Helper\\NameSchemaService')
5970
                ->disableOriginalConstructor()
5971
                ->getMock();
5972
        }
5973
5974
        return $this->nameSchemaServiceMock;
5975
    }
5976
5977
    protected $contentTypeServiceMock;
5978
5979
    /**
5980
     * @return \PHPUnit_Framework_MockObject_MockObject|\eZ\Publish\API\Repository\ContentTypeService
5981
     */
5982
    protected function getContentTypeServiceMock()
5983
    {
5984
        if (!isset($this->contentTypeServiceMock)) {
5985
            $this->contentTypeServiceMock = $this
5986
                ->getMockBuilder('eZ\\Publish\\API\\Repository\\ContentTypeService')
5987
                ->disableOriginalConstructor()
5988
                ->getMock();
5989
        }
5990
5991
        return $this->contentTypeServiceMock;
5992
    }
5993
5994
    protected $locationServiceMock;
5995
5996
    /**
5997
     * @return \PHPUnit_Framework_MockObject_MockObject|\eZ\Publish\API\Repository\LocationService
5998
     */
5999
    protected function getLocationServiceMock()
6000
    {
6001
        if (!isset($this->locationServiceMock)) {
6002
            $this->locationServiceMock = $this
6003
                ->getMockBuilder('eZ\\Publish\\API\\Repository\\LocationService')
6004
                ->disableOriginalConstructor()
6005
                ->getMock();
6006
        }
6007
6008
        return $this->locationServiceMock;
6009
    }
6010
6011
    /**
6012
     * @var \eZ\Publish\Core\Repository\ContentService
6013
     */
6014
    protected $partlyMockedContentService;
6015
6016
    /**
6017
     * Returns the content service to test with $methods mocked.
6018
     *
6019
     * Injected Repository comes from {@see getRepositoryMock()} and persistence handler from {@see getPersistenceMock()}
6020
     *
6021
     * @param string[] $methods
6022
     *
6023
     * @return \eZ\Publish\Core\Repository\ContentService|\PHPUnit_Framework_MockObject_MockObject
6024
     */
6025
    protected function getPartlyMockedContentService(array $methods = null)
6026
    {
6027
        if (!isset($this->partlyMockedContentService)) {
6028
            $this->partlyMockedContentService = $this->getMockBuilder('eZ\\Publish\\Core\\Repository\\ContentService')
6029
                ->setMethods($methods)
6030
                ->setConstructorArgs(
6031
                    [
6032
                        $this->getRepositoryMock(),
6033
                        $this->getPersistenceMock(),
6034
                        $this->getDomainMapperMock(),
6035
                        $this->getRelationProcessorMock(),
6036
                        $this->getNameSchemaServiceMock(),
6037
                        $this->getFieldTypeRegistryMock(),
6038
                        [],
6039
                    ]
6040
                )
6041
                ->getMock();
6042
        }
6043
6044
        return $this->partlyMockedContentService;
6045
    }
6046
}
6047