Completed
Push — signal_search_issues ( 5556b2...f328ba )
by André
63:06 queued 07:22
created

ContentTest::getPartlyMockedContentService()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 14
nc 2
nop 1
dl 0
loc 20
rs 9.4285
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
 * @version //autogentag//
10
 */
11
namespace eZ\Publish\Core\Repository\Tests\Service\Mock;
12
13
use eZ\Publish\API\Repository\Values\Content\Language;
14
use eZ\Publish\API\Repository\Values\Content\LocationCreateStruct;
15
use eZ\Publish\Core\Base\Exceptions\ContentFieldValidationException;
16
use eZ\Publish\Core\Base\Exceptions\ContentValidationException;
17
use eZ\Publish\Core\Repository\Tests\Service\Mock\Base as BaseServiceMockTest;
18
use eZ\Publish\Core\Repository\ContentService;
19
use eZ\Publish\Core\Repository\Values\Content\Location;
20
use eZ\Publish\Core\Repository\Values\Content\Content;
21
use eZ\Publish\Core\Repository\Values\Content\ContentCreateStruct;
22
use eZ\Publish\Core\Repository\Values\Content\ContentUpdateStruct;
23
use eZ\Publish\API\Repository\Values\Content\Content as APIContent;
24
use eZ\Publish\API\Repository\Values\Content\VersionInfo as APIVersionInfo;
25
use eZ\Publish\Core\Repository\Values\Content\VersionInfo;
26
use eZ\Publish\API\Repository\Values\Content\Field;
27
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
28
use eZ\Publish\Core\Repository\Values\ContentType\ContentType;
29
use eZ\Publish\Core\Repository\Values\ContentType\FieldDefinition;
30
use eZ\Publish\SPI\Persistence\Content\Location as SPILocation;
31
use eZ\Publish\SPI\Persistence\Content as SPIContent;
32
use eZ\Publish\SPI\Persistence\Content\UpdateStruct as SPIContentUpdateStruct;
33
use eZ\Publish\SPI\Persistence\Content\CreateStruct as SPIContentCreateStruct;
34
use eZ\Publish\SPI\Persistence\Content\Field as SPIField;
35
use eZ\Publish\SPI\Persistence\Content\ObjectState\Group as SPIObjectStateGroup;
36
use eZ\Publish\SPI\Persistence\Content\ObjectState as SPIObjectState;
37
use eZ\Publish\SPI\Persistence\Content\VersionInfo as SPIVersionInfo;
38
use eZ\Publish\SPI\Persistence\Content\ContentInfo as SPIContentInfo;
39
use eZ\Publish\SPI\Persistence\Content\MetadataUpdateStruct as SPIMetadataUpdateStruct;
40
use eZ\Publish\Core\Base\Exceptions\NotFoundException;
41
use eZ\Publish\Core\Repository\Values\User\UserReference;
42
use Exception;
43
44
/**
45
 * Mock test case for Content service.
46
 */
47
class ContentTest extends BaseServiceMockTest
48
{
49
    /**
50
     * Represents empty Field Value.
51
     */
52
    const EMPTY_FIELD_VALUE = 'empty';
53
54
    /**
55
     * Test for the __construct() method.
56
     *
57
     * @covers \eZ\Publish\Core\Repository\ContentService::__construct
58
     */
59
    public function testConstructor()
60
    {
61
        $repositoryMock = $this->getRepositoryMock();
62
        /** @var \eZ\Publish\SPI\Persistence\Handler $persistenceHandlerMock */
63
        $persistenceHandlerMock = $this->getPersistenceMockHandler('Handler');
64
        $domainMapperMock = $this->getDomainMapperMock();
65
        $relationProcessorMock = $this->getRelationProcessorMock();
66
        $nameSchemaServiceMock = $this->getNameSchemaServiceMock();
67
        $fieldTypeRegistryMock = $this->getFieldTypeRegistryMock();
68
        $settings = array('settings');
69
70
        $service = new ContentService(
71
            $repositoryMock,
0 ignored issues
show
Bug introduced by
It seems like $repositoryMock defined by $this->getRepositoryMock() on line 61 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...
72
            $persistenceHandlerMock,
73
            $domainMapperMock,
0 ignored issues
show
Bug introduced by
It seems like $domainMapperMock defined by $this->getDomainMapperMock() on line 64 can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, eZ\Publish\Core\Reposito...tService::__construct() does only seem to accept object<eZ\Publish\Core\R...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...
74
            $relationProcessorMock,
0 ignored issues
show
Bug introduced by
It seems like $relationProcessorMock defined by $this->getRelationProcessorMock() on line 65 can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, eZ\Publish\Core\Reposito...tService::__construct() does only seem to accept object<eZ\Publish\Core\R...lper\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...
75
            $nameSchemaServiceMock,
0 ignored issues
show
Bug introduced by
It seems like $nameSchemaServiceMock defined by $this->getNameSchemaServiceMock() on line 66 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...
76
            $fieldTypeRegistryMock,
0 ignored issues
show
Bug introduced by
It seems like $fieldTypeRegistryMock defined by $this->getFieldTypeRegistryMock() on line 67 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...
77
            $settings
78
        );
79
80
        $this->assertAttributeSame(
81
            $repositoryMock,
82
            'repository',
83
            $service
84
        );
85
86
        $this->assertAttributeSame(
87
            $persistenceHandlerMock,
88
            'persistenceHandler',
89
            $service
90
        );
91
92
        $this->assertAttributeSame(
93
            $domainMapperMock,
94
            'domainMapper',
95
            $service
96
        );
97
98
        $this->assertAttributeSame(
99
            $relationProcessorMock,
100
            'relationProcessor',
101
            $service
102
        );
103
104
        $this->assertAttributeSame(
105
            $nameSchemaServiceMock,
106
            'nameSchemaService',
107
            $service
108
        );
109
110
        $this->assertAttributeSame(
111
            $fieldTypeRegistryMock,
112
            'fieldTypeRegistry',
113
            $service
114
        );
115
116
        $this->assertAttributeSame(
117
            $settings,
118
            'settings',
119
            $service
120
        );
121
    }
122
123
    /**
124
     * Test for the loadVersionInfo() method.
125
     *
126
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById
127
     */
128
    public function testLoadVersionInfoById()
129
    {
130
        $repository = $this->getRepositoryMock();
131
        $contentServiceMock = $this->getPartlyMockedContentService(array('loadContentInfo'));
132
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
133
        $contentHandler = $this->getPersistenceMock()->contentHandler();
134
        $domainMapperMock = $this->getDomainMapperMock();
135
        $versionInfoMock = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\VersionInfo');
136
137
        $versionInfoMock->expects($this->any())
138
            ->method('__get')
139
            ->with('status')
140
            ->will($this->returnValue(APIVersionInfo::STATUS_PUBLISHED));
141
142
        $contentServiceMock->expects($this->once())
143
            ->method('loadContentInfo')
144
            ->with($this->equalTo(42))
145
            ->will(
146
                $this->returnValue(
147
                    new ContentInfo(array('currentVersionNo' => 24))
148
                )
149
            );
150
151
        $contentHandler->expects($this->once())
152
            ->method('loadVersionInfo')
153
            ->with(
154
                $this->equalTo(42),
155
                $this->equalTo(24)
156
            )->will(
157
                $this->returnValue(new SPIVersionInfo())
158
            );
159
160
        $domainMapperMock->expects($this->once())
161
            ->method('buildVersionInfoDomainObject')
162
            ->with(new SPIVersionInfo())
163
            ->will($this->returnValue($versionInfoMock));
164
165
        $repository->expects($this->once())
166
            ->method('canUser')
167
            ->with(
168
                $this->equalTo('content'),
169
                $this->equalTo('read'),
170
                $this->equalTo($versionInfoMock)
171
            )->will($this->returnValue(true));
172
173
        $result = $contentServiceMock->loadVersionInfoById(42);
174
175
        $this->assertEquals($versionInfoMock, $result);
176
    }
177
178
    /**
179
     * Test for the loadVersionInfo() method.
180
     *
181
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById
182
     * @expectedException \eZ\Publish\Core\Base\Exceptions\NotFoundException
183
     */
184
    public function testLoadVersionInfoByIdThrowsNotFoundException()
185
    {
186
        $contentServiceMock = $this->getPartlyMockedContentService(array('loadContentInfo'));
187
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
188
        $contentHandler = $this->getPersistenceMock()->contentHandler();
189
190
        $contentHandler->expects($this->once())
191
            ->method('loadVersionInfo')
192
            ->with(
193
                $this->equalTo(42),
194
                $this->equalTo(24)
195
            )->will(
196
                $this->throwException(
197
                    new NotFoundException(
198
                        'Content',
199
                        array(
200
                            'contentId' => 42,
201
                            'versionNo' => 24,
202
                        )
203
                    )
204
                )
205
            );
206
207
        $contentServiceMock->loadVersionInfoById(42, 24);
208
    }
209
210
    /**
211
     * Test for the loadVersionInfo() method.
212
     *
213
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById
214
     * @expectedException \eZ\Publish\Core\Base\Exceptions\UnauthorizedException
215
     */
216
    public function testLoadVersionInfoByIdThrowsUnauthorizedExceptionNonPublishedVersion()
217
    {
218
        $repository = $this->getRepositoryMock();
219
        $contentServiceMock = $this->getPartlyMockedContentService();
220
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
221
        $contentHandler = $this->getPersistenceMock()->contentHandler();
222
        $domainMapperMock = $this->getDomainMapperMock();
223
        $versionInfoMock = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\VersionInfo');
224
225
        $versionInfoMock->expects($this->any())
226
            ->method('__get')
227
            ->with('status')
228
            ->will($this->returnValue(APIVersionInfo::STATUS_DRAFT));
229
230
        $contentHandler->expects($this->once())
231
            ->method('loadVersionInfo')
232
            ->with(
233
                $this->equalTo(42),
234
                $this->equalTo(24)
235
            )->will(
236
                $this->returnValue(new SPIVersionInfo())
237
            );
238
239
        $domainMapperMock->expects($this->once())
240
            ->method('buildVersionInfoDomainObject')
241
            ->with(new SPIVersionInfo())
242
            ->will($this->returnValue($versionInfoMock));
243
244
        $repository->expects($this->once())
245
            ->method('canUser')
246
            ->with(
247
                $this->equalTo('content'),
248
                $this->equalTo('versionread'),
249
                $this->equalTo($versionInfoMock)
250
            )->will($this->returnValue(false));
251
252
        $contentServiceMock->loadVersionInfoById(42, 24);
253
    }
254
255
    /**
256
     * Test for the loadVersionInfo() method.
257
     *
258
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById
259
     */
260 View Code Duplication
    public function testLoadVersionInfoByIdPublishedVersion()
261
    {
262
        $repository = $this->getRepositoryMock();
263
        $contentServiceMock = $this->getPartlyMockedContentService();
264
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
265
        $contentHandler = $this->getPersistenceMock()->contentHandler();
266
        $domainMapperMock = $this->getDomainMapperMock();
267
        $versionInfoMock = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\VersionInfo');
268
269
        $versionInfoMock->expects($this->any())
270
            ->method('__get')
271
            ->with('status')
272
            ->will($this->returnValue(APIVersionInfo::STATUS_PUBLISHED));
273
274
        $contentHandler->expects($this->once())
275
            ->method('loadVersionInfo')
276
            ->with(
277
                $this->equalTo(42),
278
                $this->equalTo(24)
279
            )->will(
280
                $this->returnValue(new SPIVersionInfo())
281
            );
282
283
        $domainMapperMock->expects($this->once())
284
            ->method('buildVersionInfoDomainObject')
285
            ->with(new SPIVersionInfo())
286
            ->will($this->returnValue($versionInfoMock));
287
288
        $repository->expects($this->once())
289
            ->method('canUser')
290
            ->with(
291
                $this->equalTo('content'),
292
                $this->equalTo('read'),
293
                $this->equalTo($versionInfoMock)
294
            )->will($this->returnValue(true));
295
296
        $result = $contentServiceMock->loadVersionInfoById(42, 24);
297
298
        $this->assertEquals($versionInfoMock, $result);
299
    }
300
301
    /**
302
     * Test for the loadVersionInfo() method.
303
     *
304
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfoById
305
     */
306 View Code Duplication
    public function testLoadVersionInfoByIdNonPublishedVersion()
307
    {
308
        $repository = $this->getRepositoryMock();
309
        $contentServiceMock = $this->getPartlyMockedContentService();
310
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
311
        $contentHandler = $this->getPersistenceMock()->contentHandler();
312
        $domainMapperMock = $this->getDomainMapperMock();
313
        $versionInfoMock = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\VersionInfo');
314
315
        $versionInfoMock->expects($this->any())
316
            ->method('__get')
317
            ->with('status')
318
            ->will($this->returnValue(APIVersionInfo::STATUS_DRAFT));
319
320
        $contentHandler->expects($this->once())
321
            ->method('loadVersionInfo')
322
            ->with(
323
                $this->equalTo(42),
324
                $this->equalTo(24)
325
            )->will(
326
                $this->returnValue(new SPIVersionInfo())
327
            );
328
329
        $domainMapperMock->expects($this->once())
330
            ->method('buildVersionInfoDomainObject')
331
            ->with(new SPIVersionInfo())
332
            ->will($this->returnValue($versionInfoMock));
333
334
        $repository->expects($this->once())
335
            ->method('canUser')
336
            ->with(
337
                $this->equalTo('content'),
338
                $this->equalTo('versionread'),
339
                $this->equalTo($versionInfoMock)
340
            )->will($this->returnValue(true));
341
342
        $result = $contentServiceMock->loadVersionInfoById(42, 24);
343
344
        $this->assertEquals($versionInfoMock, $result);
345
    }
346
347
    /**
348
     * Test for the loadVersionInfo() method.
349
     *
350
     * @covers \eZ\Publish\Core\Repository\ContentService::loadVersionInfo
351
     * @depends eZ\Publish\Core\Repository\Tests\Service\Mock\ContentTest::testLoadVersionInfoById
352
     * @depends eZ\Publish\Core\Repository\Tests\Service\Mock\ContentTest::testLoadVersionInfoByIdThrowsNotFoundException
353
     * @depends eZ\Publish\Core\Repository\Tests\Service\Mock\ContentTest::testLoadVersionInfoByIdThrowsUnauthorizedExceptionNonPublishedVersion
354
     * @depends eZ\Publish\Core\Repository\Tests\Service\Mock\ContentTest::testLoadVersionInfoByIdPublishedVersion
355
     * @depends eZ\Publish\Core\Repository\Tests\Service\Mock\ContentTest::testLoadVersionInfoByIdNonPublishedVersion
356
     */
357
    public function testLoadVersionInfo()
358
    {
359
        $contentServiceMock = $this->getPartlyMockedContentService(
360
            array('loadVersionInfoById')
361
        );
362
        $contentServiceMock->expects(
363
            $this->once()
364
        )->method(
365
            'loadVersionInfoById'
366
        )->with(
367
            $this->equalTo(42),
368
            $this->equalTo(7)
369
        )->will(
370
            $this->returnValue('result')
371
        );
372
373
        $result = $contentServiceMock->loadVersionInfo(
374
            new ContentInfo(array('id' => 42)),
375
            7
376
        );
377
378
        $this->assertEquals('result', $result);
379
    }
380
381
    public function testLoadContent()
382
    {
383
        $repository = $this->getRepositoryMock();
384
        $contentService = $this->getPartlyMockedContentService(array('internalLoadContent'));
385
        $content = $this->getMock('eZ\Publish\API\Repository\Values\Content\Content');
386
        $versionInfo = $this
387
            ->getMockBuilder('eZ\Publish\API\Repository\Values\Content\VersionInfo')
388
            ->setConstructorArgs(array(array('status' => APIVersionInfo::STATUS_PUBLISHED)))
389
            ->getMockForAbstractClass();
390
        $content
391
            ->expects($this->once())
392
            ->method('getVersionInfo')
393
            ->will($this->returnValue($versionInfo));
394
        $contentId = 123;
395
        $contentService
396
            ->expects($this->once())
397
            ->method('internalLoadContent')
398
            ->with($contentId)
399
            ->will($this->returnValue($content));
400
401
        $repository
402
            ->expects($this->once())
403
            ->method('canUser')
404
            ->with('content', 'read', $content)
405
            ->will($this->returnValue(true));
406
407
        $this->assertSame($content, $contentService->loadContent($contentId));
408
    }
409
410 View Code Duplication
    public function testLoadContentNonPublished()
411
    {
412
        $repository = $this->getRepositoryMock();
413
        $contentService = $this->getPartlyMockedContentService(array('internalLoadContent'));
414
        $content = $this->getMock('eZ\Publish\API\Repository\Values\Content\Content');
415
        $versionInfo = $this
416
            ->getMockBuilder('eZ\Publish\API\Repository\Values\Content\VersionInfo')
417
            ->setConstructorArgs(array(array('status' => APIVersionInfo::STATUS_DRAFT)))
418
            ->getMockForAbstractClass();
419
        $content
420
            ->expects($this->once())
421
            ->method('getVersionInfo')
422
            ->will($this->returnValue($versionInfo));
423
        $contentId = 123;
424
        $contentService
425
            ->expects($this->once())
426
            ->method('internalLoadContent')
427
            ->with($contentId)
428
            ->will($this->returnValue($content));
429
430
        $repository
431
            ->expects($this->exactly(2))
432
            ->method('canUser')
433
            ->will(
434
                $this->returnValueMap(
435
                    array(
436
                        array('content', 'read', $content, null, true),
437
                        array('content', 'versionread', $content, null, true),
438
                    )
439
                )
440
            );
441
442
        $this->assertSame($content, $contentService->loadContent($contentId));
443
    }
444
445
    /**
446
     * @expectedException \eZ\Publish\Core\Base\Exceptions\UnauthorizedException
447
     */
448 View Code Duplication
    public function testLoadContentUnauthorized()
449
    {
450
        $repository = $this->getRepositoryMock();
451
        $contentService = $this->getPartlyMockedContentService(array('internalLoadContent'));
452
        $content = $this->getMock('eZ\Publish\API\Repository\Values\Content\Content');
453
        $contentId = 123;
454
        $contentService
455
            ->expects($this->once())
456
            ->method('internalLoadContent')
457
            ->with($contentId)
458
            ->will($this->returnValue($content));
459
460
        $repository
461
            ->expects($this->once())
462
            ->method('canUser')
463
            ->with('content', 'read', $content)
464
            ->will($this->returnValue(false));
465
466
        $contentService->loadContent($contentId);
467
    }
468
469
    /**
470
     * @expectedException \eZ\Publish\Core\Base\Exceptions\UnauthorizedException
471
     */
472 View Code Duplication
    public function testLoadContentNotPublishedStatusUnauthorized()
473
    {
474
        $repository = $this->getRepositoryMock();
475
        $contentService = $this->getPartlyMockedContentService(array('internalLoadContent'));
476
        $content = $this->getMock('eZ\Publish\API\Repository\Values\Content\Content');
477
        $versionInfo = $this
478
            ->getMockBuilder('eZ\Publish\API\Repository\Values\Content\VersionInfo')
479
            ->setConstructorArgs(array(array('status' => APIVersionInfo::STATUS_DRAFT)))
480
            ->getMockForAbstractClass();
481
        $content
482
            ->expects($this->once())
483
            ->method('getVersionInfo')
484
            ->will($this->returnValue($versionInfo));
485
        $contentId = 123;
486
        $contentService
487
            ->expects($this->once())
488
            ->method('internalLoadContent')
489
            ->with($contentId)
490
            ->will($this->returnValue($content));
491
492
        $repository
493
            ->expects($this->exactly(2))
494
            ->method('canUser')
495
            ->will(
496
                $this->returnValueMap(
497
                    array(
498
                        array('content', 'read', $content, null, true),
499
                        array('content', 'versionread', $content, null, false),
500
                    )
501
                )
502
            );
503
504
        $contentService->loadContent($contentId);
505
    }
506
507
    /**
508
     * @dataProvider internalLoadContentProvider
509
     */
510
    public function testInternalLoadContent($id, $languages, $versionNo, $isRemoteId, $useAlwaysAvailable)
511
    {
512
        $contentService = $this->getPartlyMockedContentService();
513
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
514
        $contentHandler = $this->getPersistenceMock()->contentHandler();
515
        $realVersionNo = $versionNo;
516
        $realId = $id;
517
518
        if ($isRemoteId) {
519
            $realVersionNo = $versionNo ?: 7;
520
            $realId = 123;
521
            $spiContentInfo = new SPIContentInfo(array('currentVersionNo' => $realVersionNo, 'id' => $realId));
522
            $contentHandler
523
                ->expects($this->once())
524
                ->method('loadContentInfoByRemoteId')
525
                ->with($id)
526
                ->will($this->returnValue($spiContentInfo));
527
        } elseif ($versionNo === null) {
528
            $realVersionNo = 7;
529
            $spiContentInfo = new SPIContentInfo(array('currentVersionNo' => $realVersionNo));
530
            $contentHandler
531
                ->expects($this->once())
532
                ->method('loadContentInfo')
533
                ->with($id)
534
                ->will($this->returnValue($spiContentInfo));
535
        } elseif (!empty($languages) && $useAlwaysAvailable) {
536
            $spiContentInfo = new SPIContentInfo(array('alwaysAvailable' => false));
537
            $contentHandler
538
                ->expects($this->once())
539
                ->method('loadContentInfo')
540
                ->with($id)
541
                ->will($this->returnValue($spiContentInfo));
542
        }
543
544
        $spiContent = new SPIContent();
545
        $contentHandler
546
            ->expects($this->once())
547
            ->method('load')
548
            ->with($realId, $realVersionNo, $languages)
549
            ->will($this->returnValue($spiContent));
550
        $content = $this->getMock('eZ\Publish\API\Repository\Values\Content\Content');
551
        $this->getDomainMapperMock()
552
            ->expects($this->once())
553
            ->method('buildContentDomainObject')
554
            ->with($spiContent)
555
            ->will($this->returnValue($content));
556
557
        $this->assertSame(
558
            $content,
559
            $contentService->internalLoadContent($id, $languages, $versionNo, $isRemoteId, $useAlwaysAvailable)
560
        );
561
    }
562
563
    public function internalLoadContentProvider()
564
    {
565
        return array(
566
            array(123, null, null, false, false),
567
            array(123, null, 456, false, false),
568
            array(456, null, 123, false, true),
569
            array(456, null, 2, false, false),
570
            array(456, array('eng-GB'), 2, false, true),
571
            array(456, array('eng-GB', 'fre-FR'), null, false, false),
572
            array(456, array('eng-GB', 'fre-FR', 'nor-NO'), 2, false, false),
573
            // With remoteId
574
            array(123, null, null, true, false),
575
            array('someRemoteId', null, 456, true, false),
576
            array(456, null, 123, true, false),
577
            array('someRemoteId', null, 2, true, false),
578
            array('someRemoteId', array('eng-GB'), 2, true, false),
579
            array(456, array('eng-GB', 'fre-FR'), null, true, false),
580
            array('someRemoteId', array('eng-GB', 'fre-FR', 'nor-NO'), 2, true, false),
581
        );
582
    }
583
584
    /**
585
     * @expectedException \eZ\Publish\Core\Base\Exceptions\NotFoundException
586
     */
587
    public function testInternalLoadContentNotFound()
588
    {
589
        $contentService = $this->getPartlyMockedContentService();
590
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
591
        $contentHandler = $this->getPersistenceMock()->contentHandler();
592
        $id = 123;
593
        $versionNo = 7;
594
        $languages = null;
595
        $contentHandler
596
            ->expects($this->once())
597
            ->method('load')
598
            ->with($id, $versionNo, $languages)
599
            ->will(
600
                $this->throwException(
601
                    $this->getMock('eZ\Publish\API\Repository\Exceptions\NotFoundException')
602
                )
603
            );
604
605
        $contentService->internalLoadContent($id, $languages, $versionNo);
606
    }
607
608
    /**
609
     * Test for the loadContentByContentInfo() method.
610
     *
611
     * @covers \eZ\Publish\Core\Repository\ContentService::loadContentByContentInfo
612
     */
613
    public function testLoadContentByContentInfo()
614
    {
615
        $contentServiceMock = $this->getPartlyMockedContentService(
616
            array('loadContent')
617
        );
618
        $contentServiceMock->expects(
619
            $this->once()
620
        )->method(
621
            'loadContent'
622
        )->with(
623
            $this->equalTo(42),
624
            $this->equalTo(array('cro-HR')),
625
            $this->equalTo(7),
626
            $this->equalTo(false)
627
        )->will(
628
            $this->returnValue('result')
629
        );
630
631
        $result = $contentServiceMock->loadContentByContentInfo(
632
            new ContentInfo(array('id' => 42)),
633
            array('cro-HR'),
634
            7
635
        );
636
637
        $this->assertEquals('result', $result);
638
    }
639
640
    /**
641
     * Test for the loadContentByVersionInfo() method.
642
     *
643
     * @covers \eZ\Publish\Core\Repository\ContentService::loadContentByVersionInfo
644
     */
645
    public function testLoadContentByVersionInfo()
646
    {
647
        $contentServiceMock = $this->getPartlyMockedContentService(
648
            array('loadContent')
649
        );
650
        $contentServiceMock->expects(
651
            $this->once()
652
        )->method(
653
            'loadContent'
654
        )->with(
655
            $this->equalTo(42),
656
            $this->equalTo(array('cro-HR')),
657
            $this->equalTo(7),
658
            $this->equalTo(false)
659
        )->will(
660
            $this->returnValue('result')
661
        );
662
663
        $result = $contentServiceMock->loadContentByVersionInfo(
664
            new VersionInfo(
665
                array(
666
                    'contentInfo' => new ContentInfo(array('id' => 42)),
667
                    'versionNo' => 7,
668
                )
669
            ),
670
            array('cro-HR')
671
        );
672
673
        $this->assertEquals('result', $result);
674
    }
675
676
    /**
677
     * Test for the deleteContent() method.
678
     *
679
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteContent
680
     * @expectedException \eZ\Publish\Core\Base\Exceptions\UnauthorizedException
681
     */
682
    public function testDeleteContentThrowsUnauthorizedException()
683
    {
684
        $repository = $this->getRepositoryMock();
685
        $contentService = $this->getPartlyMockedContentService(array('internalLoadContentInfo'));
686
        $contentInfo = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
687
688
        $contentInfo->expects($this->any())
689
            ->method('__get')
690
            ->with('id')
691
            ->will($this->returnValue(42));
692
693
        $contentService->expects($this->once())
694
            ->method('internalLoadContentInfo')
695
            ->with(42)
696
            ->will($this->returnValue($contentInfo));
697
698
        $repository->expects($this->once())
699
            ->method('canUser')
700
            ->with('content', 'remove')
701
            ->will($this->returnValue(false));
702
703
        /* @var \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo */
704
        $contentService->deleteContent($contentInfo);
705
    }
706
707
    /**
708
     * Test for the deleteContent() method.
709
     *
710
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteContent
711
     */
712
    public function testDeleteContent()
713
    {
714
        $repository = $this->getRepositoryMock();
715
716
        $repository->expects($this->once())
717
            ->method('canUser')
718
            ->with('content', 'remove')
719
            ->will($this->returnValue(true));
720
721
        $contentService = $this->getPartlyMockedContentService(array('internalLoadContentInfo'));
722
        /** @var \PHPUnit_Framework_MockObject_MockObject $urlAliasHandler */
723
        $urlAliasHandler = $this->getPersistenceMock()->urlAliasHandler();
724
        /** @var \PHPUnit_Framework_MockObject_MockObject $locationHandler */
725
        $locationHandler = $this->getPersistenceMock()->locationHandler();
726
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
727
        $contentHandler = $this->getPersistenceMock()->contentHandler();
728
729
        $contentInfo = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
730
731
        $contentService->expects($this->once())
732
            ->method('internalLoadContentInfo')
733
            ->with(42)
734
            ->will($this->returnValue($contentInfo));
735
736
        $contentInfo->expects($this->any())
737
            ->method('__get')
738
            ->with('id')
739
            ->will($this->returnValue(42));
740
741
        $repository->expects($this->once())->method('beginTransaction');
742
743
        $spiLocations = array(
744
            new SPILocation(array('id' => 1)),
745
            new SPILocation(array('id' => 2)),
746
        );
747
        $locationHandler->expects($this->once())
748
            ->method('loadLocationsByContent')
749
            ->with(42)
750
            ->will($this->returnValue($spiLocations));
751
752
        $contentHandler->expects($this->once())
753
            ->method('deleteContent')
754
            ->with(42);
755
756
        foreach ($spiLocations as $index => $spiLocation) {
757
            $urlAliasHandler->expects($this->at($index))
758
                ->method('locationDeleted')
759
                ->with($spiLocation->id);
760
        }
761
762
        $repository->expects($this->once())->method('commit');
763
764
        /* @var \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo */
765
        $contentService->deleteContent($contentInfo);
766
    }
767
768
    /**
769
     * Test for the deleteContent() method.
770
     *
771
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteContent
772
     * @expectedException \Exception
773
     */
774
    public function testDeleteContentWithRollback()
775
    {
776
        $repository = $this->getRepositoryMock();
777
778
        $repository->expects($this->once())
779
            ->method('canUser')
780
            ->with('content', 'remove')
781
            ->will($this->returnValue(true));
782
783
        $contentService = $this->getPartlyMockedContentService(array('internalLoadContentInfo'));
784
        /** @var \PHPUnit_Framework_MockObject_MockObject $locationHandler */
785
        $locationHandler = $this->getPersistenceMock()->locationHandler();
786
787
        $contentInfo = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
788
789
        $contentService->expects($this->once())
790
            ->method('internalLoadContentInfo')
791
            ->with(42)
792
            ->will($this->returnValue($contentInfo));
793
794
        $contentInfo->expects($this->any())
795
            ->method('__get')
796
            ->with('id')
797
            ->will($this->returnValue(42));
798
799
        $repository->expects($this->once())->method('beginTransaction');
800
801
        $locationHandler->expects($this->once())
802
            ->method('loadLocationsByContent')
803
            ->with(42)
804
            ->will($this->throwException(new \Exception()));
805
806
        $repository->expects($this->once())->method('rollback');
807
808
        /* @var \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo */
809
        $contentService->deleteContent($contentInfo);
810
    }
811
812
    /**
813
     * Test for the deleteVersion() method.
814
     *
815
     * @covers \eZ\Publish\Core\Repository\ContentService::deleteVersion
816
     * @expectedException \eZ\Publish\API\Repository\Exceptions\BadStateException
817
     */
818
    public function testDeleteVersionThrowsBadStateExceptionLastVersion()
819
    {
820
        $repository = $this->getRepositoryMock();
821
        $repository
822
            ->expects($this->once())
823
            ->method('canUser')
824
            ->with('content', 'versionremove')
825
            ->will($this->returnValue(true));
826
        $repository
827
            ->expects($this->never())
828
            ->method('beginTransaction');
829
830
        $contentService = $this->getPartlyMockedContentService();
831
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandler */
832
        $contentHandler = $this->getPersistenceMock()->contentHandler();
833
        $contentInfo = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
834
        $versionInfo = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\VersionInfo');
835
836
        $contentInfo
837
            ->expects($this->any())
838
            ->method('__get')
839
            ->with('id')
840
            ->will($this->returnValue(42));
841
842
        $versionInfo
843
            ->expects($this->any())
844
            ->method('__get')
845
            ->will(
846
                $this->returnValueMap(
847
                    array(
848
                        array('versionNo', 123),
849
                        array('status', VersionInfo::STATUS_DRAFT),
850
                        array('contentInfo', $contentInfo),
851
                    )
852
                )
853
            );
854
855
        $contentHandler
856
            ->expects($this->once())
857
            ->method('listVersions')
858
            ->with(42)
859
            ->will($this->returnValue(array('version')));
860
861
        /* @var \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo */
862
        $contentService->deleteVersion($versionInfo);
863
    }
864
865
    /**
866
     * Test for the createContent() method.
867
     *
868
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
869
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
870
     * @expectedExceptionMessage Argument '$contentCreateStruct' is invalid: 'mainLanguageCode' property must be set
871
     */
872
    public function testCreateContentThrowsInvalidArgumentExceptionMainLanguageCodeNotSet()
873
    {
874
        $mockedService = $this->getPartlyMockedContentService();
875
        $mockedService->createContent(new ContentCreateStruct(), array());
876
    }
877
878
    /**
879
     * Test for the createContent() method.
880
     *
881
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
882
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
883
     * @expectedExceptionMessage Argument '$contentCreateStruct' is invalid: 'contentType' property must be set
884
     */
885
    public function testCreateContentThrowsInvalidArgumentExceptionContentTypeNotSet()
886
    {
887
        $mockedService = $this->getPartlyMockedContentService();
888
        $mockedService->createContent(
889
            new ContentCreateStruct(array('mainLanguageCode' => 'eng-US')),
890
            array()
891
        );
892
    }
893
894
    /**
895
     * Test for the createContent() method.
896
     *
897
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
898
     * @expectedException \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
899
     */
900
    public function testCreateContentThrowsUnauthorizedException()
901
    {
902
        $repositoryMock = $this->getRepositoryMock();
903
        $mockedService = $this->getPartlyMockedContentService();
904
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
905
        $contentType = new ContentType(
906
            array(
907
                'id' => 123,
908
                'fieldDefinitions' => array(),
909
            )
910
        );
911
        $contentCreateStruct = new ContentCreateStruct(
912
            array(
913
                'ownerId' => 169,
914
                'alwaysAvailable' => false,
915
                'mainLanguageCode' => 'eng-US',
916
                'contentType' => $contentType,
917
            )
918
        );
919
920
        $repositoryMock->expects($this->once())
921
            ->method('getCurrentUserReference')
922
            ->will($this->returnValue(new UserReference(169)));
923
924
        $contentTypeServiceMock->expects($this->once())
925
            ->method('loadContentType')
926
            ->with($this->equalTo(123))
927
            ->will($this->returnValue($contentType));
928
929
        $repositoryMock->expects($this->once())
930
            ->method('getContentTypeService')
931
            ->will($this->returnValue($contentTypeServiceMock));
932
933
        $repositoryMock->expects($this->once())
934
            ->method('canUser')
935
            ->with(
936
                $this->equalTo('content'),
937
                $this->equalTo('create'),
938
                $this->isInstanceOf($contentCreateStruct),
0 ignored issues
show
Documentation introduced by
$contentCreateStruct is of type object<eZ\Publish\Core\R...nt\ContentCreateStruct>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
939
                $this->equalTo(array())
940
            )->will($this->returnValue(false));
941
942
        $mockedService->createContent(
943
            new ContentCreateStruct(
944
                array(
945
                    'mainLanguageCode' => 'eng-US',
946
                    'contentType' => $contentType,
947
                )
948
            ),
949
            array()
950
        );
951
    }
952
953
    /**
954
     * Test for the createContent() method.
955
     *
956
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
957
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
958
     * @exceptionMessage Argument '$contentCreateStruct' is invalid: Another content with remoteId 'faraday' exists
959
     */
960
    public function testCreateContentThrowsInvalidArgumentExceptionDuplicateRemoteId()
961
    {
962
        $repositoryMock = $this->getRepositoryMock();
963
        $mockedService = $this->getPartlyMockedContentService(array('loadContentByRemoteId'));
964
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
965
        $contentType = new ContentType(
966
            array(
967
                'id' => 123,
968
                'fieldDefinitions' => array(),
969
            )
970
        );
971
        $contentCreateStruct = new ContentCreateStruct(
972
            array(
973
                'ownerId' => 169,
974
                'alwaysAvailable' => false,
975
                'remoteId' => 'faraday',
976
                'mainLanguageCode' => 'eng-US',
977
                'contentType' => $contentType,
978
            )
979
        );
980
981
        $repositoryMock->expects($this->once())
982
            ->method('getCurrentUserReference')
983
            ->will($this->returnValue(new UserReference(169)));
984
985
        $contentTypeServiceMock->expects($this->once())
986
            ->method('loadContentType')
987
            ->with($this->equalTo(123))
988
            ->will($this->returnValue($contentType));
989
990
        $repositoryMock->expects($this->once())
991
            ->method('getContentTypeService')
992
            ->will($this->returnValue($contentTypeServiceMock));
993
994
        $repositoryMock->expects($this->once())
995
            ->method('canUser')
996
            ->with(
997
                $this->equalTo('content'),
998
                $this->equalTo('create'),
999
                $this->isInstanceOf($contentCreateStruct),
0 ignored issues
show
Documentation introduced by
$contentCreateStruct is of type object<eZ\Publish\Core\R...nt\ContentCreateStruct>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1000
                $this->equalTo(array())
1001
            )->will($this->returnValue(true));
1002
1003
        $mockedService->expects($this->once())
1004
            ->method('loadContentByRemoteId')
1005
            ->with($contentCreateStruct->remoteId)
1006
            ->will($this->returnValue('Hello...'));
1007
1008
        $mockedService->createContent(
1009
            new ContentCreateStruct(
1010
                array(
1011
                    'remoteId' => 'faraday',
1012
                    'mainLanguageCode' => 'eng-US',
1013
                    'contentType' => $contentType,
1014
                )
1015
            ),
1016
            array()
1017
        );
1018
    }
1019
1020
    /**
1021
     * @param string $mainLanguageCode
1022
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
1023
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
1024
     *
1025
     * @return array
1026
     */
1027
    protected function mapStructFieldsForCreate($mainLanguageCode, $structFields, $fieldDefinitions)
1028
    {
1029
        $mappedFieldDefinitions = array();
1030
        foreach ($fieldDefinitions as $fieldDefinition) {
1031
            $mappedFieldDefinitions[$fieldDefinition->identifier] = $fieldDefinition;
1032
        }
1033
1034
        $mappedStructFields = array();
1035
        foreach ($structFields as $structField) {
1036
            if ($structField->languageCode === null) {
1037
                $languageCode = $mainLanguageCode;
1038
            } else {
1039
                $languageCode = $structField->languageCode;
1040
            }
1041
1042
            $mappedStructFields[$structField->fieldDefIdentifier][$languageCode] = (string)$structField->value;
0 ignored issues
show
Documentation introduced by
The property $value is declared protected in eZ\Publish\API\Repository\Values\Content\Field. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1043
        }
1044
1045
        return $mappedStructFields;
1046
    }
1047
1048
    /**
1049
     * Returns full, possibly redundant array of field values, indexed by field definition
1050
     * identifier and language code.
1051
     *
1052
     * @throws \RuntimeException Method is intended to be used only with consistent fixtures
1053
     *
1054
     * @param string $mainLanguageCode
1055
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
1056
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
1057
     * @param array $languageCodes
1058
     *
1059
     * @return array
1060
     */
1061
    protected function determineValuesForCreate(
1062
        $mainLanguageCode,
1063
        array $structFields,
1064
        array $fieldDefinitions,
1065
        array $languageCodes
1066
    ) {
1067
        $mappedStructFields = $this->mapStructFieldsForCreate(
1068
            $mainLanguageCode,
1069
            $structFields,
1070
            $fieldDefinitions
1071
        );
1072
1073
        $values = array();
1074
1075
        foreach ($fieldDefinitions as $fieldDefinition) {
1076
            $identifier = $fieldDefinition->identifier;
1077
            foreach ($languageCodes as $languageCode) {
1078 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...
1079
                    if (isset($mappedStructFields[$identifier][$mainLanguageCode])) {
1080
                        $values[$identifier][$languageCode] = $mappedStructFields[$identifier][$mainLanguageCode];
1081
                    } else {
1082
                        $values[$identifier][$languageCode] = (string)$fieldDefinition->defaultValue;
0 ignored issues
show
Documentation introduced by
The property $defaultValue is declared protected in eZ\Publish\API\Repositor...entType\FieldDefinition. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1083
                    }
1084
                    continue;
1085
                }
1086
1087 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...
1088
                    $values[$identifier][$languageCode] = $mappedStructFields[$identifier][$languageCode];
1089
                    continue;
1090
                }
1091
1092
                $values[$identifier][$languageCode] = (string)$fieldDefinition->defaultValue;
0 ignored issues
show
Documentation introduced by
The property $defaultValue is declared protected in eZ\Publish\API\Repositor...entType\FieldDefinition. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1093
            }
1094
        }
