Completed
Push — master ( 696c56...a8c737 )
by André
259:23 queued 232:42
created

testDeleteTranslationOfContentWithSingleTranslationVersion()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 33
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 18
nc 3
nop 1
dl 0
loc 33
rs 8.8571
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the Functional\ContentTest class.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Bundle\EzPublishRestBundle\Tests\Functional;
10
11
use Buzz\Message\Response;
12
use eZ\Bundle\EzPublishRestBundle\Tests\Functional\TestCase as RESTFunctionalTestCase;
13
use Psr\Http\Message\ResponseInterface;
14
15
class ContentTest extends RESTFunctionalTestCase
16
{
17
    /**
18
     * Covers POST /content/objects.
19
     *
20
     * @return string REST content ID
21
     */
22
    public function testCreateContent()
23
    {
24
        $string = $this->addTestSuffix(__FUNCTION__);
25
        $body = <<< XML
26
<?xml version="1.0" encoding="UTF-8"?>
27
<ContentCreate>
28
  <ContentType href="/api/ezp/v2/content/types/1" />
29
  <mainLanguageCode>eng-GB</mainLanguageCode>
30
  <LocationCreate>
31
    <ParentLocation href="/api/ezp/v2/content/locations/1/2" />
32
    <priority>0</priority>
33
    <hidden>false</hidden>
34
    <sortField>PATH</sortField>
35
    <sortOrder>ASC</sortOrder>
36
  </LocationCreate>
37
  <Section href="/api/ezp/v2/content/sections/1" />
38
  <alwaysAvailable>true</alwaysAvailable>
39
  <remoteId>{$string}</remoteId>
40
  <User href="/api/ezp/v2/user/users/14" />
41
  <modificationDate>2012-09-30T12:30:00</modificationDate>
42
  <fields>
43
    <field>
44
      <fieldDefinitionIdentifier>name</fieldDefinitionIdentifier>
45
      <languageCode>eng-GB</languageCode>
46
      <fieldValue>{$string}</fieldValue>
47
    </field>
48
  </fields>
49
</ContentCreate>
50
XML;
51
        $request = $this->createHttpRequest(
52
            'POST',
53
            '/api/ezp/v2/content/objects',
54
            'ContentCreate+xml',
55
            'ContentInfo+json',
56
            $body
57
        );
58
59
        $response = $this->sendHttpRequest($request);
60
61
        self::assertHttpResponseCodeEquals($response, 201);
62
        self::assertHttpResponseHasHeader($response, 'Location');
63
64
        $href = $response->getHeader('Location')[0];
65
        $this->addCreatedElement($href);
66
67
        return $href;
68
    }
69
70
    /**
71
     * @depends testCreateContent
72
     * Covers PUBLISH /content/objects/<contentId>/versions/<versionNumber>
73
     *
74
     * @return string REST content ID
75
     */
76
    public function testPublishContent($restContentHref)
77
    {
78
        $response = $this->sendHttpRequest(
79
            $this->createHttpRequest('PUBLISH', "$restContentHref/versions/1")
80
        );
81
        self::assertHttpResponseCodeEquals($response, 204);
82
83
        return $restContentHref;
84
    }
85
86
    /**
87
     * @depends testPublishContent
88
     * Covers GET /content/objects?remoteId=<remoteId>
89
     */
90 View Code Duplication
    public function testRedirectContent($restContentHref)
91
    {
92
        $response = $this->sendHttpRequest(
93
            $this->createHttpRequest('GET', '/api/ezp/v2/content/objects?remoteId=' . $this->addTestSuffix('testCreateContent'))
94
        );
95
96
        self::assertHttpResponseCodeEquals($response, 307);
97
        self::assertEquals($response->getHeader('Location')[0], $restContentHref);
98
    }
99
100
    /**
101
     * @depends testPublishContent
102
     */
103
    public function testLoadContent($restContentHref)
104
    {
105
        $response = $this->sendHttpRequest(
106
            $this->createHttpRequest('GET', $restContentHref)
107
        );
108
109
        self::assertHttpResponseCodeEquals($response, 200);
110
        // @todo test data a bit ?
111
    }
112
113
    /**
114
     * @depends testPublishContent
115
     */
116
    public function testUpdateContentMetadata($restContentHref)
117
    {
118
        $string = $this->addTestSuffix(__FUNCTION__);
119
        $content = <<< XML
120
<?xml version="1.0" encoding="UTF-8"?>
121
<ContentUpdate>
122
  <Owner href="/api/ezp/v2/user/users/10"/>
123
  <remoteId>{$string}</remoteId>
124
</ContentUpdate>
125
XML;
126
        $request = $this->createHttpRequest(
127
            'PATCH',
128
            $restContentHref,
129
            'ContentUpdate+xml',
130
            'ContentInfo+json',
131
            $content
132
        );
133
        $response = $this->sendHttpRequest($request);
134
        self::assertHttpResponseCodeEquals($response, 200);
135
136
        // @todo test data
137
    }
138
139
    /**
140
     * @depends testPublishContent
141
     *
142
     * @param string $restContentHref
143
     *
144
     * @return string ContentVersion REST ID
145
     */
146
    public function testCreateDraftFromVersion(string $restContentHref)
147
    {
148
        $response = $this->sendHttpRequest(
149
            $this->createHttpRequest('COPY', "{$restContentHref}/versions/1")
150
        );
151
152
        self::assertHttpResponseCodeEquals($response, 201);
153
        self::assertEquals($response->getHeader('Location')[0], "{$restContentHref}/versions/2");
154
155
        return $response->getHeader('Location')[0];
156
    }
157
158
    /**
159
     * @depends testPublishContent
160
     * Covers GET /content/objects/<contentId>/currentversion
161
     * @covers \eZ\Publish\Core\REST\Server\Controller\Content::redirectCurrentVersion
162
     *
163
     * @param string $restContentHref
164
     *
165
     * @throws \Psr\Http\Client\ClientException
166
     */
167
    public function testRedirectCurrentVersion(string $restContentHref)
168
    {
169
        $response = $this->sendHttpRequest(
170
            $this->createHttpRequest('GET', "$restContentHref/currentversion")
171
        );
172
173
        self::assertHttpResponseCodeEquals($response, 307);
174
175
        self::assertHttpResponseHasHeader($response, 'Location', "$restContentHref/versions/1");
176
    }
177
178
    /**
179
     * @depends testCreateDraftFromVersion
180
     * Covers GET /content/objects/<contentId>/versions/<versionNumber>
181
     *
182
     * @param string $restContentVersionHref
183
     */
184
    public function testLoadContentVersion($restContentVersionHref)
185
    {
186
        $response = $this->sendHttpRequest(
187
            $this->createHttpRequest('GET', $restContentVersionHref)
188
        );
189
190
        self::assertHttpResponseCodeEquals($response, 200);
191
        $this->assertVersionResponseContainsExpectedFields($response);
192
        // @todo test filtering (language, fields, etc)
193
    }
194
195
    /**
196
     * Covers COPY /content/objects/<contentId>.
197
     * @depends testPublishContent
198
     *
199
     * @return string the copied content href
200
     */
201
    public function testCopyContent($restContentHref)
202
    {
203
        $testContent = $this->loadContent($restContentHref);
204
205
        $request = $this->createHttpRequest(
206
            'COPY',
207
            $restContentHref,
208
            '',
209
            '',
210
            '',
211
            ['Destination' => $testContent['MainLocation']['_href']]
212
        );
213
        $response = $this->sendHttpRequest($request);
214
215
        self::assertHttpResponseCodeEquals($response, 201);
216
        self::assertStringStartsWith(
217
            '/api/ezp/v2/content/objects/',
218
            $response->getHeader('Location')[0]
219
        );
220
221
        $this->addCreatedElement($response->getHeader('Location')[0]);
222
223
        return $response->getHeader('Location')[0];
224
    }
225
226
    /**
227
     * Covers DELETE /content/objects/<versionNumber>.
228
     * @depends testCopyContent
229
     */
230
    public function testDeleteContent($restContentHref)
231
    {
232
        self::markTestSkipped("Fails as the content created by copyContent isn't found");
233
        $response = $this->sendHttpRequest(
234
            $this->createHttpRequest('DELETE', $restContentHref)
235
        );
236
237
        self::assertHttpResponseCodeEquals($response, 204);
238
    }
239
240
    /**
241
     * @depends testPublishContent
242
     * Covers GET /content/objects/<contentId>/versions
243
     */
244
    public function testLoadContentVersions($restContentHref)
245
    {
246
        $response = $this->sendHttpRequest(
247
            $this->createHttpRequest('GET', "$restContentHref/versions", '', 'VersionList')
248
        );
249
250
        self::assertHttpResponseCodeEquals($response, 200);
251
    }
252
253
    /**
254
     * @depends testPublishContent
255
     *
256
     * @param string $restContentHref /content/objects/<contentId>
257
     * Covers COPY /content/objects/<contentId>/currentversion
258
     *
259
     * @return string the ID of the created version (/content/objects/<contentId>/versions/<versionNumber>
260
     */
261
    public function testCreateDraftFromCurrentVersion($restContentHref)
262
    {
263
        $response = $this->sendHttpRequest(
264
            $this->createHttpRequest('COPY', "$restContentHref/currentversion")
265
        );
266
267
        self::assertHttpResponseCodeEquals($response, 201);
268
        self::assertHttpResponseHasHeader($response, 'Location');
269
270
        return $response->getHeader('Location')[0];
271
    }
272
273
    /**
274
     * @depends testCreateDraftFromCurrentVersion
275
     *
276
     * @param string $restContentVersionHref /api/ezp/v2/content/objects/<contentId>/versions>/<versionNumber>
277
     * Covers DELETE /api/ezp/v2/content/objects/<contentId>/versions>/<versionNumber>
278
     */
279
    public function testDeleteContentVersion($restContentVersionHref)
280
    {
281
        $response = $this->sendHttpRequest(
282
            $this->createHttpRequest('DELETE', $restContentVersionHref)
283
        );
284
285
        self::assertHttpResponseCodeEquals($response, 204);
286
    }
287
288
    /**
289
     * @depends testCreateDraftFromVersion
290
     * Covers PATCH /content/objects/<contentId>/versions>/<versionNumber>
291
     *
292
     * @param string $restContentVersionHref /content/objects/<contentId>/versions>/<versionNumber>
293
     */
294 View Code Duplication
    public function testUpdateVersion($restContentVersionHref)
295
    {
296
        $xml = <<< XML
297
<VersionUpdate>
298
    <fields>
299
        <field>
300
            <fieldDefinitionIdentifier>name</fieldDefinitionIdentifier>
301
            <languageCode>eng-GB</languageCode>
302
            <fieldValue>testUpdateVersion</fieldValue>
303
        </field>
304
    </fields>
305
</VersionUpdate>
306
XML;
307
308
        $request = $this->createHttpRequest(
309
            'PATCH',
310
            $restContentVersionHref,
311
            'VersionUpdate+xml',
312
            'Version+json',
313
            $xml
314
        );
315
        $response = $this->sendHttpRequest($request);
316
317
        self::assertHttpResponseCodeEquals($response, 200);
318
    }
319
320
    /**
321
     * @depends testPublishContent
322
     * Covers GET /content/objects/<contentId>/relations
323
     */
324
    public function testRedirectCurrentVersionRelations($restContentHref)
325
    {
326
        $response = $this->sendHttpRequest(
327
            $this->createHttpRequest('GET', "$restContentHref/relations")
328
        );
329
330
        self::assertHttpResponseCodeEquals($response, 307);
331
332
        // @todo Fix, see EZP-21059. Meanwhile, the test is skipped if it fails as expected
333
        // self::assertHttpResponseHasHeader( $response, 'Location', "$restContentHref/versions/1/relations" );
334
        self::assertHttpResponseHasHeader($response, 'Location', "$restContentHref/relations?versionNumber=1");
335
        self::markTestIncomplete('@todo Fix issue EZP-21059');
336
    }
337
338
    /**
339
     * @depends testCreateDraftFromVersion
340
     * Covers GET /content/objects/<contentId>/versions/<versionNumber>/relations
341
     */
342
    public function testLoadVersionRelations($restContentVersionHref)
343
    {
344
        $response = $this->sendHttpRequest(
345
            $this->createHttpRequest('GET', "$restContentVersionHref/relations")
346
        );
347
348
        self::assertHttpResponseCodeEquals($response, 200);
349
    }
350
351
    /**
352
     * @depends testCreateDraftFromVersion
353
     * Covers POST /content/objects/<contentId>/versions/<versionNumber>/relations/<relationId>
354
     *
355
     * @return string created relation HREF (/content/objects/<contentId>/versions/<versionNumber>/relations/<relationId>
356
     */
357
    public function testCreateRelation($restContentVersionHref)
358
    {
359
        $content = <<< XML
360
<?xml version="1.0" encoding="UTF-8"?>
361
<RelationCreate>
362
  <Destination href="/api/ezp/v2/content/objects/10"/>
363
</RelationCreate>
364
XML;
365
366
        $request = $this->createHttpRequest(
367
            'POST',
368
            "$restContentVersionHref/relations",
369
            'RelationCreate+xml',
370
            'Relation+json',
371
            $content
372
        );
373
        $response = $this->sendHttpRequest($request);
374
375
        self::assertHttpResponseCodeEquals($response, 201);
376
377
        $response = json_decode($response->getBody(), true);
378
379
        return $response['Relation']['_href'];
380
    }
381
382
    /**
383
     * @depends testCreateRelation
384
     * Covers GET /content/objects/<contentId>/versions/<versionNo>/relations/<relationId>
385
     */
386
    public function testLoadVersionRelation($restContentRelationHref)
387
    {
388
        $response = $this->sendHttpRequest(
389
            $this->createHttpRequest('GET', $restContentRelationHref)
390
        );
391
392
        self::assertHttpResponseCodeEquals($response, 200);
393
394
        // @todo test data
395
    }
396
397
    /**
398
     * Returns the Content key from the decoded JSON of $restContentId's contentInfo.
399
     *
400
     *
401
     * @throws \InvalidArgumentException
402
     *
403
     * @param string $restContentHref /api/ezp/v2/content/objects/<contentId>
404
     *
405
     * @return array
406
     */
407
    private function loadContent($restContentHref)
408
    {
409
        $response = $this->sendHttpRequest(
410
            $this->createHttpRequest('GET', $restContentHref, '', 'ContentInfo+json')
411
        );
412
413
        if ($response->getStatusCode() != 200) {
414
            throw new \InvalidArgumentException("Content with ID $restContentHref could not be loaded");
415
        }
416
417
        $array = json_decode($response->getBody(), true);
418
        if ($array === null) {
419
            self::fail('Error loading content. Response: ' . $response->getBody());
420
        }
421
422
        return $array['Content'];
423
    }
424
425
    public function testCreateView()
426
    {
427
        $body = <<< XML
428
<?xml version="1.0" encoding="UTF-8"?>
429
<ViewInput>
430
  <identifier>testCreateView</identifier>
431
  <Query>
432
    <Criteria>
433
      <ContentTypeIdentifierCriterion>folder</ContentTypeIdentifierCriterion>
434
    </Criteria>
435
    <limit>10</limit>
436
    <offset>0</offset>
437
  </Query>
438
</ViewInput>
439
XML;
440
        $request = $this->createHttpRequest(
441
            'POST',
442
            '/api/ezp/v2/content/views',
443
            'ViewInput+xml',
444
            'View+json',
445
            $body
446
        );
447
        $response = $this->sendHttpRequest($request);
448
449
        // Returns 301 since 6.0 (deprecated in favour of /views)
450
        self::assertHttpResponseCodeEquals($response, 301);
451
        self::assertHttpResponseHasHeader($response, 'Location');
452
    }
453
454
    /**
455
     * Covers DELETE /content/objects/<contentId>/versions/<versionNo>/translations/<languageCode>.
456
     *
457
     * @depends testCreateDraftFromVersion
458
     *
459
     * @param string $restContentVersionHref
460
     */
461
    public function testDeleteTranslationFromDraft($restContentVersionHref)
462
    {
463
        // create pol-PL Translation
464
        $translationToDelete = 'pol-PL';
465
        $this->createVersionTranslation($restContentVersionHref, $translationToDelete, 'Polish');
466
467
        $response = $this->sendHttpRequest(
468
            $this->createHttpRequest('DELETE', $restContentVersionHref . "/translations/{$translationToDelete}")
469
        );
470
        self::assertHttpResponseCodeEquals($response, 204);
471
472
        // check that the Translation was deleted by reloading Version
473
        $response = $this->sendHttpRequest(
474
            $this->createHttpRequest('GET', $restContentVersionHref, '', 'Version+json')
475
        );
476
477
        $version = json_decode($response->getBody(), true);
478
        self::assertNotContains($translationToDelete, $version['Version']['VersionInfo']['languageCodes']);
479
    }
480
481
    /**
482
     * Test that VersionInfo loaded in VersionList contains working DeleteTranslation resource link.
483
     *
484
     * Covers DELETE /content/objects/<contentId>/versions/<versionNo>/translations/<languageCode>.
485
     * Covers GET /content/objects/<contentId>/versions
486
     *
487
     * @depends testCreateDraftFromVersion
488
     *
489
     * @param string $restContentVersionHref
490
     */
491
    public function testLoadContentVersionsProvidesDeleteTranslationFromDraftResourceLink($restContentVersionHref)
492
    {
493
        $translationToDelete = 'pol-PL';
494
        // create Version Draft containing pol-PL Translation
495
        $this->createVersionTranslation($restContentVersionHref, $translationToDelete, 'Polish');
496
497
        // load Version
498
        $response = $this->sendHttpRequest(
499
            $this->createHttpRequest('GET', $restContentVersionHref, '', 'Version+json')
500
        );
501
        self::assertHttpResponseCodeEquals($response, 200);
502
        $version = json_decode($response->getBody(), true);
503
504
        // load all Versions
505
        self::assertNotEmpty($version['Version']['VersionInfo']['Content']['_href']);
506
        $restLoadContentVersionsHref = $version['Version']['VersionInfo']['Content']['_href'] . '/versions';
507
        $response = $this->sendHttpRequest(
508
            $this->createHttpRequest('GET', $restLoadContentVersionsHref, '', 'VersionList+json')
509
        );
510
        self::assertHttpResponseCodeEquals($response, 200);
511
512
        // load Version list
513
        $versionList = json_decode($response->getBody(), true);
514
        $version = $this->getVersionInfoFromJSONVersionListByStatus(
515
            $versionList['VersionList'],
516
            'DRAFT'
517
        );
518
519
        // validate VersionTranslationInfo structure
520
        self::assertNotEmpty($version['VersionTranslationInfo']['Language']);
521
        foreach ($version['VersionTranslationInfo']['Language'] as $versionTranslationInfo) {
522
            // Other Translation, as the main one, shouldn't be deletable
523
            if ($versionTranslationInfo['languageCode'] !== $translationToDelete) {
524
                // check that endpoint is not provided for non-deletable Translation
525
                self::assertTrue(empty($versionTranslationInfo['DeleteTranslation']['_href']));
526
            } else {
527
                // check that provided endpoint works
528
                self::assertNotEmpty($versionTranslationInfo['DeleteTranslation']['_href']);
529
                $response = $this->sendHttpRequest(
530
                    $this->createHttpRequest(
531
                        'DELETE',
532
                        $versionTranslationInfo['DeleteTranslation']['_href']
533
                    )
534
                );
535
                self::assertHttpResponseCodeEquals($response, 204);
536
            }
537
        }
538
    }
539
540
    /**
541
     * Covers DELETE /content/objects/<contentId>/translations/<languageCode>.
542
     */
543
    public function testDeleteTranslation()
544
    {
545
        // create independent Content
546
        $content = $this->createContentDraft(
547
            '/api/ezp/v2/content/types/1',
548
            '/api/ezp/v2/content/locations/1/2',
549
            '/api/ezp/v2/content/sections/1',
550
            '/api/ezp/v2/user/users/14',
551
            [
552
                'name' => [
553
                    'eng-GB' => $this->addTestSuffix(__FUNCTION__),
554
                ],
555
            ]
556
        );
557
        $restContentHref = $content['_href'];
558
        $restContentVersionHref = "{$content['Versions']['_href']}/{$content['currentVersionNo']}";
559
        $this->publishContentVersionDraft($restContentVersionHref);
560
        $restContentVersionHref = $this->createDraftFromVersion($content['CurrentVersion']['_href']);
561
562
        // create pol-PL Translation
563
        $translationToDelete = 'pol-PL';
564
        $this->createVersionTranslation($restContentVersionHref, $translationToDelete, 'Polish');
565
        $this->publishContentVersionDraft($restContentVersionHref);
566
567
        // delete Translation
568
        $response = $this->sendHttpRequest(
569
            $this->createHttpRequest('DELETE', "{$restContentHref}/translations/{$translationToDelete}")
570
        );
571
        self::assertHttpResponseCodeEquals($response, 204);
572
573
        // check that deleted Translation no longer exists
574
        $response = $this->sendHttpRequest(
575
            $this->createHttpRequest('GET', "$restContentHref/versions", '', 'VersionList+json')
576
        );
577
        self::assertHttpResponseCodeEquals($response, 200);
578
        $versionList = json_decode($response->getBody(), true);
579
        foreach ($versionList['VersionList']['VersionItem'] as $versionItem) {
580
            self::assertNotContains($translationToDelete, $versionItem['VersionInfo']['languageCodes']);
581
            foreach ($versionItem['VersionInfo']['names']['value'] as $name) {
582
                self::assertNotEquals($translationToDelete, $name['_languageCode']);
583
            }
584
        }
585
586
        return $restContentHref;
587
    }
588
589
    /**
590
     * Test that deleting content which has Version(s) with single Translation being deleted is supported.
591
     *
592
     * Covers DELETE /content/objects/<contentId>/translations/<languageCode>.
593
     *
594
     * @depends testDeleteTranslation
595
     *
596
     * @param string $restContentHref
597
     */
598
    public function testDeleteTranslationOfContentWithSingleTranslationVersion($restContentHref)
599
    {
600
        // create draft independent from other tests
601
        $restContentVersionHref = $this->createDraftFromVersion("$restContentHref/versions/1");
602
603
        // create pol-PL Translation to have more than one Translation
604
        $this->createVersionTranslation($restContentVersionHref, 'pol-PL', 'Polish');
605
        $this->publishContentVersionDraft($restContentVersionHref);
606
607
        // change Main Translation to just created pol-PL
608
        $this->updateMainTranslation($restContentHref, 'pol-PL');
609
610
        // delete eng-GB Translation
611
        $translationToDelete = 'eng-GB';
612
        $response = $this->sendHttpRequest(
613
            $this->createHttpRequest('DELETE', "{$restContentHref}/translations/{$translationToDelete}")
614
        );
615
        self::assertHttpResponseCodeEquals($response, 204);
616
617
        // check that deleted Translation no longer exists
618
        $response = $this->sendHttpRequest(
619
            $this->createHttpRequest('GET', "$restContentHref/versions", '', 'VersionList+json')
620
        );
621
        self::assertHttpResponseCodeEquals($response, 200);
622
        $versionList = json_decode($response->getBody(), true);
623
        foreach ($versionList['VersionList']['VersionItem'] as $versionItem) {
624
            self::assertNotEmpty($versionItem['VersionInfo']['languageCodes']);
625
            self::assertNotContains($translationToDelete, $versionItem['VersionInfo']['languageCodes']);
626
            foreach ($versionItem['VersionInfo']['names']['value'] as $name) {
627
                self::assertNotEquals($translationToDelete, $name['_languageCode']);
628
            }
629
        }
630
    }
631
632
    /**
633
     * Publish another Version with new Translation.
634
     *
635
     * @param string $restContentVersionHref
636
     *
637
     * @param string $languageCode
638
     * @param string $languageName
639
     *
640
     * @return string
641
     */
642 View Code Duplication
    private function createVersionTranslation($restContentVersionHref, $languageCode, $languageName)
643
    {
644
        // @todo Implement EZP-21171 to check if Language exists and add it
645
        // for now adding is done by ez:behat:create-language command executed in Travis job
646
647
        $xml = <<< XML
648
<VersionUpdate>
649
    <fields>
650
        <field>
651
            <fieldDefinitionIdentifier>name</fieldDefinitionIdentifier>
652
            <languageCode>{$languageCode}</languageCode>
653
            <fieldValue>{$languageName} translated name</fieldValue>
654
        </field>
655
    </fields>
656
</VersionUpdate>
657
XML;
658
659
        $request = $this->createHttpRequest(
660
            'PATCH',
661
            $restContentVersionHref,
662
            'VersionUpdate+xml',
663
            'Version+json',
664
            $xml
665
        );
666
        $response = $this->sendHttpRequest($request);
667
668
        self::assertHttpResponseCodeEquals($response, 200);
669
    }
670
671
    /**
672
     * Iterate through Version Items returned by REST view for ContentType: VersionList+json
673
     * and return first VersionInfo data matching given status.
674
     *
675
     * @param array $versionList
676
     * @param string $status uppercase string representation of Version status
677
     *
678
     * @return array
679
     */
680
    private function getVersionInfoFromJSONVersionListByStatus(array $versionList, $status)
681
    {
682
        foreach ($versionList['VersionItem'] as $versionItem) {
683
            if ($versionItem['VersionInfo']['status'] === $status) {
684
                return $versionItem['VersionInfo'];
685
            }
686
        }
687
688
        throw new \RuntimeException("Test internal error: Version with status {$status} not found");
689
    }
690
691
    /**
692
     * Assert that Version REST Response contains proper fields.
693
     *
694
     * @param \Psr\Http\Message\ResponseInterface $response
695
     */
696
    private function assertVersionResponseContainsExpectedFields(ResponseInterface $response)
697
    {
698
        self::assertHttpResponseHasHeader($response, 'Content-Type');
699
        $contentType = $response->getHeader('Content-Type')[0];
700
        self::assertNotEmpty($contentType);
701
702
        $responseBody = $response->getBody();
703
704
        // check if response is of an expected Content-Type
705
        self::assertEquals('Version+xml', $this->getMediaFromTypeString($contentType));
706
707
        // validate by custom XSD
708
        $document = new \DOMDocument();
709
        $document->loadXML($responseBody);
710
        $document->schemaValidate(__DIR__ . '/xsd/Version.xsd');
711
    }
712
713
    /**
714
     * Create new Content Draft.
715
     *
716
     * @param string $restContentTypeHref Content Type REST resource link
717
     * @param string $restParentLocationHref Parent Location REST resource link
718
     * @param string $restSectionHref Section REST resource link
719
     * @param string $restUserHref User REST resource link
720
     * @param array $fieldValues multilingual field values <code>['fieldIdentifier' => ['languageCode' => 'value']]</code>
721
     *
722
     * @return array Content structure decoded from JSON
723
     */
724
    private function createContentDraft($restContentTypeHref, $restParentLocationHref, $restSectionHref, $restUserHref, array $fieldValues)
725
    {
726
        $remoteId = md5(microtime() . uniqid());
727
        $modificationDate = new \DateTime();
728
729
        $fieldsXML = '';
730
        foreach ($fieldValues as $fieldIdentifier => $multilingualValues) {
731
            foreach ($multilingualValues as $languageCode => $fieldValue) {
732
                $fieldsXML .= <<< XML
733
<field>
734
  <fieldDefinitionIdentifier>{$fieldIdentifier}</fieldDefinitionIdentifier>
735
  <languageCode>{$languageCode}</languageCode>
736
  <fieldValue>{$fieldValue}</fieldValue>
737
</field>
738
XML;
739
            }
740
        }
741
742
        $body = <<< XML
743
<?xml version="1.0" encoding="UTF-8"?>
744
<ContentCreate>
745
  <ContentType href="{$restContentTypeHref}" />
746
  <mainLanguageCode>eng-GB</mainLanguageCode>
747
  <LocationCreate>
748
    <ParentLocation href="{$restParentLocationHref}" />
749
    <priority>0</priority>
750
    <hidden>false</hidden>
751
    <sortField>PATH</sortField>
752
    <sortOrder>ASC</sortOrder>
753
  </LocationCreate>
754
  <Section href="{$restSectionHref}" />
755
  <alwaysAvailable>true</alwaysAvailable>
756
  <remoteId>{$remoteId}</remoteId>
757
  <User href="{$restUserHref}" />
758
  <modificationDate>{$modificationDate->format('c')}</modificationDate>
759
  <fields>
760
    {$fieldsXML}
761
  </fields>
762
</ContentCreate>
763
XML;
764
        $request = $this->createHttpRequest(
765
            'POST',
766
            '/api/ezp/v2/content/objects',
767
            'ContentCreate+xml',
768
            'ContentInfo+json',
769
            $body
770
        );
771
772
        $response = $this->sendHttpRequest($request);
773
774
        self::assertHttpResponseCodeEquals($response, 201);
775
        self::assertHttpResponseHasHeader($response, 'Location');
776
777
        $href = $response->getHeader('Location')[0];
778
        $this->addCreatedElement($href);
779
780
        $content = json_decode($response->getBody(), true);
781
        self::assertNotEmpty($content['Content']);
782
783
        return $content['Content'];
784
    }
785
786
    /**
787
     * Create Draft of a given Content and versionNo.
788
     *
789
     * @param string $restContentVersionHref REST resource link of Content Version
790
     *
791
     * @return string Content Version Draft REST resource link
792
     */
793
    private function createDraftFromVersion($restContentVersionHref)
794
    {
795
        $response = $this->sendHttpRequest(
796
            $this->createHttpRequest('COPY', "{$restContentVersionHref}")
797
        );
798
        self::assertHttpResponseCodeEquals($response, 201);
799
800
        $href = $response->getHeader('Location')[0];
801
        self::assertNotEmpty($href);
802
803
        return $href;
804
    }
805
806
    /**
807
     * Publish Content Version Draft given by REST resource link.
808
     *
809
     * @param string $restContentVersionHref REST resource link of Version Draft
810
     */
811
    private function publishContentVersionDraft($restContentVersionHref)
812
    {
813
        $response = $this->sendHttpRequest(
814
            $this->createHttpRequest('PUBLISH', $restContentVersionHref)
815
        );
816
        self::assertHttpResponseCodeEquals($response, 204);
817
    }
818
819
    /**
820
     * Update Main Translation of a Content.
821
     *
822
     * @param string $restContentHref REST resource link of Content
823
     * @param string $languageCode new Main Translation language code
824
     */
825 View Code Duplication
    private function updateMainTranslation($restContentHref, $languageCode)
826
    {
827
        $content = <<< XML
828
<?xml version="1.0" encoding="UTF-8"?>
829
<ContentUpdate>
830
  <mainLanguageCode>{$languageCode}</mainLanguageCode>
831
</ContentUpdate>
832
XML;
833
834
        $request = $this->createHttpRequest(
835
            'PATCH',
836
            $restContentHref,
837
            'ContentUpdate+xml',
838
            'ContentInfo+json',
839
            $content
840
        );
841
        $response = $this->sendHttpRequest($request);
842
843
        self::assertHttpResponseCodeEquals($response, 200);
844
    }
845
}
846