public function ParagraphsTranslationTest::testParagraphTranslation

Same name in this branch
  1. 8.x-1.x paragraphs/tests/src/Functional/WidgetStable/ParagraphsTranslationTest.php \Drupal\Tests\paragraphs\Functional\WidgetStable\ParagraphsTranslationTest::testParagraphTranslation()
  2. 8.x-1.x paragraphs/tests/src/Functional/WidgetLegacy/ParagraphsTranslationTest.php \Drupal\Tests\paragraphs\Functional\WidgetLegacy\ParagraphsTranslationTest::testParagraphTranslation()

Tests the paragraph translation.

File

paragraphs/tests/src/Functional/WidgetStable/ParagraphsTranslationTest.php, line 96

Class

ParagraphsTranslationTest
Tests the configuration of paragraphs.

Namespace

Drupal\Tests\paragraphs\Functional\WidgetStable

Code

public function testParagraphTranslation() {

  // We need to add a permission to administer roles to deal with revisions.
  $roles = $this->loggedInUser
    ->getRoles();
  $this
    ->grantPermissions(Role::load(array_shift($roles)), [
    'administer nodes',
  ]);
  $this
    ->drupalGet('admin/config/regional/content-language');

  // Check the settings are saved correctly.
  $this
    ->assertSession()
    ->checkboxChecked('edit-entity-types-paragraph');
  $this
    ->assertSession()
    ->checkboxChecked('edit-settings-node-paragraphed-content-demo-translatable');
  $this
    ->assertSession()
    ->checkboxChecked('edit-settings-paragraph-text-image-translatable');
  $this
    ->assertSession()
    ->checkboxChecked('edit-settings-paragraph-images-columns-field-images-demo-alt');
  $this
    ->assertSession()
    ->checkboxChecked('edit-settings-paragraph-images-columns-field-images-demo-title');

  // Check if the publish/unpublish option works.
  $this
    ->drupalGet('admin/structure/paragraphs_type/text_image/form-display');
  $edit = array(
    'fields[status][type]' => 'boolean_checkbox',
    'fields[status][region]' => 'content',
  );

  // Use the stable widget.
  $form_display = EntityFormDisplay::load('node.paragraphed_content_demo.default')
    ->setComponent('field_paragraphs_demo', [
    'type' => 'paragraphs',
  ]);
  $form_display
    ->save();

  // Use the stable widget.
  $form_display = EntityFormDisplay::load('paragraph.nested_paragraph.default')
    ->setComponent('field_paragraphs_demo', [
    'type' => 'paragraphs',
  ]);
  $form_display
    ->save();
  $this
    ->submitForm($edit, 'Save');
  $this
    ->drupalGet('node/add/paragraphed_content_demo');
  $this
    ->submitForm([], 'Add text_image');
  $this
    ->assertSession()
    ->responseContains('edit-field-paragraphs-demo-0-subform-status-value');
  $edit = [
    'title[0][value]' => 'example_publish_unpublish',
    'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Example published and unpublished',
  ];
  $this
    ->submitForm($edit, 'Save');
  $this
    ->assertSession()
    ->pageTextContains('Example published and unpublished');
  $this
    ->clickLink('Edit');
  $this
    ->submitForm([], 'field_paragraphs_demo_nested_paragraph_add_more');
  $this
    ->submitForm([], 'field_paragraphs_demo_1_subform_field_paragraphs_demo_text_add_more');
  $edit = [
    'field_paragraphs_demo[0][subform][status][value]' => FALSE,
    'field_paragraphs_demo[1][subform][field_paragraphs_demo][0][subform][field_text_demo][0][value]' => 'Dummy text',
  ];
  $this
    ->submitForm($edit, 'Save');
  $this
    ->assertSession()
    ->pageTextNotContains('Example published and unpublished');

  // Check the parent fields are set properly. Get the node.
  $node = $this
    ->drupalGetNodeByTitle('example_publish_unpublish');

  // Loop over the paragraphs of the node.
  foreach ($node->field_paragraphs_demo
    ->referencedEntities() as $paragraph) {
    $node_paragraph = Paragraph::load($paragraph
      ->id())
      ->toArray();

    // Check if the fields are set properly.
    $this
      ->assertEquals($node_paragraph['parent_id'][0]['value'], $node
      ->id());
    $this
      ->assertEquals($node_paragraph['parent_type'][0]['value'], 'node');
    $this
      ->assertEquals($node_paragraph['parent_field_name'][0]['value'], 'field_paragraphs_demo');

    // If the paragraph is nested type load the child.
    if ($node_paragraph['type'][0]['target_id'] == 'nested_paragraph') {
      $nested_paragraph = Paragraph::load($node_paragraph['field_paragraphs_demo'][0]['target_id'])
        ->toArray();

      // Check if the fields are properly set.
      $this
        ->assertEquals($nested_paragraph['parent_id'][0]['value'], $paragraph
        ->id());
      $this
        ->assertEquals($nested_paragraph['parent_type'][0]['value'], 'paragraph');
      $this
        ->assertEquals($nested_paragraph['parent_field_name'][0]['value'], 'field_paragraphs_demo');
    }
  }

  // Add paragraphed content.
  $this
    ->drupalGet('node/add/paragraphed_content_demo');
  $this
    ->submitForm([], 'Add text_image');
  $edit = array(
    'title[0][value]' => 'Title in english',
    'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Text in english',
  );

  // The button to remove a paragraph is present.
  $this
    ->assertSession()
    ->responseContains('Remove');
  $this
    ->submitForm($edit, 'Save');
  $node = $this
    ->drupalGetNodeByTitle('Title in english');

  // The text is present when editing again.
  $this
    ->clickLink('Edit');
  $this
    ->assertSession()
    ->pageTextContains('Title in english');
  $this
    ->assertSession()
    ->pageTextContains('Text in english');

  // Add french translation.
  $this
    ->clickLink('Translate');
  $this
    ->clickLink('Add', 1);

  // Make sure the Add / Remove paragraph buttons are hidden.
  $this
    ->assertSession()
    ->responseNotContains('Remove');
  $this
    ->assertSession()
    ->responseNotContains('Add text_image');

  // Make sure that the original paragraph text is displayed.
  $this
    ->assertSession()
    ->pageTextContains('Text in english');
  $edit = array(
    'title[0][value]' => 'Title in french',
    'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'Text in french',
    'revision' => TRUE,
    'revision_log[0][value]' => 'french 1',
  );
  $this
    ->submitForm($edit, 'Save (this translation)');
  $this
    ->assertSession()
    ->pageTextContains('paragraphed_content_demo Title in french has been updated.');

  // Check the english translation.
  $this
    ->drupalGet('node/' . $node
    ->id());
  $this
    ->assertSession()
    ->pageTextContains('Title in english');
  $this
    ->assertSession()
    ->pageTextContains('Text in english');
  $this
    ->assertSession()
    ->pageTextNotContains('Title in french');
  $this
    ->assertSession()
    ->pageTextNotContains('Text in french');

  // Check the french translation.
  $this
    ->drupalGet('fr/node/' . $node
    ->id());
  $this
    ->assertSession()
    ->pageTextContains('Title in french');
  $this
    ->assertSession()
    ->pageTextContains('Text in french');
  $this
    ->assertSession()
    ->pageTextNotContains('Title in english');

  // The translation is still present when editing again.
  $this
    ->clickLink('Edit');
  $this
    ->assertSession()
    ->pageTextContains('Title in french');
  $this
    ->assertSession()
    ->pageTextContains('Text in french');
  $edit = array(
    'title[0][value]' => 'Title Change in french',
    'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'New text in french',
    'revision' => TRUE,
    'revision_log[0][value]' => 'french 2',
  );
  $this
    ->submitForm($edit, 'Save (this translation)');
  $this
    ->assertSession()
    ->pageTextContains('Title Change in french');
  $this
    ->assertSession()
    ->pageTextContains('New text in french');

  // Back to the source language.
  $this
    ->drupalGet('node/' . $node
    ->id());
  $this
    ->clickLink('Edit');
  $this
    ->assertSession()
    ->pageTextContains('Title in english');
  $this
    ->assertSession()
    ->pageTextContains('Text in english');

  // Save the original content on second request.
  $this
    ->submitForm([], 'Save (this translation)');
  $this
    ->assertSession()
    ->pageTextContains('paragraphed_content_demo Title in english has been updated.');

  // Test if reverting to old paragraphs revisions works, make sure that
  // the reverted node can be saved again.
  $this
    ->drupalGet('fr/node/' . $node
    ->id() . '/revisions');
  $this
    ->clickLink('Revert');
  $this
    ->submitForm([
    'revert_untranslated_fields' => TRUE,
  ], 'Revert');
  $this
    ->clickLink('Edit');
  $this
    ->assertSession()
    ->responseContains('Title in french');
  $this
    ->assertSession()
    ->pageTextContains('Text in french');
  $this
    ->submitForm([], 'Save (this translation)');
  $this
    ->assertSession()
    ->responseNotContains('The content has either been modified by another user, or you have already submitted modifications');
  $this
    ->assertSession()
    ->pageTextContains('Text in french');

  //Add paragraphed content with untranslatable language
  $this
    ->drupalGet('node/add/paragraphed_content_demo');
  $edit = array(
    'langcode[0][value]' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
  );
  $this
    ->submitForm($edit, 'Add text_image');
  $this
    ->assertSession()
    ->statusCodeEquals(200);

  // Make 'Images' paragraph field translatable, enable alt and title fields.
  $this
    ->drupalGet('admin/structure/paragraphs_type/images/fields');
  $this
    ->clickLink('Edit');
  $edit = [
    'translatable' => 1,
    'settings[alt_field]' => 1,
    'settings[title_field]' => 1,
  ];
  $this
    ->submitForm($edit, 'Save settings');

  // Create a node with an image paragraph, its alt and title text.
  $files = $this
    ->getTestFiles('image');
  $file_system = \Drupal::service('file_system');
  $file_path = $file_system
    ->realpath($file_system
    ->realpath($files[0]->uri));
  $this
    ->drupalGet('node/add/paragraphed_content_demo');
  $this
    ->submitForm([], 'Add images');
  $this
    ->submitForm([
    'files[field_paragraphs_demo_0_subform_field_images_demo_0][]' => $file_path,
  ], 'Upload');
  $edit = [
    'title[0][value]' => 'Title EN',
    'field_paragraphs_demo[0][subform][field_images_demo][0][alt]' => 'Image alt',
    'field_paragraphs_demo[0][subform][field_images_demo][0][title]' => 'Image title',
  ];
  $this
    ->submitForm($edit, 'Save');

  // Translate the node with the image paragraph.
  $this
    ->clickLink('Translate');
  $this
    ->clickLink('Add', 1);
  $edit = [
    'title[0][value]' => 'Title FR',
    'field_paragraphs_demo[0][subform][field_images_demo][0][alt]' => 'Image alt FR',
    'field_paragraphs_demo[0][subform][field_images_demo][0][title]' => 'Image title FR',
  ];
  $this
    ->submitForm($edit, 'Save (this translation)');
  $this
    ->assertSession()
    ->responseContains('Title FR');
  $this
    ->drupalGet('node/add/paragraphed_content_demo');
  $this
    ->submitForm([], 'Add text');
  $edit = [
    'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'texto',
    'title[0][value]' => 'titulo',
    'langcode[0][value]' => 'de',
  ];
  $this
    ->submitForm($edit, 'Save');
  $node = $this
    ->drupalGetNodeByTitle('titulo');
  $this
    ->assertParagraphsLangcode($node
    ->id(), 'de');

  // Test langcode matching when Paragraphs and node have different language.
  $paragraph_1 = Paragraph::create([
    'title' => 'Paragraph',
    'type' => 'text',
    'langcode' => 'en',
    'field_text_demo' => 'english_text_1',
  ]);
  $paragraph_1
    ->save();
  $paragraph_2 = Paragraph::create([
    'title' => 'Paragraph',
    'type' => 'text',
    'langcode' => 'en',
    'field_text_demo' => 'english_text_2',
  ]);
  $paragraph_2
    ->save();
  $paragraph_data = $paragraph_2
    ->toArray();
  $paragraph_data['field_text_demo'] = 'german_text_2';
  $paragraph_2
    ->addTranslation('de', $paragraph_data);
  $paragraph_2
    ->save();
  $translated_paragraph = $paragraph_2
    ->getTranslation('en');
  $node = $this
    ->createNode([
    'langcode' => 'de',
    'type' => 'paragraphed_content_demo',
    'field_paragraphs_demo' => [
      $paragraph_1,
      $translated_paragraph,
    ],
  ]);
  $this
    ->drupalGet('node/' . $node
    ->id() . '/edit');
  $this
    ->submitForm([], 'Save');
  $this
    ->assertSession()
    ->pageTextContains('paragraphed_content_demo ' . $node
    ->label() . ' has been updated.');

  // Check that first paragraph langcode has been updated.
  \Drupal::entityTypeManager()
    ->getStorage('paragraph')
    ->resetCache([
    $paragraph_1
      ->id(),
    $paragraph_2
      ->id(),
  ]);
  $paragraph = Paragraph::load($paragraph_1
    ->id());
  $this
    ->assertEquals($paragraph
    ->language()
    ->getId(), 'de');
  $this
    ->assertFalse($paragraph
    ->hasTranslation('en'));

  // Check that second paragraph has two translations.
  $paragraph = Paragraph::load($paragraph_2
    ->id());
  $this
    ->assertTrue($paragraph
    ->hasTranslation('de'));
  $this
    ->assertTrue($paragraph
    ->hasTranslation('en'));
  $this
    ->assertSession()
    ->responseContains('german_text');

  // Create an english translation of the node.
  $edit = [
    'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'english_translation_1',
    'field_paragraphs_demo[1][subform][field_text_demo][0][value]' => 'english_translation_2',
  ];
  $this
    ->drupalGet('node/' . $node
    ->id() . '/translations/add/de/en');
  $this
    ->submitForm($edit, 'Save (this translation)');

  // Attempt to create a french translation.
  $this
    ->drupalGet('node/' . $node
    ->id() . '/translations/add/de/fr');

  // Check that the german translation of the paragraphs is displayed.
  $this
    ->assertSession()
    ->fieldValueEquals('field_paragraphs_demo[0][subform][field_text_demo][0][value]', 'english_text_1');
  $this
    ->assertSession()
    ->fieldValueEquals('field_paragraphs_demo[1][subform][field_text_demo][0][value]', 'german_text_2');
  $this
    ->submitForm([
    'source_langcode[source]' => 'en',
  ], 'Change');

  // Check that the english translation of the paragraphs is displayed.
  $this
    ->assertSession()
    ->fieldValueEquals('field_paragraphs_demo[0][subform][field_text_demo][0][value]', 'english_translation_1');
  $this
    ->assertSession()
    ->fieldValueEquals('field_paragraphs_demo[1][subform][field_text_demo][0][value]', 'english_translation_2');

  // Create a node with empty Paragraphs.
  $this
    ->drupalGet('node/add/paragraphed_content_demo');
  $this
    ->submitForm([], 'Add nested_paragraph');
  $edit = [
    'title[0][value]' => 'empty_node',
  ];
  $this
    ->submitForm($edit, 'Save');

  // Attempt to translate it.
  $this
    ->clickLink('Translate');
  $this
    ->clickLink('Add');

  // Check the add button is not displayed.
  $this
    ->assertEquals(count($this
    ->xpath('//*[@name="field_paragraphs_demo_0_subform_field_paragraphs_demo_images_add_more"]')), 0);

  // Add a non translatable field to Text Paragraph type.
  static::fieldUIAddNewField('admin/structure/paragraphs_type/text', 'untranslatable_field', 'untranslatable_field', 'text_long', [], []);

  // Add a non translatable reference field.
  static::fieldUIAddNewField('admin/structure/paragraphs_type/text', 'untranslatable_ref_field', 'untranslatable_ref_field', 'field_ui:entity_reference:node', [], [
    'settings[handler_settings][target_bundles][paragraphed_content_demo]' => TRUE,
  ]);

  // Add a non translatable link field.
  static::fieldUIAddNewField('admin/structure/paragraphs_type/text', 'untranslatable_link_field', 'untranslatable_link_field', 'link', [], []);

  // Attempt to add a translation.
  $this
    ->drupalGet('node/' . $node
    ->id() . '/translations/add/de/fr');
  $this
    ->assertSession()
    ->pageTextContains('untranslatable_field (all languages)');
  $this
    ->assertSession()
    ->pageTextContains('untranslatable_ref_field (all languages)');
  $this
    ->assertSession()
    ->pageTextContains('untranslatable_link_field (all languages)');
  $this
    ->assertSession()
    ->pageTextNotContains('Text (all languages)');

  // Enable translations for the reference and link field.
  $edit = [
    'translatable' => TRUE,
  ];
  $this
    ->drupalGet('admin/structure/paragraphs_type/text/fields/paragraph.text.field_untranslatable_ref_field');
  $this
    ->submitForm($edit, 'Save settings');
  $this
    ->drupalGet('admin/structure/paragraphs_type/text/fields/paragraph.text.field_untranslatable_link_field');
  $this
    ->submitForm($edit, 'Save settings');

  // Attempt to add a translation.
  $this
    ->drupalGet('node/' . $node
    ->id() . '/translations/add/de/fr');
  $this
    ->assertSession()
    ->pageTextContains('untranslatable_field (all languages)');
  $this
    ->assertSession()
    ->pageTextNotContains('untranslatable_link_field (all languages)');
  $this
    ->assertSession()
    ->pageTextNotContains('untranslatable_ref_field (all languages)');
  $this
    ->assertSession()
    ->pageTextNotContains('Text (all languages)');

  // Test the summary in multilingual scenarios.
  // Case 1: Nested Paragraphs.
  $this
    ->setParagraphsWidgetSettings('paragraphed_content_demo', 'field_paragraphs_demo', [
    'edit_mode' => 'closed',
  ]);

  // Create a node with a text and a nested paragraph.
  $this
    ->drupalGet('node/add/paragraphed_content_demo');
  $this
    ->submitForm([], 'Add text');
  $this
    ->submitForm([], 'Add nested_paragraph');
  $this
    ->submitForm([], 'field_paragraphs_demo_1_subform_field_paragraphs_demo_text_add_more');
  $edit = [
    'title[0][value]' => 'EN llama',
    'langcode[0][value]' => 'en',
    'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'EN text llama',
    'field_paragraphs_demo[1][subform][field_paragraphs_demo][0][subform][field_text_demo][0][value]' => 'EN nested text llama',
  ];
  $this
    ->submitForm($edit, 'Save');
  $this
    ->assertSession()
    ->pageTextContains('paragraphed_content_demo EN llama has been created.');

  // Create a german translation.
  $node = $this
    ->drupalGetNodeByTitle('EN llama');
  $this
    ->drupalGet('node/' . $node
    ->id() . '/translations/add/en/de');
  $this
    ->submitForm([], 'field_paragraphs_demo_edit_all');
  $edit = [
    'title[0][value]' => 'DE llama',
    'field_paragraphs_demo[0][subform][field_text_demo][0][value]' => 'DE text llama',
    'field_paragraphs_demo[1][subform][field_paragraphs_demo][0][subform][field_text_demo][0][value]' => 'DE nested text llama',
  ];
  $this
    ->submitForm($edit, 'Save (this translation)');

  // Assert that the summary is displayed in the current language.
  $this
    ->drupalGet('de/node/' . $node
    ->id() . '/edit');
  $this
    ->assertSession()
    ->fieldValueEquals('title[0][value]', 'DE llama');
  $this
    ->assertSession()
    ->responseContains('<span class="summary-content">DE text llama</span></div></div>');
  $this
    ->assertSession()
    ->responseContains('<span class="summary-content">DE nested text llama</span></div></div>');

  // Case 2: Referenced entities.
  $this
    ->addParagraphsType('node_reference');
  static::fieldUIAddNewField('admin/structure/paragraphs_type/node_reference', 'entity_reference', 'Entity reference', 'entity_reference', [
    'settings[target_type]' => 'node',
    'cardinality' => '-1',
  ], [
    'settings[handler_settings][target_bundles][paragraphed_content_demo]' => TRUE,
  ]);

  // Add a node with a reference paragraph.
  $this
    ->drupalGet('node/add/paragraphed_content_demo');
  $this
    ->submitForm([], 'Add node_reference');
  $edit = [
    'title[0][value]' => 'EN referencing llama',
    'langcode[0][value]' => 'en',
    'field_paragraphs_demo[0][subform][field_entity_reference][0][target_id]' => $node
      ->label() . ' (' . $node
      ->id() . ')',
  ];
  $this
    ->submitForm($edit, 'Save');
  $referencing_node = $this
    ->drupalGetNodeByTitle('EN referencing llama');

  // Translate the node.
  $this
    ->drupalGet('node/' . $referencing_node
    ->id() . '/translations/add/en/de');
  $edit = [
    'title[0][value]' => 'DE referencing llama',
  ];
  $this
    ->submitForm($edit, 'Save (this translation)');

  // Edit the node again and check the paragraph summary.
  $this
    ->drupalGet('de/node/' . $referencing_node
    ->id() . '/edit');
  $this
    ->assertSession()
    ->responseContains('<span class="summary-content">DE llama</span></div></div>');
}