1095
1096
        return $this->stubValues($values);
1097
    }
1098
1099
    /**
1100
     * @param string $mainLanguageCode
1101
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
1102
     *
1103
     * @return string[]
1104
     */
1105
    protected function determineLanguageCodesForCreate($mainLanguageCode, array $structFields)
1106
    {
1107
        $languageCodes = array();
1108
1109 View Code Duplication
        foreach ($structFields as $field) {
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...
1110
            if ($field->languageCode === null || isset($languageCodes[$field->languageCode])) {
1111
                continue;
1112
            }
1113
1114
            $languageCodes[$field->languageCode] = true;
1115
        }
1116
1117
        $languageCodes[$mainLanguageCode] = true;
1118
1119
        return array_keys($languageCodes);
1120
    }
1121
1122
    /**
1123
     * Asserts that calling createContent() with given API field set causes calling
1124
     * Handler::createContent() with given SPI field set.
1125
     *
1126
     * @param string $mainLanguageCode
1127
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
1128
     * @param \eZ\Publish\SPI\Persistence\Content\Field[] $spiFields
1129
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
1130
     * @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct[] $locationCreateStructs
1131
     * @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...
1132
     * @param bool $execute
1133
     *
1134
     * @return mixed
1135
     */
1136
    protected function assertForTestCreateContentNonRedundantFieldSet(
1137
        $mainLanguageCode,
1138
        array $structFields,
1139
        array $spiFields,
1140
        array $fieldDefinitions,
1141
        array $locationCreateStructs = array(),
1142
        $withObjectStates = false,
1143
        $execute = true
1144
    ) {
1145
        $repositoryMock = $this->getRepositoryMock();
1146
        $mockedService = $this->getPartlyMockedContentService();
1147
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
1148
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
1149
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
1150
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
1151
        /** @var \PHPUnit_Framework_MockObject_MockObject $objectStateHandlerMock */
1152
        $objectStateHandlerMock = $this->getPersistenceMock()->objectStateHandler();
1153
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
1154
        $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...
1155
        $domainMapperMock = $this->getDomainMapperMock();
1156
        $relationProcessorMock = $this->getRelationProcessorMock();
1157
        $nameSchemaServiceMock = $this->getNameSchemaServiceMock();
1158
        $fieldTypeMock = $this->getMock('eZ\\Publish\\SPI\\FieldType\\FieldType');
1159
        $languageCodes = $this->determineLanguageCodesForCreate($mainLanguageCode, $structFields);
1160
        $contentType = new ContentType(
1161
            array(
1162
                'id' => 123,
1163
                'fieldDefinitions' => $fieldDefinitions,
1164
                'nameSchema' => '<nameSchema>',
1165
            )
1166
        );
1167
        $contentCreateStruct = new ContentCreateStruct(
1168
            array(
1169
                'fields' => $structFields,
1170
                'mainLanguageCode' => $mainLanguageCode,
1171
                'contentType' => $contentType,
1172
                'alwaysAvailable' => false,
1173
                'ownerId' => 169,
1174
                'sectionId' => 1,
1175
            )
1176
        );
1177
1178
        $languageHandlerMock->expects($this->any())
1179
            ->method('loadByLanguageCode')
1180
            ->with($this->isType('string'))
1181
            ->will(
1182
                $this->returnCallback(
1183
                    function () {
1184
                        return new Language(array('id' => 4242));
1185
                    }
1186
                )
1187
            );
1188
1189
        $repositoryMock->expects($this->once())->method('beginTransaction');
1190
1191
        $contentTypeServiceMock->expects($this->once())
1192
            ->method('loadContentType')
1193
            ->with($this->equalTo($contentType->id))
1194
            ->will($this->returnValue($contentType));
1195
1196
        $repositoryMock->expects($this->once())
1197
            ->method('getContentTypeService')
1198
            ->will($this->returnValue($contentTypeServiceMock));
1199
1200
        $that = $this;
1201
        $repositoryMock->expects($this->once())
1202
            ->method('canUser')
1203
            ->with(
1204
                $this->equalTo('content'),
1205
                $this->equalTo('create'),
1206
                $this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'),
1207
                $this->equalTo($locationCreateStructs)
1208
            )->will(
1209
                $this->returnCallback(
1210
                    function () use ($that, $contentCreateStruct) {
1211
                        $that->assertEquals($contentCreateStruct, func_get_arg(2));
1212
1213
                        return true;
1214
                    }
1215
                )
1216
            );
1217
1218
        $domainMapperMock->expects($this->once())
1219
            ->method('getUniqueHash')
1220
            ->with($this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'))
1221
            ->will(
1222
                $this->returnCallback(
1223
                    function ($object) use ($that, $contentCreateStruct) {
1224
                        $that->assertEquals($contentCreateStruct, $object);
1225
1226
                        return 'hash';
1227
                    }
1228
                )
1229
            );
1230
1231
        $fieldTypeMock->expects($this->any())
1232
            ->method('acceptValue')
1233
            ->will(
1234
                $this->returnCallback(
1235
                    function ($valueString) {
1236
                        return new ValueStub($valueString);
1237
                    }
1238
                )
1239
            );
1240
1241
        $fieldTypeMock->expects($this->any())
1242
            ->method('toPersistenceValue')
1243
            ->will(
1244
                $this->returnCallback(
1245
                    function (ValueStub $value) {
1246
                        return (string)$value;
1247
                    }
1248
                )
1249
            );
1250
1251
        $emptyValue = self::EMPTY_FIELD_VALUE;
1252
        $fieldTypeMock->expects($this->any())
1253
            ->method('isEmptyValue')
1254
            ->will(
1255
                $this->returnCallback(
1256
                    function (ValueStub $value) use ($emptyValue) {
1257
                        return $emptyValue === (string)$value;
1258
                    }
1259
                )
1260
            );
1261
1262
        $fieldTypeMock->expects($this->any())
1263
            ->method('validate')
1264
            ->will($this->returnValue(array()));
1265
1266
        $this->getFieldTypeRegistryMock()->expects($this->any())
1267
            ->method('getFieldType')
1268
            ->will($this->returnValue($fieldTypeMock));
1269
1270
        $relationProcessorMock
1271
            ->expects($this->exactly(count($fieldDefinitions) * count($languageCodes)))
1272
            ->method('appendFieldRelations')
1273
            ->with(
1274
                $this->isType('array'),
1275
                $this->isType('array'),
1276
                $this->isInstanceOf('eZ\\Publish\\SPI\\FieldType\\FieldType'),
1277
                $this->isInstanceOf('eZ\\Publish\\Core\\FieldType\\Value'),
1278
                $this->anything()
1279
            );
1280
1281
        $values = $this->determineValuesForCreate(
1282
            $mainLanguageCode,
1283
            $structFields,
1284
            $fieldDefinitions,
1285
            $languageCodes
1286
        );
1287
        $nameSchemaServiceMock->expects($this->once())
1288
            ->method('resolve')
1289
            ->with(
1290
                $this->equalTo($contentType->nameSchema),
1291
                $this->equalTo($contentType),
1292
                $this->equalTo($values),
1293
                $this->equalTo($languageCodes)
1294
            )->will($this->returnValue(array()));
1295
1296
        $relationProcessorMock->expects($this->any())
1297
            ->method('processFieldRelations')
1298
            ->with(
1299
                $this->isType('array'),
1300
                $this->equalTo(42),
1301
                $this->isType('int'),
1302
                $this->equalTo($contentType),
1303
                $this->equalTo(array())
1304
            );
1305
1306
        if (!$withObjectStates) {
1307
            $objectStateHandlerMock->expects($this->once())
1308
                ->method('loadAllGroups')
1309
                ->will($this->returnValue(array()));
1310
        }
1311
1312
        if ($execute) {
1313
            $spiContentCreateStruct = new SPIContentCreateStruct(
1314
                array(
1315
                    'name' => array(),
1316
                    'typeId' => 123,
1317
                    'sectionId' => 1,
1318
                    'ownerId' => 169,
1319
                    'remoteId' => 'hash',
1320
                    'fields' => $spiFields,
1321
                    'modified' => time(),
1322
                    'initialLanguageId' => 4242,
1323
                )
1324
            );
1325
            $spiContentCreateStruct2 = clone $spiContentCreateStruct;
1326
            ++$spiContentCreateStruct2->modified;
1327
1328
            $spiContent = new SPIContent(
1329
                array(
1330
                    'versionInfo' => new SPIContent\VersionInfo(
1331
                        array(
1332
                            'contentInfo' => new SPIContent\ContentInfo(array('id' => 42)),
1333
                            'versionNo' => 7,
1334
                        )
1335
                    ),
1336
                )
1337
            );
1338
1339
            $contentHandlerMock->expects($this->once())
1340
                ->method('create')
1341
                ->with($this->logicalOr($spiContentCreateStruct, $spiContentCreateStruct2))
1342
                ->will($this->returnValue($spiContent));
1343
1344
            $repositoryMock->expects($this->once())->method('commit');
1345
            $domainMapperMock->expects($this->once())
1346
                ->method('buildContentDomainObject')
1347
                ->with(
1348
                    $this->isInstanceOf('eZ\\Publish\\SPI\\Persistence\\Content'),
1349
                    $this->equalTo(null)
1350
                );
1351
1352
            $mockedService->createContent($contentCreateStruct, array());
1353
        }
1354
1355
        return $contentCreateStruct;
1356
    }
1357
1358
    public function providerForTestCreateContentNonRedundantFieldSet1()
1359
    {
1360
        $spiFields = array(
1361
            new SPIField(
1362
                array(
1363
                    'fieldDefinitionId' => 'fieldDefinitionId',
1364
                    'type' => 'fieldTypeIdentifier',
1365
                    'value' => 'newValue',
1366
                    'languageCode' => 'eng-US',
1367
                )
1368
            ),
1369
        );
1370
1371
        return array(
1372
            // 0. Without language set
1373
            array(
1374
                'eng-US',
1375
                array(
1376
                    new Field(
1377
                        array(
1378
                            'fieldDefIdentifier' => 'identifier',
1379
                            'value' => 'newValue',
1380
                            'languageCode' => 'eng-US',
1381
                        )
1382
                    ),
1383
                ),
1384
                $spiFields,
1385
            ),
1386
            // 1. Without language set
1387
            array(
1388
                'eng-US',
1389
                array(
1390
                    new Field(
1391
                        array(
1392
                            'fieldDefIdentifier' => 'identifier',
1393
                            'value' => 'newValue',
1394
                            'languageCode' => null,
1395
                        )
1396
                    ),
1397
                ),
1398
                $spiFields,
1399
            ),
1400
        );
1401
    }
1402
1403
    /**
1404
     * Test for the createContent() method.
1405
     *
1406
     * Testing the simplest use case.
1407
     *
1408
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
1409
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
1410
     * @covers \eZ\Publish\Core\Repository\ContentService::cloneField
1411
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
1412
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
1413
     * @dataProvider providerForTestCreateContentNonRedundantFieldSet1
1414
     */
1415 View Code Duplication
    public function testCreateContentNonRedundantFieldSet1($mainLanguageCode, $structFields, $spiFields)
1416
    {
1417
        $fieldDefinitions = array(
1418
            new FieldDefinition(
1419
                array(
1420
                    'id' => 'fieldDefinitionId',
1421
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1422
                    'isTranslatable' => false,
1423
                    'identifier' => 'identifier',
1424
                    'isRequired' => false,
1425
                    'defaultValue' => 'defaultValue',
1426
                )
1427
            ),
1428
        );
1429
1430
        $this->assertForTestCreateContentNonRedundantFieldSet(
1431
            $mainLanguageCode,
1432
            $structFields,
1433
            $spiFields,
1434
            $fieldDefinitions
1435
        );
1436
    }
1437
1438
    public function providerForTestCreateContentNonRedundantFieldSet2()
1439
    {
1440
        $spiFields = array(
1441
            new SPIField(
1442
                array(
1443
                    'fieldDefinitionId' => 'fieldDefinitionId1',
1444
                    'type' => 'fieldTypeIdentifier',
1445
                    'value' => 'newValue1',
1446
                    'languageCode' => 'eng-US',
1447
                )
1448
            ),
1449
            new SPIField(
1450
                array(
1451
                    'fieldDefinitionId' => 'fieldDefinitionId2',
1452
                    'type' => 'fieldTypeIdentifier',
1453
                    'value' => 'newValue2',
1454
                    'languageCode' => 'ger-DE',
1455
                )
1456
            ),
1457
        );
1458
1459
        return array(
1460
            // 0. With language set
1461
            array(
1462
                'eng-US',
1463
                array(
1464
                    new Field(
1465
                        array(
1466
                            'fieldDefIdentifier' => 'identifier1',
1467
                            'value' => 'newValue1',
1468
                            'languageCode' => 'eng-US',
1469
                        )
1470
                    ),
1471
                    new Field(
1472
                        array(
1473
                            'fieldDefIdentifier' => 'identifier2',
1474
                            'value' => 'newValue2',
1475
                            'languageCode' => 'ger-DE',
1476
                        )
1477
                    ),
1478
                ),
1479
                $spiFields,
1480
            ),
1481
            // 1. Without language set
1482
            array(
1483
                'eng-US',
1484
                array(
1485
                    new Field(
1486
                        array(
1487
                            'fieldDefIdentifier' => 'identifier1',
1488
                            'value' => 'newValue1',
1489
                            'languageCode' => null,
1490
                        )
1491
                    ),
1492
                    new Field(
1493
                        array(
1494
                            'fieldDefIdentifier' => 'identifier2',
1495
                            'value' => 'newValue2',
1496
                            'languageCode' => 'ger-DE',
1497
                        )
1498
                    ),
1499
                ),
1500
                $spiFields,
1501
            ),
1502
        );
1503
    }
1504
1505
    /**
1506
     * Test for the createContent() method.
1507
     *
1508
     * Testing multiple languages with multiple translatable fields with empty default value.
1509
     *
1510
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
1511
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
1512
     * @covers \eZ\Publish\Core\Repository\ContentService::cloneField
1513
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
1514
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
1515
     * @dataProvider providerForTestCreateContentNonRedundantFieldSet2
1516
     */
1517
    public function testCreateContentNonRedundantFieldSet2($mainLanguageCode, $structFields, $spiFields)
1518
    {
1519
        $fieldDefinitions = array(
1520
            new FieldDefinition(
1521
                array(
1522
                    'id' => 'fieldDefinitionId1',
1523
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1524
                    'isTranslatable' => true,
1525
                    'identifier' => 'identifier1',
1526
                    'isRequired' => false,
1527
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
1528
                )
1529
            ),
1530
            new FieldDefinition(
1531
                array(
1532
                    'id' => 'fieldDefinitionId2',
1533
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1534
                    'isTranslatable' => true,
1535
                    'identifier' => 'identifier2',
1536
                    'isRequired' => false,
1537
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
1538
                )
1539
            ),
1540
        );
1541
1542
        $this->assertForTestCreateContentNonRedundantFieldSet(
1543
            $mainLanguageCode,
1544
            $structFields,
1545
            $spiFields,
1546
            $fieldDefinitions
1547
        );
1548
    }
1549
1550
    public function providerForTestCreateContentNonRedundantFieldSetComplex()
1551
    {
1552
        $spiFields0 = array(
1553
            new SPIField(
1554
                array(
1555
                    'fieldDefinitionId' => 'fieldDefinitionId2',
1556
                    'type' => 'fieldTypeIdentifier',
1557
                    'value' => 'defaultValue2',
1558
                    'languageCode' => 'eng-US',
1559
                )
1560
            ),
1561
            new SPIField(
1562
                array(
1563
                    'fieldDefinitionId' => 'fieldDefinitionId4',
1564
                    'type' => 'fieldTypeIdentifier',
1565
                    'value' => 'defaultValue4',
1566
                    'languageCode' => 'eng-US',
1567
                )
1568
            ),
1569
        );
1570
        $spiFields1 = array(
1571
            new SPIField(
1572
                array(
1573
                    'fieldDefinitionId' => 'fieldDefinitionId1',
1574
                    'type' => 'fieldTypeIdentifier',
1575
                    'value' => 'newValue1',
1576
                    'languageCode' => 'ger-DE',
1577
                )
1578
            ),
1579
            new SPIField(
1580
                array(
1581
                    'fieldDefinitionId' => 'fieldDefinitionId2',
1582
                    'type' => 'fieldTypeIdentifier',
1583
                    'value' => 'defaultValue2',
1584
                    'languageCode' => 'ger-DE',
1585
                )
1586
            ),
1587
            new SPIField(
1588
                array(
1589
                    'fieldDefinitionId' => 'fieldDefinitionId2',
1590
                    'type' => 'fieldTypeIdentifier',
1591
                    'value' => 'newValue2',
1592
                    'languageCode' => 'eng-US',
1593
                )
1594
            ),
1595
            new SPIField(
1596
                array(
1597
                    'fieldDefinitionId' => 'fieldDefinitionId4',
1598
                    'type' => 'fieldTypeIdentifier',
1599
                    'value' => 'newValue4',
1600
                    'languageCode' => 'eng-US',
1601
                )
1602
            ),
1603
        );
1604
1605
        return array(
1606
            // 0. Creating by default values only
1607
            array(
1608
                'eng-US',
1609
                array(),
1610
                $spiFields0,
1611
            ),
1612
            // 1. Multiple languages with language set
1613
            array(
1614
                'eng-US',
1615
                array(
1616
                    new Field(
1617
                        array(
1618
                            'fieldDefIdentifier' => 'identifier1',
1619
                            'value' => 'newValue1',
1620
                            'languageCode' => 'ger-DE',
1621
                        )
1622
                    ),
1623
                    new Field(
1624
                        array(
1625
                            'fieldDefIdentifier' => 'identifier2',
1626
                            'value' => 'newValue2',
1627
                            'languageCode' => 'eng-US',
1628
                        )
1629
                    ),
1630
                    new Field(
1631
                        array(
1632
                            'fieldDefIdentifier' => 'identifier4',
1633
                            'value' => 'newValue4',
1634
                            'languageCode' => 'eng-US',
1635
                        )
1636
                    ),
1637
                ),
1638
                $spiFields1,
1639
            ),
1640
            // 2. Multiple languages without language set
1641
            array(
1642
                'eng-US',
1643
                array(
1644
                    new Field(
1645
                        array(
1646
                            'fieldDefIdentifier' => 'identifier1',
1647
                            'value' => 'newValue1',
1648
                            'languageCode' => 'ger-DE',
1649
                        )
1650
                    ),
1651
                    new Field(
1652
                        array(
1653
                            'fieldDefIdentifier' => 'identifier2',
1654
                            'value' => 'newValue2',
1655
                            'languageCode' => null,
1656
                        )
1657
                    ),
1658
                    new Field(
1659
                        array(
1660
                            'fieldDefIdentifier' => 'identifier4',
1661
                            'value' => 'newValue4',
1662
                            'languageCode' => null,
1663
                        )
1664
                    ),
1665
                ),
1666
                $spiFields1,
1667
            ),
1668
        );
1669
    }
1670
1671
    protected function fixturesForTestCreateContentNonRedundantFieldSetComplex()
1672
    {
1673
        return array(
1674
            new FieldDefinition(
1675
                array(
1676
                    'id' => 'fieldDefinitionId1',
1677
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1678
                    'isTranslatable' => true,
1679
                    'identifier' => 'identifier1',
1680
                    'isRequired' => false,
1681
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
1682
                )
1683
            ),
1684
            new FieldDefinition(
1685
                array(
1686
                    'id' => 'fieldDefinitionId2',
1687
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1688
                    'isTranslatable' => true,
1689
                    'identifier' => 'identifier2',
1690
                    'isRequired' => false,
1691
                    'defaultValue' => 'defaultValue2',
1692
                )
1693
            ),
1694
            new FieldDefinition(
1695
                array(
1696
                    'id' => 'fieldDefinitionId3',
1697
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1698
                    'isTranslatable' => false,
1699
                    'identifier' => 'identifier3',
1700
                    'isRequired' => false,
1701
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
1702
                )
1703
            ),
1704
            new FieldDefinition(
1705
                array(
1706
                    'id' => 'fieldDefinitionId4',
1707
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1708
                    'isTranslatable' => false,
1709
                    'identifier' => 'identifier4',
1710
                    'isRequired' => false,
1711
                    'defaultValue' => 'defaultValue4',
1712
                )
1713
            ),
1714
        );
1715
    }
1716
1717
    /**
1718
     * Test for the createContent() method.
1719
     *
1720
     * Testing multiple languages with multiple translatable fields with empty default value.
1721
     *
1722
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
1723
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
1724
     * @covers \eZ\Publish\Core\Repository\ContentService::cloneField
1725
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
1726
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
1727
     * @dataProvider providerForTestCreateContentNonRedundantFieldSetComplex
1728
     */
1729
    public function testCreateContentNonRedundantFieldSetComplex($mainLanguageCode, $structFields, $spiFields)
1730
    {
1731
        $fieldDefinitions = $this->fixturesForTestCreateContentNonRedundantFieldSetComplex();
1732
1733
        $this->assertForTestCreateContentNonRedundantFieldSet(
1734
            $mainLanguageCode,
1735
            $structFields,
1736
            $spiFields,
1737
            $fieldDefinitions
1738
        );
1739
    }
1740
1741 View Code Duplication
    public function providerForTestCreateContentWithInvalidLanguage()
1742
    {
1743
        return array(
1744
            array(
1745
                'eng-GB',
1746
                array(
1747
                    new Field(
1748
                        array(
1749
                            'fieldDefIdentifier' => 'identifier',
1750
                            'value' => 'newValue',
1751
                            'languageCode' => 'Klingon',
1752
                        )
1753
                    ),
1754
                ),
1755
            ),
1756
            array(
1757
                'Klingon',
1758
                array(
1759
                    new Field(
1760
                        array(
1761
                            'fieldDefIdentifier' => 'identifier',
1762
                            'value' => 'newValue',
1763
                            'languageCode' => 'eng-GB',
1764
                        )
1765
                    ),
1766
                ),
1767
            ),
1768
        );
1769
    }
1770
1771
    /**
1772
     * Test for the updateContent() method.
1773
     *
1774
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
1775
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
1776
     * @dataProvider providerForTestCreateContentWithInvalidLanguage
1777
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
1778
     * @expectedExceptionMessage Could not find 'Language' with identifier 'Klingon'
1779
     */
1780
    public function testCreateContentWithInvalidLanguage($mainLanguageCode, $structFields)
1781
    {
1782
        $repositoryMock = $this->getRepositoryMock();
1783
        $mockedService = $this->getPartlyMockedContentService();
1784
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
1785
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
1786
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
1787
        $domainMapperMock = $this->getDomainMapperMock();
1788
        $contentType = new ContentType(
1789
            array(
1790
                'id' => 123,
1791
                'fieldDefinitions' => array(),
1792
            )
1793
        );
1794
        $contentCreateStruct = new ContentCreateStruct(
1795
            array(
1796
                'fields' => $structFields,
1797
                'mainLanguageCode' => $mainLanguageCode,
1798
                'contentType' => $contentType,
1799
                'alwaysAvailable' => false,
1800
                'ownerId' => 169,
1801
                'sectionId' => 1,
1802
            )
1803
        );
1804
1805
        $languageHandlerMock->expects($this->any())
1806
            ->method('loadByLanguageCode')
1807
            ->with($this->isType('string'))
1808
            ->will(
1809
                $this->returnCallback(
1810 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...
1811
                        if ($languageCode === 'Klingon') {
1812
                            throw new NotFoundException('Language', 'Klingon');
1813
                        }
1814
1815
                        return new Language(array('id' => 4242));
1816
                    }
1817
                )
1818
            );
1819
1820
        $contentTypeServiceMock->expects($this->once())
1821
            ->method('loadContentType')
1822
            ->with($this->equalTo($contentType->id))
1823
            ->will($this->returnValue($contentType));
1824
1825
        $repositoryMock->expects($this->once())
1826
            ->method('getContentTypeService')
1827
            ->will($this->returnValue($contentTypeServiceMock));
1828
1829
        $that = $this;
1830
        $repositoryMock->expects($this->once())
1831
            ->method('canUser')
1832
            ->with(
1833
                $this->equalTo('content'),
1834
                $this->equalTo('create'),
1835
                $this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'),
1836
                $this->equalTo(array())
1837
            )->will(
1838
                $this->returnCallback(
1839
                    function () use ($that, $contentCreateStruct) {
1840
                        $that->assertEquals($contentCreateStruct, func_get_arg(2));
1841
1842
                        return true;
1843
                    }
1844
                )
1845
            );
1846
1847
        $domainMapperMock->expects($this->once())
1848
            ->method('getUniqueHash')
1849
            ->with($this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'))
1850
            ->will(
1851
                $this->returnCallback(
1852
                    function ($object) use ($that, $contentCreateStruct) {
1853
                        $that->assertEquals($contentCreateStruct, $object);
1854
1855
                        return 'hash';
1856
                    }
1857
                )
1858
            );
1859
1860
        $mockedService->createContent($contentCreateStruct, array());
1861
    }
1862
1863
    protected function assertForCreateContentContentValidationException(
1864
        $mainLanguageCode,
1865
        $structFields,
1866
        $fieldDefinitions = array()
1867
    ) {
1868
        $repositoryMock = $this->getRepositoryMock();
1869
        $mockedService = $this->getPartlyMockedContentService(array('loadContentByRemoteId'));
1870
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
1871
        $contentType = new ContentType(
1872
            array(
1873
                'id' => 123,
1874
                'fieldDefinitions' => $fieldDefinitions,
1875
            )
1876
        );
1877
        $contentCreateStruct = new ContentCreateStruct(
1878
            array(
1879
                'ownerId' => 169,
1880
                'alwaysAvailable' => false,
1881
                'remoteId' => 'faraday',
1882
                'mainLanguageCode' => $mainLanguageCode,
1883
                'fields' => $structFields,
1884
                'contentType' => $contentType,
1885
            )
1886
        );
1887
1888
        $contentTypeServiceMock->expects($this->once())
1889
            ->method('loadContentType')
1890
            ->with($this->equalTo(123))
1891
            ->will($this->returnValue($contentType));
1892
1893
        $repositoryMock->expects($this->once())
1894
            ->method('getContentTypeService')
1895
            ->will($this->returnValue($contentTypeServiceMock));
1896
1897
        $repositoryMock->expects($this->once())
1898
            ->method('canUser')
1899
            ->with(
1900
                $this->equalTo('content'),
1901
                $this->equalTo('create'),
1902
                $this->isInstanceOf($contentCreateStruct),
0 ignored issues
show
Documentation introduced by
$contentCreateStruct is of type object<eZ\Publish\Core\R...nt\ContentCreateStruct>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1903
                $this->equalTo(array())
1904
            )->will($this->returnValue(true));
1905
1906
        $mockedService->expects($this->once())
1907
            ->method('loadContentByRemoteId')
1908
            ->with($contentCreateStruct->remoteId)
1909
            ->will(
1910
                $this->throwException(new NotFoundException('Content', 'faraday'))
1911
            );
1912
1913
        $mockedService->createContent($contentCreateStruct, array());
1914
    }
1915
1916 View Code Duplication
    public function providerForTestCreateContentThrowsContentValidationExceptionFieldDefinition()
1917
    {
1918
        return array(
1919
            array(
1920
                'eng-GB',
1921
                array(
1922
                    new Field(
1923
                        array(
1924
                            'fieldDefIdentifier' => 'identifier',
1925
                            'value' => 'newValue',
1926
                            'languageCode' => 'eng-GB',
1927
                        )
1928
                    ),
1929
                ),
1930
            ),
1931
        );
1932
    }
1933
1934
    /**
1935
     * Test for the createContent() method.
1936
     *
1937
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
1938
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
1939
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
1940
     * @dataProvider providerForTestCreateContentThrowsContentValidationExceptionFieldDefinition
1941
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentValidationException
1942
     * @expectedExceptionMessage Field definition 'identifier' does not exist in given ContentType
1943
     */
1944
    public function testCreateContentThrowsContentValidationExceptionFieldDefinition($mainLanguageCode, $structFields)
1945
    {
1946
        $this->assertForCreateContentContentValidationException(
1947
            $mainLanguageCode,
1948
            $structFields,
1949
            array()
1950
        );
1951
    }
1952
1953 View Code Duplication
    public function providerForTestCreateContentThrowsContentValidationExceptionTranslation()
1954
    {
1955
        return array(
1956
            array(
1957
                'eng-GB',
1958
                array(
1959
                    new Field(
1960
                        array(
1961
                            'fieldDefIdentifier' => 'identifier',
1962
                            'value' => 'newValue',
1963
                            'languageCode' => 'eng-US',
1964
                        )
1965
                    ),
1966
                ),
1967
            ),
1968
        );
1969
    }
1970
1971
    /**
1972
     * Test for the createContent() method.
1973
     *
1974
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
1975
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
1976
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
1977
     * @dataProvider providerForTestCreateContentThrowsContentValidationExceptionTranslation
1978
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentValidationException
1979
     * @expectedExceptionMessage A value is set for non translatable field definition 'identifier' with language 'eng-US'
1980
     */
1981 View Code Duplication
    public function testCreateContentThrowsContentValidationExceptionTranslation($mainLanguageCode, $structFields)
1982
    {
1983
        $fieldDefinitions = array(
1984
            new FieldDefinition(
1985
                array(
1986
                    'id' => 'fieldDefinitionId1',
1987
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
1988
                    'isTranslatable' => false,
1989
                    'identifier' => 'identifier',
1990
                    'isRequired' => false,
1991
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
1992
                )
1993
            ),
1994
        );
1995
1996
        $this->assertForCreateContentContentValidationException(
1997
            $mainLanguageCode,
1998
            $structFields,
1999
            $fieldDefinitions
2000
        );
2001
    }
2002
2003
    /**
2004
     * Asserts behaviour necessary for testing ContentValidationException because of required
2005
     * field being empty.
2006
     *
2007
     * @param string $mainLanguageCode
2008
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
2009
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
2010
     *
2011
     * @return mixed
2012
     */
2013
    protected function assertForTestCreateContentThrowsContentValidationExceptionRequiredField(
2014
        $mainLanguageCode,
2015
        array $structFields,
2016
        array $fieldDefinitions
2017
    ) {
2018
        $repositoryMock = $this->getRepositoryMock();
2019
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
2020
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
2021
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
2022
        $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...
2023
        $domainMapperMock = $this->getDomainMapperMock();
2024
        $fieldTypeMock = $this->getMock('eZ\\Publish\\SPI\\FieldType\\FieldType');
2025
        $contentType = new ContentType(
2026
            array(
2027
                'id' => 123,
2028
                'fieldDefinitions' => $fieldDefinitions,
2029
                'nameSchema' => '<nameSchema>',
2030
            )
2031
        );
2032
        $contentCreateStruct = new ContentCreateStruct(
2033
            array(
2034
                'fields' => $structFields,
2035
                'mainLanguageCode' => $mainLanguageCode,
2036
                'contentType' => $contentType,
2037
                'alwaysAvailable' => false,
2038
                'ownerId' => 169,
2039
                'sectionId' => 1,
2040
            )
2041
        );
2042
2043
        $languageHandlerMock->expects($this->any())
2044
            ->method('loadByLanguageCode')
2045
            ->with($this->isType('string'))
2046
            ->will(
2047
                $this->returnCallback(
2048
                    function () {
2049
                        return new Language(array('id' => 4242));
2050
                    }
2051
                )
2052
            );
2053
2054
        $contentTypeServiceMock->expects($this->once())
2055
            ->method('loadContentType')
2056
            ->with($this->equalTo($contentType->id))
2057
            ->will($this->returnValue($contentType));
2058
2059
        $repositoryMock->expects($this->once())
2060
            ->method('getContentTypeService')
2061
            ->will($this->returnValue($contentTypeServiceMock));
2062
2063
        $that = $this;
2064
        $repositoryMock->expects($this->once())
2065
            ->method('canUser')
2066
            ->with(
2067
                $this->equalTo('content'),
2068
                $this->equalTo('create'),
2069
                $this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'),
2070
                $this->equalTo(array())
2071
            )->will(
2072
                $this->returnCallback(
2073
                    function () use ($that, $contentCreateStruct) {
2074
                        $that->assertEquals($contentCreateStruct, func_get_arg(2));
2075
2076
                        return true;
2077
                    }
2078
                )
2079
            );
2080
2081
        $domainMapperMock->expects($this->once())
2082
            ->method('getUniqueHash')
2083
            ->with($this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'))
2084
            ->will(
2085
                $this->returnCallback(
2086
                    function ($object) use ($that, $contentCreateStruct) {
2087
                        $that->assertEquals($contentCreateStruct, $object);
2088
2089
                        return 'hash';
2090
                    }
2091
                )
2092
            );
2093
2094
        $fieldTypeMock->expects($this->any())
2095
            ->method('acceptValue')
2096
            ->will(
2097
                $this->returnCallback(
2098
                    function ($valueString) {
2099
                        return new ValueStub($valueString);
2100
                    }
2101
                )
2102
            );
2103
2104
        $emptyValue = self::EMPTY_FIELD_VALUE;
2105
        $fieldTypeMock->expects($this->any())
2106
            ->method('isEmptyValue')
2107
            ->will(
2108
                $this->returnCallback(
2109
                    function (ValueStub $value) use ($emptyValue) {
2110
                        return $emptyValue === (string)$value;
2111
                    }
2112
                )
2113
            );
2114
2115
        $fieldTypeMock->expects($this->any())
2116
            ->method('validate')
2117
            ->will($this->returnValue(array()));
2118
2119
        $this->getFieldTypeRegistryMock()->expects($this->any())
2120
            ->method('getFieldType')
2121
            ->will($this->returnValue($fieldTypeMock));
2122
2123
        return $contentCreateStruct;
2124
    }
2125
2126 View Code Duplication
    public function providerForTestCreateContentThrowsContentValidationExceptionRequiredField()
2127
    {
2128
        return array(
2129
            array(
2130
                'eng-US',
2131
                array(
2132
                    new Field(
2133
                        array(
2134
                            'fieldDefIdentifier' => 'identifier',
2135
                            'value' => self::EMPTY_FIELD_VALUE,
2136
                            'languageCode' => null,
2137
                        )
2138
                    ),
2139
                ),
2140
                'identifier',
2141
                'eng-US',
2142
            ),
2143
        );
2144
    }
2145
2146
    /**
2147
     * Test for the createContent() method.
2148
     *
2149
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
2150
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
2151
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
2152
     * @dataProvider providerForTestCreateContentThrowsContentValidationExceptionRequiredField
2153
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentValidationException
2154
     */
2155
    public function testCreateContentThrowsContentValidationExceptionRequiredField(
2156
        $mainLanguageCode,
2157
        $structFields,
2158
        $identifier,
2159
        $languageCode
2160
    ) {
2161
        $fieldDefinitions = array(
2162
            new FieldDefinition(
2163
                array(
2164
                    'id' => 'fieldDefinitionId',
2165
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
2166
                    'isTranslatable' => true,
2167
                    'identifier' => 'identifier',
2168
                    'isRequired' => true,
2169
                    'defaultValue' => 'defaultValue',
2170
                )
2171
            ),
2172
        );
2173
        $contentCreateStruct = $this->assertForTestCreateContentThrowsContentValidationExceptionRequiredField(
2174
            $mainLanguageCode,
2175
            $structFields,
2176
            $fieldDefinitions
2177
        );
2178
2179
        $mockedService = $this->getPartlyMockedContentService();
2180
2181
        try {
2182
            $mockedService->createContent($contentCreateStruct, array());
2183
        } catch (ContentValidationException $e) {
2184
            $this->assertEquals(
2185
                "Value for required field definition '{$identifier}' with language '{$languageCode}' is empty",
2186
                $e->getMessage()
2187
            );
2188
2189
            throw $e;
2190
        }
2191
    }
2192
2193
    /**
2194
     * Asserts behaviour necessary for testing ContentFieldValidationException because of
2195
     * field not being valid.
2196
     *
2197
     * @param string $mainLanguageCode
2198
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
2199
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
2200
     *
2201
     * @return mixed
2202
     */
2203
    protected function assertForTestCreateContentThrowsContentFieldValidationException(
2204
        $mainLanguageCode,
2205
        array $structFields,
2206
        array $fieldDefinitions
2207
    ) {
2208
        $repositoryMock = $this->getRepositoryMock();
2209
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
2210
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
2211
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
2212
        $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...
2213
        $domainMapperMock = $this->getDomainMapperMock();
2214
        $relationProcessorMock = $this->getRelationProcessorMock();
2215
        $fieldTypeMock = $this->getMock('eZ\\Publish\\SPI\\FieldType\\FieldType');
2216
        $languageCodes = $this->determineLanguageCodesForCreate($mainLanguageCode, $structFields);
2217
        $contentType = new ContentType(
2218
            array(
2219
                'id' => 123,
2220
                'fieldDefinitions' => $fieldDefinitions,
2221
                'nameSchema' => '<nameSchema>',
2222
            )
2223
        );
2224
        $contentCreateStruct = new ContentCreateStruct(
2225
            array(
2226
                'fields' => $structFields,
2227
                'mainLanguageCode' => $mainLanguageCode,
2228
                'contentType' => $contentType,
2229
                'alwaysAvailable' => false,
2230
                'ownerId' => 169,
2231
                'sectionId' => 1,
2232
            )
2233
        );
2234
2235
        $languageHandlerMock->expects($this->any())
2236
            ->method('loadByLanguageCode')
2237
            ->with($this->isType('string'))
2238
            ->will(
2239
                $this->returnCallback(
2240
                    function () {
2241
                        return new Language(array('id' => 4242));
2242
                    }
2243
                )
2244
            );
2245
2246
        $contentTypeServiceMock->expects($this->once())
2247
            ->method('loadContentType')
2248
            ->with($this->equalTo($contentType->id))
2249
            ->will($this->returnValue($contentType));
2250
2251
        $repositoryMock->expects($this->once())
2252
            ->method('getContentTypeService')
2253
            ->will($this->returnValue($contentTypeServiceMock));
2254
2255
        $that = $this;
2256
        $repositoryMock->expects($this->once())
2257
            ->method('canUser')
2258
            ->with(
2259
                $this->equalTo('content'),
2260
                $this->equalTo('create'),
2261
                $this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'),
2262
                $this->equalTo(array())
2263
            )->will(
2264
                $this->returnCallback(
2265
                    function () use ($that, $contentCreateStruct) {
2266
                        $that->assertEquals($contentCreateStruct, func_get_arg(2));
2267
2268
                        return true;
2269
                    }
2270
                )
2271
            );
2272
2273
        $domainMapperMock->expects($this->once())
2274
            ->method('getUniqueHash')
2275
            ->with($this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'))
2276
            ->will(
2277
                $this->returnCallback(
2278
                    function ($object) use ($that, $contentCreateStruct) {
2279
                        $that->assertEquals($contentCreateStruct, $object);
2280
2281
                        return 'hash';
2282
                    }
2283
                )
2284
            );
2285
2286
        $this->getFieldTypeRegistryMock()->expects($this->any())
2287
            ->method('getFieldType')
2288
            ->will($this->returnValue($fieldTypeMock));
2289
2290
        $relationProcessorMock
2291
            ->expects($this->any())
2292
            ->method('appendFieldRelations')
2293
            ->with(
2294
                $this->isType('array'),
2295
                $this->isType('array'),
2296
                $this->isInstanceOf('eZ\\Publish\\SPI\\FieldType\\FieldType'),
2297
                $this->isInstanceOf('eZ\\Publish\\Core\\FieldType\\Value'),
2298
                $this->anything()
2299
            );
2300
2301
        $fieldValues = $this->determineValuesForCreate(
2302
            $mainLanguageCode,
2303
            $structFields,
2304
            $fieldDefinitions,
2305
            $languageCodes
2306
        );
2307
        $allFieldErrors = array();
2308
        $validateCount = 0;
2309
        $emptyValue = self::EMPTY_FIELD_VALUE;
2310 View Code Duplication
        foreach ($contentType->getFieldDefinitions() as $fieldDefinition) {
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...
2311
            foreach ($fieldValues[$fieldDefinition->identifier] as $languageCode => $value) {
2312
                $fieldTypeMock->expects($this->at($validateCount++))
2313
                    ->method('acceptValue')
2314
                    ->will(
2315
                        $this->returnCallback(
2316
                            function ($valueString) {
2317
                                return new ValueStub($valueString);
2318
                            }
2319
                        )
2320
                    );
2321
2322
                $fieldTypeMock->expects($this->at($validateCount++))
2323
                    ->method('isEmptyValue')
2324
                    ->will(
2325
                        $this->returnCallback(
2326
                            function (ValueStub $value) use ($emptyValue) {
2327
                                return $emptyValue === (string)$value;
2328
                            }
2329
                        )
2330
                    );
2331
2332
                if (self::EMPTY_FIELD_VALUE === (string)$value) {
2333
                    continue;
2334
                }
2335
2336
                $fieldTypeMock->expects($this->at($validateCount++))
2337
                    ->method('validate')
2338
                    ->with(
2339
                        $this->equalTo($fieldDefinition),
2340
                        $this->equalTo($value)
2341
                    )->will($this->returnArgument(1));
2342
2343
                $allFieldErrors[$fieldDefinition->id][$languageCode] = $value;
2344
            }
2345
        }
2346
2347
        return array($contentCreateStruct, $allFieldErrors);
2348
    }
2349
2350
    public function providerForTestCreateContentThrowsContentFieldValidationException()
2351
    {
2352
        return $this->providerForTestCreateContentNonRedundantFieldSetComplex();
2353
    }
2354
2355
    /**
2356
     * Test for the createContent() method.
2357
     *
2358
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
2359
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
2360
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
2361
     * @dataProvider providerForTestCreateContentThrowsContentFieldValidationException
2362
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
2363
     * @expectedExceptionMessage Content fields did not validate
2364
     */
2365
    public function testCreateContentThrowsContentFieldValidationException($mainLanguageCode, $structFields)
2366
    {
2367
        $fieldDefinitions = $this->fixturesForTestCreateContentNonRedundantFieldSetComplex();
2368
        list($contentCreateStruct, $allFieldErrors) =
2369
            $this->assertForTestCreateContentThrowsContentFieldValidationException(
2370
                $mainLanguageCode,
2371
                $structFields,
2372
                $fieldDefinitions
2373
            );
2374
2375
        $mockedService = $this->getPartlyMockedContentService();
2376
2377
        try {
2378
            $mockedService->createContent($contentCreateStruct);
2379
        } catch (ContentFieldValidationException $e) {
2380
            $this->assertEquals($allFieldErrors, $e->getFieldErrors());
2381
            throw $e;
2382
        }
2383
    }
2384
2385
    /**
2386
     * Test for the createContent() method.
2387
     *
2388
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
2389
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
2390
     * @covers \eZ\Publish\Core\Repository\ContentService::buildSPILocationCreateStructs
2391
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
2392
     */
2393
    public function testCreateContentWithLocations()
2394
    {
2395
        $spiFields = array(
2396
            new SPIField(
2397
                array(
2398
                    'fieldDefinitionId' => 'fieldDefinitionId',
2399
                    'type' => 'fieldTypeIdentifier',
2400
                    'value' => 'defaultValue',
2401
                    'languageCode' => 'eng-US',
2402
                )
2403
            ),
2404
        );
2405
        $fieldDefinitions = array(
2406
            new FieldDefinition(
2407
                array(
2408
                    'id' => 'fieldDefinitionId',
2409
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
2410
                    'isTranslatable' => false,
2411
                    'identifier' => 'identifier',
2412
                    'isRequired' => false,
2413
                    'defaultValue' => 'defaultValue',
2414
                )
2415
            ),
2416
        );
2417
2418
        // Set up a simple case that will pass
2419
        $locationCreateStruct1 = new LocationCreateStruct(array('parentLocationId' => 321));
2420
        $locationCreateStruct2 = new LocationCreateStruct(array('parentLocationId' => 654));
2421
        $locationCreateStructs = array($locationCreateStruct1, $locationCreateStruct2);
2422
        $contentCreateStruct = $this->assertForTestCreateContentNonRedundantFieldSet(
2423
            'eng-US',
2424
            array(),
2425
            $spiFields,
2426
            $fieldDefinitions,
2427
            $locationCreateStructs,
2428
            false,
2429
            // Do not execute
2430
            false
2431
        );
2432
2433
        $repositoryMock = $this->getRepositoryMock();
2434
        $mockedService = $this->getPartlyMockedContentService();
2435
        $locationServiceMock = $this->getLocationServiceMock();
2436
        /** @var \PHPUnit_Framework_MockObject_MockObject $handlerMock */
2437
        $handlerMock = $this->getPersistenceMock()->contentHandler();
2438
        $domainMapperMock = $this->getDomainMapperMock();
2439
        $spiLocationCreateStruct = new SPILocation\CreateStruct();
2440
        $parentLocation = new Location(array('contentInfo' => new ContentInfo(array('sectionId' => 1))));
2441
2442
        $locationServiceMock->expects($this->at(0))
2443
            ->method('loadLocation')
2444
            ->with($this->equalTo(321))
2445
            ->will($this->returnValue($parentLocation));
2446
2447
        $locationServiceMock->expects($this->at(1))
2448
            ->method('loadLocation')
2449
            ->with($this->equalTo(654))
2450
            ->will($this->returnValue($parentLocation));
2451
2452
        $repositoryMock->expects($this->atLeastOnce())
2453
            ->method('getLocationService')
2454
            ->will($this->returnValue($locationServiceMock));
2455
2456
        $domainMapperMock->expects($this->at(1))
2457
            ->method('buildSPILocationCreateStruct')
2458
            ->with(
2459
                $this->equalTo($locationCreateStruct1),
2460
                $this->equalTo($parentLocation),
2461
                $this->equalTo(true),
2462
                $this->equalTo(null),
2463
                $this->equalTo(null)
2464
            )->will($this->returnValue($spiLocationCreateStruct));
2465
2466
        $domainMapperMock->expects($this->at(2))
2467
            ->method('buildSPILocationCreateStruct')
2468
            ->with(
2469
                $this->equalTo($locationCreateStruct2),
2470
                $this->equalTo($parentLocation),
2471
                $this->equalTo(false),
2472
                $this->equalTo(null),
2473
                $this->equalTo(null)
2474
            )->will($this->returnValue($spiLocationCreateStruct));
2475
2476
        $spiContentCreateStruct = new SPIContentCreateStruct(
2477
            array(
2478
                'name' => array(),
2479
                'typeId' => 123,
2480
                'sectionId' => 1,
2481
                'ownerId' => 169,
2482
                'remoteId' => 'hash',
2483
                'fields' => $spiFields,
2484
                'modified' => time(),
2485
                'initialLanguageId' => 4242,
2486
                'locations' => array($spiLocationCreateStruct, $spiLocationCreateStruct),
2487
            )
2488
        );
2489
        $spiContentCreateStruct2 = clone $spiContentCreateStruct;
2490
        ++$spiContentCreateStruct2->modified;
2491
2492
        $spiContent = new SPIContent(
2493
            array(
2494
                'versionInfo' => new SPIContent\VersionInfo(
2495
                    array(
2496
                        'contentInfo' => new SPIContent\ContentInfo(array('id' => 42)),
2497
                        'versionNo' => 7,
2498
                    )
2499
                ),
2500
            )
2501
        );
2502
2503
        $handlerMock->expects($this->once())
2504
            ->method('create')
2505
            ->with($this->logicalOr($spiContentCreateStruct, $spiContentCreateStruct2))
2506
            ->will($this->returnValue($spiContent));
2507
2508
        $domainMapperMock->expects($this->once())
2509
            ->method('buildContentDomainObject')
2510
            ->with(
2511
                $this->isInstanceOf('eZ\\Publish\\SPI\\Persistence\\Content'),
2512
                $this->equalTo(null)
2513
            );
2514
2515
        $repositoryMock->expects($this->once())->method('commit');
2516
2517
        // Execute
2518
        $mockedService->createContent($contentCreateStruct, $locationCreateStructs);
2519
    }
2520
2521
    /**
2522
     * Test for the createContent() method.
2523
     *
2524
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
2525
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
2526
     * @covers \eZ\Publish\Core\Repository\ContentService::buildSPILocationCreateStructs
2527
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
2528
     * @expectedException \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
2529
     * @expectedExceptionMessage Multiple LocationCreateStructs with the same parent Location '321' are given
2530
     */
2531
    public function testCreateContentWithLocationsDuplicateUnderParent()
2532
    {
2533
        $fieldDefinitions = array(
2534
            new FieldDefinition(
2535
                array(
2536
                    'id' => 'fieldDefinitionId',
2537
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
2538
                    'isTranslatable' => false,
2539
                    'identifier' => 'identifier',
2540
                    'isRequired' => false,
2541
                    'defaultValue' => 'defaultValue',
2542
                )
2543
            ),
2544
        );
2545
2546
        $repositoryMock = $this->getRepositoryMock();
2547
        $mockedService = $this->getPartlyMockedContentService();
2548
        $locationServiceMock = $this->getLocationServiceMock();
2549
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
2550
        $domainMapperMock = $this->getDomainMapperMock();
2551
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
2552
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
2553
        $spiLocationCreateStruct = new SPILocation\CreateStruct();
2554
        $parentLocation = new Location(array('id' => 321));
2555
        $locationCreateStruct = new LocationCreateStruct(array('parentLocationId' => 321));
2556
        $locationCreateStructs = array($locationCreateStruct, clone $locationCreateStruct);
2557
        $contentType = new ContentType(
2558
            array(
2559
                'id' => 123,
2560
                'fieldDefinitions' => $fieldDefinitions,
2561
                'nameSchema' => '<nameSchema>',
2562
            )
2563
        );
2564
        $contentCreateStruct = new ContentCreateStruct(
2565
            array(
2566
                'fields' => array(),
2567
                'mainLanguageCode' => 'eng-US',
2568
                'contentType' => $contentType,
2569
                'alwaysAvailable' => false,
2570
                'ownerId' => 169,
2571
                'sectionId' => 1,
2572
            )
2573
        );
2574
2575
        $languageHandlerMock->expects($this->any())
2576
            ->method('loadByLanguageCode')
2577
            ->with($this->isType('string'))
2578
            ->will(
2579
                $this->returnCallback(
2580
                    function () {
2581
                        return new Language(array('id' => 4242));
2582
                    }
2583
                )
2584
            );
2585
2586
        $contentTypeServiceMock->expects($this->once())
2587
            ->method('loadContentType')
2588
            ->with($this->equalTo($contentType->id))
2589
            ->will($this->returnValue($contentType));
2590
2591
        $repositoryMock->expects($this->once())
2592
            ->method('getContentTypeService')
2593
            ->will($this->returnValue($contentTypeServiceMock));
2594
2595
        $that = $this;
2596
        $repositoryMock->expects($this->once())
2597
            ->method('canUser')
2598
            ->with(
2599
                $this->equalTo('content'),
2600
                $this->equalTo('create'),
2601
                $this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'),
2602
                $this->equalTo($locationCreateStructs)
2603
            )->will(
2604
                $this->returnCallback(
2605
                    function () use ($that, $contentCreateStruct) {
2606
                        $that->assertEquals($contentCreateStruct, func_get_arg(2));
2607
2608
                        return true;
2609
                    }
2610
                )
2611
            );
2612
2613
        $domainMapperMock->expects($this->once())
2614
            ->method('getUniqueHash')
2615
            ->with($this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentCreateStruct'))
2616
            ->will(
2617
                $this->returnCallback(
2618
                    function ($object) use ($that, $contentCreateStruct) {
2619
                        $that->assertEquals($contentCreateStruct, $object);
2620
2621
                        return 'hash';
2622
                    }
2623
                )
2624
            );
2625
2626
        $locationServiceMock->expects($this->once())
2627
            ->method('loadLocation')
2628
            ->with($this->equalTo(321))
2629
            ->will($this->returnValue($parentLocation));
2630
2631
        $repositoryMock->expects($this->any())
2632
            ->method('getLocationService')
2633
            ->will($this->returnValue($locationServiceMock));
2634
2635
        $domainMapperMock->expects($this->any())
2636
            ->method('buildSPILocationCreateStruct')
2637
            ->with(
2638
                $this->equalTo($locationCreateStruct),
2639
                $this->equalTo($parentLocation),
2640
                $this->equalTo(true),
2641
                $this->equalTo(null),
2642
                $this->equalTo(null)
2643
            )->will($this->returnValue($spiLocationCreateStruct));
2644
2645
        $mockedService->createContent(
2646
            $contentCreateStruct,
2647
            $locationCreateStructs
2648
        );
2649
    }
2650
2651
    /**
2652
     * Test for the createContent() method.
2653
     *
2654
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
2655
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
2656
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
2657
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
2658
     */
2659
    public function testCreateContentObjectStates()
2660
    {
2661
        $spiFields = array(
2662
            new SPIField(
2663
                array(
2664
                    'fieldDefinitionId' => 'fieldDefinitionId',
2665
                    'type' => 'fieldTypeIdentifier',
2666
                    'value' => 'defaultValue',
2667
                    'languageCode' => 'eng-US',
2668
                )
2669
            ),
2670
        );
2671
        $fieldDefinitions = array(
2672
            new FieldDefinition(
2673
                array(
2674
                    'id' => 'fieldDefinitionId',
2675
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
2676
                    'isTranslatable' => false,
2677
                    'identifier' => 'identifier',
2678
                    'isRequired' => false,
2679
                    'defaultValue' => 'defaultValue',
2680
                )
2681
            ),
2682
        );
2683
        $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...
2684
            new SPIObjectStateGroup(array('id' => 10)),
2685
            new SPIObjectStateGroup(array('id' => 20)),
2686
        );
2687
2688
        // Set up a simple case that will pass
2689
        $contentCreateStruct = $this->assertForTestCreateContentNonRedundantFieldSet(
2690
            'eng-US',
2691
            array(),
2692
            $spiFields,
2693
            $fieldDefinitions,
2694
            array(),
2695
            true,
2696
            // Do not execute
2697
            false
2698
        );
2699
        $timestamp = time();
2700
        $contentCreateStruct->modificationDate = new \DateTime("@{$timestamp}");
2701
2702
        $repositoryMock = $this->getRepositoryMock();
2703
        $mockedService = $this->getPartlyMockedContentService();
2704
        /** @var \PHPUnit_Framework_MockObject_MockObject $handlerMock */
2705
        $handlerMock = $this->getPersistenceMock()->contentHandler();
2706
        $domainMapperMock = $this->getDomainMapperMock();
2707
2708
        $this->mockGetDefaultObjectStates();
2709
        $this->mockSetDefaultObjectStates();
2710
2711
        $spiContentCreateStruct = new SPIContentCreateStruct(
2712
            array(
2713
                'name' => array(),
2714
                'typeId' => 123,
2715
                'sectionId' => 1,
2716
                'ownerId' => 169,
2717
                'remoteId' => 'hash',
2718
                'fields' => $spiFields,
2719
                'modified' => $timestamp,
2720
                'initialLanguageId' => 4242,
2721
                'locations' => array(),
2722
            )
2723
        );
2724
        $spiContentCreateStruct2 = clone $spiContentCreateStruct;
2725
        ++$spiContentCreateStruct2->modified;
2726
2727
        $spiContent = new SPIContent(
2728
            array(
2729
                'versionInfo' => new SPIContent\VersionInfo(
2730
                    array(
2731
                        'contentInfo' => new SPIContent\ContentInfo(array('id' => 42)),
2732
                        'versionNo' => 7,
2733
                    )
2734
                ),
2735
            )
2736
        );
2737
2738
        $handlerMock->expects($this->once())
2739
            ->method('create')
2740
            ->with($this->equalTo($spiContentCreateStruct))
2741
            ->will($this->returnValue($spiContent));
2742
2743
        $domainMapperMock->expects($this->once())
2744
            ->method('buildContentDomainObject')
2745
            ->with(
2746
                $this->isInstanceOf('eZ\\Publish\\SPI\\Persistence\\Content'),
2747
                $this->equalTo(null)
2748
            );
2749
2750
        $repositoryMock->expects($this->once())->method('commit');
2751
2752
        // Execute
2753
        $mockedService->createContent($contentCreateStruct, array());
2754
    }
2755
2756
    /**
2757
     * Test for the createContent() method.
2758
     *
2759
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForCreate
2760
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForCreate
2761
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
2762
     * @covers \eZ\Publish\Core\Repository\ContentService::createContent
2763
     * @dataProvider providerForTestCreateContentThrowsContentValidationExceptionTranslation
2764
     * @expectedException \Exception
2765
     * @expectedExceptionMessage Store failed
2766
     */
2767
    public function testCreateContentWithRollback()
2768
    {
2769
        $fieldDefinitions = array(
2770
            new FieldDefinition(
2771
                array(
2772
                    'id' => 'fieldDefinitionId',
2773
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
2774
                    'isTranslatable' => false,
2775
                    'identifier' => 'identifier',
2776
                    'isRequired' => false,
2777
                    'defaultValue' => 'defaultValue',
2778
                )
2779
            ),
2780
        );
2781
2782
        // Setup a simple case that will pass
2783
        $contentCreateStruct = $this->assertForTestCreateContentNonRedundantFieldSet(
2784
            'eng-US',
2785
            array(),
2786
            array(),
2787
            $fieldDefinitions,
2788
            array(),
2789
            false,
2790
            // Do not execute test
2791
            false
2792
        );
2793
2794
        $repositoryMock = $this->getRepositoryMock();
2795
        $repositoryMock->expects($this->never())->method('commit');
2796
        $repositoryMock->expects($this->once())->method('rollback');
2797
2798
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
2799
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
2800
        $contentHandlerMock->expects($this->once())
2801
            ->method('create')
2802
            ->with($this->anything())
2803
            ->will($this->throwException(new \Exception('Store failed')));
2804
2805
        // Execute
2806
        $this->partlyMockedContentService->createContent($contentCreateStruct, array());
2807
    }
2808
2809
    public function providerForTestUpdateContentThrowsBadStateException()
2810
    {
2811
        return array(
2812
            array(VersionInfo::STATUS_PUBLISHED),
2813
            array(VersionInfo::STATUS_ARCHIVED),
2814
        );
2815
    }
2816
2817
    /**
2818
     * Test for the updateContent() method.
2819
     *
2820
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
2821
     * @expectedException \eZ\Publish\API\Repository\Exceptions\BadStateException
2822
     * @dataProvider providerForTestUpdateContentThrowsBadStateException
2823
     */
2824
    public function testUpdateContentThrowsBadStateException($status)
2825
    {
2826
        $mockedService = $this->getPartlyMockedContentService(array('loadContent'));
2827
        $contentUpdateStruct = new ContentUpdateStruct();
2828
        $versionInfo = new VersionInfo(
2829
            array(
2830
                'contentInfo' => new ContentInfo(array('id' => 42)),
2831
                'versionNo' => 7,
2832
                'status' => $status,
2833
            )
2834
        );
2835
        $content = new Content(
2836
            array(
2837
                'versionInfo' => $versionInfo,
2838
                'internalFields' => array(),
2839
            )
2840
        );
2841
2842
        $mockedService->expects($this->once())
2843
            ->method('loadContent')
2844
            ->with(
2845
                $this->equalTo(42),
2846
                $this->equalTo(null),
2847
                $this->equalTo(7)
2848
            )->will(
2849
                $this->returnValue($content)
2850
            );
2851
2852
        $mockedService->updateContent($versionInfo, $contentUpdateStruct);
2853
    }
2854
2855
    /**
2856
     * Test for the updateContent() method.
2857
     *
2858
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
2859
     * @expectedException \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
2860
     */
2861
    public function testUpdateContentThrowsUnauthorizedException()
2862
    {
2863
        $repositoryMock = $this->getRepositoryMock();
2864
        $mockedService = $this->getPartlyMockedContentService(array('loadContent'));
2865
        $contentUpdateStruct = new ContentUpdateStruct();
2866
        $versionInfo = new VersionInfo(
2867
            array(
2868
                'contentInfo' => new ContentInfo(array('id' => 42)),
2869
                'versionNo' => 7,
2870
                'status' => VersionInfo::STATUS_DRAFT,
2871
            )
2872
        );
2873
        $content = new Content(
2874
            array(
2875
                'versionInfo' => $versionInfo,
2876
                'internalFields' => array(),
2877
            )
2878
        );
2879
2880
        $mockedService->expects($this->once())
2881
            ->method('loadContent')
2882
            ->with(
2883
                $this->equalTo(42),
2884
                $this->equalTo(null),
2885
                $this->equalTo(7)
2886
            )->will(
2887
                $this->returnValue($content)
2888
            );
2889
2890
        $repositoryMock->expects($this->once())
2891
            ->method('canUser')
2892
            ->with(
2893
                $this->equalTo('content'),
2894
                $this->equalTo('edit'),
2895
                $this->equalTo($content)
2896
            )->will($this->returnValue(false));
2897
2898
        $mockedService->updateContent($versionInfo, $contentUpdateStruct);
2899
    }
2900
2901
    /**
2902
     * @param string $initialLanguageCode
2903
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
2904
     * @param string[] $existingLanguages
2905
     *
2906
     * @return string[]
2907
     */
2908
    protected function determineLanguageCodesForUpdate($initialLanguageCode, array $structFields, $existingLanguages)
2909
    {
2910
        $languageCodes = array_fill_keys($existingLanguages, true);
2911
        if ($initialLanguageCode !== null) {
2912
            $languageCodes[$initialLanguageCode] = true;
2913
        }
2914
2915 View Code Duplication
        foreach ($structFields as $field) {
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...
2916
            if ($field->languageCode === null || isset($languageCodes[$field->languageCode])) {
2917
                continue;
2918
            }
2919
2920
            $languageCodes[$field->languageCode] = true;
2921
        }
2922
2923
        return array_keys($languageCodes);
2924
    }
2925
2926
    /**
2927
     * @param string $initialLanguageCode
2928
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
2929
     * @param string $mainLanguageCode
2930
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
2931
     *
2932
     * @return array
2933
     */
2934
    protected function mapStructFieldsForUpdate($initialLanguageCode, $structFields, $mainLanguageCode, $fieldDefinitions)
2935
    {
2936
        $initialLanguageCode = $initialLanguageCode ?: $mainLanguageCode;
2937
2938
        $mappedFieldDefinitions = array();
2939
        foreach ($fieldDefinitions as $fieldDefinition) {
2940
            $mappedFieldDefinitions[$fieldDefinition->identifier] = $fieldDefinition;
2941
        }
2942
2943
        $mappedStructFields = array();
2944
        foreach ($structFields as $structField) {
2945
            $identifier = $structField->fieldDefIdentifier;
2946
2947
            if ($structField->languageCode !== null) {
2948
                $languageCode = $structField->languageCode;
2949
            } elseif ($mappedFieldDefinitions[$identifier]->isTranslatable) {
2950
                $languageCode = $initialLanguageCode;
2951
            } else {
2952
                $languageCode = $mainLanguageCode;
2953
            }
2954
2955
            $mappedStructFields[$identifier][$languageCode] = (string)$structField->value;
0 ignored issues
show
Documentation introduced by
The property $value is declared protected in eZ\Publish\API\Repository\Values\Content\Field. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
2956
        }
2957
2958
        return $mappedStructFields;
2959
    }
2960
2961
    /**
2962
     * Returns full, possibly redundant array of field values, indexed by field definition
2963
     * identifier and language code.
2964
     *
2965
     * @param string $initialLanguageCode
2966
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
2967
     * @param \eZ\Publish\Core\Repository\Values\Content\Content $content
2968
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
2969
     * @param array $languageCodes
2970
     *
2971
     * @return array
2972
     */
2973
    protected function determineValuesForUpdate(
2974
        $initialLanguageCode,
2975
        array $structFields,
2976
        Content $content,
2977
        array $fieldDefinitions,
2978
        array $languageCodes
2979
    ) {
2980
        $mainLanguageCode = $content->versionInfo->contentInfo->mainLanguageCode;
2981
2982
        $mappedStructFields = $this->mapStructFieldsForUpdate(
2983
            $initialLanguageCode,
2984
            $structFields,
2985
            $mainLanguageCode,
2986
            $fieldDefinitions
2987
        );
2988
2989
        $values = array();
2990
2991
        foreach ($fieldDefinitions as $fieldDefinition) {
2992
            $identifier = $fieldDefinition->identifier;
2993
            foreach ($languageCodes as $languageCode) {
2994 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...
2995
                    if (isset($mappedStructFields[$identifier][$mainLanguageCode])) {
2996
                        $values[$identifier][$languageCode] = $mappedStructFields[$identifier][$mainLanguageCode];
2997
                    } else {
2998
                        $values[$identifier][$languageCode] = (string)$content->fields[$identifier][$mainLanguageCode];
2999
                    }
3000
                    continue;
3001
                }
3002
3003 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...
3004
                    $values[$identifier][$languageCode] = $mappedStructFields[$identifier][$languageCode];
3005
                    continue;
3006
                }
3007
3008
                if (isset($content->fields[$identifier][$languageCode])) {
3009
                    $values[$identifier][$languageCode] = (string)$content->fields[$identifier][$languageCode];
3010
                    continue;
3011
                }
3012
3013
                $values[$identifier][$languageCode] = (string)$fieldDefinition->defaultValue;
0 ignored issues
show
Documentation introduced by
The property $defaultValue is declared protected in eZ\Publish\API\Repositor...entType\FieldDefinition. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
3014
            }
3015
        }
3016
3017
        return $this->stubValues($values);
3018
    }
3019
3020
    protected function stubValues(array $fieldValues)
3021
    {
3022
        foreach ($fieldValues as &$languageValues) {
3023
            foreach ($languageValues as &$value) {
3024
                $value = new ValueStub($value);
3025
            }
3026
        }
3027
3028
        return $fieldValues;
3029
    }
3030
3031
    /**
3032
     * Asserts that calling updateContent() with given API field set causes calling
3033
     * Handler::updateContent() with given SPI field set.
3034
     *
3035
     * @param string $initialLanguageCode
3036
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $structFields
3037
     * @param \eZ\Publish\SPI\Persistence\Content\Field[] $spiFields
3038
     * @param \eZ\Publish\API\Repository\Values\Content\Field[] $existingFields
3039
     * @param \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition[] $fieldDefinitions
3040
     * @param bool $execute
3041
     *
3042
     * @return mixed
3043
     */
3044
    protected function assertForTestUpdateContentNonRedundantFieldSet(
3045
        $initialLanguageCode,
3046
        array $structFields,
3047
        array $spiFields,
3048
        array $existingFields,
3049
        array $fieldDefinitions,
3050
        $execute = true
3051
    ) {
3052
        $repositoryMock = $this->getRepositoryMock();
3053
        $mockedService = $this->getPartlyMockedContentService(array('loadContent', 'loadRelations'));
3054
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
3055
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
3056
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
3057
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
3058
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
3059
        $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...
3060
        $domainMapperMock = $this->getDomainMapperMock();
3061
        $relationProcessorMock = $this->getRelationProcessorMock();
3062
        $nameSchemaServiceMock = $this->getNameSchemaServiceMock();
3063
        $fieldTypeMock = $this->getMock('eZ\\Publish\\SPI\\FieldType\\FieldType');
3064
        $existingLanguageCodes = array_map(
3065
            function (Field $field) {
3066
                return $field->languageCode;
3067
            },
3068
            $existingFields
3069
        );
3070
        $languageCodes = $this->determineLanguageCodesForUpdate(
3071
            $initialLanguageCode,
3072
            $structFields,
3073
            $existingLanguageCodes
3074
        );
3075
        $versionInfo = new VersionInfo(
3076
            array(
3077
                'contentInfo' => new ContentInfo(
3078
                    array(
3079
                        'id' => 42,
3080
                        'contentTypeId' => 24,
3081
                        'mainLanguageCode' => 'eng-GB',
3082
                    )
3083
                ),
3084
                'versionNo' => 7,
3085
                'languageCodes' => $existingLanguageCodes,
3086
                'status' => VersionInfo::STATUS_DRAFT,
3087
            )
3088
        );
3089
        $content = new Content(
3090
            array(
3091
                'versionInfo' => $versionInfo,
3092
                'internalFields' => $existingFields,
3093
            )
3094
        );
3095
        $contentType = new ContentType(array('fieldDefinitions' => $fieldDefinitions));
3096
3097
        $languageHandlerMock->expects($this->any())
3098
            ->method('loadByLanguageCode')
3099
            ->with($this->isType('string'))
3100
            ->will(
3101
                $this->returnCallback(
3102
                    function () {
3103
                        return new Language(array('id' => 4242));
3104
                    }
3105
                )
3106
            );
3107
3108
        $mockedService->expects($this->once())
3109
            ->method('loadContent')
3110
            ->with(
3111
                $this->equalTo(42),
3112
                $this->equalTo(null),
3113
                $this->equalTo(7)
3114
            )->will(
3115
                $this->returnValue($content)
3116
            );
3117
3118
        $repositoryMock->expects($this->once())->method('beginTransaction');
3119
3120
        $repositoryMock->expects($this->once())
3121
            ->method('canUser')
3122
            ->with(
3123
                $this->equalTo('content'),
3124
                $this->equalTo('edit'),
3125
                $this->equalTo($content)
3126
            )->will($this->returnValue(true));
3127
3128
        $contentTypeServiceMock->expects($this->once())
3129
            ->method('loadContentType')
3130
            ->with($this->equalTo(24))
3131
            ->will($this->returnValue($contentType));
3132
3133
        $repositoryMock->expects($this->once())
3134
            ->method('getContentTypeService')
3135
            ->will($this->returnValue($contentTypeServiceMock));
3136
3137
        $repositoryMock->expects($this->once())
3138
            ->method('getCurrentUserReference')
3139
            ->will($this->returnValue(new UserReference(169)));
3140
3141
        $fieldTypeMock->expects($this->any())
3142
            ->method('acceptValue')
3143
            ->will(
3144
                $this->returnCallback(
3145
                    function ($valueString) {
3146
                        return new ValueStub($valueString);
3147
                    }
3148
                )
3149
            );
3150
3151
        $emptyValue = self::EMPTY_FIELD_VALUE;
3152
        $fieldTypeMock->expects($this->any())
3153
            ->method('toPersistenceValue')
3154
            ->will(
3155
                $this->returnCallback(
3156
                    function (ValueStub $value) {
3157
                        return (string)$value;
3158
                    }
3159
                )
3160
            );
3161
3162
        $fieldTypeMock->expects($this->any())
3163
            ->method('isEmptyValue')
3164
            ->will(
3165
                $this->returnCallback(
3166
                    function (ValueStub $value) use ($emptyValue) {
3167
                        return $emptyValue === (string)$value;
3168
                    }
3169
                )
3170
            );
3171
3172
        $fieldTypeMock->expects($this->any())
3173
            ->method('validate')
3174
            ->will($this->returnValue(array()));
3175
3176
        $this->getFieldTypeRegistryMock()->expects($this->any())
3177
            ->method('getFieldType')
3178
            ->will($this->returnValue($fieldTypeMock));
3179
3180
        $relationProcessorMock
3181
            ->expects($this->exactly(count($fieldDefinitions) * count($languageCodes)))
3182
            ->method('appendFieldRelations')
3183
            ->with(
3184
                $this->isType('array'),
3185
                $this->isType('array'),
3186
                $this->isInstanceOf('eZ\\Publish\\SPI\\FieldType\\FieldType'),
3187
                $this->isInstanceOf('eZ\\Publish\\Core\\FieldType\\Value'),
3188
                $this->anything()
3189
            );
3190
3191
        $values = $this->determineValuesForUpdate(
3192
            $initialLanguageCode,
3193
            $structFields,
3194
            $content,
3195
            $fieldDefinitions,
3196
            $languageCodes
3197
        );
3198
        $nameSchemaServiceMock->expects($this->once())
3199
            ->method('resolveNameSchema')
3200
            ->with(
3201
                $this->equalTo($content),
3202
                $this->equalTo($values),
3203
                $this->equalTo($languageCodes)
3204
            )->will($this->returnValue(array()));
3205
3206
        $existingRelations = array('RELATIONS!!!');
3207
        $mockedService->expects($this->once())
3208
            ->method('loadRelations')
3209
            ->with($content->versionInfo)
3210
            ->will($this->returnValue($existingRelations));
3211
        $relationProcessorMock->expects($this->any())
3212
            ->method('processFieldRelations')
3213
            ->with(
3214
                $this->isType('array'),
3215
                $this->equalTo(42),
3216
                $this->isType('int'),
3217
                $this->equalTo($contentType),
3218
                $this->equalTo($existingRelations)
3219
            );
3220
3221
        $contentUpdateStruct = new ContentUpdateStruct(
3222
            array(
3223
                'fields' => $structFields,
3224
                'initialLanguageCode' => $initialLanguageCode,
3225
            )
3226
        );
3227
3228
        if ($execute) {
3229
            $spiContentUpdateStruct = new SPIContentUpdateStruct(
3230
                array(
3231
                    'creatorId' => 169,
3232
                    'fields' => $spiFields,
3233
                    'modificationDate' => time(),
3234
                    'initialLanguageId' => 4242,
3235
                )
3236
            );
3237
3238
            // During code coverage runs, timestamp might differ 1-3 seconds
3239
            $spiContentUpdateStructTs1 = clone $spiContentUpdateStruct;
3240
            ++$spiContentUpdateStructTs1->modificationDate;
3241
3242
            $spiContentUpdateStructTs2 = clone $spiContentUpdateStructTs1;
3243
            ++$spiContentUpdateStructTs2->modificationDate;
3244
3245
            $spiContentUpdateStructTs3 = clone $spiContentUpdateStructTs2;
3246
            ++$spiContentUpdateStructTs3->modificationDate;
3247
3248
            $spiContent = new SPIContent(
3249
                array(
3250
                    'versionInfo' => new SPIContent\VersionInfo(
3251
                        array(
3252
                            'contentInfo' => new SPIContent\ContentInfo(array('id' => 42)),
3253
                            'versionNo' => 7,
3254
                        )
3255
                    ),
3256
                )
3257
            );
3258
3259
            $contentHandlerMock->expects($this->once())
3260
                ->method('updateContent')
3261
                ->with(
3262
                    42,
3263
                    7,
3264
                    $this->logicalOr($spiContentUpdateStruct, $spiContentUpdateStructTs1, $spiContentUpdateStructTs2, $spiContentUpdateStructTs3)
3265
                )
3266
                ->will($this->returnValue($spiContent));
3267
3268
            $repositoryMock->expects($this->once())->method('commit');
3269
            $domainMapperMock->expects($this->once())
3270
                ->method('buildContentDomainObject')
3271
                ->with(
3272
                    $this->isInstanceOf('eZ\\Publish\\SPI\\Persistence\\Content'),
3273
                    $this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\ContentType\\ContentType')
3274
                );
3275
3276
            $mockedService->updateContent($content->versionInfo, $contentUpdateStruct);
3277
        }
3278
3279
        return array($content->versionInfo, $contentUpdateStruct);
3280
    }
3281
3282
    public function providerForTestUpdateContentNonRedundantFieldSet1()
3283
    {
3284
        $spiFields = array(
3285
            new SPIField(
3286
                array(
3287
                    'id' => '100',
3288
                    'fieldDefinitionId' => 'fieldDefinitionId',
3289
                    'type' => 'fieldTypeIdentifier',
3290
                    'value' => 'newValue',
3291
                    'languageCode' => 'eng-GB',
3292
                    'versionNo' => 7,
3293
                )
3294
            ),
3295
        );
3296
3297
        return array(
3298
            // With languages set
3299
            array(
3300
                'eng-GB',
3301
                array(
3302
                    new Field(
3303
                        array(
3304
                            'fieldDefIdentifier' => 'identifier',
3305
                            'value' => 'newValue',
3306
                            'languageCode' => 'eng-GB',
3307
                        )
3308
                    ),
3309
                ),
3310
                $spiFields,
3311
            ),
3312
            // Without languages set
3313
            array(
3314
                null,
3315
                array(
3316
                    new Field(
3317
                        array(
3318
                            'fieldDefIdentifier' => 'identifier',
3319
                            'value' => 'newValue',
3320
                            'languageCode' => null,
3321
                        )
3322
                    ),
3323
                ),
3324
                $spiFields,
3325
            ),
3326
            // Adding new language without fields
3327
            array(
3328
                'eng-US',
3329
                array(),
3330
                array(),
3331
            ),
3332
        );
3333
    }
3334
3335
    /**
3336
     * Test for the updateContent() method.
3337
     *
3338
     * Testing the simplest use case.
3339
     *
3340
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
3341
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
3342
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
3343
     * @dataProvider providerForTestUpdateContentNonRedundantFieldSet1
3344
     */
3345 View Code Duplication
    public function testUpdateContentNonRedundantFieldSet1($initialLanguageCode, $structFields, $spiFields)
3346
    {
3347
        $existingFields = array(
3348
            new Field(
3349
                array(
3350
                    'id' => '100',
3351
                    'fieldDefIdentifier' => 'identifier',
3352
                    'value' => 'initialValue',
3353
                    'languageCode' => 'eng-GB',
3354
                )
3355
            ),
3356
        );
3357
3358
        $fieldDefinitions = array(
3359
            new FieldDefinition(
3360
                array(
3361
                    'id' => 'fieldDefinitionId',
3362
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
3363
                    'isTranslatable' => false,
3364
                    'identifier' => 'identifier',
3365
                    'isRequired' => false,
3366
                    'defaultValue' => 'defaultValue',
3367
                )
3368
            ),
3369
        );
3370
3371
        $this->assertForTestUpdateContentNonRedundantFieldSet(
3372
            $initialLanguageCode,
3373
            $structFields,
3374
            $spiFields,
3375
            $existingFields,
3376
            $fieldDefinitions
3377
        );
3378
    }
3379
3380
    public function providerForTestUpdateContentNonRedundantFieldSet2()
3381
    {
3382
        $spiFields0 = array(
3383
            new SPIField(
3384
                array(
3385
                    'id' => '100',
3386
                    'fieldDefinitionId' => 'fieldDefinitionId',
3387
                    'type' => 'fieldTypeIdentifier',
3388
                    'value' => 'newValue',
3389
                    'languageCode' => 'eng-GB',
3390
                    'versionNo' => 7,
3391
                )
3392
            ),
3393
        );
3394
        $spiFields1 = array(
3395
            new SPIField(
3396
                array(
3397
                    'id' => null,
3398
                    'fieldDefinitionId' => 'fieldDefinitionId',
3399
                    'type' => 'fieldTypeIdentifier',
3400
                    'value' => 'newValue',
3401
                    'languageCode' => 'eng-US',
3402
                    'versionNo' => 7,
3403
                )
3404
            ),
3405
        );
3406
        $spiFields2 = array(
3407
            new SPIField(
3408
                array(
3409
                    'id' => 100,
3410
                    'fieldDefinitionId' => 'fieldDefinitionId',
3411
                    'type' => 'fieldTypeIdentifier',
3412
                    'value' => 'newValue2',
3413
                    'languageCode' => 'eng-GB',
3414
                    'versionNo' => 7,
3415
                )
3416
            ),
3417
            new SPIField(
3418
                array(
3419
                    'id' => null,
3420
                    'fieldDefinitionId' => 'fieldDefinitionId',
3421
                    'type' => 'fieldTypeIdentifier',
3422
                    'value' => 'newValue1',
3423
                    'languageCode' => 'eng-US',
3424
                    'versionNo' => 7,
3425
                )
3426
            ),
3427
        );
3428
3429
        return array(
3430
            // 0. With languages set
3431
            array(
3432
                'eng-GB',
3433
                array(
3434
                    new Field(
3435
                        array(
3436
                            'fieldDefIdentifier' => 'identifier',
3437
                            'value' => 'newValue',
3438
                            'languageCode' => 'eng-GB',
3439
                        )
3440
                    ),
3441
                ),
3442
                $spiFields0,
3443
            ),
3444
            // 1. Without languages set
3445
            array(
3446
                null,
3447
                array(
3448
                    new Field(
3449
                        array(
3450
                            'fieldDefIdentifier' => 'identifier',
3451
                            'value' => 'newValue',
3452
                            'languageCode' => null,
3453
                        )
3454
                    ),
3455
                ),
3456
                $spiFields0,
3457
            ),
3458
            // 2. New language with language set
3459
            array(
3460
                'eng-GB',
3461
                array(
3462
                    new Field(
3463
                        array(
3464
                            'fieldDefIdentifier' => 'identifier',
3465
                            'value' => 'newValue',
3466
                            'languageCode' => 'eng-US',
3467
                        )
3468
                    ),
3469
                ),
3470
                $spiFields1,
3471
            ),
3472
            // 3. New language without language set
3473
            array(
3474
                'eng-US',
3475
                array(
3476
                    new Field(
3477
                        array(
3478
                            'fieldDefIdentifier' => 'identifier',
3479
                            'value' => 'newValue',
3480
                            'languageCode' => null,
3481
                        )
3482
                    ),
3483
                ),
3484
                $spiFields1,
3485
            ),
3486
            // 4. New language and existing language with language set
3487
            array(
3488
                'eng-GB',
3489
                array(
3490
                    new Field(
3491
                        array(
3492
                            'fieldDefIdentifier' => 'identifier',
3493
                            'value' => 'newValue1',
3494
                            'languageCode' => 'eng-US',
3495
                        )
3496
                    ),
3497
                    new Field(
3498
                        array(
3499
                            'fieldDefIdentifier' => 'identifier',
3500
                            'value' => 'newValue2',
3501
                            'languageCode' => 'eng-GB',
3502
                        )
3503
                    ),
3504
                ),
3505
                $spiFields2,
3506
            ),
3507
            // 5. New language and existing language without language set
3508
            array(
3509
                'eng-US',
3510
                array(
3511
                    new Field(
3512
                        array(
3513
                            'fieldDefIdentifier' => 'identifier',
3514
                            'value' => 'newValue1',
3515
                            'languageCode' => null,
3516
                        )
3517
                    ),
3518
                    new Field(
3519
                        array(
3520
                            'fieldDefIdentifier' => 'identifier',
3521
                            'value' => 'newValue2',
3522
                            'languageCode' => 'eng-GB',
3523
                        )
3524
                    ),
3525
                ),
3526
                $spiFields2,
3527
            ),
3528
            // 6. Adding new language without fields
3529
            array(
3530
                'eng-US',
3531
                array(),
3532
                array(
3533
                    new SPIField(
3534
                        array(
3535
                            'id' => null,
3536
                            'fieldDefinitionId' => 'fieldDefinitionId',
3537
                            'type' => 'fieldTypeIdentifier',
3538
                            'value' => 'defaultValue',
3539
                            'languageCode' => 'eng-US',
3540
                            'versionNo' => 7,
3541
                        )
3542
                    ),
3543
                ),
3544
            ),
3545
        );
3546
    }
3547
3548
    /**
3549
     * Test for the updateContent() method.
3550
     *
3551
     * Testing with translatable field.
3552
     *
3553
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
3554
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
3555
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
3556
     * @dataProvider providerForTestUpdateContentNonRedundantFieldSet2
3557
     */
3558 View Code Duplication
    public function testUpdateContentNonRedundantFieldSet2($initialLanguageCode, $structFields, $spiFields)
3559
    {
3560
        $existingFields = array(
3561
            new Field(
3562
                array(
3563
                    'id' => '100',
3564
                    'fieldDefIdentifier' => 'identifier',
3565
                    'value' => 'initialValue',
3566
                    'languageCode' => 'eng-GB',
3567
                )
3568
            ),
3569
        );
3570
3571
        $fieldDefinitions = array(
3572
            new FieldDefinition(
3573
                array(
3574
                    'id' => 'fieldDefinitionId',
3575
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
3576
                    'isTranslatable' => true,
3577
                    'identifier' => 'identifier',
3578
                    'isRequired' => false,
3579
                    'defaultValue' => 'defaultValue',
3580
                )
3581
            ),
3582
        );
3583
3584
        $this->assertForTestUpdateContentNonRedundantFieldSet(
3585
            $initialLanguageCode,
3586
            $structFields,
3587
            $spiFields,
3588
            $existingFields,
3589
            $fieldDefinitions
3590
        );
3591
    }
3592
3593
    public function providerForTestUpdateContentNonRedundantFieldSet3()
3594
    {
3595
        $spiFields0 = array(
3596
            new SPIField(
3597
                array(
3598
                    'id' => null,
3599
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3600
                    'type' => 'fieldTypeIdentifier',
3601
                    'value' => 'newValue1',
3602
                    'languageCode' => 'eng-US',
3603
                    'versionNo' => 7,
3604
                )
3605
            ),
3606
        );
3607
        $spiFields1 = array(
3608
            new SPIField(
3609
                array(
3610
                    'id' => 100,
3611
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3612
                    'type' => 'fieldTypeIdentifier',
3613
                    'value' => 'newValue2',
3614
                    'languageCode' => 'eng-GB',
3615
                    'versionNo' => 7,
3616
                )
3617
            ),
3618
            new SPIField(
3619
                array(
3620
                    'id' => null,
3621
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3622
                    'type' => 'fieldTypeIdentifier',
3623
                    'value' => 'newValue1',
3624
                    'languageCode' => 'eng-US',
3625
                    'versionNo' => 7,
3626
                )
3627
            ),
3628
        );
3629
        $spiFields2 = array(
3630
            new SPIField(
3631
                array(
3632
                    'id' => 100,
3633
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3634
                    'type' => 'fieldTypeIdentifier',
3635
                    'value' => 'newValue2',
3636
                    'languageCode' => 'eng-GB',
3637
                    'versionNo' => 7,
3638
                )
3639
            ),
3640
            new SPIField(
3641
                array(
3642
                    'id' => null,
3643
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3644
                    'type' => 'fieldTypeIdentifier',
3645
                    'value' => 'newValue1',
3646
                    'languageCode' => 'eng-US',
3647
                    'versionNo' => 7,
3648
                )
3649
            ),
3650
            new SPIField(
3651
                array(
3652
                    'id' => 101,
3653
                    'fieldDefinitionId' => 'fieldDefinitionId2',
3654
                    'type' => 'fieldTypeIdentifier',
3655
                    'value' => 'newValue3',
3656
                    'languageCode' => 'eng-GB',
3657
                    'versionNo' => 7,
3658
                )
3659
            ),
3660
        );
3661
        $spiFields3 = array(
3662
            new SPIField(
3663
                array(
3664
                    'id' => null,
3665
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3666
                    'type' => 'fieldTypeIdentifier',
3667
                    'value' => 'defaultValue1',
3668
                    'languageCode' => 'eng-US',
3669
                    'versionNo' => 7,
3670
                )
3671
            ),
3672
        );
3673
3674
        return array(
3675
            // 0. ew language with language set
3676
            array(
3677
                'eng-US',
3678
                array(
3679
                    new Field(
3680
                        array(
3681
                            'fieldDefIdentifier' => 'identifier1',
3682
                            'value' => 'newValue1',
3683
                            'languageCode' => 'eng-US',
3684
                        )
3685
                    ),
3686
                ),
3687
                $spiFields0,
3688
            ),
3689
            // 1. New language without language set
3690
            array(
3691
                'eng-US',
3692
                array(
3693
                    new Field(
3694
                        array(
3695
                            'fieldDefIdentifier' => 'identifier1',
3696
                            'value' => 'newValue1',
3697
                            'languageCode' => null,
3698
                        )
3699
                    ),
3700
                ),
3701
                $spiFields0,
3702
            ),
3703
            // 2. New language and existing language with language set
3704
            array(
3705
                'eng-US',
3706
                array(
3707
                    new Field(
3708
                        array(
3709
                            'fieldDefIdentifier' => 'identifier1',
3710
                            'value' => 'newValue1',
3711
                            'languageCode' => 'eng-US',
3712
                        )
3713
                    ),
3714
                    new Field(
3715
                        array(
3716
                            'fieldDefIdentifier' => 'identifier1',
3717
                            'value' => 'newValue2',
3718
                            'languageCode' => 'eng-GB',
3719
                        )
3720
                    ),
3721
                ),
3722
                $spiFields1,
3723
            ),
3724
            // 3. New language and existing language without language set
3725
            array(
3726
                'eng-US',
3727
                array(
3728
                    new Field(
3729
                        array(
3730
                            'fieldDefIdentifier' => 'identifier1',
3731
                            'value' => 'newValue1',
3732
                            'languageCode' => null,
3733
                        )
3734
                    ),
3735
                    new Field(
3736
                        array(
3737
                            'fieldDefIdentifier' => 'identifier1',
3738
                            'value' => 'newValue2',
3739
                            'languageCode' => 'eng-GB',
3740
                        )
3741
                    ),
3742
                ),
3743
                $spiFields1,
3744
            ),
3745
            // 4. New language and existing language with untranslatable field, with language set
3746
            array(
3747
                'eng-US',
3748
                array(
3749
                    new Field(
3750
                        array(
3751
                            'fieldDefIdentifier' => 'identifier1',
3752
                            'value' => 'newValue1',
3753
                            'languageCode' => 'eng-US',
3754
                        )
3755
                    ),
3756
                    new Field(
3757
                        array(
3758
                            'fieldDefIdentifier' => 'identifier1',
3759
                            'value' => 'newValue2',
3760
                            'languageCode' => 'eng-GB',
3761
                        )
3762
                    ),
3763
                    new Field(
3764
                        array(
3765
                            'fieldDefIdentifier' => 'identifier2',
3766
                            'value' => 'newValue3',
3767
                            'languageCode' => 'eng-GB',
3768
                        )
3769
                    ),
3770
                ),
3771
                $spiFields2,
3772
            ),
3773
            // 5. New language and existing language with untranslatable field, without language set
3774
            array(
3775
                'eng-US',
3776
                array(
3777
                    new Field(
3778
                        array(
3779
                            'fieldDefIdentifier' => 'identifier1',
3780
                            'value' => 'newValue1',
3781
                            'languageCode' => null,
3782
                        )
3783
                    ),
3784
                    new Field(
3785
                        array(
3786
                            'fieldDefIdentifier' => 'identifier1',
3787
                            'value' => 'newValue2',
3788
                            'languageCode' => 'eng-GB',
3789
                        )
3790
                    ),
3791
                    new Field(
3792
                        array(
3793
                            'fieldDefIdentifier' => 'identifier2',
3794
                            'value' => 'newValue3',
3795
                            'languageCode' => null,
3796
                        )
3797
                    ),
3798
                ),
3799
                $spiFields2,
3800
            ),
3801
            // 6. Adding new language without fields
3802
            array(
3803
                'eng-US',
3804
                array(),
3805
                $spiFields3,
3806
            ),
3807
        );
3808
    }
3809
3810
    /**
3811
     * Test for the updateContent() method.
3812
     *
3813
     * Testing with new language and untranslatable field.
3814
     *
3815
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
3816
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
3817
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
3818
     * @dataProvider providerForTestUpdateContentNonRedundantFieldSet3
3819
     */
3820
    public function testUpdateContentNonRedundantFieldSet3($initialLanguageCode, $structFields, $spiFields)
3821
    {
3822
        $existingFields = array(
3823
            new Field(
3824
                array(
3825
                    'id' => '100',
3826
                    'fieldDefIdentifier' => 'identifier1',
3827
                    'value' => 'initialValue1',
3828
                    'languageCode' => 'eng-GB',
3829
                )
3830
            ),
3831
            new Field(
3832
                array(
3833
                    'id' => '101',
3834
                    'fieldDefIdentifier' => 'identifier2',
3835
                    'value' => 'initialValue2',
3836
                    'languageCode' => 'eng-GB',
3837
                )
3838
            ),
3839
        );
3840
3841
        $fieldDefinitions = array(
3842
            new FieldDefinition(
3843
                array(
3844
                    'id' => 'fieldDefinitionId1',
3845
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
3846
                    'isTranslatable' => true,
3847
                    'identifier' => 'identifier1',
3848
                    'isRequired' => false,
3849
                    'defaultValue' => 'defaultValue1',
3850
                )
3851
            ),
3852
            new FieldDefinition(
3853
                array(
3854
                    'id' => 'fieldDefinitionId2',
3855
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
3856
                    'isTranslatable' => false,
3857
                    'identifier' => 'identifier2',
3858
                    'isRequired' => false,
3859
                    'defaultValue' => 'defaultValue2',
3860
                )
3861
            ),
3862
        );
3863
3864
        $this->assertForTestUpdateContentNonRedundantFieldSet(
3865
            $initialLanguageCode,
3866
            $structFields,
3867
            $spiFields,
3868
            $existingFields,
3869
            $fieldDefinitions
3870
        );
3871
    }
3872
3873
    public function providerForTestUpdateContentNonRedundantFieldSet4()
3874
    {
3875
        $spiFields0 = array(
3876
            new SPIField(
3877
                array(
3878
                    'id' => null,
3879
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3880
                    'type' => 'fieldTypeIdentifier',
3881
                    'value' => 'newValue1',
3882
                    'languageCode' => 'eng-US',
3883
                    'versionNo' => 7,
3884
                )
3885
            ),
3886
        );
3887
        $spiFields1 = array(
3888
            new SPIField(
3889
                array(
3890
                    'id' => 100,
3891
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3892
                    'type' => 'fieldTypeIdentifier',
3893
                    'value' => self::EMPTY_FIELD_VALUE,
3894
                    'languageCode' => 'eng-GB',
3895
                    'versionNo' => 7,
3896
                )
3897
            ),
3898
            new SPIField(
3899
                array(
3900
                    'id' => null,
3901
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3902
                    'type' => 'fieldTypeIdentifier',
3903
                    'value' => 'newValue1',
3904
                    'languageCode' => 'eng-US',
3905
                    'versionNo' => 7,
3906
                )
3907
            ),
3908
        );
3909
        $spiFields2 = array(
3910
            new SPIField(
3911
                array(
3912
                    'id' => 100,
3913
                    'fieldDefinitionId' => 'fieldDefinitionId1',
3914
                    'type' => 'fieldTypeIdentifier',
3915
                    'value' => self::EMPTY_FIELD_VALUE,
3916
                    'languageCode' => 'eng-GB',
3917
                    'versionNo' => 7,
3918
                )
3919
            ),
3920
        );
3921
3922
        return array(
3923
            // 0. New translation with empty field by default
3924
            array(
3925
                'eng-US',
3926
                array(
3927
                    new Field(
3928
                        array(
3929
                            'fieldDefIdentifier' => 'identifier1',
3930
                            'value' => 'newValue1',
3931
                            'languageCode' => 'eng-US',
3932
                        )
3933
                    ),
3934
                ),
3935
                $spiFields0,
3936
            ),
3937
            // 1. New translation with empty field by default, without language set
3938
            array(
3939
                'eng-US',
3940
                array(
3941
                    new Field(
3942
                        array(
3943
                            'fieldDefIdentifier' => 'identifier1',
3944
                            'value' => 'newValue1',
3945
                            'languageCode' => null,
3946
                        )
3947
                    ),
3948
                ),
3949
                $spiFields0,
3950
            ),
3951
            // 2. New translation with empty field given
3952
            array(
3953
                'eng-US',
3954
                array(
3955
                    new Field(
3956
                        array(
3957
                            'fieldDefIdentifier' => 'identifier1',
3958
                            'value' => 'newValue1',
3959
                            'languageCode' => 'eng-US',
3960
                        )
3961
                    ),
3962
                    new Field(
3963
                        array(
3964
                            'fieldDefIdentifier' => 'identifier2',
3965
                            'value' => self::EMPTY_FIELD_VALUE,
3966
                            'languageCode' => 'eng-US',
3967
                        )
3968
                    ),
3969
                ),
3970
                $spiFields0,
3971
            ),
3972
            // 3. New translation with empty field given, without language set
3973
            array(
3974
                'eng-US',
3975
                array(
3976
                    new Field(
3977
                        array(
3978
                            'fieldDefIdentifier' => 'identifier1',
3979
                            'value' => 'newValue1',
3980
                            'languageCode' => null,
3981
                        )
3982
                    ),
3983
                    new Field(
3984
                        array(
3985
                            'fieldDefIdentifier' => 'identifier2',
3986
                            'value' => self::EMPTY_FIELD_VALUE,
3987
                            'languageCode' => null,
3988
                        )
3989
                    ),
3990
                ),
3991
                $spiFields0,
3992
            ),
3993
            // 4. Updating existing language with empty value
3994
            array(
3995
                'eng-US',
3996
                array(
3997
                    new Field(
3998
                        array(
3999
                            'fieldDefIdentifier' => 'identifier1',
4000
                            'value' => 'newValue1',
4001
                            'languageCode' => 'eng-US',
4002
                        )
4003
                    ),
4004
                    new Field(
4005
                        array(
4006
                            'fieldDefIdentifier' => 'identifier1',
4007
                            'value' => self::EMPTY_FIELD_VALUE,
4008
                            'languageCode' => 'eng-GB',
4009
                        )
4010
                    ),
4011
                ),
4012
                $spiFields1,
4013
            ),
4014
            // 5. Updating existing language with empty value, without language set
4015
            array(
4016
                'eng-US',
4017
                array(
4018
                    new Field(
4019
                        array(
4020
                            'fieldDefIdentifier' => 'identifier1',
4021
                            'value' => 'newValue1',
4022
                            'languageCode' => null,
4023
                        )
4024
                    ),
4025
                    new Field(
4026
                        array(
4027
                            'fieldDefIdentifier' => 'identifier1',
4028
                            'value' => self::EMPTY_FIELD_VALUE,
4029
                            'languageCode' => 'eng-GB',
4030
                        )
4031
                    ),
4032
                ),
4033
                $spiFields1,
4034
            ),
4035
            // 6. Updating existing language with empty value and adding new language with empty value
4036
            array(
4037
                'eng-US',
4038
                array(
4039
                    new Field(
4040
                        array(
4041
                            'fieldDefIdentifier' => 'identifier1',
4042
                            'value' => self::EMPTY_FIELD_VALUE,
4043
                            'languageCode' => 'eng-US',
4044
                        )
4045
                    ),
4046
                    new Field(
4047
                        array(
4048
                            'fieldDefIdentifier' => 'identifier1',
4049
                            'value' => self::EMPTY_FIELD_VALUE,
4050
                            'languageCode' => 'eng-GB',
4051
                        )
4052
                    ),
4053
                ),
4054
                $spiFields2,
4055
            ),
4056
            // 7. Updating existing language with empty value and adding new language with empty value,
4057
            // without language set
4058
            array(
4059
                'eng-US',
4060
                array(
4061
                    new Field(
4062
                        array(
4063
                            'fieldDefIdentifier' => 'identifier1',
4064
                            'value' => self::EMPTY_FIELD_VALUE,
4065
                            'languageCode' => null,
4066
                        )
4067
                    ),
4068
                    new Field(
4069
                        array(
4070
                            'fieldDefIdentifier' => 'identifier1',
4071
                            'value' => self::EMPTY_FIELD_VALUE,
4072
                            'languageCode' => 'eng-GB',
4073
                        )
4074
                    ),
4075
                ),
4076
                $spiFields2,
4077
            ),
4078
            // 8. Adding new language with no fields given
4079
            array(
4080
                'eng-US',
4081
                array(),
4082
                array(),
4083
            ),
4084
            // 9. Adding new language with fields
4085
            array(
4086
                'eng-US',
4087
                array(
4088
                    new Field(
4089
                        array(
4090
                            'fieldDefIdentifier' => 'identifier1',
4091
                            'value' => self::EMPTY_FIELD_VALUE,
4092
                            'languageCode' => 'eng-US',
4093
                        )
4094
                    ),
4095
                ),
4096
                array(),
4097
            ),
4098
            // 10. Adding new language with fields, without language set
4099
            array(
4100
                'eng-US',
4101
                array(
4102
                    new Field(
4103
                        array(
4104
                            'fieldDefIdentifier' => 'identifier1',
4105
                            'value' => self::EMPTY_FIELD_VALUE,
4106
                            'languageCode' => null,
4107
                        )
4108
                    ),
4109
                ),
4110
                array(),
4111
            ),
4112
        );
4113
    }
4114
4115
    /**
4116
     * Test for the updateContent() method.
4117
     *
4118
     * Testing with empty values.
4119
     *
4120
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
4121
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
4122
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
4123
     * @dataProvider providerForTestUpdateContentNonRedundantFieldSet4
4124
     */
4125
    public function testUpdateContentNonRedundantFieldSet4($initialLanguageCode, $structFields, $spiFields)
4126
    {
4127
        $existingFields = array(
4128
            new Field(
4129
                array(
4130
                    'id' => '100',
4131
                    'fieldDefIdentifier' => 'identifier1',
4132
                    'value' => 'initialValue1',
4133
                    'languageCode' => 'eng-GB',
4134
                )
4135
            ),
4136
            new Field(
4137
                array(
4138
                    'id' => '101',
4139
                    'fieldDefIdentifier' => 'identifier2',
4140
                    'value' => 'initialValue2',
4141
                    'languageCode' => 'eng-GB',
4142
                )
4143
            ),
4144
        );
4145
4146
        $fieldDefinitions = array(
4147
            new FieldDefinition(
4148
                array(
4149
                    'id' => 'fieldDefinitionId1',
4150
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4151
                    'isTranslatable' => true,
4152
                    'identifier' => 'identifier1',
4153
                    'isRequired' => false,
4154
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
4155
                )
4156
            ),
4157
            new FieldDefinition(
4158
                array(
4159
                    'id' => 'fieldDefinitionId2',
4160
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4161
                    'isTranslatable' => true,
4162
                    'identifier' => 'identifier2',
4163
                    'isRequired' => false,
4164
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
4165
                )
4166
            ),
4167
        );
4168
4169
        $this->assertForTestUpdateContentNonRedundantFieldSet(
4170
            $initialLanguageCode,
4171
            $structFields,
4172
            $spiFields,
4173
            $existingFields,
4174
            $fieldDefinitions
4175
        );
4176
    }
4177
4178
    /**
4179
     * @todo add first field empty
4180
     *
4181
     * @return array
4182
     */
4183
    public function providerForTestUpdateContentNonRedundantFieldSetComplex()
4184
    {
4185
        $spiFields0 = array(
4186
            new SPIField(
4187
                array(
4188
                    'id' => 100,
4189
                    'fieldDefinitionId' => 'fieldDefinitionId1',
4190
                    'type' => 'fieldTypeIdentifier',
4191
                    'value' => 'newValue1-eng-GB',
4192
                    'languageCode' => 'eng-GB',
4193
                    'versionNo' => 7,
4194
                )
4195
            ),
4196
            new SPIField(
4197
                array(
4198
                    'id' => null,
4199
                    'fieldDefinitionId' => 'fieldDefinitionId4',
4200
                    'type' => 'fieldTypeIdentifier',
4201
                    'value' => 'newValue4',
4202
                    'languageCode' => 'eng-US',
4203
                    'versionNo' => 7,
4204
                )
4205
            ),
4206
        );
4207
        $spiFields1 = array(
4208
            new SPIField(
4209
                array(
4210
                    'id' => 100,
4211
                    'fieldDefinitionId' => 'fieldDefinitionId1',
4212
                    'type' => 'fieldTypeIdentifier',
4213
                    'value' => 'newValue1-eng-GB',
4214
                    'languageCode' => 'eng-GB',
4215
                    'versionNo' => 7,
4216
                )
4217
            ),
4218
            new SPIField(
4219
                array(
4220
                    'id' => null,
4221
                    'fieldDefinitionId' => 'fieldDefinitionId2',
4222
                    'type' => 'fieldTypeIdentifier',
4223
                    'value' => 'newValue2',
4224
                    'languageCode' => 'eng-US',
4225
                    'versionNo' => 7,
4226
                )
4227
            ),
4228
            new SPIField(
4229
                array(
4230
                    'id' => null,
4231
                    'fieldDefinitionId' => 'fieldDefinitionId4',
4232
                    'type' => 'fieldTypeIdentifier',
4233
                    'value' => 'defaultValue4',
4234
                    'languageCode' => 'eng-US',
4235
                    'versionNo' => 7,
4236
                )
4237
            ),
4238
        );
4239
        $spiFields2 = array(
4240
            new SPIField(
4241
                array(
4242
                    'id' => 100,
4243
                    'fieldDefinitionId' => 'fieldDefinitionId1',
4244
                    'type' => 'fieldTypeIdentifier',
4245
                    'value' => 'newValue1-eng-GB',
4246
                    'languageCode' => 'eng-GB',
4247
                    'versionNo' => 7,
4248
                )
4249
            ),
4250
            new SPIField(
4251
                array(
4252
                    'id' => null,
4253
                    'fieldDefinitionId' => 'fieldDefinitionId2',
4254
                    'type' => 'fieldTypeIdentifier',
4255
                    'value' => 'newValue2',
4256
                    'languageCode' => 'eng-US',
4257
                    'versionNo' => 7,
4258
                )
4259
            ),
4260
            new SPIField(
4261
                array(
4262
                    'id' => null,
4263
                    'fieldDefinitionId' => 'fieldDefinitionId4',
4264
                    'type' => 'fieldTypeIdentifier',
4265
                    'value' => 'defaultValue4',
4266
                    'languageCode' => 'ger-DE',
4267
                    'versionNo' => 7,
4268
                )
4269
            ),
4270
            new SPIField(
4271
                array(
4272
                    'id' => null,
4273
                    'fieldDefinitionId' => 'fieldDefinitionId4',
4274
                    'type' => 'fieldTypeIdentifier',
4275
                    'value' => 'defaultValue4',
4276
                    'languageCode' => 'eng-US',
4277
                    'versionNo' => 7,
4278
                )
4279
            ),
4280
        );
4281
4282
        return array(
4283
            // 0. Add new language and update existing
4284
            array(
4285
                'eng-US',
4286
                array(
4287
                    new Field(
4288
                        array(
4289
                            'fieldDefIdentifier' => 'identifier4',
4290
                            'value' => 'newValue4',
4291
                            'languageCode' => 'eng-US',
4292
                        )
4293
                    ),
4294
                    new Field(
4295
                        array(
4296
                            'fieldDefIdentifier' => 'identifier1',
4297
                            'value' => 'newValue1-eng-GB',
4298
                            'languageCode' => 'eng-GB',
4299
                        )
4300
                    ),
4301
                ),
4302
                $spiFields0,
4303
            ),
4304
            // 1. Add new language and update existing, without language set
4305
            array(
4306
                'eng-US',
4307
                array(
4308
                    new Field(
4309
                        array(
4310
                            'fieldDefIdentifier' => 'identifier4',
4311
                            'value' => 'newValue4',
4312
                            'languageCode' => null,
4313
                        )
4314
                    ),
4315
                    new Field(
4316
                        array(
4317
                            'fieldDefIdentifier' => 'identifier1',
4318
                            'value' => 'newValue1-eng-GB',
4319
                            'languageCode' => 'eng-GB',
4320
                        )
4321
                    ),
4322
                ),
4323
                $spiFields0,
4324
            ),
4325
            // 2. Add new language and update existing variant
4326
            array(
4327
                'eng-US',
4328
                array(
4329
                    new Field(
4330
                        array(
4331
                            'fieldDefIdentifier' => 'identifier2',
4332
                            'value' => 'newValue2',
4333
                            'languageCode' => 'eng-US',
4334
                        )
4335
                    ),
4336
                    new Field(
4337
                        array(
4338
                            'fieldDefIdentifier' => 'identifier1',
4339
                            'value' => 'newValue1-eng-GB',
4340
                            'languageCode' => 'eng-GB',
4341
                        )
4342
                    ),
4343
                ),
4344
                $spiFields1,
4345
            ),
4346
            // 3. Add new language and update existing variant, without language set
4347
            array(
4348
                'eng-US',
4349
                array(
4350
                    new Field(
4351
                        array(
4352
                            'fieldDefIdentifier' => 'identifier2',
4353
                            'value' => 'newValue2',
4354
                            'languageCode' => null,
4355
                        )
4356
                    ),
4357
                    new Field(
4358
                        array(
4359
                            'fieldDefIdentifier' => 'identifier1',
4360
                            'value' => 'newValue1-eng-GB',
4361
                            'languageCode' => 'eng-GB',
4362
                        )
4363
                    ),
4364
                ),
4365
                $spiFields1,
4366
            ),
4367
            // 4. Update with multiple languages
4368
            array(
4369
                'ger-DE',
4370
                array(
4371
                    new Field(
4372
                        array(
4373
                            'fieldDefIdentifier' => 'identifier2',
4374
                            'value' => 'newValue2',
4375
                            'languageCode' => 'eng-US',
4376
                        )
4377
                    ),
4378
                    new Field(
4379
                        array(
4380
                            'fieldDefIdentifier' => 'identifier1',
4381
                            'value' => 'newValue1-eng-GB',
4382
                            'languageCode' => 'eng-GB',
4383
                        )
4384
                    ),
4385
                ),
4386
                $spiFields2,
4387
            ),
4388
            // 5. Update with multiple languages without language set
4389
            array(
4390
                'ger-DE',
4391
                array(
4392
                    new Field(
4393
                        array(
4394
                            'fieldDefIdentifier' => 'identifier2',
4395
                            'value' => 'newValue2',
4396
                            'languageCode' => 'eng-US',
4397
                        )
4398
                    ),
4399
                    new Field(
4400
                        array(
4401
                            'fieldDefIdentifier' => 'identifier1',
4402
                            'value' => 'newValue1-eng-GB',
4403
                            'languageCode' => null,
4404
                        )
4405
                    ),
4406
                ),
4407
                $spiFields2,
4408
            ),
4409
        );
4410
    }
4411
4412
    protected function fixturesForTestUpdateContentNonRedundantFieldSetComplex()
4413
    {
4414
        $existingFields = array(
4415
            new Field(
4416
                array(
4417
                    'id' => '100',
4418
                    'fieldDefIdentifier' => 'identifier1',
4419
                    'value' => 'initialValue1',
4420
                    'languageCode' => 'eng-GB',
4421
                )
4422
            ),
4423
            new Field(
4424
                array(
4425
                    'id' => '101',
4426
                    'fieldDefIdentifier' => 'identifier2',
4427
                    'value' => 'initialValue2',
4428
                    'languageCode' => 'eng-GB',
4429
                )
4430
            ),
4431
            new Field(
4432
                array(
4433
                    'id' => '102',
4434
                    'fieldDefIdentifier' => 'identifier3',
4435
                    'value' => 'initialValue3',
4436
                    'languageCode' => 'eng-GB',
4437
                )
4438
            ),
4439
            new Field(
4440
                array(
4441
                    'id' => '103',
4442
                    'fieldDefIdentifier' => 'identifier4',
4443
                    'value' => 'initialValue4',
4444
                    'languageCode' => 'eng-GB',
4445
                )
4446
            ),
4447
        );
4448
4449
        $fieldDefinitions = array(
4450
            new FieldDefinition(
4451
                array(
4452
                    'id' => 'fieldDefinitionId1',
4453
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4454
                    'isTranslatable' => false,
4455
                    'identifier' => 'identifier1',
4456
                    'isRequired' => false,
4457
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
4458
                )
4459
            ),
4460
            new FieldDefinition(
4461
                array(
4462
                    'id' => 'fieldDefinitionId2',
4463
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4464
                    'isTranslatable' => true,
4465
                    'identifier' => 'identifier2',
4466
                    'isRequired' => false,
4467
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
4468
                )
4469
            ),
4470
            new FieldDefinition(
4471
                array(
4472
                    'id' => 'fieldDefinitionId3',
4473
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4474
                    'isTranslatable' => false,
4475
                    'identifier' => 'identifier3',
4476
                    'isRequired' => false,
4477
                    'defaultValue' => 'defaultValue3',
4478
                )
4479
            ),
4480
            new FieldDefinition(
4481
                array(
4482
                    'id' => 'fieldDefinitionId4',
4483
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4484
                    'isTranslatable' => true,
4485
                    'identifier' => 'identifier4',
4486
                    'isRequired' => false,
4487
                    'defaultValue' => 'defaultValue4',
4488
                )
4489
            ),
4490
        );
4491
4492
        return array($existingFields, $fieldDefinitions);
4493
    }
4494
4495
    /**
4496
     * Test for the updateContent() method.
4497
     *
4498
     * Testing more complex cases.
4499
     *
4500
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
4501
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
4502
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
4503
     * @dataProvider providerForTestUpdateContentNonRedundantFieldSetComplex
4504
     */
4505
    public function testUpdateContentNonRedundantFieldSetComplex($initialLanguageCode, $structFields, $spiFields)
4506
    {
4507
        list($existingFields, $fieldDefinitions) = $this->fixturesForTestUpdateContentNonRedundantFieldSetComplex();
4508
4509
        $this->assertForTestUpdateContentNonRedundantFieldSet(
4510
            $initialLanguageCode,
4511
            $structFields,
4512
            $spiFields,
4513
            $existingFields,
4514
            $fieldDefinitions
4515
        );
4516
    }
4517
4518 View Code Duplication
    public function providerForTestUpdateContentWithInvalidLanguage()
4519
    {
4520
        return array(
4521
            array(
4522
                'eng-GB',
4523
                array(
4524
                    new Field(
4525
                        array(
4526
                            'fieldDefIdentifier' => 'identifier',
4527
                            'value' => 'newValue',
4528
                            'languageCode' => 'Klingon',
4529
                        )
4530
                    ),
4531
                ),
4532
            ),
4533
            array(
4534
                'Klingon',
4535
                array(
4536
                    new Field(
4537
                        array(
4538
                            'fieldDefIdentifier' => 'identifier',
4539
                            'value' => 'newValue',
4540
                            'languageCode' => 'eng-GB',
4541
                        )
4542
                    ),
4543
                ),
4544
            ),
4545
        );
4546
    }
4547
4548
    /**
4549
     * Test for the updateContent() method.
4550
     *
4551
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
4552
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
4553
     * @dataProvider providerForTestUpdateContentWithInvalidLanguage
4554
     * @expectedException \eZ\Publish\API\Repository\Exceptions\NotFoundException
4555
     * @expectedExceptionMessage Could not find 'Language' with identifier 'Klingon'
4556
     */
4557
    public function testUpdateContentWithInvalidLanguage($initialLanguageCode, $structFields)
4558
    {
4559
        $repositoryMock = $this->getRepositoryMock();
4560
        $mockedService = $this->getPartlyMockedContentService(array('loadContent'));
4561
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
4562
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
4563
        $versionInfo = new VersionInfo(
4564
            array(
4565
                'contentInfo' => new ContentInfo(
4566
                    array(
4567
                        'id' => 42,
4568
                        'contentTypeId' => 24,
4569
                        'mainLanguageCode' => 'eng-GB',
4570
                    )
4571
                ),
4572
                'versionNo' => 7,
4573
                'languageCodes' => array('eng-GB'),
4574
                'status' => VersionInfo::STATUS_DRAFT,
4575
            )
4576
        );
4577
        $content = new Content(
4578
            array(
4579
                'versionInfo' => $versionInfo,
4580
                'internalFields' => array(),
4581
            )
4582
        );
4583
4584
        $languageHandlerMock->expects($this->any())
4585
            ->method('loadByLanguageCode')
4586
            ->with($this->isType('string'))
4587
            ->will(
4588
                $this->returnCallback(
4589 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...
4590
                        if ($languageCode === 'Klingon') {
4591
                            throw new NotFoundException('Language', 'Klingon');
4592
                        }
4593
4594
                        return new Language(array('id' => 4242));
4595
                    }
4596
                )
4597
            );
4598
4599
        $mockedService->expects($this->once())
4600
            ->method('loadContent')
4601
            ->with(
4602
                $this->equalTo(42),
4603
                $this->equalTo(null),
4604
                $this->equalTo(7)
4605
            )->will(
4606
                $this->returnValue($content)
4607
            );
4608
4609
        $repositoryMock->expects($this->once())
4610
            ->method('canUser')
4611
            ->with(
4612
                $this->equalTo('content'),
4613
                $this->equalTo('edit'),
4614
                $this->equalTo($content)
4615
            )->will($this->returnValue(true));
4616
4617
        $contentUpdateStruct = new ContentUpdateStruct(
4618
            array(
4619
                'fields' => $structFields,
4620
                'initialLanguageCode' => $initialLanguageCode,
4621
            )
4622
        );
4623
4624
        $mockedService->updateContent($content->versionInfo, $contentUpdateStruct);
4625
    }
