annotate core/modules/node/tests/src/Functional/NodeAccessLanguageAwareTest.php @ 19:fa3358dc1485 tip

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