NodeAccessLanguageAwareTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <?php
  2. namespace Drupal\Tests\node\Functional;
  3. use Drupal\Core\Language\LanguageInterface;
  4. use Drupal\field\Entity\FieldConfig;
  5. use Drupal\language\Entity\ConfigurableLanguage;
  6. use Drupal\user\Entity\User;
  7. use Drupal\field\Entity\FieldStorageConfig;
  8. /**
  9. * Tests node_access and db_select() with node_access tag functionality with
  10. * multiple languages with node_access_test_language which is language-aware.
  11. *
  12. * @group node
  13. */
  14. class NodeAccessLanguageAwareTest extends NodeTestBase {
  15. /**
  16. * Enable language and a language-aware node access module.
  17. *
  18. * @var array
  19. */
  20. public static $modules = ['language', 'node_access_test_language'];
  21. /**
  22. * A set of nodes to use in testing.
  23. *
  24. * @var \Drupal\node\NodeInterface[]
  25. */
  26. protected $nodes = [];
  27. /**
  28. * A user with permission to bypass access content.
  29. *
  30. * @var \Drupal\user\UserInterface
  31. */
  32. protected $adminUser;
  33. /**
  34. * A normal authenticated user.
  35. *
  36. * @var \Drupal\user\UserInterface
  37. */
  38. protected $webUser;
  39. protected function setUp() {
  40. parent::setUp();
  41. // Create the 'private' field, which allows the node to be marked as private
  42. // (restricted access) in a given translation.
  43. $field_storage = FieldStorageConfig::create([
  44. 'field_name' => 'field_private',
  45. 'entity_type' => 'node',
  46. 'type' => 'boolean',
  47. 'cardinality' => 1,
  48. ]);
  49. $field_storage->save();
  50. FieldConfig::create([
  51. 'field_storage' => $field_storage,
  52. 'bundle' => 'page',
  53. 'widget' => [
  54. 'type' => 'options_buttons',
  55. ],
  56. 'settings' => [
  57. 'on_label' => 'Private',
  58. 'off_label' => 'Not private',
  59. ],
  60. ])->save();
  61. // After enabling a node access module, the access table has to be rebuild.
  62. node_access_rebuild();
  63. // Create a normal authenticated user.
  64. $this->webUser = $this->drupalCreateUser(['access content']);
  65. // Load the user 1 user for later use as an admin user with permission to
  66. // see everything.
  67. $this->adminUser = User::load(1);
  68. // Add Hungarian and Catalan.
  69. ConfigurableLanguage::createFromLangcode('hu')->save();
  70. ConfigurableLanguage::createFromLangcode('ca')->save();
  71. // The node_access_test_language module allows individual translations of a
  72. // node to be marked private (not viewable by normal users).
  73. // Create six nodes:
  74. // 1. Four Hungarian nodes with Catalan translations
  75. // - One with neither language marked as private.
  76. // - One with only the Hungarian translation private.
  77. // - One with only the Catalan translation private.
  78. // - One with both the Hungarian and Catalan translations private.
  79. // 2. Two nodes with no language specified.
  80. // - One public.
  81. // - One private.
  82. $this->nodes['both_public'] = $node = $this->drupalCreateNode([
  83. 'body' => [[]],
  84. 'langcode' => 'hu',
  85. 'field_private' => [['value' => 0]],
  86. ]);
  87. $translation = $node->addTranslation('ca');
  88. $translation->title->value = $this->randomString();
  89. $translation->field_private->value = 0;
  90. $node->save();
  91. $this->nodes['ca_private'] = $node = $this->drupalCreateNode([
  92. 'body' => [[]],
  93. 'langcode' => 'hu',
  94. 'field_private' => [['value' => 0]],
  95. ]);
  96. $translation = $node->addTranslation('ca');
  97. $translation->title->value = $this->randomString();
  98. $translation->field_private->value = 1;
  99. $node->save();
  100. $this->nodes['hu_private'] = $node = $this->drupalCreateNode([
  101. 'body' => [[]],
  102. 'langcode' => 'hu',
  103. 'field_private' => [['value' => 1]],
  104. ]);
  105. $translation = $node->addTranslation('ca');
  106. $translation->title->value = $this->randomString();
  107. $translation->field_private->value = 0;
  108. $node->save();
  109. $this->nodes['both_private'] = $node = $this->drupalCreateNode([
  110. 'body' => [[]],
  111. 'langcode' => 'hu',
  112. 'field_private' => [['value' => 1]],
  113. ]);
  114. $translation = $node->addTranslation('ca');
  115. $translation->title->value = $this->randomString();
  116. $translation->field_private->value = 1;
  117. $node->save();
  118. $this->nodes['no_language_public'] = $this->drupalCreateNode([
  119. 'field_private' => [['value' => 0]],
  120. 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
  121. ]);
  122. $this->nodes['no_language_private'] = $this->drupalCreateNode([
  123. 'field_private' => [['value' => 1]],
  124. 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
  125. ]);
  126. }
  127. /**
  128. * Tests node access and node access queries with multiple node languages.
  129. */
  130. public function testNodeAccessLanguageAware() {
  131. // The node_access_test_language module only grants view access.
  132. $expected_node_access = ['view' => TRUE, 'update' => FALSE, 'delete' => FALSE];
  133. $expected_node_access_no_access = ['view' => FALSE, 'update' => FALSE, 'delete' => FALSE];
  134. // When both Hungarian and Catalan are marked as public, access to the
  135. // Hungarian translation should be granted with the default entity object or
  136. // when the Hungarian translation is specified explicitly.
  137. $this->assertNodeAccess($expected_node_access, $this->nodes['both_public'], $this->webUser);
  138. $this->assertNodeAccess($expected_node_access, $this->nodes['both_public']->getTranslation('hu'), $this->webUser);
  139. // Access to the Catalan translation should also be granted.
  140. $this->assertNodeAccess($expected_node_access, $this->nodes['both_public']->getTranslation('ca'), $this->webUser);
  141. // When Hungarian is marked as private, access to the Hungarian translation
  142. // should be denied with the default entity object or when the Hungarian
  143. // translation is specified explicitly.
  144. $this->assertNodeAccess($expected_node_access_no_access, $this->nodes['hu_private'], $this->webUser);
  145. $this->assertNodeAccess($expected_node_access_no_access, $this->nodes['hu_private']->getTranslation('hu'), $this->webUser);
  146. // Access to the Catalan translation should be granted.
  147. $this->assertNodeAccess($expected_node_access, $this->nodes['hu_private']->getTranslation('ca'), $this->webUser);
  148. // When Catalan is marked as private, access to the Hungarian translation
  149. // should be granted with the default entity object or when the Hungarian
  150. // translation is specified explicitly.
  151. $this->assertNodeAccess($expected_node_access, $this->nodes['ca_private'], $this->webUser);
  152. $this->assertNodeAccess($expected_node_access, $this->nodes['ca_private']->getTranslation('hu'), $this->webUser);
  153. // Access to the Catalan translation should be granted.
  154. $this->assertNodeAccess($expected_node_access_no_access, $this->nodes['ca_private']->getTranslation('ca'), $this->webUser);
  155. // When both translations are marked as private, access should be denied
  156. // regardless of the entity object specified.
  157. $this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_private'], $this->webUser);
  158. $this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_private']->getTranslation('hu'), $this->webUser);
  159. $this->assertNodeAccess($expected_node_access_no_access, $this->nodes['both_private']->getTranslation('ca'), $this->webUser);
  160. // When no language is specified for a private node, access to every node
  161. // translation is denied.
  162. $this->assertNodeAccess($expected_node_access_no_access, $this->nodes['no_language_private'], $this->webUser);
  163. // When no language is specified for a public node, access should be
  164. // granted.
  165. $this->assertNodeAccess($expected_node_access, $this->nodes['no_language_public'], $this->webUser);
  166. // Query the node table with the node access tag in several languages.
  167. // Query with no language specified. The fallback (hu) will be used.
  168. $select = db_select('node', 'n')
  169. ->fields('n', ['nid'])
  170. ->addMetaData('account', $this->webUser)
  171. ->addTag('node_access');
  172. $nids = $select->execute()->fetchAllAssoc('nid');
  173. // Three nodes should be returned:
  174. // - Node with both translations public.
  175. // - Node with only the Catalan translation marked as private.
  176. // - No language node marked as public.
  177. $this->assertEqual(count($nids), 3, 'db_select() returns 3 nodes when no langcode is specified.');
  178. $this->assertTrue(array_key_exists($this->nodes['both_public']->id(), $nids), 'The node with both translations public is returned.');
  179. $this->assertTrue(array_key_exists($this->nodes['ca_private']->id(), $nids), 'The node with only the Catalan translation private is returned.');
  180. $this->assertTrue(array_key_exists($this->nodes['no_language_public']->id(), $nids), 'The node with no language is returned.');
  181. // Query with Hungarian (hu) specified.
  182. $select = db_select('node', 'n')
  183. ->fields('n', ['nid'])
  184. ->addMetaData('account', $this->webUser)
  185. ->addMetaData('langcode', 'hu')
  186. ->addTag('node_access');
  187. $nids = $select->execute()->fetchAllAssoc('nid');
  188. // Two nodes should be returned: the node with both translations public, and
  189. // the node with only the Catalan translation marked as private.
  190. $this->assertEqual(count($nids), 2, 'db_select() returns 2 nodes when the hu langcode is specified.');
  191. $this->assertTrue(array_key_exists($this->nodes['both_public']->id(), $nids), 'The node with both translations public is returned.');
  192. $this->assertTrue(array_key_exists($this->nodes['ca_private']->id(), $nids), 'The node with only the Catalan translation private is returned.');
  193. // Query with Catalan (ca) specified.
  194. $select = db_select('node', 'n')
  195. ->fields('n', ['nid'])
  196. ->addMetaData('account', $this->webUser)
  197. ->addMetaData('langcode', 'ca')
  198. ->addTag('node_access');
  199. $nids = $select->execute()->fetchAllAssoc('nid');
  200. // Two nodes should be returned: the node with both translations public, and
  201. // the node with only the Hungarian translation marked as private.
  202. $this->assertEqual(count($nids), 2, 'db_select() returns 2 nodes when the hu langcode is specified.');
  203. $this->assertTrue(array_key_exists($this->nodes['both_public']->id(), $nids), 'The node with both translations public is returned.');
  204. $this->assertTrue(array_key_exists($this->nodes['hu_private']->id(), $nids), 'The node with only the Hungarian translation private is returned.');
  205. // Query with German (de) specified.
  206. $select = db_select('node', 'n')
  207. ->fields('n', ['nid'])
  208. ->addMetaData('account', $this->webUser)
  209. ->addMetaData('langcode', 'de')
  210. ->addTag('node_access');
  211. $nids = $select->execute()->fetchAllAssoc('nid');
  212. // There are no nodes with German translations, so no results are returned.
  213. $this->assertTrue(empty($nids), 'db_select() returns an empty result when the de langcode is specified.');
  214. // Query the nodes table as admin user (full access) with the node access
  215. // tag and no specific langcode.
  216. $select = db_select('node', 'n')
  217. ->fields('n', ['nid'])
  218. ->addMetaData('account', $this->adminUser)
  219. ->addTag('node_access');
  220. $nids = $select->execute()->fetchAllAssoc('nid');
  221. // All nodes are returned.
  222. $this->assertEqual(count($nids), 6, 'db_select() returns all nodes.');
  223. // Query the nodes table as admin user (full access) with the node access
  224. // tag and langcode de.
  225. $select = db_select('node', 'n')
  226. ->fields('n', ['nid'])
  227. ->addMetaData('account', $this->adminUser)
  228. ->addMetaData('langcode', 'de')
  229. ->addTag('node_access');
  230. $nids = $select->execute()->fetchAllAssoc('nid');
  231. // Even though there is no German translation, all nodes are returned
  232. // because node access filtering does not occur when the user is user 1.
  233. $this->assertEqual(count($nids), 6, 'db_select() returns all nodes.');
  234. }
  235. }