4626
4627
    protected function assertForUpdateContentContentValidationException(
4628
        $initialLanguageCode,
4629
        $structFields,
4630
        $fieldDefinitions = array()
4631
    ) {
4632
        $repositoryMock = $this->getRepositoryMock();
4633
        $mockedService = $this->getPartlyMockedContentService(array('loadContent'));
4634
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
4635
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
4636
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
4637
        $versionInfo = new VersionInfo(
4638
            array(
4639
                'contentInfo' => new ContentInfo(
4640
                    array(
4641
                        'id' => 42,
4642
                        'contentTypeId' => 24,
4643
                        'mainLanguageCode' => 'eng-GB',
4644
                    )
4645
                ),
4646
                'versionNo' => 7,
4647
                'languageCodes' => array('eng-GB'),
4648
                'status' => VersionInfo::STATUS_DRAFT,
4649
            )
4650
        );
4651
        $content = new Content(
4652
            array(
4653
                'versionInfo' => $versionInfo,
4654
                'internalFields' => array(),
4655
            )
4656
        );
4657
        $contentType = new ContentType(array('fieldDefinitions' => $fieldDefinitions));
4658
4659
        $languageHandlerMock->expects($this->any())
4660
            ->method('loadByLanguageCode')
4661
            ->with($this->isType('string'))
4662
            ->will(
4663
                $this->returnCallback(
4664 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...
4665
                        if ($languageCode === 'Klingon') {
4666
                            throw new NotFoundException('Language', 'Klingon');
4667
                        }
4668
4669
                        return new Language(array('id' => 4242));
4670
                    }
4671
                )
4672
            );
