1<?php
2
3namespace Drupal\Tests\taxonomy\Functional;
4
5use Drupal\Tests\content_translation\Functional\ContentTranslationUITestBase;
6use Drupal\Core\Language\LanguageInterface;
7use Drupal\taxonomy\Entity\Vocabulary;
8
9/**
10 * Tests the Term Translation UI.
11 *
12 * @group taxonomy
13 */
14class TermTranslationUITest extends ContentTranslationUITestBase {
15
16  /**
17   * The vocabulary used for creating terms.
18   *
19   * @var \Drupal\taxonomy\VocabularyInterface
20   */
21  protected $vocabulary;
22
23  /**
24   * Modules to enable.
25   *
26   * @var array
27   */
28  protected static $modules = ['language', 'content_translation', 'taxonomy'];
29
30  /**
31   * {@inheritdoc}
32   */
33  protected $defaultTheme = 'classy';
34
35  protected function setUp(): void {
36    $this->entityTypeId = 'taxonomy_term';
37    $this->bundle = 'tags';
38    parent::setUp();
39  }
40
41  /**
42   * {@inheritdoc}
43   */
44  protected function setupBundle() {
45    parent::setupBundle();
46
47    // Create a vocabulary.
48    $this->vocabulary = Vocabulary::create([
49      'name' => $this->bundle,
50      'description' => $this->randomMachineName(),
51      'vid' => $this->bundle,
52      'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
53      'weight' => mt_rand(0, 10),
54    ]);
55    $this->vocabulary->save();
56  }
57
58  /**
59   * {@inheritdoc}
60   */
61  protected function getTranslatorPermissions() {
62    return array_merge(parent::getTranslatorPermissions(), ['administer taxonomy']);
63  }
64
65  /**
66   * {@inheritdoc}
67   */
68  protected function getNewEntityValues($langcode) {
69    return ['name' => $this->randomMachineName()] + parent::getNewEntityValues($langcode);
70  }
71
72  /**
73   * Returns an edit array containing the values to be posted.
74   */
75  protected function getEditValues($values, $langcode, $new = FALSE) {
76    $edit = parent::getEditValues($values, $langcode, $new);
77
78    // To be able to post values for the configurable base fields (name,
79    // description) have to be suffixed with [0][value].
80    foreach ($edit as $property => $value) {
81      foreach (['name', 'description'] as $key) {
82        if ($property == $key) {
83          $edit[$key . '[0][value]'] = $value;
84          unset($edit[$property]);
85        }
86      }
87    }
88    return $edit;
89  }
90
91  /**
92   * {@inheritdoc}
93   */
94  public function testTranslationUI() {
95    parent::testTranslationUI();
96
97    // Make sure that no row was inserted for taxonomy vocabularies which do
98    // not have translations enabled.
99    $tids = \Drupal::entityQueryAggregate('taxonomy_term')
100      ->accessCheck(FALSE)
101      ->aggregate('tid', 'COUNT')
102      ->condition('vid', $this->bundle, '<>')
103      ->groupBy('tid')
104      ->execute();
105
106    foreach ($tids as $tid) {
107      $this->assertTrue($tid['tid_count'] < 2, 'Term does have translations.');
108    }
109  }
110
111  /**
112   * Tests translate link on vocabulary term list.
113   */
114  public function testTranslateLinkVocabularyAdminPage() {
115    $this->drupalLogin($this->drupalCreateUser(array_merge(parent::getTranslatorPermissions(), ['access administration pages', 'administer taxonomy'])));
116
117    $values = [
118      'name' => $this->randomMachineName(),
119    ];
120    $translatable_tid = $this->createEntity($values, $this->langcodes[0], $this->vocabulary->id());
121
122    // Create an untranslatable vocabulary.
123    $untranslatable_vocabulary = Vocabulary::create([
124      'name' => 'untranslatable_voc',
125      'description' => $this->randomMachineName(),
126      'vid' => 'untranslatable_voc',
127      'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
128      'weight' => mt_rand(0, 10),
129    ]);
130    $untranslatable_vocabulary->save();
131
132    $values = [
133      'name' => $this->randomMachineName(),
134    ];
135    $untranslatable_tid = $this->createEntity($values, $this->langcodes[0], $untranslatable_vocabulary->id());
136
137    // Verify translation links.
138    $this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
139    $this->assertSession()->statusCodeEquals(200);
140    $this->assertSession()->linkByHrefExists('term/' . $translatable_tid . '/translations', 0, 'The translations link exists for a translatable vocabulary.');
141    $this->assertSession()->linkByHrefExists('term/' . $translatable_tid . '/edit', 0, 'The edit link exists for a translatable vocabulary.');
142
143    $this->drupalGet('admin/structure/taxonomy/manage/' . $untranslatable_vocabulary->id() . '/overview');
144    $this->assertSession()->statusCodeEquals(200);
145    $this->assertSession()->linkByHrefExists('term/' . $untranslatable_tid . '/edit');
146    $this->assertSession()->linkByHrefNotExists('term/' . $untranslatable_tid . '/translations');
147  }
148
149  /**
150   * {@inheritdoc}
151   */
152  protected function doTestTranslationEdit() {
153    $storage = $this->container->get('entity_type.manager')
154      ->getStorage($this->entityTypeId);
155    $storage->resetCache([$this->entityId]);
156    $entity = $storage->load($this->entityId);
157    $languages = $this->container->get('language_manager')->getLanguages();
158
159    foreach ($this->langcodes as $langcode) {
160      // We only want to test the title for non-english translations.
161      if ($langcode != 'en') {
162        $options = ['language' => $languages[$langcode]];
163        $url = $entity->toUrl('edit-form', $options);
164        $this->drupalGet($url);
165        $this->assertSession()->pageTextContains("{$entity->getTranslation($langcode)->label()} [{$languages[$langcode]->getName()} translation]");
166      }
167    }
168  }
169
170  /**
171   * {@inheritdoc}
172   */
173  protected function doTestPublishedStatus() {
174    $storage = $this->container->get('entity_type.manager')
175      ->getStorage($this->entityTypeId);
176    $storage->resetCache([$this->entityId]);
177    $entity = $storage->load($this->entityId);
178    $languages = $this->container->get('language_manager')->getLanguages();
179
180    $statuses = [
181      TRUE,
182      FALSE,
183    ];
184
185    foreach ($statuses as $index => $value) {
186      // (Un)publish the term translations and check that the translation
187      // statuses are (un)published accordingly.
188      foreach ($this->langcodes as $langcode) {
189        $options = ['language' => $languages[$langcode]];
190        $url = $entity->toUrl('edit-form', $options);
191        $this->drupalGet($url, $options);
192        $this->submitForm(['status[value]' => $value], 'Save');
193      }
194      $storage->resetCache([$this->entityId]);
195      $entity = $storage->load($this->entityId);
196      foreach ($this->langcodes as $langcode) {
197        // The term is created as unpublished thus we switch to the published
198        // status first.
199        $status = !$index;
200        $translation = $entity->getTranslation($langcode);
201        $this->assertEquals($status, $this->manager->getTranslationMetadata($translation)->isPublished(), 'The translation has been correctly unpublished.');
202      }
203    }
204  }
205
206}
207