PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/core/modules/content_translation/src/Tests/ContentTranslationWorkflowsTest.php

https://gitlab.com/geeta7/drupal
PHP | 258 lines | 160 code | 30 blank | 68 comment | 20 complexity | dc87564252ca7f97b56bb55030144e33 MD5 | raw file
  1. <?php
  2. /**
  3. * @file
  4. * Contains \Drupal\content_translation\Tests\ContentTranslationWorkflowsTest.
  5. */
  6. namespace Drupal\content_translation\Tests;
  7. use Drupal\Component\Utility\SafeMarkup;
  8. use Drupal\Core\Language\LanguageInterface;
  9. use Drupal\Core\Url;
  10. use Drupal\user\UserInterface;
  11. /**
  12. * Tests the content translation workflows for the test entity.
  13. *
  14. * @group content_translation
  15. */
  16. class ContentTranslationWorkflowsTest extends ContentTranslationTestBase {
  17. /**
  18. * The entity used for testing.
  19. *
  20. * @var \Drupal\Core\Entity\EntityInterface
  21. */
  22. protected $entity;
  23. /**
  24. * Modules to enable.
  25. *
  26. * @var array
  27. */
  28. public static $modules = array('language', 'content_translation', 'entity_test');
  29. protected function setUp() {
  30. parent::setUp();
  31. $this->setupEntity();
  32. }
  33. /**
  34. * {@inheritdoc}
  35. */
  36. protected function getTranslatorPermissions() {
  37. $permissions = parent::getTranslatorPermissions();
  38. $permissions[] = 'view test entity';
  39. return $permissions;
  40. }
  41. /**
  42. * {@inheritdoc}
  43. */
  44. protected function getEditorPermissions() {
  45. return array('administer entity_test content');
  46. }
  47. /**
  48. * Creates a test entity and translate it.
  49. */
  50. protected function setupEntity() {
  51. $default_langcode = $this->langcodes[0];
  52. // Create a test entity.
  53. $user = $this->drupalCreateUser();
  54. $values = array(
  55. 'name' => $this->randomMachineName(),
  56. 'user_id' => $user->id(),
  57. $this->fieldName => array(array('value' => $this->randomMachineName(16))),
  58. );
  59. $id = $this->createEntity($values, $default_langcode);
  60. $this->entity = entity_load($this->entityTypeId, $id, TRUE);
  61. // Create a translation.
  62. $this->drupalLogin($this->translator);
  63. $add_translation_url = Url::fromRoute("entity.$this->entityTypeId.content_translation_add", [$this->entityTypeId => $this->entity->id(), 'source' => $default_langcode, 'target' => $this->langcodes[2]]);
  64. $this->drupalPostForm($add_translation_url, array(), t('Save'));
  65. $this->rebuildContainer();
  66. }
  67. /**
  68. * Test simple and editorial translation workflows.
  69. */
  70. function testWorkflows() {
  71. // Test workflows for the editor.
  72. $expected_status = [
  73. 'edit' => 200,
  74. 'delete' => 200,
  75. 'overview' => 403,
  76. 'add_translation' => 403,
  77. 'edit_translation' => 403,
  78. 'delete_translation' => 403,
  79. ];
  80. $this->doTestWorkflows($this->editor, $expected_status);
  81. // Test workflows for the translator.
  82. $expected_status = [
  83. 'edit' => 403,
  84. 'delete' => 403,
  85. 'overview' => 200,
  86. 'add_translation' => 200,
  87. 'edit_translation' => 200,
  88. 'delete_translation' => 200,
  89. ];
  90. $this->doTestWorkflows($this->translator, $expected_status);
  91. // Test workflows for the admin.
  92. $expected_status = [
  93. 'edit' => 200,
  94. 'delete' => 200,
  95. 'overview' => 200,
  96. 'add_translation' => 200,
  97. 'edit_translation' => 403,
  98. 'delete_translation' => 403,
  99. ];
  100. $this->doTestWorkflows($this->administrator, $expected_status);
  101. // Check that translation permissions allow the associated operations.
  102. $ops = array('create' => t('Add'), 'update' => t('Edit'), 'delete' => t('Delete'));
  103. $translations_url = $this->entity->urlInfo('drupal:content-translation-overview');
  104. foreach ($ops as $current_op => $item) {
  105. $user = $this->drupalCreateUser(array($this->getTranslatePermission(), "$current_op content translations", 'view test entity'));
  106. $this->drupalLogin($user);
  107. $this->drupalGet($translations_url);
  108. // Make sure that the user.permissions cache context and the cache tags
  109. // for the entity are present.
  110. $this->assertCacheContext('user.permissions');
  111. foreach ($this->entity->getCacheTags() as $cache_tag) {
  112. $this->assertCacheTag($cache_tag);
  113. }
  114. foreach ($ops as $op => $label) {
  115. if ($op != $current_op) {
  116. $this->assertNoLink($label, format_string('No %op link found.', array('%op' => $label)));
  117. }
  118. else {
  119. $this->assertLink($label, 0, format_string('%op link found.', array('%op' => $label)));
  120. }
  121. }
  122. }
  123. }
  124. /**
  125. * Checks that workflows have the expected behaviors for the given user.
  126. *
  127. * @param \Drupal\user\UserInterface $user
  128. * The user to test the workflow behavior against.
  129. * @param array $expected_status
  130. * The an associative array with the operation name as key and the expected
  131. * status as value.
  132. */
  133. protected function doTestWorkflows(UserInterface $user, $expected_status) {
  134. $default_langcode = $this->langcodes[0];
  135. $languages = $this->container->get('language_manager')->getLanguages();
  136. $args = ['@user_label' => $user->getUsername()];
  137. $options = ['language' => $languages[$default_langcode], 'absolute' => TRUE];
  138. $this->drupalLogin($user);
  139. // Check whether the user is allowed to access the entity form in edit mode.
  140. $edit_url = $this->entity->urlInfo('edit-form', $options);
  141. $this->drupalGet($edit_url, $options);
  142. $this->assertResponse($expected_status['edit'], SafeMarkup::format('The @user_label has the expected edit access.', $args));
  143. // Check whether the user is allowed to access the entity delete form.
  144. $delete_url = $this->entity->urlInfo('delete-form', $options);
  145. $this->drupalGet($delete_url, $options);
  146. $this->assertResponse($expected_status['delete'], SafeMarkup::format('The @user_label has the expected delete access.', $args));
  147. // Check whether the user is allowed to access the translation overview.
  148. $langcode = $this->langcodes[1];
  149. $options['language'] = $languages[$langcode];
  150. $translations_url = $this->entity->url('drupal:content-translation-overview', $options);
  151. $this->drupalGet($translations_url);
  152. $this->assertResponse($expected_status['overview'], SafeMarkup::format('The @user_label has the expected translation overview access.', $args));
  153. // Check whether the user is allowed to create a translation.
  154. $add_translation_url = Url::fromRoute("entity.$this->entityTypeId.content_translation_add", [$this->entityTypeId => $this->entity->id(), 'source' => $default_langcode, 'target' => $langcode], $options);
  155. if ($expected_status['add_translation'] == 200) {
  156. $this->clickLink('Add');
  157. $this->assertUrl($add_translation_url->toString(), [], 'The translation overview points to the translation form when creating translations.');
  158. // Check that the translation form does not contain shared elements for
  159. // translators.
  160. if ($expected_status['edit'] == 403) {
  161. $this->assertNoSharedElements();
  162. }
  163. }
  164. else {
  165. $this->drupalGet($add_translation_url);
  166. }
  167. $this->assertResponse($expected_status['add_translation'], SafeMarkup::format('The @user_label has the expected translation creation access.', $args));
  168. // Check whether the user is allowed to edit a translation.
  169. $langcode = $this->langcodes[2];
  170. $options['language'] = $languages[$langcode];
  171. $edit_translation_url = Url::fromRoute("entity.$this->entityTypeId.content_translation_edit", [$this->entityTypeId => $this->entity->id(), 'language' => $langcode], $options);
  172. if ($expected_status['edit_translation'] == 200) {
  173. $this->drupalGet($translations_url);
  174. $editor = $expected_status['edit'] == 200;
  175. if ($editor) {
  176. $this->clickLink('Edit', 2);
  177. // An editor should be pointed to the entity form in multilingual mode.
  178. // We need a new expected edit path with a new language.
  179. $expected_edit_path = $this->entity->url('edit-form', $options);
  180. $this->assertUrl($expected_edit_path, [], 'The translation overview points to the edit form for editors when editing translations.');
  181. }
  182. else {
  183. $this->clickLink('Edit');
  184. // While a translator should be pointed to the translation form.
  185. $this->assertUrl($edit_translation_url->toString(), [], 'The translation overview points to the translation form for translators when editing translations.');
  186. // Check that the translation form does not contain shared elements.
  187. $this->assertNoSharedElements();
  188. }
  189. }
  190. else {
  191. $this->drupalGet($edit_translation_url);
  192. }
  193. $this->assertResponse($expected_status['edit_translation'], SafeMarkup::format('The @user_label has the expected translation edit access.', $args));
  194. // Check whether the user is allowed to delete a translation.
  195. $langcode = $this->langcodes[2];
  196. $options['language'] = $languages[$langcode];
  197. $delete_translation_url = Url::fromRoute("entity.$this->entityTypeId.content_translation_delete", [$this->entityTypeId => $this->entity->id(), 'language' => $langcode], $options);
  198. if ($expected_status['delete_translation'] == 200) {
  199. $this->drupalGet($translations_url);
  200. $editor = $expected_status['delete'] == 200;
  201. if ($editor) {
  202. $this->clickLink('Delete', 2);
  203. // An editor should be pointed to the entity deletion form in
  204. // multilingual mode. We need a new expected delete path with a new
  205. // language.
  206. $expected_delete_path = $this->entity->url('delete-form', $options);
  207. $this->assertUrl($expected_delete_path, [], 'The translation overview points to the delete form for editors when deleting translations.');
  208. }
  209. else {
  210. $this->clickLink('Delete');
  211. // While a translator should be pointed to the translation deletion
  212. // form.
  213. $this->assertUrl($delete_translation_url->toString(), [], 'The translation overview points to the translation deletion form for translators when deleting translations.');
  214. }
  215. }
  216. else {
  217. $this->drupalGet($delete_translation_url);
  218. }
  219. $this->assertResponse($expected_status['delete_translation'], SafeMarkup::format('The @user_label has the expected translation deletion access.', $args));
  220. }
  221. /**
  222. * Assert that the current page does not contain shared form elements.
  223. */
  224. protected function assertNoSharedElements() {
  225. $language_none = LanguageInterface::LANGCODE_NOT_SPECIFIED;
  226. return $this->assertNoFieldByXPath("//input[@name='field_test_text[$language_none][0][value]']", NULL, 'Shared elements are not available on the translation form.');
  227. }
  228. }