4673
4674
        $mockedService->expects($this->once())
4675
            ->method('loadContent')
4676
            ->with(
4677
                $this->equalTo(42),
4678
                $this->equalTo(null),
4679
                $this->equalTo(7)
4680
            )->will(
4681
                $this->returnValue($content)
4682
            );
4683
4684
        $repositoryMock->expects($this->once())
4685
            ->method('canUser')
4686
            ->with(
4687
                $this->equalTo('content'),
4688
                $this->equalTo('edit'),
4689
                $this->equalTo($content)
4690
            )->will($this->returnValue(true));
4691
4692
        $contentTypeServiceMock->expects($this->once())
4693
            ->method('loadContentType')
4694
            ->with($this->equalTo(24))
4695
            ->will($this->returnValue($contentType));
4696
4697
        $repositoryMock->expects($this->once())
4698
            ->method('getContentTypeService')
4699
            ->will($this->returnValue($contentTypeServiceMock));
4700
4701
        $contentUpdateStruct = new ContentUpdateStruct(
4702
            array(
4703
                'fields' => $structFields,
4704
                'initialLanguageCode' => $initialLanguageCode,
4705
            )
4706
        );
4707
4708
        $mockedService->updateContent($content->versionInfo, $contentUpdateStruct);
4709
    }
