annotate core/modules/node/tests/src/Functional/NodeAccessLanguageAwareTest.php @ 6:875880e46745

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