Completed
Push — master ( 727c99...0dc4f6 )
by André
21:06
created

ContentTest::testLoadVersionInfoById()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

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

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
6050
                ->setMethods($methods)
6051
                ->setConstructorArgs(
6052
                    array(
6053
                        $this->getRepositoryMock(),
6054
                        $this->getPersistenceMock(),
6055
                        $this->getDomainMapperMock(),
6056
                        $this->getRelationProcessorMock(),
6057
                        $this->getNameSchemaServiceMock(),
6058
                        $this->getFieldTypeRegistryMock(),
6059
                        array(),
6060
                    )
6061
                )
6062
                ->getMock();
6063
        }
6064
6065
        return $this->partlyMockedContentService;
6066
    }
6067
}
6068