4710
4711 View Code Duplication
    public function providerForTestUpdateContentThrowsContentValidationExceptionFieldDefinition()
4712
    {
4713
        return array(
4714
            array(
4715
                'eng-GB',
4716
                array(
4717
                    new Field(
4718
                        array(
4719
                            'fieldDefIdentifier' => 'identifier',
4720
                            'value' => 'newValue',
4721
                            'languageCode' => 'eng-GB',
4722
                        )
4723
                    ),
4724
                ),
4725
            ),
4726
        );
4727
    }
4728
4729
    /**
4730
     * Test for the updateContent() method.
4731
     *
4732
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
4733
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
4734
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
4735
     * @dataProvider providerForTestUpdateContentThrowsContentValidationExceptionFieldDefinition
4736
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentValidationException
4737
     * @expectedExceptionMessage Field definition 'identifier' does not exist in given ContentType
4738
     */
4739
    public function testUpdateContentThrowsContentValidationExceptionFieldDefinition($initialLanguageCode, $structFields)
4740
    {
4741
        $this->assertForUpdateContentContentValidationException(
4742
            $initialLanguageCode,
4743
            $structFields,
4744
            array()
4745
        );
4746
    }
4747
4748 View Code Duplication
    public function providerForTestUpdateContentThrowsContentValidationExceptionTranslation()
