Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Tests\node\Functional;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Core\Entity\EntityInterface;
|
Chris@0
|
6 use Drupal\Tests\content_translation\Functional\ContentTranslationUITestBase;
|
Chris@0
|
7 use Drupal\Core\Language\LanguageInterface;
|
Chris@0
|
8 use Drupal\Core\Url;
|
Chris@0
|
9 use Drupal\node\Entity\Node;
|
Chris@0
|
10 use Drupal\language\Entity\ConfigurableLanguage;
|
Chris@0
|
11
|
Chris@0
|
12 /**
|
Chris@0
|
13 * Tests the Node Translation UI.
|
Chris@0
|
14 *
|
Chris@0
|
15 * @group node
|
Chris@0
|
16 */
|
Chris@0
|
17 class NodeTranslationUITest extends ContentTranslationUITestBase {
|
Chris@0
|
18
|
Chris@0
|
19 /**
|
Chris@0
|
20 * {inheritdoc}
|
Chris@0
|
21 */
|
Chris@0
|
22 protected $defaultCacheContexts = [
|
Chris@0
|
23 'languages:language_interface',
|
Chris@0
|
24 'theme',
|
Chris@0
|
25 'route',
|
Chris@0
|
26 'timezone',
|
Chris@0
|
27 'url.path.parent',
|
Chris@0
|
28 'url.query_args:_wrapper_format',
|
Chris@18
|
29 'url.site',
|
Chris@14
|
30 'user.roles',
|
Chris@17
|
31 'url.path.is_front',
|
Chris@14
|
32 // These two cache contexts are added by BigPipe.
|
Chris@14
|
33 'cookies:big_pipe_nojs',
|
Chris@14
|
34 'session.exists',
|
Chris@0
|
35 ];
|
Chris@0
|
36
|
Chris@0
|
37 /**
|
Chris@0
|
38 * Modules to enable.
|
Chris@0
|
39 *
|
Chris@0
|
40 * @var array
|
Chris@0
|
41 */
|
Chris@0
|
42 public static $modules = ['block', 'language', 'content_translation', 'node', 'datetime', 'field_ui', 'help'];
|
Chris@0
|
43
|
Chris@0
|
44 /**
|
Chris@0
|
45 * The profile to install as a basis for testing.
|
Chris@0
|
46 *
|
Chris@0
|
47 * @var string
|
Chris@0
|
48 */
|
Chris@0
|
49 protected $profile = 'standard';
|
Chris@0
|
50
|
Chris@0
|
51 protected function setUp() {
|
Chris@0
|
52 $this->entityTypeId = 'node';
|
Chris@0
|
53 $this->bundle = 'article';
|
Chris@0
|
54 parent::setUp();
|
Chris@0
|
55
|
Chris@0
|
56 // Ensure the help message is shown even with prefixed paths.
|
Chris@0
|
57 $this->drupalPlaceBlock('help_block', ['region' => 'content']);
|
Chris@0
|
58
|
Chris@0
|
59 // Display the language selector.
|
Chris@0
|
60 $this->drupalLogin($this->administrator);
|
Chris@0
|
61 $edit = ['language_configuration[language_alterable]' => TRUE];
|
Chris@0
|
62 $this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
|
Chris@0
|
63 $this->drupalLogin($this->translator);
|
Chris@0
|
64 }
|
Chris@0
|
65
|
Chris@0
|
66 /**
|
Chris@0
|
67 * Tests the basic translation UI.
|
Chris@0
|
68 */
|
Chris@0
|
69 public function testTranslationUI() {
|
Chris@0
|
70 parent::testTranslationUI();
|
Chris@0
|
71 $this->doUninstallTest();
|
Chris@0
|
72 }
|
Chris@0
|
73
|
Chris@0
|
74 /**
|
Chris@0
|
75 * Tests changing the published status on a node without fields.
|
Chris@0
|
76 */
|
Chris@0
|
77 public function testPublishedStatusNoFields() {
|
Chris@0
|
78 // Test changing the published status of an article without fields.
|
Chris@0
|
79 $this->drupalLogin($this->administrator);
|
Chris@0
|
80 // Delete all fields.
|
Chris@0
|
81 $this->drupalGet('admin/structure/types/manage/article/fields');
|
Chris@0
|
82 $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.' . $this->fieldName . '/delete', [], t('Delete'));
|
Chris@0
|
83 $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_tags/delete', [], t('Delete'));
|
Chris@0
|
84 $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_image/delete', [], t('Delete'));
|
Chris@0
|
85
|
Chris@0
|
86 // Add a node.
|
Chris@0
|
87 $default_langcode = $this->langcodes[0];
|
Chris@0
|
88 $values[$default_langcode] = ['title' => [['value' => $this->randomMachineName()]]];
|
Chris@0
|
89 $this->entityId = $this->createEntity($values[$default_langcode], $default_langcode);
|
Chris@0
|
90 $storage = $this->container->get('entity_type.manager')
|
Chris@0
|
91 ->getStorage($this->entityTypeId);
|
Chris@0
|
92 $storage->resetCache([$this->entityId]);
|
Chris@0
|
93 $entity = $storage->load($this->entityId);
|
Chris@0
|
94
|
Chris@0
|
95 // Add a content translation.
|
Chris@0
|
96 $langcode = 'fr';
|
Chris@0
|
97 $language = ConfigurableLanguage::load($langcode);
|
Chris@0
|
98 $values[$langcode] = ['title' => [['value' => $this->randomMachineName()]]];
|
Chris@0
|
99
|
Chris@0
|
100 $entity_type_id = $entity->getEntityTypeId();
|
Chris@0
|
101 $add_url = Url::fromRoute("entity.$entity_type_id.content_translation_add", [
|
Chris@0
|
102 $entity->getEntityTypeId() => $entity->id(),
|
Chris@0
|
103 'source' => $default_langcode,
|
Chris@17
|
104 'target' => $langcode,
|
Chris@0
|
105 ], ['language' => $language]);
|
Chris@0
|
106 $edit = $this->getEditValues($values, $langcode);
|
Chris@0
|
107 $edit['status[value]'] = FALSE;
|
Chris@0
|
108 $this->drupalPostForm($add_url, $edit, t('Save (this translation)'));
|
Chris@0
|
109
|
Chris@0
|
110 $storage->resetCache([$this->entityId]);
|
Chris@0
|
111 $entity = $storage->load($this->entityId);
|
Chris@0
|
112 $translation = $entity->getTranslation($langcode);
|
Chris@0
|
113 // Make sure we unpublished the node correctly.
|
Chris@0
|
114 $this->assertFalse($this->manager->getTranslationMetadata($translation)->isPublished(), 'The translation has been correctly unpublished.');
|
Chris@0
|
115 }
|
Chris@0
|
116
|
Chris@0
|
117 /**
|
Chris@0
|
118 * {@inheritdoc}
|
Chris@0
|
119 */
|
Chris@0
|
120 protected function getTranslatorPermissions() {
|
Chris@0
|
121 return array_merge(parent::getTranslatorPermissions(), ['administer nodes', "edit any $this->bundle content"]);
|
Chris@0
|
122 }
|
Chris@0
|
123
|
Chris@0
|
124 /**
|
Chris@0
|
125 * {@inheritdoc}
|
Chris@0
|
126 */
|
Chris@0
|
127 protected function getEditorPermissions() {
|
Chris@0
|
128 return ['administer nodes', 'create article content'];
|
Chris@0
|
129 }
|
Chris@0
|
130
|
Chris@0
|
131 /**
|
Chris@0
|
132 * {@inheritdoc}
|
Chris@0
|
133 */
|
Chris@0
|
134 protected function getAdministratorPermissions() {
|
Chris@0
|
135 return array_merge(parent::getAdministratorPermissions(), ['access administration pages', 'administer content types', 'administer node fields', 'access content overview', 'bypass node access', 'administer languages', 'administer themes', 'view the administration theme']);
|
Chris@0
|
136 }
|
Chris@0
|
137
|
Chris@0
|
138 /**
|
Chris@0
|
139 * {@inheritdoc}
|
Chris@0
|
140 */
|
Chris@0
|
141 protected function getNewEntityValues($langcode) {
|
Chris@0
|
142 return ['title' => [['value' => $this->randomMachineName()]]] + parent::getNewEntityValues($langcode);
|
Chris@0
|
143 }
|
Chris@0
|
144
|
Chris@0
|
145 /**
|
Chris@0
|
146 * {@inheritdoc}
|
Chris@0
|
147 */
|
Chris@0
|
148 protected function doTestPublishedStatus() {
|
Chris@0
|
149 $storage = $this->container->get('entity_type.manager')
|
Chris@0
|
150 ->getStorage($this->entityTypeId);
|
Chris@0
|
151 $storage->resetCache([$this->entityId]);
|
Chris@0
|
152 $entity = $storage->load($this->entityId);
|
Chris@0
|
153 $languages = $this->container->get('language_manager')->getLanguages();
|
Chris@0
|
154
|
Chris@0
|
155 $statuses = [
|
Chris@0
|
156 TRUE,
|
Chris@0
|
157 FALSE,
|
Chris@0
|
158 ];
|
Chris@0
|
159
|
Chris@0
|
160 foreach ($statuses as $index => $value) {
|
Chris@0
|
161 // (Un)publish the node translations and check that the translation
|
Chris@0
|
162 // statuses are (un)published accordingly.
|
Chris@0
|
163 foreach ($this->langcodes as $langcode) {
|
Chris@0
|
164 $options = ['language' => $languages[$langcode]];
|
Chris@18
|
165 $url = $entity->toUrl('edit-form', $options);
|
Chris@0
|
166 $this->drupalPostForm($url, ['status[value]' => $value], t('Save') . $this->getFormSubmitSuffix($entity, $langcode), $options);
|
Chris@0
|
167 }
|
Chris@0
|
168 $storage->resetCache([$this->entityId]);
|
Chris@0
|
169 $entity = $storage->load($this->entityId);
|
Chris@0
|
170 foreach ($this->langcodes as $langcode) {
|
Chris@0
|
171 // The node is created as unpublished thus we switch to the published
|
Chris@0
|
172 // status first.
|
Chris@0
|
173 $status = !$index;
|
Chris@0
|
174 $translation = $entity->getTranslation($langcode);
|
Chris@0
|
175 $this->assertEqual($status, $this->manager->getTranslationMetadata($translation)->isPublished(), 'The translation has been correctly unpublished.');
|
Chris@0
|
176 }
|
Chris@0
|
177 }
|
Chris@0
|
178 }
|
Chris@0
|
179
|
Chris@0
|
180 /**
|
Chris@0
|
181 * {@inheritdoc}
|
Chris@0
|
182 */
|
Chris@0
|
183 protected function doTestAuthoringInfo() {
|
Chris@0
|
184 $storage = $this->container->get('entity_type.manager')
|
Chris@0
|
185 ->getStorage($this->entityTypeId);
|
Chris@0
|
186 $storage->resetCache([$this->entityId]);
|
Chris@0
|
187 $entity = $storage->load($this->entityId);
|
Chris@0
|
188 $languages = $this->container->get('language_manager')->getLanguages();
|
Chris@0
|
189 $values = [];
|
Chris@0
|
190
|
Chris@0
|
191 // Post different base field information for each translation.
|
Chris@0
|
192 foreach ($this->langcodes as $langcode) {
|
Chris@0
|
193 $user = $this->drupalCreateUser();
|
Chris@0
|
194 $values[$langcode] = [
|
Chris@0
|
195 'uid' => $user->id(),
|
Chris@0
|
196 'created' => REQUEST_TIME - mt_rand(0, 1000),
|
Chris@0
|
197 'sticky' => (bool) mt_rand(0, 1),
|
Chris@0
|
198 'promote' => (bool) mt_rand(0, 1),
|
Chris@0
|
199 ];
|
Chris@18
|
200 /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
|
Chris@18
|
201 $date_formatter = $this->container->get('date.formatter');
|
Chris@0
|
202 $edit = [
|
Chris@18
|
203 'uid[0][target_id]' => $user->getAccountName(),
|
Chris@18
|
204 'created[0][value][date]' => $date_formatter->format($values[$langcode]['created'], 'custom', 'Y-m-d'),
|
Chris@18
|
205 'created[0][value][time]' => $date_formatter->format($values[$langcode]['created'], 'custom', 'H:i:s'),
|
Chris@0
|
206 'sticky[value]' => $values[$langcode]['sticky'],
|
Chris@0
|
207 'promote[value]' => $values[$langcode]['promote'],
|
Chris@0
|
208 ];
|
Chris@0
|
209 $options = ['language' => $languages[$langcode]];
|
Chris@18
|
210 $url = $entity->toUrl('edit-form', $options);
|
Chris@0
|
211 $this->drupalPostForm($url, $edit, $this->getFormSubmitAction($entity, $langcode), $options);
|
Chris@0
|
212 }
|
Chris@0
|
213
|
Chris@0
|
214 $storage->resetCache([$this->entityId]);
|
Chris@0
|
215 $entity = $storage->load($this->entityId);
|
Chris@0
|
216 foreach ($this->langcodes as $langcode) {
|
Chris@0
|
217 $translation = $entity->getTranslation($langcode);
|
Chris@0
|
218 $metadata = $this->manager->getTranslationMetadata($translation);
|
Chris@0
|
219 $this->assertEqual($metadata->getAuthor()->id(), $values[$langcode]['uid'], 'Translation author correctly stored.');
|
Chris@0
|
220 $this->assertEqual($metadata->getCreatedTime(), $values[$langcode]['created'], 'Translation date correctly stored.');
|
Chris@0
|
221 $this->assertEqual($translation->isSticky(), $values[$langcode]['sticky'], 'Sticky of Translation correctly stored.');
|
Chris@0
|
222 $this->assertEqual($translation->isPromoted(), $values[$langcode]['promote'], 'Promoted of Translation correctly stored.');
|
Chris@0
|
223 }
|
Chris@0
|
224 }
|
Chris@0
|
225
|
Chris@0
|
226 /**
|
Chris@0
|
227 * Tests that translation page inherits admin status of edit page.
|
Chris@0
|
228 */
|
Chris@0
|
229 public function testTranslationLinkTheme() {
|
Chris@0
|
230 $this->drupalLogin($this->administrator);
|
Chris@0
|
231 $article = $this->drupalCreateNode(['type' => 'article', 'langcode' => $this->langcodes[0]]);
|
Chris@0
|
232
|
Chris@0
|
233 // Set up Seven as the admin theme and use it for node editing.
|
Chris@0
|
234 $this->container->get('theme_handler')->install(['seven']);
|
Chris@0
|
235 $edit = [];
|
Chris@0
|
236 $edit['admin_theme'] = 'seven';
|
Chris@0
|
237 $edit['use_admin_theme'] = TRUE;
|
Chris@0
|
238 $this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
|
Chris@0
|
239 $this->drupalGet('node/' . $article->id() . '/translations');
|
Chris@0
|
240 $this->assertRaw('core/themes/seven/css/base/elements.css', 'Translation uses admin theme if edit is admin.');
|
Chris@0
|
241
|
Chris@0
|
242 // Turn off admin theme for editing, assert inheritance to translations.
|
Chris@0
|
243 $edit['use_admin_theme'] = FALSE;
|
Chris@0
|
244 $this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
|
Chris@0
|
245 $this->drupalGet('node/' . $article->id() . '/translations');
|
Chris@0
|
246 $this->assertNoRaw('core/themes/seven/css/base/elements.css', 'Translation uses frontend theme if edit is frontend.');
|
Chris@0
|
247
|
Chris@0
|
248 // Assert presence of translation page itself (vs. DisabledBundle below).
|
Chris@0
|
249 $this->assertResponse(200);
|
Chris@0
|
250 }
|
Chris@0
|
251
|
Chris@0
|
252 /**
|
Chris@0
|
253 * Tests that no metadata is stored for a disabled bundle.
|
Chris@0
|
254 */
|
Chris@0
|
255 public function testDisabledBundle() {
|
Chris@0
|
256 // Create a bundle that does not have translation enabled.
|
Chris@0
|
257 $disabledBundle = $this->randomMachineName();
|
Chris@0
|
258 $this->drupalCreateContentType(['type' => $disabledBundle, 'name' => $disabledBundle]);
|
Chris@0
|
259
|
Chris@0
|
260 // Create a node for each bundle.
|
Chris@0
|
261 $node = $this->drupalCreateNode([
|
Chris@0
|
262 'type' => $this->bundle,
|
Chris@0
|
263 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
Chris@0
|
264 ]);
|
Chris@0
|
265
|
Chris@0
|
266 // Make sure that nothing was inserted into the {content_translation} table.
|
Chris@0
|
267 $rows = db_query('SELECT nid, count(nid) AS count FROM {node_field_data} WHERE type <> :type GROUP BY nid HAVING count(nid) >= 2', [':type' => $this->bundle])->fetchAll();
|
Chris@0
|
268 $this->assertEqual(0, count($rows));
|
Chris@0
|
269
|
Chris@0
|
270 // Ensure the translation tab is not accessible.
|
Chris@0
|
271 $this->drupalGet('node/' . $node->id() . '/translations');
|
Chris@0
|
272 $this->assertResponse(403);
|
Chris@0
|
273 }
|
Chris@0
|
274
|
Chris@0
|
275 /**
|
Chris@0
|
276 * Tests that translations are rendered properly.
|
Chris@0
|
277 */
|
Chris@0
|
278 public function testTranslationRendering() {
|
Chris@0
|
279 $default_langcode = $this->langcodes[0];
|
Chris@0
|
280 $values[$default_langcode] = $this->getNewEntityValues($default_langcode);
|
Chris@0
|
281 $this->entityId = $this->createEntity($values[$default_langcode], $default_langcode);
|
Chris@0
|
282 $node = \Drupal::entityManager()->getStorage($this->entityTypeId)->load($this->entityId);
|
Chris@0
|
283 $node->setPromoted(TRUE);
|
Chris@0
|
284
|
Chris@0
|
285 // Create translations.
|
Chris@0
|
286 foreach (array_diff($this->langcodes, [$default_langcode]) as $langcode) {
|
Chris@0
|
287 $values[$langcode] = $this->getNewEntityValues($langcode);
|
Chris@0
|
288 $translation = $node->addTranslation($langcode, $values[$langcode]);
|
Chris@0
|
289 // Publish and promote the translation to frontpage.
|
Chris@0
|
290 $translation->setPromoted(TRUE);
|
Chris@17
|
291 $translation->setPublished();
|
Chris@0
|
292 }
|
Chris@0
|
293 $node->save();
|
Chris@0
|
294
|
Chris@0
|
295 // Test that the frontpage view displays the correct translations.
|
Chris@0
|
296 \Drupal::service('module_installer')->install(['views'], TRUE);
|
Chris@0
|
297 $this->rebuildContainer();
|
Chris@0
|
298 $this->doTestTranslations('node', $values);
|
Chris@0
|
299
|
Chris@0
|
300 // Enable the translation language renderer.
|
Chris@0
|
301 $view = \Drupal::entityManager()->getStorage('view')->load('frontpage');
|
Chris@0
|
302 $display = &$view->getDisplay('default');
|
Chris@0
|
303 $display['display_options']['rendering_language'] = '***LANGUAGE_entity_translation***';
|
Chris@0
|
304 $view->save();
|
Chris@0
|
305
|
Chris@0
|
306 // Need to check from the beginning, including the base_path, in the url
|
Chris@0
|
307 // since the pattern for the default language might be a substring of
|
Chris@0
|
308 // the strings for other languages.
|
Chris@0
|
309 $base_path = base_path();
|
Chris@0
|
310
|
Chris@0
|
311 // Check the frontpage for 'Read more' links to each translation.
|
Chris@0
|
312 // See also assertTaxonomyPage() in NodeAccessBaseTableTest.
|
Chris@0
|
313 $node_href = 'node/' . $node->id();
|
Chris@0
|
314 foreach ($this->langcodes as $langcode) {
|
Chris@0
|
315 $this->drupalGet('node', ['language' => \Drupal::languageManager()->getLanguage($langcode)]);
|
Chris@0
|
316 $num_match_found = 0;
|
Chris@0
|
317 if ($langcode == 'en') {
|
Chris@0
|
318 // Site default language does not have langcode prefix in the URL.
|
Chris@0
|
319 $expected_href = $base_path . $node_href;
|
Chris@0
|
320 }
|
Chris@0
|
321 else {
|
Chris@0
|
322 $expected_href = $base_path . $langcode . '/' . $node_href;
|
Chris@0
|
323 }
|
Chris@0
|
324 $pattern = '|^' . $expected_href . '$|';
|
Chris@0
|
325 foreach ($this->xpath("//a[text()='Read more']") as $link) {
|
Chris@0
|
326 if (preg_match($pattern, $link->getAttribute('href'), $matches) == TRUE) {
|
Chris@0
|
327 $num_match_found++;
|
Chris@0
|
328 }
|
Chris@0
|
329 }
|
Chris@0
|
330 $this->assertTrue($num_match_found == 1, 'There is 1 Read more link, ' . $expected_href . ', for the ' . $langcode . ' translation of a node on the frontpage. (Found ' . $num_match_found . '.)');
|
Chris@0
|
331 }
|
Chris@0
|
332
|
Chris@0
|
333 // Check the frontpage for 'Add new comment' links that include the
|
Chris@0
|
334 // language.
|
Chris@0
|
335 $comment_form_href = 'node/' . $node->id() . '#comment-form';
|
Chris@0
|
336 foreach ($this->langcodes as $langcode) {
|
Chris@0
|
337 $this->drupalGet('node', ['language' => \Drupal::languageManager()->getLanguage($langcode)]);
|
Chris@0
|
338 $num_match_found = 0;
|
Chris@0
|
339 if ($langcode == 'en') {
|
Chris@0
|
340 // Site default language does not have langcode prefix in the URL.
|
Chris@0
|
341 $expected_href = $base_path . $comment_form_href;
|
Chris@0
|
342 }
|
Chris@0
|
343 else {
|
Chris@0
|
344 $expected_href = $base_path . $langcode . '/' . $comment_form_href;
|
Chris@0
|
345 }
|
Chris@0
|
346 $pattern = '|^' . $expected_href . '$|';
|
Chris@0
|
347 foreach ($this->xpath("//a[text()='Add new comment']") as $link) {
|
Chris@0
|
348 if (preg_match($pattern, $link->getAttribute('href'), $matches) == TRUE) {
|
Chris@0
|
349 $num_match_found++;
|
Chris@0
|
350 }
|
Chris@0
|
351 }
|
Chris@0
|
352 $this->assertTrue($num_match_found == 1, 'There is 1 Add new comment link, ' . $expected_href . ', for the ' . $langcode . ' translation of a node on the frontpage. (Found ' . $num_match_found . '.)');
|
Chris@0
|
353 }
|
Chris@0
|
354
|
Chris@0
|
355 // Test that the node page displays the correct translations.
|
Chris@0
|
356 $this->doTestTranslations('node/' . $node->id(), $values);
|
Chris@0
|
357
|
Chris@0
|
358 // Test that the node page has the correct alternate hreflang links.
|
Chris@18
|
359 $this->doTestAlternateHreflangLinks($node->toUrl());
|
Chris@0
|
360 }
|
Chris@0
|
361
|
Chris@0
|
362 /**
|
Chris@0
|
363 * Tests that the given path displays the correct translation values.
|
Chris@0
|
364 *
|
Chris@0
|
365 * @param string $path
|
Chris@0
|
366 * The path to be tested.
|
Chris@0
|
367 * @param array $values
|
Chris@0
|
368 * The translation values to be found.
|
Chris@0
|
369 */
|
Chris@0
|
370 protected function doTestTranslations($path, array $values) {
|
Chris@0
|
371 $languages = $this->container->get('language_manager')->getLanguages();
|
Chris@0
|
372 foreach ($this->langcodes as $langcode) {
|
Chris@0
|
373 $this->drupalGet($path, ['language' => $languages[$langcode]]);
|
Chris@0
|
374 $this->assertText($values[$langcode]['title'][0]['value'], format_string('The %langcode node translation is correctly displayed.', ['%langcode' => $langcode]));
|
Chris@0
|
375 }
|
Chris@0
|
376 }
|
Chris@0
|
377
|
Chris@0
|
378 /**
|
Chris@0
|
379 * Tests that the given path provides the correct alternate hreflang links.
|
Chris@0
|
380 *
|
Chris@0
|
381 * @param \Drupal\Core\Url $url
|
Chris@0
|
382 * The path to be tested.
|
Chris@0
|
383 */
|
Chris@0
|
384 protected function doTestAlternateHreflangLinks(Url $url) {
|
Chris@0
|
385 $languages = $this->container->get('language_manager')->getLanguages();
|
Chris@0
|
386 $url->setAbsolute();
|
Chris@0
|
387 $urls = [];
|
Chris@0
|
388 foreach ($this->langcodes as $langcode) {
|
Chris@0
|
389 $language_url = clone $url;
|
Chris@0
|
390 $urls[$langcode] = $language_url->setOption('language', $languages[$langcode]);
|
Chris@0
|
391 }
|
Chris@0
|
392 foreach ($this->langcodes as $langcode) {
|
Chris@0
|
393 $this->drupalGet($urls[$langcode]);
|
Chris@0
|
394 foreach ($urls as $alternate_langcode => $language_url) {
|
Chris@0
|
395 // Retrieve desired link elements from the HTML head.
|
Chris@0
|
396 $links = $this->xpath('head/link[@rel = "alternate" and @href = :href and @hreflang = :hreflang]',
|
Chris@0
|
397 [':href' => $language_url->toString(), ':hreflang' => $alternate_langcode]);
|
Chris@0
|
398 $this->assert(isset($links[0]), format_string('The %langcode node translation has the correct alternate hreflang link for %alternate_langcode: %link.', ['%langcode' => $langcode, '%alternate_langcode' => $alternate_langcode, '%link' => $url->toString()]));
|
Chris@0
|
399 }
|
Chris@0
|
400 }
|
Chris@0
|
401 }
|
Chris@0
|
402
|
Chris@0
|
403 /**
|
Chris@0
|
404 * {@inheritdoc}
|
Chris@0
|
405 */
|
Chris@0
|
406 protected function getFormSubmitSuffix(EntityInterface $entity, $langcode) {
|
Chris@0
|
407 if (!$entity->isNew() && $entity->isTranslatable()) {
|
Chris@0
|
408 $translations = $entity->getTranslationLanguages();
|
Chris@0
|
409 if ((count($translations) > 1 || !isset($translations[$langcode])) && ($field = $entity->getFieldDefinition('status'))) {
|
Chris@0
|
410 return ' ' . ($field->isTranslatable() ? t('(this translation)') : t('(all translations)'));
|
Chris@0
|
411 }
|
Chris@0
|
412 }
|
Chris@0
|
413 return '';
|
Chris@0
|
414 }
|
Chris@0
|
415
|
Chris@0
|
416 /**
|
Chris@0
|
417 * Tests uninstalling content_translation.
|
Chris@0
|
418 */
|
Chris@0
|
419 protected function doUninstallTest() {
|
Chris@0
|
420 // Delete all the nodes so there is no data.
|
Chris@0
|
421 $nodes = Node::loadMultiple();
|
Chris@0
|
422 foreach ($nodes as $node) {
|
Chris@0
|
423 $node->delete();
|
Chris@0
|
424 }
|
Chris@0
|
425 $language_count = count(\Drupal::configFactory()->listAll('language.content_settings.'));
|
Chris@0
|
426 \Drupal::service('module_installer')->uninstall(['content_translation']);
|
Chris@0
|
427 $this->rebuildContainer();
|
Chris@0
|
428 $this->assertEqual($language_count, count(\Drupal::configFactory()->listAll('language.content_settings.')), 'Languages have been fixed rather than deleted during content_translation uninstall.');
|
Chris@0
|
429 }
|
Chris@0
|
430
|
Chris@0
|
431 /**
|
Chris@0
|
432 * {@inheritdoc}
|
Chris@0
|
433 */
|
Chris@0
|
434 protected function doTestTranslationEdit() {
|
Chris@0
|
435 $storage = $this->container->get('entity_type.manager')
|
Chris@0
|
436 ->getStorage($this->entityTypeId);
|
Chris@0
|
437 $storage->resetCache([$this->entityId]);
|
Chris@0
|
438 $entity = $storage->load($this->entityId);
|
Chris@0
|
439 $languages = $this->container->get('language_manager')->getLanguages();
|
Chris@0
|
440 $type_name = node_get_type_label($entity);
|
Chris@0
|
441
|
Chris@0
|
442 foreach ($this->langcodes as $langcode) {
|
Chris@0
|
443 // We only want to test the title for non-english translations.
|
Chris@0
|
444 if ($langcode != 'en') {
|
Chris@0
|
445 $options = ['language' => $languages[$langcode]];
|
Chris@18
|
446 $url = $entity->toUrl('edit-form', $options);
|
Chris@0
|
447 $this->drupalGet($url);
|
Chris@0
|
448
|
Chris@0
|
449 $title = t('<em>Edit @type</em> @title [%language translation]', [
|
Chris@0
|
450 '@type' => $type_name,
|
Chris@0
|
451 '@title' => $entity->getTranslation($langcode)->label(),
|
Chris@0
|
452 '%language' => $languages[$langcode]->getName(),
|
Chris@0
|
453 ]);
|
Chris@0
|
454 $this->assertRaw($title);
|
Chris@0
|
455 }
|
Chris@0
|
456 }
|
Chris@0
|
457 }
|
Chris@0
|
458
|
Chris@0
|
459 /**
|
Chris@0
|
460 * Tests that revision translations are rendered properly.
|
Chris@0
|
461 */
|
Chris@0
|
462 public function testRevisionTranslationRendering() {
|
Chris@0
|
463 $storage = \Drupal::entityTypeManager()->getStorage('node');
|
Chris@0
|
464
|
Chris@0
|
465 // Create a node.
|
Chris@0
|
466 $nid = $this->createEntity(['title' => 'First rev en title'], 'en');
|
Chris@0
|
467 $node = $storage->load($nid);
|
Chris@0
|
468 $original_revision_id = $node->getRevisionId();
|
Chris@0
|
469
|
Chris@0
|
470 // Add a French translation.
|
Chris@0
|
471 $translation = $node->addTranslation('fr');
|
Chris@0
|
472 $translation->title = 'First rev fr title';
|
Chris@0
|
473 $translation->setNewRevision(FALSE);
|
Chris@0
|
474 $translation->save();
|
Chris@0
|
475
|
Chris@0
|
476 // Create a new revision.
|
Chris@0
|
477 $node->title = 'Second rev en title';
|
Chris@0
|
478 $node->setNewRevision(TRUE);
|
Chris@0
|
479 $node->save();
|
Chris@0
|
480
|
Chris@0
|
481 // Get an English view of this revision.
|
Chris@0
|
482 $original_revision = $storage->loadRevision($original_revision_id);
|
Chris@0
|
483 $original_revision_url = $original_revision->toUrl('revision')->toString();
|
Chris@0
|
484
|
Chris@0
|
485 // Should be different from regular node URL.
|
Chris@0
|
486 $this->assertNotIdentical($original_revision_url, $original_revision->toUrl()->toString());
|
Chris@0
|
487 $this->drupalGet($original_revision_url);
|
Chris@0
|
488 $this->assertResponse(200);
|
Chris@0
|
489
|
Chris@0
|
490 // Contents should be in English, of correct revision.
|
Chris@0
|
491 $this->assertText('First rev en title');
|
Chris@0
|
492 $this->assertNoText('First rev fr title');
|
Chris@0
|
493
|
Chris@0
|
494 // Get a French view.
|
Chris@0
|
495 $url_fr = $original_revision->getTranslation('fr')->toUrl('revision')->toString();
|
Chris@0
|
496
|
Chris@0
|
497 // Should have different URL from English.
|
Chris@0
|
498 $this->assertNotIdentical($url_fr, $original_revision->toUrl()->toString());
|
Chris@0
|
499 $this->assertNotIdentical($url_fr, $original_revision_url);
|
Chris@0
|
500 $this->drupalGet($url_fr);
|
Chris@0
|
501 $this->assertResponse(200);
|
Chris@0
|
502
|
Chris@0
|
503 // Contents should be in French, of correct revision.
|
Chris@0
|
504 $this->assertText('First rev fr title');
|
Chris@0
|
505 $this->assertNoText('First rev en title');
|
Chris@0
|
506 }
|
Chris@0
|
507
|
Chris@17
|
508 /**
|
Chris@17
|
509 * Test that title is not escaped (but XSS-filtered) for details form element.
|
Chris@17
|
510 */
|
Chris@17
|
511 public function testDetailsTitleIsNotEscaped() {
|
Chris@17
|
512 $this->drupalLogin($this->administrator);
|
Chris@17
|
513 // Make the image field a multi-value field in order to display a
|
Chris@17
|
514 // details form element.
|
Chris@17
|
515 $edit = ['cardinality_number' => 2];
|
Chris@17
|
516 $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_image/storage', $edit, t('Save field settings'));
|
Chris@17
|
517
|
Chris@17
|
518 // Make the image field non-translatable.
|
Chris@17
|
519 $edit = ['settings[node][article][fields][field_image]' => FALSE];
|
Chris@17
|
520 $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration'));
|
Chris@17
|
521
|
Chris@17
|
522 // Create a node.
|
Chris@17
|
523 $nid = $this->createEntity(['title' => 'Node with multi-value image field en title'], 'en');
|
Chris@17
|
524
|
Chris@17
|
525 // Add a French translation and assert the title markup is not escaped.
|
Chris@17
|
526 $this->drupalGet("node/$nid/translations/add/en/fr");
|
Chris@17
|
527 $markup = 'Image <span class="translation-entity-all-languages">(all languages)</span>';
|
Chris@17
|
528 $this->assertSession()->assertNoEscaped($markup);
|
Chris@17
|
529 $this->assertSession()->responseContains($markup);
|
Chris@17
|
530 }
|
Chris@17
|
531
|
Chris@0
|
532 }
|