d1644ef41e556da5f4f3410263ca10f707ca358d
[yaffs-website] / web / modules / contrib / paragraphs / src / Tests / Experimental / ParagraphsExperimentalTranslationTest.php
1 <?php
2
3 namespace Drupal\paragraphs\Tests\Experimental;
4
5 use Drupal\Component\Render\FormattableMarkup;
6 use Drupal\Core\Entity\Entity\EntityFormDisplay;
7 use Drupal\Core\Language\LanguageInterface;
8 use Drupal\paragraphs\Entity\Paragraph;
9 use Drupal\node\Entity\Node;
10
11 /**
12  * Tests the configuration of paragraphs.
13  *
14  * @group paragraphs
15  */
16 class ParagraphsExperimentalTranslationTest extends ParagraphsExperimentalTestBase {
17
18   /**
19    * Modules to enable.
20    *
21    * @var array
22    */
23   public static $modules = array(
24     'paragraphs_demo',
25     'content_translation',
26     'link',
27   );
28
29   /**
30    * {@inheritdoc}
31    */
32   protected function setUp() {
33     parent::setUp();
34     $this->loginAsAdmin([
35       'administer site configuration',
36       'create paragraphed_content_demo content',
37       'edit any paragraphed_content_demo content',
38       'delete any paragraphed_content_demo content',
39       'administer content translation',
40       'translate any entity',
41       'create content translations',
42       'administer languages',
43     ]);
44     $edit = [
45       'settings[paragraph][nested_paragraph][translatable]' => TRUE,
46       'settings[paragraph][nested_paragraph][settings][language][language_alterable]' => TRUE,
47       'settings[paragraph][images][fields][field_images_demo]' => TRUE,
48     ];
49     $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration'));
50   }
51
52   /**
53    * Tests the paragraph translation.
54    */
55   public function testParagraphTranslation() {
56     $this->drupalGet('admin/config/regional/content-language');
57
58     // Check the settings are saved correctly.
59     $this->assertFieldChecked('edit-entity-types-paragraph');
60     $this->assertFieldChecked('edit-settings-node-paragraphed-content-demo-translatable');
61     $this->assertFieldChecked('edit-settings-paragraph-text-image-translatable');
62     $this->assertFieldChecked('edit-settings-paragraph-images-columns-field-images-demo-alt');
63     $this->assertFieldChecked('edit-settings-paragraph-images-columns-field-images-demo-title');
64
65     // Check if the publish/unpublish option works.
66     $this->drupalGet('admin/structure/paragraphs_type/text_image/form-display');
67     $edit = array(
68       'fields[status][type]' => 'boolean_checkbox',
69       'fields[status][region]' => 'content',
70     );
71     // Use the experimental widget.
72     $form_display = EntityFormDisplay::load('node.paragraphed_content_demo.default')
73       ->setComponent('field_paragraphs_demo', [
74         'type' => 'paragraphs',
75       ]);
76     $form_display->save();
77     // Use the experimental widget.
78     $form_display = EntityFormDisplay::load('paragraph.nested_paragraph.default')
79       ->setComponent('field_paragraphs_demo', [
80         'type' => 'paragraphs',
81       ]);
82     $form_display->save();
83     $this->drupalPostForm(NULL, $edit, t('Save'));
84     $this->drupalGet('node/add/paragraphed_content_demo');
85     $this->drupalPostForm(NULL, NULL, t('Add Text + Image'));
86     $this->assertRaw('edit-field-paragraphs-demo-0-subform-status-value');
87     $edit = [
88       'title[0][value]' => 'example_publish_unpublish',
89       'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Example published and unpublished',
90     ];
91     $this->drupalPostForm(NULL, $edit, t('Save and publish'));
92     $this->assertText(t('Example published and unpublished'));
93     $this->clickLink(t('Edit'));
94
95     $this->drupalPostAjaxForm(NULL, NULL, 'field_paragraphs_demo_nested_paragraph_add_more');
96     $this->drupalPostAjaxForm(NULL, NULL, 'field_paragraphs_demo_1_subform_field_paragraphs_demo_text_add_more');
97     $edit = [
98       'field_paragraphs_demo[0][subform][status][value]' => FALSE,
99       'field_paragraphs_demo[1][subform][field_paragraphs_demo][0][subform][field_text_demo][0][value]' => 'Dummy text'
100     ];
101     $this->drupalPostForm(NULL, $edit, t('Save and keep published'));
102     $this->assertNoText(t('Example published and unpublished'));
103
104     // Check the parent fields are set properly. Get the node.
105     $node = $this->drupalGetNodeByTitle('example_publish_unpublish');
106     // Loop over the paragraphs of the node.
107     foreach ($node->field_paragraphs_demo->referencedEntities() as $paragraph) {
108       $node_paragraph = Paragraph::load($paragraph->id())->toArray();
109       // Check if the fields are set properly.
110       $this->assertEqual($node_paragraph['parent_id'][0]['value'], $node->id());
111       $this->assertEqual($node_paragraph['parent_type'][0]['value'], 'node');
112       $this->assertEqual($node_paragraph['parent_field_name'][0]['value'], 'field_paragraphs_demo');
113       // If the paragraph is nested type load the child.
114       if ($node_paragraph['type'][0]['target_id'] == 'nested_paragraph') {
115         $nested_paragraph = Paragraph::load($node_paragraph['field_paragraphs_demo'][0]['target_id'])->toArray();
116         // Check if the fields are properly set.
117         $this->assertEqual($nested_paragraph['parent_id'][0]['value'], $paragraph->id());
118         $this->assertEqual($nested_paragraph['parent_type'][0]['value'], 'paragraph');
119         $this->assertEqual($nested_paragraph['parent_field_name'][0]['value'], 'field_paragraphs_demo');
120       }
121     }
122
123     // Add paragraphed content.
124     $this->drupalGet('node/add/paragraphed_content_demo');
125     $this->drupalPostForm(NULL, NULL, t('Add Text + Image'));
126     $edit = array(
127       'title[0][value]' => 'Title in english',
128       'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Text in english',
129     );
130     // The button to remove a paragraph is present.
131     $this->assertRaw(t('Remove'));
132     $this->drupalPostForm(NULL, $edit, t('Save and publish'));
133     $node = $this->drupalGetNodeByTitle('Title in english');
134     // The text is present when editing again.
135     $this->clickLink(t('Edit'));
136     $this->assertText('Title in english');
137     $this->assertText('Text in english');
138
139     // Add french translation.
140     $this->clickLink(t('Translate'));
141     $this->clickLink(t('Add'), 1);
142     // Make sure the Add / Remove paragraph buttons are hidden.
143     $this->assertNoRaw(t('Remove'));
144     $this->assertNoRaw(t('Add Text + Image'));
145     // Make sure that the original paragraph text is displayed.
146     $this->assertText('Text in english');
147
148     $edit = array(
149       'title[0][value]' => 'Title in french',
150       'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Text in french',
151       'revision' => TRUE,
152       'revision_log[0][value]' => 'french 1',
153     );
154     $this->drupalPostForm(NULL, $edit, t('Save and keep published (this translation)'));
155     $this->assertText('Paragraphed article Title in french has been updated.');
156
157     // Check the english translation.
158     $this->drupalGet('node/' . $node->id());
159     $this->assertText('Title in english');
160     $this->assertText('Text in english');
161     $this->assertNoText('Title in french');
162     $this->assertNoText('Text in french');
163
164     // Check the french translation.
165     $this->drupalGet('fr/node/' . $node->id());
166     $this->assertText('Title in french');
167     $this->assertText('Text in french');
168     $this->assertNoText('Title in english');
169     // The translation is still present when editing again.
170     $this->clickLink(t('Edit'));
171     $this->assertText('Title in french');
172     $this->assertText('Text in french');
173     $edit = array(
174       'title[0][value]' => 'Title Change in french',
175       'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'New text in french',
176       'revision' => TRUE,
177       'revision_log[0][value]' => 'french 2',
178     );
179     $this->drupalPostForm(NULL, $edit, t('Save and keep published (this translation)'));
180     $this->assertText('Title Change in french');
181     $this->assertText('New text in french');
182
183     // Back to the source language.
184     $this->drupalGet('node/' . $node->id());
185     $this->clickLink(t('Edit'));
186     $this->assertText('Title in english');
187     $this->assertText('Text in english');
188     // Save the original content on second request.
189     $this->drupalPostForm(NULL, NULL, t('Save and keep published (this translation)'));
190     $this->assertText('Paragraphed article Title in english has been updated.');
191
192     // Test if reverting to old paragraphs revisions works, make sure that
193     // the reverted node can be saved again.
194     $this->drupalGet('fr/node/' . $node->id() . '/revisions');
195     $this->clickLink(t('Revert'));
196     $this->drupalPostForm(NULL, ['revert_untranslated_fields' => TRUE], t('Revert'));
197     $this->clickLink(t('Edit'));
198     $this->assertRaw('Title in french');
199     $this->assertText('Text in french');
200     $this->drupalPostForm(NULL, [], t('Save and keep published (this translation)'));
201     $this->assertNoRaw('The content has either been modified by another user, or you have already submitted modifications');
202     $this->assertText('Text in french');
203
204     //Add paragraphed content with untranslatable language
205     $this->drupalGet('node/add/paragraphed_content_demo');
206     $edit = array('langcode[0][value]' => LanguageInterface::LANGCODE_NOT_SPECIFIED);
207     $this->drupalPostForm(NULL, $edit, t('Add Text + Image'));
208     $this->assertResponse(200);
209
210     // Make 'Images' paragraph field translatable, enable alt and title fields.
211     $this->drupalGet('admin/structure/paragraphs_type/images/fields');
212     $this->clickLink('Edit');
213     $edit = [
214       'translatable' => 1,
215       'settings[alt_field]' => 1,
216       'settings[title_field]' => 1,
217     ];
218     $this->drupalPostForm(NULL, $edit, t('Save settings'));
219
220     // Create a node with an image paragraph, its alt and title text.
221     $text = 'Trust me I\'m an image';
222     file_put_contents('temporary://Image.jpg', $text);
223     $file_path = $this->container->get('file_system')->realpath('temporary://Image.jpg');
224     $this->drupalGet('node/add/paragraphed_content_demo');
225     $this->drupalPostForm(NULL, [], t('Add Images'));
226     $this->drupalPostForm(NULL, ['files[field_paragraphs_demo_0_subform_field_images_demo_0][]' => $file_path], t('Upload'));
227     $edit = [
228       'title[0][value]' => 'Title EN',
229       'field_paragraphs_demo[0][subform][field_images_demo][0][alt]' => 'Image alt',
230       'field_paragraphs_demo[0][subform][field_images_demo][0][title]' => 'Image title',
231       'field_paragraphs_demo[0][subform][field_images_demo][0][width]' => 100,
232       'field_paragraphs_demo[0][subform][field_images_demo][0][height]' => 100,
233     ];
234     $this->drupalPostForm(NULL, $edit, t('Save and publish'));
235
236     // Translate the node with the image paragraph.
237     $this->clickLink('Translate');
238     $this->clickLink(t('Add'), 1);
239     $edit = [
240       'title[0][value]' => 'Title FR',
241       'field_paragraphs_demo[0][subform][field_images_demo][0][alt]' => 'Image alt FR',
242       'field_paragraphs_demo[0][subform][field_images_demo][0][title]' => 'Image title FR',
243     ];
244     $this->drupalPostForm(NULL, $edit, t('Save and keep published (this translation)'));
245     $this->assertRaw('Title FR');
246
247     $this->drupalGet('node/add/paragraphed_content_demo');
248     $this->drupalPostForm(NULL, [], t('Add Text'));
249     $edit = [
250       'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'texto',
251       'title[0][value]' => 'titulo',
252       'langcode[0][value]' => 'de',
253     ];
254     $this->drupalPostForm(NULL, $edit, t('Save and publish'));
255     $node = $this->drupalGetNodeByTitle('titulo');
256     $this->assertParagraphsLangcode($node->id(), 'de');
257
258     // Test langcode matching when Paragraphs and node have different language.
259     $paragraph_1 = Paragraph::create([
260       'title' => 'Paragraph',
261       'type' => 'text',
262       'langcode' => 'en',
263       'field_text_demo' => 'english_text_1',
264     ]);
265     $paragraph_1->save();
266
267     $paragraph_2 = Paragraph::create([
268       'title' => 'Paragraph',
269       'type' => 'text',
270       'langcode' => 'en',
271       'field_text_demo' => 'english_text_2',
272     ]);
273     $paragraph_2->save();
274
275     $paragraph_data = $paragraph_2->toArray();
276     $paragraph_data['field_text_demo'] = 'german_text_2';
277     $paragraph_2->addTranslation('de', $paragraph_data);
278     $paragraph_2->save();
279     $translated_paragraph = $paragraph_2->getTranslation('en');
280
281     $node = $this->createNode([
282       'langcode' => 'de',
283       'type' => 'paragraphed_content_demo',
284       'field_paragraphs_demo' => [$paragraph_1, $translated_paragraph],
285     ]);
286     $this->drupalGet('node/' . $node->id() . '/edit');
287     $this->drupalPostForm(NULL, [], t('Save and keep published'));
288     $this->assertText('Paragraphed article ' . $node->label() . ' has been updated.');
289     // Check that first paragraph langcode has been updated.
290     $paragraph = Paragraph::load($paragraph_1->id());
291     $this->assertEqual($paragraph->language()->getId(), 'de');
292     $this->assertFalse($paragraph->hasTranslation('en'));
293     // Check that second paragraph has two translations.
294     $paragraph = Paragraph::load($paragraph_2->id());
295     $this->assertTrue($paragraph->hasTranslation('de'));
296     $this->assertTrue($paragraph->hasTranslation('en'));
297     $this->assertRaw('german_text');
298
299     // Create an english translation of the node.
300     $edit = [
301       'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'english_translation_1',
302       'field_paragraphs_demo[1][subform][field_text_demo][0][value]' => 'english_translation_2',
303     ];
304     $this->drupalPostForm('node/' . $node->id() . '/translations/add/de/en', $edit, t('Save and keep published (this translation)'));
305     // Attempt to create a french translation.
306     $this->drupalGet('node/' . $node->id() . '/translations/add/de/fr');
307     // Check that the german translation of the paragraphs is displayed.
308     $this->assertFieldByName('field_paragraphs_demo[0][subform][field_text_demo][0][value]', 'english_text_1');
309     $this->assertFieldByName('field_paragraphs_demo[1][subform][field_text_demo][0][value]', 'german_text_2');
310     $this->drupalPostForm(NULL, ['source_langcode[source]' => 'en'], t('Change'));
311     // Check that the english translation of the paragraphs is displayed.
312     $this->assertFieldByName('field_paragraphs_demo[0][subform][field_text_demo][0][value]', 'english_translation_1');
313     $this->assertFieldByName('field_paragraphs_demo[1][subform][field_text_demo][0][value]', 'english_translation_2');
314
315     // Create a node with empty Paragraphs.
316     $this->drupalGet('node/add/paragraphed_content_demo');
317     $this->drupalPostForm(NULL, [], t('Add Nested Paragraph'));
318     $this->drupalPostForm(NULL, ['title[0][value]' => 'empty_node'], t('Save and publish'));
319     // Attempt to translate it.
320     $this->clickLink(t('Translate'));
321     $this->clickLink(t('Add'));
322     // Check the add button is not displayed.
323     $this->assertEqual(count($this->xpath('//*[@name="field_paragraphs_demo_0_subform_field_paragraphs_demo_images_add_more"]')), 0);
324
325     // Add a non translatable field to Text Paragraph type.
326     $edit = [
327       'new_storage_type' => 'text_long',
328       'label' => 'untranslatable_field',
329       'field_name' => 'untranslatable_field',
330     ];
331     $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/add-field', $edit, t('Save and continue'));
332     $this->drupalPostForm(NULL, [], t('Save field settings'));
333     $this->drupalPostForm(NULL, [], t('Save settings'));
334
335     // Add a non translatable reference field.
336     $edit = [
337       'new_storage_type' => 'field_ui:entity_reference:node',
338       'label' => 'untranslatable_ref_field',
339       'field_name' => 'untranslatable_ref_field',
340     ];
341     $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/add-field', $edit, t('Save and continue'));
342     $this->drupalPostForm(NULL, [], t('Save field settings'));
343     $this->drupalPostForm(NULL, ['settings[handler_settings][target_bundles][paragraphed_content_demo]' => TRUE], t('Save settings'));
344
345     // Add a non translatable link field.
346     $edit = [
347       'new_storage_type' => 'link',
348       'label' => 'untranslatable_link_field',
349       'field_name' => 'untranslatable_link_field',
350     ];
351     $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/add-field', $edit, t('Save and continue'));
352     $this->drupalPostForm(NULL, [], t('Save field settings'));
353     $this->drupalPostForm(NULL, [], t('Save settings'));
354
355     // Attempt to add a translation.
356     $this->drupalGet('node/' . $node->id() . '/translations/add/de/fr');
357     $this->assertText('untranslatable_field (all languages)');
358     $this->assertText('untranslatable_ref_field (all languages)');
359     $this->assertText('untranslatable_link_field (all languages)');
360     $this->assertNoText('Text (all languages)');
361
362     // Enable translations for the reference and link field.
363     $edit = [
364       'translatable' => TRUE,
365     ];
366     $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/paragraph.text.field_untranslatable_ref_field', $edit, t('Save settings'));
367     $this->drupalPostForm('admin/structure/paragraphs_type/text/fields/paragraph.text.field_untranslatable_link_field', $edit, t('Save settings'));
368
369     // Attempt to add a translation.
370     $this->drupalGet('node/' . $node->id() . '/translations/add/de/fr');
371     $this->assertText('untranslatable_field (all languages)');
372     $this->assertNoText('untranslatable_link_field (all languages)');
373     $this->assertNoText('untranslatable_ref_field (all languages)');
374     $this->assertNoText('Text (all languages)');
375   }
376
377   /**
378    * Tests the paragraph buttons presence in translation multilingual workflow.
379    *
380    * This test covers the following test cases:
381    * 1) original node langcode in EN, translate in FR, change to DE.
382    * 2) original node langcode in DE, change site langcode to DE, change node
383    *    langcode to EN.
384    */
385   public function testParagraphTranslationMultilingual() {
386     // Case 1: original node langcode in EN, translate in FR, change to DE.
387
388     // Add 'Images' paragraph and check the paragraphs buttons are displayed.
389     // Use the experimental widget.
390     $form_display = EntityFormDisplay::load('node.paragraphed_content_demo.default')
391       ->setComponent('field_paragraphs_demo', [
392         'type' => 'paragraphs',
393       ]);
394     $form_display->save();
395     // Use the experimental widget.
396     $form_display = EntityFormDisplay::load('paragraph.nested_paragraph.default')
397       ->setComponent('field_paragraphs_demo', [
398         'type' => 'paragraphs',
399       ]);
400     $form_display->save();
401     $this->drupalGet('node/add/paragraphed_content_demo');
402     $this->drupalPostForm(NULL, NULL, t('Add Images'));
403     $this->assertParagraphsButtons(1);
404     // Upload an image and check the paragraphs buttons are still displayed.
405     $images = $this->drupalGetTestFiles('image')[0];
406     $edit = [
407       'title[0][value]' => 'Title in english',
408       'files[field_paragraphs_demo_0_subform_field_images_demo_0][]' => $images->uri,
409     ];
410     $this->drupalPostForm(NULL, $edit, t('Upload'));
411     $this->assertParagraphsButtons(1);
412     $this->drupalPostForm(NULL, NULL, t('Save and publish'));
413     $this->assertText('Title in english');
414     $node = $this->drupalGetNodeByTitle('Title in english');
415     // Check the paragraph langcode is 'en'.
416     $this->assertParagraphsLangcode($node->id());
417
418     // Add french translation.
419     $this->clickLink(t('Translate'));
420     $this->clickLink(t('Add'), 1);
421     // Make sure the host entity and its paragraphs have valid source language
422     // and check that the paragraphs buttons are hidden.
423     $this->assertNoParagraphsButtons(1);
424     $edit = [
425       'title[0][value]' => 'Title in french',
426     ];
427     $this->drupalPostForm(NULL, $edit, t('Save and keep published (this translation)'));
428     $this->assertParagraphsLangcode($node->id(), 'en', 'fr');
429     $this->assertText('Paragraphed article Title in french has been updated.');
430     $this->assertText('Title in french');
431     $this->assertNoText('Title in english');
432     // Check the original node and the paragraph langcode is still 'en'.
433     $this->assertParagraphsLangcode($node->id());
434
435     // Edit the french translation and upload a new image.
436     $this->clickLink('Edit');
437     $images = $this->drupalGetTestFiles('image')[1];
438     $this->drupalPostForm(NULL, [
439       'files[field_paragraphs_demo_0_subform_field_images_demo_1][]' => $images->uri,
440     ], t('Upload'));
441     // Check editing a translation does not affect the source langcode and
442     // check that the paragraphs buttons are still hidden.
443     $this->assertParagraphsLangcode($node->id(), 'en', 'fr');
444     $this->assertNoParagraphsButtons(1);
445     $this->drupalPostForm(NULL, NULL, t('Save and keep published (this translation)'));
446     $this->assertText('Title in french');
447     $this->assertNoText('Title in english');
448
449     // Back to the original node.
450     $this->drupalGet('node/' . $node->id());
451     $this->assertText('Title in english');
452     $this->assertNoText('Title in french');
453     // Check the original node and the paragraph langcode are still 'en' and
454     // check that the paragraphs buttons are still displayed.
455     $this->clickLink('Edit');
456     $this->assertParagraphsLangcode($node->id());
457     $this->assertParagraphsButtons(1);
458     // Change the node langcode to 'german', add a 'Nested Paragraph', check
459     // the paragraphs langcode are still 'en' and their buttons are displayed.
460     $edit = [
461       'title[0][value]' => 'Title in english (de)',
462       'langcode[0][value]' => 'de',
463     ];
464     $this->drupalPostForm(NULL, $edit, t('Add Nested Paragraph'));
465     $this->assertParagraphsLangcode($node->id());
466     $this->assertParagraphsButtons(2);
467     // Add an 'Images' paragraph inside the nested one, check the paragraphs
468     // langcode are still 'en' and the paragraphs buttons are still displayed.
469     $this->drupalPostAjaxForm(NULL, NULL, 'field_paragraphs_demo_1_subform_field_paragraphs_demo_images_add_more');
470     $this->assertParagraphsLangcode($node->id());
471     $this->assertParagraphsButtons(2);
472     // Upload a new image, check the paragraphs langcode are still 'en' and the
473     // paragraphs buttons are displayed.
474     $images = $this->drupalGetTestFiles('image')[2];
475     $this->drupalPostForm(NULL, [
476       'files[field_paragraphs_demo_1_subform_field_paragraphs_demo_0_subform_field_images_demo_0][]' => $images->uri,
477     ], t('Upload'));
478     $this->assertParagraphsLangcode($node->id());
479     $this->assertParagraphsButtons(2);
480     $this->drupalPostForm(NULL, NULL, t('Save and keep published (this translation)'));
481     $this->assertText('Title in english (de)');
482     $this->assertNoText('Title in french');
483     // Check the original node and the paragraphs langcode are now 'de'.
484     $this->assertParagraphsLangcode($node->id(), 'de');
485
486     // Check the french translation.
487     $this->drupalGet('fr/node/' . $node->id());
488     $this->assertText('Title in french');
489     $this->assertNoText('Title in english (de)');
490     // Check editing a translation does not affect the source langcode and
491     // check that the paragraphs buttons are still hidden.
492     $this->clickLink('Edit');
493     $this->assertParagraphsLangcode($node->id(), 'de', 'fr');
494     $this->assertNoParagraphsButtons(2);
495
496     // Case 2: original node langcode in DE, change site langcode to DE, change
497     // node langcode to EN.
498
499     // Change the site langcode to french.
500     $this->drupalPostForm('admin/config/regional/language', [
501       'site_default_language' => 'fr',
502     ], t('Save configuration'));
503
504     // Check the original node and its paragraphs langcode are still 'de'
505     // and the paragraphs buttons are still displayed.
506     $this->drupalGet('node/' . $node->id() . '/edit');
507     $this->assertParagraphsLangcode($node->id(), 'de');
508     $this->assertParagraphsButtons(2);
509
510     // Go to the french translation.
511     $this->drupalGet('node/' . $node->id() . '/translations');
512     $this->clickLink(t('Edit'), 1);
513     // Check editing a translation does not affect the source langcode and
514     // check that the paragraphs buttons are still hidden.
515     $this->assertParagraphsLangcode($node->id(), 'de', 'fr');
516     $this->assertNoParagraphsButtons(2);
517     // Upload another image.
518     $images = $this->drupalGetTestFiles('image')[3];
519     $this->drupalPostForm(NULL, [
520       'files[field_paragraphs_demo_1_subform_field_paragraphs_demo_0_subform_field_images_demo_1][]' => $images->uri,
521     ], t('Upload'));
522     // Check editing a translation does not affect the source langcode and
523     // check that the paragraphs buttons are still hidden.
524     $this->assertParagraphsLangcode($node->id(), 'de', 'fr');
525     $this->assertNoParagraphsButtons(2);
526     $this->drupalPostForm(NULL, NULL, t('Save and keep published (this translation)'));
527     // Check the paragraphs langcode are still 'de' after saving the translation.
528     $this->assertParagraphsLangcode($node->id(), 'de', 'fr');
529     $this->assertText('Title in french');
530     $this->assertNoText('Title in english (de)');
531
532     // Back to the original node.
533     $this->drupalGet('node/' . $node->id());
534     $this->assertText('Title in english (de)');
535     $this->assertNoText('Title in french');
536     // Check the original node and the paragraphs langcode are still 'de' and
537     // check that the paragraphs buttons are still displayed.
538     $this->clickLink('Edit');
539     $this->assertParagraphsLangcode($node->id(), 'de');
540     $this->assertParagraphsButtons(2);
541     // Change the node langcode back to 'english', add an 'Images' paragraph,
542     // check the paragraphs langcode are still 'de' and their buttons are shown.
543     $edit = [
544       'title[0][value]' => 'Title in english',
545       'langcode[0][value]' => 'en',
546     ];
547     $this->drupalPostForm(NULL, $edit, t('Add Images'));
548     $this->assertParagraphsLangcode($node->id(), 'de');
549     $this->assertParagraphsButtons(3);
550     // Upload a new image, check the paragraphs langcode are still 'de' and the
551     // paragraphs buttons are displayed.
552     $images = $this->drupalGetTestFiles('image')[4];
553     $this->drupalPostForm(NULL, [
554       'files[field_paragraphs_demo_2_subform_field_images_demo_0][]' => $images->uri,
555     ], t('Upload'));
556     $this->assertParagraphsLangcode($node->id(), 'de');
557     $this->assertParagraphsButtons(3);
558     $this->drupalPostForm(NULL, NULL, t('Save and keep published (this translation)'));
559     // Check the original node and the paragraphs langcode are now 'en'.
560     $this->assertParagraphsLangcode($node->id());
561   }
562
563   /**
564    * Tests the paragraphs buttons presence in multilingual workflow.
565    *
566    * This test covers the following test cases:
567    * 1) original node langcode in german, change to english.
568    * 2) original node langcode in english, change to german.
569    * 3) original node langcode in english, change site langcode to german,
570    *   change node langcode to german.
571    */
572   public function testParagraphsMultilingualWorkflow() {
573     // Case 1: Check the paragraphs buttons after changing the NODE language
574     // (original node langcode in GERMAN, default site langcode in english).
575     // Use the experimental widget.
576     $form_display = EntityFormDisplay::load('node.paragraphed_content_demo.default')
577       ->setComponent('field_paragraphs_demo', [
578         'type' => 'paragraphs',
579       ]);
580     $form_display->save();
581     // Use the experimental widget.
582     $form_display = EntityFormDisplay::load('paragraph.nested_paragraph.default')
583       ->setComponent('field_paragraphs_demo', [
584         'type' => 'paragraphs',
585       ]);
586     $form_display->save();
587     // Create a node and check that the node langcode is 'english'.
588     $this->drupalGet('node/add/paragraphed_content_demo');
589     $this->assertOptionSelected('edit-langcode-0-value', 'en');
590     // Change the node langcode to 'german' and add a 'Nested Paragraph'.
591     $edit = [
592       'title[0][value]' => 'Title in german',
593       'langcode[0][value]' => 'de',
594     ];
595     $this->drupalPostForm(NULL, $edit, t('Add Nested Paragraph'));
596     // Check that the paragraphs buttons are displayed and add an 'Images'
597     // paragraph inside the nested paragraph.
598     $this->assertParagraphsButtons(1);
599     $this->drupalPostAjaxForm(NULL, NULL, 'field_paragraphs_demo_0_subform_field_paragraphs_demo_images_add_more');
600     // Upload an image and check the paragraphs buttons are still displayed.
601     $images = $this->drupalGetTestFiles('image')[0];
602     $this->drupalPostForm(NULL, [
603       'files[field_paragraphs_demo_0_subform_field_paragraphs_demo_0_subform_field_images_demo_0][]' => $images->uri,
604     ], t('Upload'));
605     $this->assertParagraphsButtons(1);
606     $this->drupalPostForm(NULL, NULL, t('Save and publish'));
607     $this->assertText('Title in german');
608     $node1 = $this->getNodeByTitle('Title in german');
609
610     // Check the paragraph langcode is 'de' and its buttons are displayed.
611     // @todo check for the nested children paragraphs buttons and langcode
612     // when it's supported.
613     $this->clickLink(t('Edit'));
614     $this->assertParagraphsLangcode($node1->id(), 'de');
615     $this->assertParagraphsButtons(1);
616     // Change the node langcode to 'english' and upload another image.
617     $images = $this->drupalGetTestFiles('image')[1];
618     $edit = [
619       'title[0][value]' => 'Title in german (en)',
620       'langcode[0][value]' => 'en',
621       'files[field_paragraphs_demo_0_subform_field_paragraphs_demo_0_subform_field_images_demo_1][]' => $images->uri,
622     ];
623     $this->drupalPostForm(NULL, $edit, t('Upload'));
624     // Check the paragraph langcode is still 'de' and its buttons are shown.
625     $this->assertParagraphsLangcode($node1->id(), 'de');
626     $this->assertParagraphsButtons(1);
627     $this->drupalPostForm(NULL, NULL, t('Save and keep published'));
628     // Check the paragraph langcode is now 'en' after saving.
629     $this->assertParagraphsLangcode($node1->id());
630
631     // Check the paragraph langcode is 'en' and its buttons are still shown.
632     $this->clickLink(t('Edit'));
633     $this->assertParagraphsLangcode($node1->id());
634     $this->assertParagraphsButtons(1);
635
636     // Case 2: Check the paragraphs buttons after changing the NODE language
637     // (original node langcode in ENGLISH, default site langcode in english).
638
639     // Create another node.
640     $this->drupalGet('node/add/paragraphed_content_demo');
641     // Check that the node langcode is 'english' and add a 'Nested Paragraph'.
642     $this->assertOptionSelected('edit-langcode-0-value', 'en');
643     $this->drupalPostForm(NULL, NULL, t('Add Nested Paragraph'));
644     // Check that the paragraphs buttons are displayed and add an 'Images'
645     // paragraph inside the nested paragraph.
646     $this->assertParagraphsButtons(1);
647     $this->drupalPostAjaxForm(NULL, NULL, 'field_paragraphs_demo_0_subform_field_paragraphs_demo_images_add_more');
648     // Upload an image and check the paragraphs buttons are still displayed.
649     $images = $this->drupalGetTestFiles('image')[0];
650     $edit = [
651       'title[0][value]' => 'Title in english',
652       'files[field_paragraphs_demo_0_subform_field_paragraphs_demo_0_subform_field_images_demo_0][]' => $images->uri,
653     ];
654     $this->drupalPostForm(NULL, $edit, t('Upload'));
655     $this->assertParagraphsButtons(1);
656     $this->drupalPostForm(NULL, NULL, t('Save and publish'));
657     $this->assertText('Title in english');
658     $node2 = $this->drupalGetNodeByTitle('Title in english');
659
660     // Check the paragraph langcode is 'en' and its buttons are displayed.
661     // @todo check for the nested children paragraphs buttons and langcode
662     // when it's supported.
663     $this->clickLink(t('Edit'));
664     $this->assertParagraphsLangcode($node2->id());
665     $this->assertParagraphsButtons(1);
666     // Change the node langcode to 'german' and add another 'Images' paragraph.
667     $edit = [
668       'title[0][value]' => 'Title in english (de)',
669       'langcode[0][value]' => 'de',
670     ];
671     $this->drupalPostForm(NULL, $edit, t('Add Images'));
672     // Check the paragraphs langcode are still 'en' and their buttons are shown.
673     $this->assertParagraphsLangcode($node2->id());
674     $this->assertParagraphsButtons(2);
675     // Upload an image, check the paragraphs langcode are still 'en' and their
676     // buttons are displayed.
677     $images = $this->drupalGetTestFiles('image')[1];
678     $this->drupalPostForm(NULL, [
679       'files[field_paragraphs_demo_1_subform_field_images_demo_0][]' => $images->uri,
680     ], t('Upload'));
681     $this->assertParagraphsLangcode($node2->id());
682     $this->assertParagraphsButtons(2);
683     $this->drupalPostForm(NULL, NULL, t('Save and keep published'));
684     // Check the paragraphs langcode are now 'de' after saving.
685     $this->assertParagraphsLangcode($node2->id(), 'de');
686
687     // Change node langcode back to 'english' and save.
688     $this->clickLink(t('Edit'));
689     $edit = [
690       'title[0][value]' => 'Title in english',
691       'langcode[0][value]' => 'en',
692     ];
693     $this->drupalPostForm(NULL, $edit, t('Save and keep published'));
694     // Check the paragraphs langcode are now 'en' after saving.
695     $this->assertParagraphsLangcode($node2->id());
696
697     // Case 3: Check the paragraphs buttons after changing the SITE language.
698
699     // Change the site langcode to german.
700     $edit = [
701       'site_default_language' => 'de',
702     ];
703     $this->drupalPostForm('admin/config/regional/language', $edit, t('Save configuration'));
704
705     // Check the original node and the paragraphs langcode are still 'en' and
706     // check that the paragraphs buttons are still displayed.
707     $this->drupalGet('node/' . $node2->id() . '/edit');
708     $this->assertParagraphsLangcode($node2->id());
709     $this->assertParagraphsButtons(2);
710     // Add another 'Images' paragraph with node langcode as 'english'.
711     $this->drupalPostForm(NULL, NULL, t('Add Images'));
712     // Check the paragraph langcode are still 'en' and their buttons are shown.
713     $this->assertParagraphsLangcode($node2->id());
714     $this->assertParagraphsButtons(3);
715     // Upload an image, check the paragraphs langcode are still 'en' and their
716     // buttons are displayed.
717     $images = $this->drupalGetTestFiles('image')[2];
718     $this->drupalPostForm(NULL, [
719       'files[field_paragraphs_demo_2_subform_field_images_demo_0][]' => $images->uri,
720     ], t('Upload'));
721     $this->assertParagraphsLangcode($node2->id());
722     $this->assertParagraphsButtons(3);
723     $this->drupalPostForm(NULL, NULL, t('Save and keep published'));
724     // Check the paragraphs langcode are still 'en' after saving.
725     $this->assertParagraphsLangcode($node2->id());
726
727     // Check the paragraphs langcode are still 'en' and their buttons are shown.
728     $this->clickLink(t('Edit'));
729     $this->assertParagraphsLangcode($node2->id());
730     $this->assertParagraphsButtons(3);
731     // Change node langcode to 'german' and add another 'Images' paragraph.
732     $edit = [
733       'title[0][value]' => 'Title in english (de)',
734       'langcode[0][value]' => 'de',
735     ];
736     $this->drupalPostForm(NULL, $edit, t('Add Images'));
737     // Check the paragraphs langcode are still 'en' and their buttons are shown.
738     $this->assertParagraphsLangcode($node2->id());
739     $this->assertParagraphsButtons(4);
740     // Upload an image, check the paragraphs langcode are still 'en' and their
741     // buttons are displayed.
742     $images = $this->drupalGetTestFiles('image')[3];
743     $this->drupalPostForm(NULL, [
744       'files[field_paragraphs_demo_3_subform_field_images_demo_0][]' => $images->uri,
745     ], t('Upload'));
746     $this->assertParagraphsLangcode($node2->id());
747     $this->assertParagraphsButtons(4);
748     $this->drupalPostForm(NULL, NULL, t('Save and keep published'));
749     // Check the paragraphs langcode are now 'de' after saving.
750     $this->assertParagraphsLangcode($node2->id(), 'de');
751   }
752
753   /**
754    * Passes if the paragraphs buttons are present.
755    *
756    * @param int $count
757    *   Number of paragraphs buttons to look for.
758    */
759   protected function assertParagraphsButtons($count) {
760     $this->assertParagraphsButtonsHelper($count, FALSE);
761   }
762
763   /**
764    * Passes if the paragraphs buttons are NOT present.
765    *
766    * @param int $count
767    *   Number of paragraphs buttons to look for.
768    */
769   protected function assertNoParagraphsButtons($count) {
770     $this->assertParagraphsButtonsHelper($count, TRUE);
771   }
772
773   /**
774    * Helper for assertParagraphsButtons and assertNoParagraphsButtons.
775    *
776    * @param int $count
777    *   Number of paragraphs buttons to look for.
778    * @param bool $hidden
779    *   TRUE if these buttons should not be shown, FALSE otherwise.
780    *   Defaults to TRUE.
781    */
782   protected function assertParagraphsButtonsHelper($count, $hidden = TRUE) {
783     for ($i = 0; $i < $count; $i++) {
784       $remove_button = $this->xpath('//*[@name="field_paragraphs_demo_' . $i . '_remove"]');
785       if (!$hidden) {
786         $this->assertNotEqual(count($remove_button), 0);
787       }
788       else {
789         $this->assertEqual(count($remove_button), 0);
790       }
791     }
792
793     // It is enough to check for the specific paragraph type 'Images' to assert
794     // the add more buttons presence for this test class.
795     $add_button = $this->xpath('//input[@value="Add Images"]');
796     if (!$hidden) {
797       $this->assertNotEqual(count($add_button), 0);
798     }
799     else {
800       $this->assertEqual(count($add_button), 0);
801     }
802   }
803
804   /**
805    * Assert each paragraph items have the same langcode as the node one.
806    *
807    * @param string $node_id
808    *   The node ID which contains the paragraph items to be checked.
809    * @param string $source_lang
810    *   The expected node source langcode. Defaults to 'en'.
811    * @param string $trans_lang
812    *   The expected translated node langcode. Defaults to NULL.
813    */
814   protected function assertParagraphsLangcode($node_id, $source_lang = 'en', $trans_lang = NULL) {
815     // Update the outdated node and check all the paragraph items langcodes.
816     \Drupal::entityTypeManager()->getStorage('node')->resetCache([$node_id]);
817     /** @var \Drupal\node\NodeInterface $node */
818     $node = Node::load($node_id);
819     $node_langcode = $node->langcode->value;
820     $this->assertEqual($node_langcode, $source_lang, 'Host langcode matches.');
821
822     /** @var \Drupal\Core\Entity\ContentEntityBase $paragraph */
823     foreach ($node->field_paragraphs_demo->referencedEntities() as $paragraph) {
824       $paragraph_langcode = $paragraph->language()->getId();
825       $message = new FormattableMarkup('Node langcode is "@node", paragraph item langcode is "@item".', ['@node' => $source_lang, '@item' => $paragraph_langcode]);
826       $this->assertEqual($paragraph_langcode, $source_lang, $message);
827     }
828
829     // Check the translation.
830     if (!empty($trans_lang)) {
831       $this->assertTrue($node->hasTranslation($trans_lang), 'Translation exists.');
832     }
833     if ($node->hasTranslation($trans_lang)) {
834       $trans_node = $node->getTranslation($trans_lang);
835       $trans_node_langcode = $trans_node->language()->getId();
836       $this->assertEqual($trans_node_langcode, $trans_lang, 'Translated node langcode matches.');
837
838       // Check the paragraph item langcode matching the translated node langcode.
839       foreach ($trans_node->field_paragraphs_demo->referencedEntities() as $paragraph) {
840         if ($paragraph->hasTranslation($trans_lang)) {
841           $trans_item = $paragraph->getTranslation($trans_lang);
842           $paragraph_langcode = $trans_item->language()->getId();
843           $message = new FormattableMarkup('Translated node langcode is "@node", paragraph item langcode is "@item".', ['@node' => $trans_lang, '@item' => $paragraph_langcode]);
844           $this->assertEqual($paragraph_langcode, $trans_lang, $message);
845         }
846       }
847     }
848   }
849 }