4749
    {
4750
        return array(
4751
            array(
4752
                'eng-US',
4753
                array(
4754
                    new Field(
4755
                        array(
4756
                            'fieldDefIdentifier' => 'identifier',
4757
                            'value' => 'newValue',
4758
                            'languageCode' => 'eng-US',
4759
                        )
4760
                    ),
4761
                ),
4762
            ),
4763
        );
4764
    }
4765
4766
    /**
4767
     * Test for the updateContent() method.
4768
     *
4769
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
4770
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
4771
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
4772
     * @dataProvider providerForTestUpdateContentThrowsContentValidationExceptionTranslation
4773
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentValidationException
4774
     * @expectedExceptionMessage A value is set for non translatable field definition 'identifier' with language 'eng-US'
4775
     */
4776 View Code Duplication
    public function testUpdateContentThrowsContentValidationExceptionTranslation($initialLanguageCode, $structFields)
4777
    {
4778
        $fieldDefinitions = array(
4779
            new FieldDefinition(
4780
                array(
4781
                    'id' => 'fieldDefinitionId1',
4782
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4783
                    'isTranslatable' => false,
4784
                    'identifier' => 'identifier',
4785
                    'isRequired' => false,
4786
                    'defaultValue' => self::EMPTY_FIELD_VALUE,
4787
                )
4788
            ),
4789
        );
4790
4791
        $this->assertForUpdateContentContentValidationException(
4792
            $initialLanguageCode,
4793
            $structFields,
4794
            $fieldDefinitions
4795
        );
4796
    }
