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