3 namespace Drupal\Tests\node\Functional;
5 use Drupal\language\Entity\ConfigurableLanguage;
8 * Tests that the node_access system stores the proper fallback marker.
12 class NodeAccessLanguageFallbackTest extends NodeTestBase {
15 * Enable language and a non-language-aware node access module.
19 public static $modules = ['language', 'node_access_test', 'content_translation'];
24 protected function setUp() {
27 // After enabling a node access module, the {node_access} table has to be
29 node_access_rebuild();
31 // Add Hungarian, Catalan, and Afrikaans.
32 ConfigurableLanguage::createFromLangcode('hu')->save();
33 ConfigurableLanguage::createFromLangcode('ca')->save();
34 ConfigurableLanguage::createFromLangcode('af')->save();
36 // Enable content translation for the current entity type.
37 \Drupal::service('content_translation.manager')->setEnabled('node', 'page', TRUE);
41 * Tests node access fallback handling with multiple node languages.
43 public function testNodeAccessLanguageFallback() {
44 // The node_access_test module allows nodes to be marked private. We need to
45 // ensure that system honors the fallback system of node access properly.
46 // Note that node_access_test_language is language-sensitive and does not
47 // apply to the fallback test.
49 // Create one node in Hungarian and marked as private.
50 $node = $this->drupalCreateNode([
53 'private' => [['value' => 1]],
57 // There should be one entry in node_access, with fallback set to hu.
58 $this->checkRecords(1, 'hu');
60 // Create a translation user.
61 $admin = $this->drupalCreateUser([
64 'translate any entity',
65 'administer content translation',
67 $this->drupalLogin($admin);
68 $this->drupalGet('node/' . $node->id() . '/translations');
69 $this->assertSession()->statusCodeEquals(200);
71 // Create a Catalan translation through the UI.
72 $url_options = ['language' => \Drupal::languageManager()->getLanguage('ca')];
73 $this->drupalGet('node/' . $node->id() . '/translations/add/hu/ca', $url_options);
74 $this->assertSession()->statusCodeEquals(200);
76 $this->getSession()->getPage()->pressButton('Save (this translation)');
77 $this->assertSession()->statusCodeEquals(200);
79 // Check the node access table.
80 $this->checkRecords(2, 'hu');
82 // Programmatically create a translation. This process lets us check that
83 // both forms and code behave in the same way.
84 $storage = \Drupal::entityTypeManager()->getStorage('node');
86 $node = $storage->load(1);
87 // Create an Afrikaans translation.
88 $translation = $node->addTranslation('af');
89 $translation->title->value = $this->randomString();
90 $translation->status = 1;
93 // Check the node access table.
94 $this->checkRecords(3, 'hu');
96 // For completeness, edit the Catalan version again.
97 $this->drupalGet('node/' . $node->id() . '/edit', $url_options);
98 $this->assertSession()->statusCodeEquals(200);
100 $this->getSession()->getPage()->pressButton('Save (this translation)');
101 $this->assertSession()->statusCodeEquals(200);
102 // Check the node access table.
103 $this->checkRecords(3, 'hu');
107 * Queries the node_access table and checks for proper storage.
110 * The number of rows expected by the query (equal to the translation
113 * The expected language code set as the fallback property.
115 public function checkRecords($count, $langcode = 'hu') {
116 $select = \Drupal::database()
117 ->select('node_access', 'na')
118 ->fields('na', ['nid', 'fallback', 'langcode', 'grant_view'])
119 ->condition('na.realm', 'node_access_test', '=')
120 ->condition('na.gid', 8888, '=');
121 $records = $select->execute()->fetchAll();
122 // Check that the expected record count is returned.
123 $this->assertEquals(count($records), $count);
124 // The fallback value is 'hu' and should be set to 1. For other languages,
125 // it should be set to 0. Casting to boolean lets us run that comparison.
126 foreach ($records as $record) {
127 $this->assertEquals((bool) $record->fallback, $record->langcode === $langcode);