4797
4798
    public function assertForTestUpdateContentThrowsContentValidationExceptionRequiredField(
4799
        $initialLanguageCode,
4800
        $structFields,
4801
        $existingFields,
4802
        $fieldDefinitions
4803
    ) {
4804
        $repositoryMock = $this->getRepositoryMock();
4805
        $mockedService = $this->getPartlyMockedContentService(array('loadContent'));
4806
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
4807
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
4808
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
4809
        $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...
4810
        $fieldTypeMock = $this->getMock('eZ\\Publish\\SPI\\FieldType\\FieldType');
4811
        $existingLanguageCodes = array_map(
4812
            function (Field $field) {
4813
                return $field->languageCode;
4814
            },
4815
            $existingFields
4816
        );
4817
        $versionInfo = new VersionInfo(
4818
            array(
4819
                'contentInfo' => new ContentInfo(
4820
                    array(
4821
                        'id' => 42,
4822
                        'contentTypeId' => 24,
4823
                        'mainLanguageCode' => 'eng-GB',
4824
                    )
4825
                ),
4826
                'versionNo' => 7,
4827
                'languageCodes' => $existingLanguageCodes,
4828
                'status' => VersionInfo::STATUS_DRAFT,
4829
            )
4830
        );
4831
        $content = new Content(
4832
            array(
4833
                'versionInfo' => $versionInfo,
4834
                'internalFields' => $existingFields,
4835
            )
4836
        );
4837
        $contentType = new ContentType(array('fieldDefinitions' => $fieldDefinitions));
4838
4839
        $languageHandlerMock->expects($this->any())
4840
            ->method('loadByLanguageCode')
4841
            ->with($this->isType('string'))
4842
            ->will(
4843
                $this->returnCallback(
4844
                    function () {
4845
                        return new Language(array('id' => 4242));
4846
                    }
4847
                )
4848
            );
4849
4850
        $mockedService->expects($this->once())
4851
            ->method('loadContent')
4852
            ->with(
4853
                $this->equalTo(42),
4854
                $this->equalTo(null),
4855
                $this->equalTo(7)
4856
            )->will(
4857
                $this->returnValue($content)
4858
            );
4859
4860
        $repositoryMock->expects($this->once())
4861
            ->method('canUser')
4862
            ->with(
4863
                $this->equalTo('content'),
4864
                $this->equalTo('edit'),
4865
                $this->equalTo($content)
4866
            )->will($this->returnValue(true));
4867
4868
        $contentTypeServiceMock->expects($this->once())
4869
            ->method('loadContentType')
4870
            ->with($this->equalTo(24))
4871
            ->will($this->returnValue($contentType));
4872
4873
        $repositoryMock->expects($this->once())
4874
            ->method('getContentTypeService')
4875
            ->will($this->returnValue($contentTypeServiceMock));
4876
4877
        $fieldTypeMock->expects($this->any())
4878
            ->method('acceptValue')
4879
            ->will(
4880
                $this->returnCallback(
4881
                    function ($valueString) {
4882
                        return new ValueStub($valueString);
4883
                    }
4884
                )
4885
            );
4886
4887
        $emptyValue = self::EMPTY_FIELD_VALUE;
4888
        $fieldTypeMock->expects($this->any())
4889
            ->method('isEmptyValue')
4890
            ->will(
4891
                $this->returnCallback(
4892
                    function (ValueStub $value) use ($emptyValue) {
4893
                        return $emptyValue === (string)$value;
4894
                    }
4895
                )
4896
            );
4897
4898
        $fieldTypeMock->expects($this->any())
4899
            ->method('validate')
4900
            ->with(
4901
                $this->isInstanceOf('eZ\\Publish\\API\\Repository\\Values\\ContentType\\FieldDefinition'),
4902
                $this->isInstanceOf('eZ\\Publish\\Core\\FieldType\\Value')
4903
            );
4904
4905
        $this->getFieldTypeRegistryMock()->expects($this->any())
4906
            ->method('getFieldType')
4907
            ->will($this->returnValue($fieldTypeMock));
4908
4909
        $contentUpdateStruct = new ContentUpdateStruct(
4910
            array(
4911
                'fields' => $structFields,
4912
                'initialLanguageCode' => $initialLanguageCode,
4913
            )
4914
        );
4915
4916
        return array($content->versionInfo, $contentUpdateStruct);
4917
    }
4918
4919 View Code Duplication
    public function providerForTestUpdateContentThrowsContentValidationExceptionRequiredField()
4920
    {
4921
        return array(
4922
            array(
4923
                'eng-US',
4924
                array(
4925
                    new Field(
4926
                        array(
4927
                            'fieldDefIdentifier' => 'identifier',
4928
                            'value' => self::EMPTY_FIELD_VALUE,
4929
                            'languageCode' => null,
4930
                        )
4931
                    ),
4932
                ),
4933
                'identifier',
4934
                'eng-US',
4935
            ),
4936
        );
4937
    }
4938
4939
    /**
4940
     * Test for the updateContent() method.
4941
     *
4942
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
4943
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
4944
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
4945
     * @dataProvider providerForTestUpdateContentThrowsContentValidationExceptionRequiredField
4946
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentValidationException
4947
     */
4948
    public function testUpdateContentThrowsContentValidationExceptionRequiredField(
4949
        $initialLanguageCode,
4950
        $structFields,
4951
        $identifier,
4952
        $languageCode
4953
    ) {
4954
        $existingFields = array(
4955
            new Field(
4956
                array(
4957
                    'id' => '100',
4958
                    'fieldDefIdentifier' => 'identifier',
4959
                    'value' => 'initialValue',
4960
                    'languageCode' => 'eng-GB',
4961
                )
4962
            ),
4963
        );
4964
        $fieldDefinitions = array(
4965
            new FieldDefinition(
4966
                array(
4967
                    'id' => 'fieldDefinitionId',
4968
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
4969
                    'isTranslatable' => true,
4970
                    'identifier' => 'identifier',
4971
                    'isRequired' => true,
4972
                    'defaultValue' => 'defaultValue',
4973
                )
4974
            ),
4975
        );
4976
        list($versionInfo, $contentUpdateStruct) =
4977
            $this->assertForTestUpdateContentThrowsContentValidationExceptionRequiredField(
4978
                $initialLanguageCode,
4979
                $structFields,
4980
                $existingFields,
4981
                $fieldDefinitions
4982
            );
4983
4984
        try {
4985
            $this->partlyMockedContentService->updateContent($versionInfo, $contentUpdateStruct);
4986
        } catch (ContentValidationException $e) {
4987
            $this->assertEquals(
4988
                "Value for required field definition '{$identifier}' with language '{$languageCode}' is empty",
4989
                $e->getMessage()
4990
            );
4991
4992
            throw $e;
4993
        }
4994
    }
4995
4996
    public function assertForTestUpdateContentThrowsContentFieldValidationException(
4997
        $initialLanguageCode,
4998
        $structFields,
4999
        $existingFields,
5000
        $fieldDefinitions
5001
    ) {
5002
        $repositoryMock = $this->getRepositoryMock();
5003
        $mockedService = $this->getPartlyMockedContentService(array('loadContent'));
5004
        /** @var \PHPUnit_Framework_MockObject_MockObject $languageHandlerMock */
5005
        $languageHandlerMock = $this->getPersistenceMock()->contentLanguageHandler();
5006
        $contentTypeServiceMock = $this->getContentTypeServiceMock();
5007
        $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...
5008
        $fieldTypeMock = $this->getMock('eZ\\Publish\\SPI\\FieldType\\FieldType');
5009
        $existingLanguageCodes = array_map(
5010
            function (Field $field) {
5011
                return $field->languageCode;
5012
            },
5013
            $existingFields
5014
        );
5015
        $languageCodes = $this->determineLanguageCodesForUpdate(
5016
            $initialLanguageCode,
5017
            $structFields,
5018
            $existingLanguageCodes
5019
        );
5020
        $versionInfo = new VersionInfo(
5021
            array(
5022
                'contentInfo' => new ContentInfo(
5023
                    array(
5024
                        'id' => 42,
5025
                        'contentTypeId' => 24,
5026
                        'mainLanguageCode' => 'eng-GB',
5027
                    )
5028
                ),
5029
                'versionNo' => 7,
5030
                'languageCodes' => $existingLanguageCodes,
5031
                'status' => VersionInfo::STATUS_DRAFT,
5032
            )
5033
        );
5034
        $content = new Content(
5035
            array(
5036
                'versionInfo' => $versionInfo,
5037
                'internalFields' => $existingFields,
5038
            )
5039
        );
5040
        $contentType = new ContentType(array('fieldDefinitions' => $fieldDefinitions));
5041
5042
        $languageHandlerMock->expects($this->any())
5043
            ->method('loadByLanguageCode')
5044
            ->with($this->isType('string'))
5045
            ->will(
5046
                $this->returnCallback(
5047
                    function () {
5048
                        return new Language(array('id' => 4242));
5049
                    }
5050
                )
5051
            );
5052
5053
        $mockedService->expects($this->once())
5054
            ->method('loadContent')
5055
            ->with(
5056
                $this->equalTo(42),
5057
                $this->equalTo(null),
5058
                $this->equalTo(7)
5059
            )->will(
5060
                $this->returnValue($content)
5061
            );
5062
5063
        $repositoryMock->expects($this->once())
5064
            ->method('canUser')
5065
            ->with(
5066
                $this->equalTo('content'),
5067
                $this->equalTo('edit'),
5068
                $this->equalTo($content)
5069
            )->will($this->returnValue(true));
5070
5071
        $contentTypeServiceMock->expects($this->once())
5072
            ->method('loadContentType')
5073
            ->with($this->equalTo(24))
5074
            ->will($this->returnValue($contentType));
5075
5076
        $repositoryMock->expects($this->once())
5077
            ->method('getContentTypeService')
5078
            ->will($this->returnValue($contentTypeServiceMock));
5079
5080
        $fieldValues = $this->determineValuesForUpdate(
5081
            $initialLanguageCode,
5082
            $structFields,
5083
            $content,
5084
            $fieldDefinitions,
5085
            $languageCodes
5086
        );
5087
        $allFieldErrors = array();
5088
        $validateCount = 0;
5089
        $emptyValue = self::EMPTY_FIELD_VALUE;
5090 View Code Duplication
        foreach ($contentType->getFieldDefinitions() as $fieldDefinition) {
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...
5091
            foreach ($fieldValues[$fieldDefinition->identifier] as $languageCode => $value) {
5092
                $fieldTypeMock->expects($this->at($validateCount++))
5093
                    ->method('acceptValue')
5094
                    ->will(
5095
                        $this->returnCallback(
5096
                            function ($valueString) {
5097
                                return new ValueStub($valueString);
5098
                            }
5099
                        )
5100
                    );
5101
5102
                $fieldTypeMock->expects($this->at($validateCount++))
5103
                    ->method('isEmptyValue')
5104
                    ->will(
5105
                        $this->returnCallback(
5106
                            function (ValueStub $value) use ($emptyValue) {
5107
                                return $emptyValue === (string)$value;
5108
                            }
5109
                        )
5110
                    );
5111
5112
                if (self::EMPTY_FIELD_VALUE === (string)$value) {
5113
                    continue;
5114
                }
5115
5116
                $fieldTypeMock->expects($this->at($validateCount++))
5117
                    ->method('validate')
5118
                    ->with(
5119
                        $this->equalTo($fieldDefinition),
5120
                        $this->equalTo($value)
5121
                    )->will($this->returnArgument(1));
5122
5123
                $allFieldErrors[$fieldDefinition->id][$languageCode] = $value;
5124
            }
5125
        }
5126
5127
        $this->getFieldTypeRegistryMock()->expects($this->any())
5128
            ->method('getFieldType')
5129
            ->will($this->returnValue($fieldTypeMock));
5130
5131
        $contentUpdateStruct = new ContentUpdateStruct(
5132
            array(
5133
                'fields' => $structFields,
5134
                'initialLanguageCode' => $initialLanguageCode,
5135
            )
5136
        );
5137
5138
        return array($content->versionInfo, $contentUpdateStruct, $allFieldErrors);
5139
    }
5140
5141
    public function providerForTestUpdateContentThrowsContentFieldValidationException()
5142
    {
5143
        return $this->providerForTestUpdateContentNonRedundantFieldSetComplex();
5144
    }
5145
5146
    /**
5147
     * Test for the updateContent() method.
5148
     *
5149
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
5150
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
5151
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
5152
     * @dataProvider providerForTestUpdateContentThrowsContentFieldValidationException
5153
     * @expectedException \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
5154
     * @expectedExceptionMessage Content fields did not validate
5155
     */
5156
    public function testUpdateContentThrowsContentFieldValidationException($initialLanguageCode, $structFields)
5157
    {
5158
        list($existingFields, $fieldDefinitions) = $this->fixturesForTestUpdateContentNonRedundantFieldSetComplex();
5159
        list($versionInfo, $contentUpdateStruct, $allFieldErrors) =
5160
            $this->assertForTestUpdateContentThrowsContentFieldValidationException(
5161
                $initialLanguageCode,
5162
                $structFields,
5163
                $existingFields,
5164
                $fieldDefinitions
5165
            );
5166
5167
        try {
5168
            $this->partlyMockedContentService->updateContent($versionInfo, $contentUpdateStruct);
5169
        } catch (ContentFieldValidationException $e) {
5170
            $this->assertEquals($allFieldErrors, $e->getFieldErrors());
5171
            throw $e;
5172
        }
5173
    }
5174
5175
    /**
5176
     * Test for the updateContent() method.
5177
     *
5178
     * @covers \eZ\Publish\Core\Repository\ContentService::getLanguageCodesForUpdate
5179
     * @covers \eZ\Publish\Core\Repository\ContentService::mapFieldsForUpdate
5180
     * @covers \eZ\Publish\Core\Repository\ContentService::updateContent
5181
     * @expectedException \Exception
5182
     * @expectedExceptionMessage Store failed
5183
     */
5184
    public function testUpdateContentTransactionRollback()
5185
    {
5186
        $existingFields = array(
5187
            new Field(
5188
                array(
5189
                    'id' => '100',
5190
                    'fieldDefIdentifier' => 'identifier',
5191
                    'value' => 'initialValue',
5192
                    'languageCode' => 'eng-GB',
5193
                )
5194
            ),
5195
        );
5196
5197
        $fieldDefinitions = array(
5198
            new FieldDefinition(
5199
                array(
5200
                    'id' => 'fieldDefinitionId',
5201
                    'fieldTypeIdentifier' => 'fieldTypeIdentifier',
5202
                    'isTranslatable' => false,
5203
                    'identifier' => 'identifier',
5204
                    'isRequired' => false,
5205
                    'defaultValue' => 'defaultValue',
5206
                )
5207
            ),
5208
        );
5209
5210
        // Setup a simple case that will pass
5211
        list($versionInfo, $contentUpdateStruct) = $this->assertForTestUpdateContentNonRedundantFieldSet(
5212
            'eng-US',
5213
            array(),
5214
            array(),
5215
            $existingFields,
5216
            $fieldDefinitions,
5217
            // Do not execute test
5218
            false
5219
        );
5220
5221
        $repositoryMock = $this->getRepositoryMock();
5222
        $repositoryMock->expects($this->never())->method('commit');
5223
        $repositoryMock->expects($this->once())->method('rollback');
5224
5225
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
5226
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
5227
        $contentHandlerMock->expects($this->once())
5228
            ->method('updateContent')
5229
            ->with(
5230
                $this->anything(),
5231
                $this->anything(),
5232
                $this->anything()
5233
            )->will($this->throwException(new \Exception('Store failed')));
5234
5235
        // Execute
5236
        $this->partlyMockedContentService->updateContent($versionInfo, $contentUpdateStruct);
5237
    }
5238
5239
    /**
5240
     * Test for the copyContent() method.
5241
     *
5242
     * @covers \eZ\Publish\Core\Repository\ContentService::copyContent
5243
     * @expectedException \eZ\Publish\Core\Base\Exceptions\UnauthorizedException
5244
     */
5245 View Code Duplication
    public function testCopyContentThrowsUnauthorizedException()
5246
    {
5247
        $repository = $this->getRepositoryMock();
5248
        $contentService = $this->getPartlyMockedContentService(array('internalLoadContentInfo'));
5249
        $contentInfo = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
5250
        $locationCreateStruct = new LocationCreateStruct();
5251
5252
        $contentInfo->expects($this->any())
5253
            ->method('__get')
5254
            ->with('sectionId')
5255
            ->will($this->returnValue(42));
5256
5257
        $repository->expects($this->once())
5258
            ->method('canUser')
5259
            ->with(
5260
                'content',
5261
                'create',
5262
                $contentInfo,
5263
                $locationCreateStruct
5264
            )
5265
            ->will($this->returnValue(false));
5266
5267
        /* @var \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo */
5268
        $contentService->copyContent($contentInfo, $locationCreateStruct);
5269
    }
5270
5271
    /**
5272
     * Test for the copyContent() method.
5273
     *
5274
     * @covers \eZ\Publish\Core\Repository\ContentService::copyContent
5275
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
5276
     * @covers \eZ\Publish\Core\Repository\ContentService::internalPublishVersion
5277
     */
5278
    public function testCopyContent()
5279
    {
5280
        $repositoryMock = $this->getRepositoryMock();
5281
        $contentService = $this->getPartlyMockedContentService(array('internalLoadContentInfo', 'internalLoadContent'));
5282
        $locationServiceMock = $this->getLocationServiceMock();
5283
        $contentInfoMock = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
5284
        $locationCreateStruct = new LocationCreateStruct();
5285
5286
        $repositoryMock->expects($this->exactly(2))
5287
            ->method('getLocationService')
5288
            ->will($this->returnValue($locationServiceMock));
5289
5290
        $contentInfoMock->expects($this->any())
5291
            ->method('__get')
5292
            ->with('id')
5293
            ->will($this->returnValue(42));
5294
        $versionInfoMock = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\VersionInfo');
5295
5296
        $versionInfoMock->expects($this->any())
5297
            ->method('__get')
5298
            ->will(
5299
                $this->returnValueMap(
5300
                    array(
5301
                        array('versionNo', 123),
5302
                        array('status', VersionInfo::STATUS_DRAFT),
5303
                    )
5304
                )
5305
            );
5306
        $versionInfoMock->expects($this->once())
5307
            ->method('getContentInfo')
5308
            ->will($this->returnValue($contentInfoMock));
5309
5310
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
5311
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
5312
        $domainMapperMock = $this->getDomainMapperMock();
5313
5314
        $repositoryMock->expects($this->once())->method('beginTransaction');
5315
        $repositoryMock->expects($this->once())->method('commit');
5316
        $repositoryMock->expects($this->once())
5317
            ->method('canUser')
5318
            ->with(
5319
                'content',
5320
                'create',
5321
                $contentInfoMock,
5322
                $locationCreateStruct
5323
            )
5324
            ->will($this->returnValue(true));
5325
5326
        $spiContentInfo = new SPIContentInfo(array('id' => 42));
5327
        $spiVersionInfo = new SPIVersionInfo(
5328
            array(
5329
                'contentInfo' => $spiContentInfo,
5330
                'creationDate' => 123456,
5331
            )
5332
        );
5333
        $spiContent = new SPIContent(array('versionInfo' => $spiVersionInfo));
5334
        $contentHandlerMock->expects($this->once())
5335
            ->method('copy')
5336
            ->with(42, null)
5337
            ->will($this->returnValue($spiContent));
5338
5339
        $this->mockGetDefaultObjectStates();
5340
        $this->mockSetDefaultObjectStates();
5341
5342
        $domainMapperMock->expects($this->once())
5343
            ->method('buildVersionInfoDomainObject')
5344
            ->with($spiVersionInfo)
5345
            ->will($this->returnValue($versionInfoMock));
5346
5347
        /* @var \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfoMock */
5348
        $content = $this->mockPublishVersion(123456);
5349
        $locationServiceMock->expects($this->once())
5350
            ->method('createLocation')
5351
            ->with(
5352
                $content->getVersionInfo()->getContentInfo(),
5353
                $locationCreateStruct
5354
            );
5355
5356
        $contentService->expects($this->once())
5357
            ->method('internalLoadContent')
5358
            ->with(
5359
                $content->id
5360
            )
5361
            ->will($this->returnValue($content));
5362
5363
        /* @var \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfoMock */
5364
        $contentService->copyContent($contentInfoMock, $locationCreateStruct, null);
5365
    }
5366
5367
    /**
5368
     * Test for the copyContent() method.
5369
     *
5370
     * @covers \eZ\Publish\Core\Repository\ContentService::copyContent
5371
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
5372
     * @covers \eZ\Publish\Core\Repository\ContentService::internalPublishVersion
5373
     */
5374
    public function testCopyContentWithVersionInfo()
5375
    {
5376
        $repositoryMock = $this->getRepositoryMock();
5377
        $contentService = $this->getPartlyMockedContentService(array('internalLoadContentInfo', 'internalLoadContent'));
5378
        $locationServiceMock = $this->getLocationServiceMock();
5379
        $contentInfoMock = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
5380
        $locationCreateStruct = new LocationCreateStruct();
5381
5382
        $repositoryMock->expects($this->exactly(2))
5383
            ->method('getLocationService')
5384
            ->will($this->returnValue($locationServiceMock));
5385
5386
        $contentInfoMock->expects($this->any())
5387
            ->method('__get')
5388
            ->with('id')
5389
            ->will($this->returnValue(42));
5390
        $versionInfoMock = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\VersionInfo');
5391
5392
        $versionInfoMock->expects($this->any())
5393
            ->method('__get')
5394
            ->will(
5395
                $this->returnValueMap(
5396
                    array(
5397
                        array('versionNo', 123),
5398
                        array('status', VersionInfo::STATUS_DRAFT),
5399
                    )
5400
                )
5401
            );
5402
        $versionInfoMock->expects($this->once())
5403
            ->method('getContentInfo')
5404
            ->will($this->returnValue($contentInfoMock));
5405
5406
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
5407
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
5408
        $domainMapperMock = $this->getDomainMapperMock();
5409
5410
        $repositoryMock->expects($this->once())->method('beginTransaction');
5411
        $repositoryMock->expects($this->once())->method('commit');
5412
        $repositoryMock->expects($this->once())
5413
            ->method('canUser')
5414
            ->with(
5415
                'content',
5416
                'create',
5417
                $contentInfoMock,
5418
                $locationCreateStruct
5419
            )
5420
            ->will($this->returnValue(true));
5421
5422
        $spiContentInfo = new SPIContentInfo(array('id' => 42));
5423
        $spiVersionInfo = new SPIVersionInfo(
5424
            array(
5425
                'contentInfo' => $spiContentInfo,
5426
                'creationDate' => 123456,
5427
            )
5428
        );
5429
        $spiContent = new SPIContent(array('versionInfo' => $spiVersionInfo));
5430
        $contentHandlerMock->expects($this->once())
5431
            ->method('copy')
5432
            ->with(42, 123)
5433
            ->will($this->returnValue($spiContent));
5434
5435
        $this->mockGetDefaultObjectStates();
5436
        $this->mockSetDefaultObjectStates();
5437
5438
        $domainMapperMock->expects($this->once())
5439
            ->method('buildVersionInfoDomainObject')
5440
            ->with($spiVersionInfo)
5441
            ->will($this->returnValue($versionInfoMock));
5442
5443
        /* @var \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfoMock */
5444
        $content = $this->mockPublishVersion(123456);
5445
        $locationServiceMock->expects($this->once())
5446
            ->method('createLocation')
5447
            ->with(
5448
                $content->getVersionInfo()->getContentInfo(),
5449
                $locationCreateStruct
5450
            );
5451
5452
        $contentService->expects($this->once())
5453
            ->method('internalLoadContent')
5454
            ->with(
5455
                $content->id
5456
            )
5457
            ->will($this->returnValue($content));
5458
5459
        /* @var \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfoMock */
5460
        $contentService->copyContent($contentInfoMock, $locationCreateStruct, $versionInfoMock);
5461
    }
5462
5463
    /**
5464
     * Test for the copyContent() method.
5465
     *
5466
     * @covers \eZ\Publish\Core\Repository\ContentService::copyContent
5467
     * @covers \eZ\Publish\Core\Repository\ContentService::getDefaultObjectStates
5468
     * @covers \eZ\Publish\Core\Repository\ContentService::internalPublishVersion
5469
     * @expectedException \Exception
5470
     * @expectedExceptionMessage Handler threw an exception
5471
     */
5472
    public function testCopyContentWithRollback()
5473
    {
5474
        $repositoryMock = $this->getRepositoryMock();
5475
        $contentService = $this->getPartlyMockedContentService();
5476
        /** @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
5477
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
5478
        $locationCreateStruct = new LocationCreateStruct();
5479
        $contentInfoMock = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
5480
        $contentInfoMock->expects($this->any())
5481
            ->method('__get')
5482
            ->with('id')
5483
            ->will($this->returnValue(42));
5484
5485
        $this->mockGetDefaultObjectStates();
5486
5487
        $repositoryMock->expects($this->once())->method('beginTransaction');
5488
        $repositoryMock->expects($this->once())->method('rollback');
5489
        $repositoryMock->expects($this->once())
5490
            ->method('canUser')
5491
            ->with(
5492
                'content',
5493
                'create',
5494
                $contentInfoMock,
5495
                $locationCreateStruct
5496
            )
5497
            ->will($this->returnValue(true));
5498
5499
        $contentHandlerMock->expects($this->once())
5500
            ->method('copy')
5501
            ->with(42, null)
5502
            ->will($this->throwException(new Exception('Handler threw an exception')));
5503
5504
        /* @var \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfoMock */
5505
        $contentService->copyContent($contentInfoMock, $locationCreateStruct, null);
5506
    }
5507
5508
    /**
5509
     */
5510
    protected function mockGetDefaultObjectStates()
5511
    {
5512
        /** @var \PHPUnit_Framework_MockObject_MockObject $objectStateHandlerMock */
5513
        $objectStateHandlerMock = $this->getPersistenceMock()->objectStateHandler();
5514
5515
        $objectStateGroups = array(
5516
            new SPIObjectStateGroup(array('id' => 10)),
5517
            new SPIObjectStateGroup(array('id' => 20)),
5518
        );
5519
5520
        /* @var \PHPUnit_Framework_MockObject_MockObject $objectStateHandlerMock */
5521
        $objectStateHandlerMock->expects($this->once())
5522
            ->method('loadAllGroups')
5523
            ->will($this->returnValue($objectStateGroups));
5524
5525
        $objectStateHandlerMock->expects($this->at(1))
5526
            ->method('loadObjectStates')
5527
            ->with($this->equalTo(10))
5528
            ->will(
5529
                $this->returnValue(
5530
                    array(
5531
                        new SPIObjectState(array('id' => 11, 'groupId' => 10)),
5532
                        new SPIObjectState(array('id' => 12, 'groupId' => 10)),
5533
                    )
5534
                )
5535
            );
5536
5537
        $objectStateHandlerMock->expects($this->at(2))
5538
            ->method('loadObjectStates')
5539
            ->with($this->equalTo(20))
5540
            ->will(
5541
                $this->returnValue(
5542
                    array(
5543
                        new SPIObjectState(array('id' => 21, 'groupId' => 20)),
5544
                        new SPIObjectState(array('id' => 22, 'groupId' => 20)),
5545
                    )
5546
                )
5547
            );
5548
    }
5549
5550
    /**
5551
     */
5552
    protected function mockSetDefaultObjectStates()
5553
    {
5554
        /** @var \PHPUnit_Framework_MockObject_MockObject $objectStateHandlerMock */
5555
        $objectStateHandlerMock = $this->getPersistenceMock()->objectStateHandler();
5556
5557
        $defaultObjectStates = array(
5558
            new SPIObjectState(array('id' => 11, 'groupId' => 10)),
5559
            new SPIObjectState(array('id' => 21, 'groupId' => 20)),
5560
        );
5561
        foreach ($defaultObjectStates as $index => $objectState) {
5562
            $objectStateHandlerMock->expects($this->at($index + 3))
5563
                ->method('setContentState')
5564
                ->with(
5565
                    42,
5566
                    $objectState->groupId,
5567
                    $objectState->id
5568
                );
5569
        }
5570
    }
5571
5572
    /**
5573
     * @param int|null $publicationDate
5574
     *
5575
     * @return \eZ\Publish\API\Repository\Values\Content\Content
5576
     */
5577
    protected function mockPublishVersion($publicationDate = null)
5578
    {
5579
        $domainMapperMock = $this->getDomainMapperMock();
5580
        $contentMock = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\Content');
5581
        /* @var \PHPUnit_Framework_MockObject_MockObject $contentHandlerMock */
5582
        $versionInfoMock = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\VersionInfo');
5583
        $contentInfoMock = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\ContentInfo');
5584
        $contentHandlerMock = $this->getPersistenceMock()->contentHandler();
5585
        $metadataUpdateStruct = new SPIMetadataUpdateStruct();
5586
5587
        $contentMock->expects($this->any())
5588
            ->method('__get')
5589
            ->will(
5590
                $this->returnValueMap(
5591
                    array(
5592
                        array('id', 42),
5593
                        array('contentInfo', $contentInfoMock),
5594
                    )
5595
                )
5596
            );
5597
        $contentMock->expects($this->any())
5598
            ->method('getVersionInfo')
5599
            ->will($this->returnValue($versionInfoMock));
5600
        $versionInfoMock->expects($this->any())
5601
            ->method('getContentInfo')
5602
            ->will($this->returnValue($contentInfoMock));
5603
        $contentInfoMock->expects($this->any())
5604
            ->method('__get')
5605
            ->will(
5606
                $this->returnValueMap(
5607
                    array(
5608
                        array('alwaysAvailable', true),
5609
                        array('mainLanguageCode', 'eng-GB'),
5610
                    )
5611
                )
5612
            );
5613
5614
        $currentTime = time();
5615
        if ($publicationDate === null && $versionInfoMock->versionNo === 1) {
5616
            $publicationDate = $currentTime;
5617
        }
5618
5619
        // Account for 1 second of test execution time
5620
        $metadataUpdateStruct->publicationDate = $publicationDate;
5621
        $metadataUpdateStruct->modificationDate = $currentTime;
5622
        $metadataUpdateStruct2 = clone $metadataUpdateStruct;
5623
        ++$metadataUpdateStruct2->publicationDate;
5624
        ++$metadataUpdateStruct2->modificationDate;
5625
5626
        $spiContent = new SPIContent();
5627
        $contentHandlerMock->expects($this->once())
5628
            ->method('publish')
5629
            ->with(
5630
                42,
5631
                123,
5632
                $this->logicalOr($metadataUpdateStruct, $metadataUpdateStruct2)
5633
            )
5634
            ->will($this->returnValue($spiContent));
5635
5636
        $domainMapperMock->expects($this->once())
5637
            ->method('buildContentDomainObject')
5638
            ->with($spiContent)
5639
            ->will($this->returnValue($contentMock));
5640
5641
        /* @var \eZ\Publish\API\Repository\Values\Content\Content $contentMock */
5642
        $this->mockPublishUrlAliasesForContent($contentMock);
5643
5644
        return $contentMock;
5645
    }
5646
5647
    /**
5648
     * @param \eZ\Publish\API\Repository\Values\Content\Content $content
5649
     */
5650
    protected function mockPublishUrlAliasesForContent(APIContent $content)
5651
    {
5652
        $nameSchemaServiceMock = $this->getNameSchemaServiceMock();
5653
        /** @var \PHPUnit_Framework_MockObject_MockObject $urlAliasHandlerMock */
5654
        $urlAliasHandlerMock = $this->getPersistenceMock()->urlAliasHandler();
5655
        $locationServiceMock = $this->getLocationServiceMock();
5656
        $location = $this->getMock('eZ\\Publish\\API\\Repository\\Values\\Content\\Location');
5657
5658
        $location->expects($this->at(0))
5659
            ->method('__get')
5660
            ->with('id')
5661
            ->will($this->returnValue(123));
5662
        $location->expects($this->at(1))
5663
            ->method('__get')
5664
            ->with('parentLocationId')
5665
            ->will($this->returnValue(456));
5666
5667
        $urlAliasNames = array('eng-GB' => 'hello');
5668
        $nameSchemaServiceMock->expects($this->once())
5669
            ->method('resolveUrlAliasSchema')
5670
            ->with($content)
5671
            ->will($this->returnValue($urlAliasNames));
5672
5673
        $locationServiceMock->expects($this->once())
5674
            ->method('loadLocations')
5675
            ->with($content->getVersionInfo()->getContentInfo())
5676
            ->will($this->returnValue(array($location)));
5677
5678
        $urlAliasHandlerMock->expects($this->once())
5679
            ->method('publishUrlAliasForLocation')
5680
            ->with(123, 456, 'hello', 'eng-GB', true, true);
5681
    }
5682
5683
    protected $domainMapperMock;
5684
5685
    /**
5686
     * @return \PHPUnit_Framework_MockObject_MockObject|\eZ\Publish\Core\Repository\Helper\DomainMapper
5687
     */
5688 View Code Duplication
    protected function getDomainMapperMock()
5689
    {
5690
        if (!isset($this->domainMapperMock)) {
5691
            $this->domainMapperMock = $this
5692
                ->getMockBuilder('eZ\\Publish\\Core\\Repository\\Helper\\DomainMapper')
5693
                ->disableOriginalConstructor()
5694
                ->getMock();
5695
        }
5696
5697
        return $this->domainMapperMock;
5698
    }
5699
5700
    protected $relationProcessorMock;
5701
5702
    /**
5703
     * @return \PHPUnit_Framework_MockObject_MockObject|\eZ\Publish\Core\Repository\Helper\RelationProcessor
5704
     */
5705
    protected function getRelationProcessorMock()
5706
    {
5707
        if (!isset($this->relationProcessorMock)) {
5708
            $this->relationProcessorMock = $this
5709
                ->getMockBuilder('eZ\\Publish\\Core\\Repository\\Helper\\RelationProcessor')
5710
                ->disableOriginalConstructor()
5711
                ->getMock();
5712
        }
5713
5714
        return $this->relationProcessorMock;
5715
    }
5716
5717
    protected $nameSchemaServiceMock;
5718
5719
    /**
5720
     * @return \PHPUnit_Framework_MockObject_MockObject|\eZ\Publish\Core\Repository\Helper\NameSchemaService
5721
     */
5722
    protected function getNameSchemaServiceMock()
5723
    {
5724
        if (!isset($this->nameSchemaServiceMock)) {
5725
            $this->nameSchemaServiceMock = $this
5726
                ->getMockBuilder('eZ\\Publish\\Core\\Repository\\Helper\\NameSchemaService')
5727
                ->disableOriginalConstructor()
5728
                ->getMock();
5729
        }
5730
5731
        return $this->nameSchemaServiceMock;
5732
    }
5733
5734
    protected $contentTypeServiceMock;
5735
5736
    /**
5737
     * @return \PHPUnit_Framework_MockObject_MockObject|\eZ\Publish\API\Repository\ContentTypeService
5738
     */
5739
    protected function getContentTypeServiceMock()
5740
    {
5741
        if (!isset($this->contentTypeServiceMock)) {
5742
            $this->contentTypeServiceMock = $this
5743
                ->getMockBuilder('eZ\\Publish\\API\\Repository\\ContentTypeService')
5744
                ->disableOriginalConstructor()
5745
                ->getMock();
5746
        }
5747
5748
        return $this->contentTypeServiceMock;
5749
    }
5750
5751
    protected $locationServiceMock;
5752
5753
    /**
5754
     * @return \PHPUnit_Framework_MockObject_MockObject|\eZ\Publish\API\Repository\LocationService
5755
     */
5756
    protected function getLocationServiceMock()
5757
    {
5758
        if (!isset($this->locationServiceMock)) {
5759
            $this->locationServiceMock = $this
5760
                ->getMockBuilder('eZ\\Publish\\API\\Repository\\LocationService')
5761
                ->disableOriginalConstructor()
5762
                ->getMock();
5763
        }
5764
5765
        return $this->locationServiceMock;
5766
    }
5767
5768
    /**
5769
     * @var \eZ\Publish\Core\Repository\ContentService
5770
     */
5771
    protected $partlyMockedContentService;
5772
5773
    /**
5774
     * Returns the content service to test with $methods mocked.
5775
     *
5776
     * Injected Repository comes from {@see getRepositoryMock()} and persistence handler from {@see getPersistenceMock()}
5777
     *
5778
     * @param string[] $methods
5779
     *
5780
     * @return \eZ\Publish\Core\Repository\ContentService|\PHPUnit_Framework_MockObject_MockObject
5781
     */
5782
    protected function getPartlyMockedContentService(array $methods = null)
5783
    {
5784
        if (!isset($this->partlyMockedContentService)) {
5785
            $this->partlyMockedContentService = $this->getMock(
5786
                'eZ\\Publish\\Core\\Repository\\ContentService',
5787
                $methods,
5788
                array(
5789
                    $this->getRepositoryMock(),
5790
                    $this->getPersistenceMock(),
5791
                    $this->getDomainMapperMock(),
5792
                    $this->getRelationProcessorMock(),
5793
                    $this->getNameSchemaServiceMock(),
5794
                    $this->getFieldTypeRegistryMock(),
5795
                    array(),
5796
                )
5797
            );
5798
        }
5799
5800
        return $this->partlyMockedContentService;
5801
    }
5802
}
5803