Follow up for #1658846-199: Add language support to node access grants and records

Problem/Motivation

Logic in the wrong class.

Proposed resolution

Move into NodeAccessController

+++ b/core/modules/node/node.module
@@ -2522,6 +2522,18 @@ function node_access($op, $node, $account = NULL, $langcode = NULL) {
+    // If the Language module is enabled, try to use the language from
+    // content negotiation.
+    if (module_exists('language')) {
+      // Load languages the node exists in.
+      $node_translations = $node->getTranslationLanguages();
+      // Load the language from content negotiation.
+      $content_negotiation_langcode = language(LANGUAGE_TYPE_CONTENT)->langcode;
+      // If there is a translation available, use it.
+      if (isset($node_translations[$content_negotiation_langcode])) {
+        $langcode = $content_negotiation_langcode;
+      }
+    }

Remaining tasks

TBD

User interface changes

No UI changes.

API changes

TBD.

Original report by @effulgentsia in #1658846-199: Add language support to node access grants and records

Posted by effulgentsia on March 22, 2013 at 7:06pm

+++ b/core/modules/node/node.module
@@ -2522,6 +2522,18 @@ function node_access($op, $node, $account = NULL, $langcode = NULL) {
+    // If the Language module is enabled, try to use the language from
+    // content negotiation.
+    if (module_exists('language')) {
+      // Load languages the node exists in.
+      $node_translations = $node->getTranslationLanguages();
+      // Load the language from content negotiation.
+      $content_negotiation_langcode = language(LANGUAGE_TYPE_CONTENT)->langcode;
+      // If there is a translation available, use it.
+      if (isset($node_translations[$content_negotiation_langcode])) {
+        $langcode = $content_negotiation_langcode;
+      }
+    }

This logic probably should be moved into NodeAccessController, but didn't do so in #198 in order to keep that a straight reroll. I think that can be follow up material though, unless someone is inspired to do it here.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

YesCT’s picture

Title: Copy of Add language support to node access grants and records » Move language node access logic into NodeAccessController
penyaskito’s picture

Status: Active » Needs review
FileSize
2.56 KB

Moved the check from node_access to NodeAccessController::viewAccess.

YesCT’s picture

the patch looks fine to me.
I'm not sure architecturally wise, but the code is moved cleanly with no changes, and the testbot come back green.
would there be any reason to think that we have a missing test that should have failed?

vijaycs85’s picture

+++ b/core/modules/node/lib/Drupal/node/NodeAccessController.phpundefined
@@ -21,6 +21,23 @@ class NodeAccessController extends EntityAccessController {
+    if (empty($langcode)) {

Is there a way to be empty as it has default LANGUAGE_DEFAULT?

penyaskito’s picture

Is there a way to be empty as it has default LANGUAGE_DEFAULT?

Yes, if the value passed is explicitly NULL (which happens in this context of the call that we do from the method where this chunk of code was prior to this patch).

Berdir’s picture

Is there a reason to not move this to a place where it's generic for all entities? Might have to wait until after the access controller refactoring that is happening here: #1947892: Improve DX with EntityAccessControllerInterface. or it needs to be duplicated quite a bit.

Also, Entity:access() and all other entity-related implementations of Accessible:access() need to be updated to default $language to NULL or this code won't get triggered because node_access() is basically just a deprecated wrapper for that and will go away. See #1947880: Replace node_access() by $entity->access(), among other issues.

Berdir’s picture

Status: Needs review » Needs work
Berdir’s picture

Priority: Minor » Normal
Status: Needs work » Needs review
FileSize
3.85 KB

Something like this.

Also changed the default value to NULL, node_access() is just a BC layer and will go away. Therefore this also isn't a minor nice to have task but needs to happen.

The problem is that core/lib now depends on language.module, which is not good. Not sure what to do about that? But it certainly makes no sense to keep this as node specific code as we want to support all languages equally in terms of language support.

vijaycs85’s picture

Status: Needs review » Needs work
Issue tags: +Entity system, +Node access, +D8MI, +language-content, +Entity Access, +Entity Field API

The last submitted patch, language-negotation-entity-access-1953892-8.patch, failed testing.

vijaycs85’s picture

Status: Needs work » Needs review
FileSize
3.82 KB

Re-rolling...

dawehner’s picture

Issue tags: +PHPUnit
FileSize
12.91 KB

Let's rerole and while we are here make it unit testable and provide one.

Berdir’s picture

Nice work on those tests ;)

I fear that NG is going to make this harder to mock/work against. Maybe we can still mock it by mocking the interfaces and not the class (e.g. for User, I'm changing the access stuff to type hint against UserInterface in the userNG issue).

You're using the base Entity class as mock but are calling the EntityTestAccessController of entity_test.module, which is the access controller for the EntityTest (NG) entity types. It works now because we just check permissions but this might break once we actually do something with $entity there...

Can you maybe do the same by mocking the base EntityAccessController directly?

andypost’s picture

andypost’s picture

clean-up and case fix

dawehner’s picture

Thanks for the cleanup @andypost

Good idea berdir.
I started with using the actual class, realized that it's not usuable, went with the test controller and then even realized that I need some mocking.

Status: Needs review » Needs work
Issue tags: -Entity system, -PHPUnit, -Node access, -D8MI, -language-content, -Entity Access, -Entity Field API

The last submitted patch, language-negotation-entity-access-1953892-16.patch, failed testing.

Berdir’s picture

Status: Needs work » Needs review
Issue tags: +Entity system, +PHPUnit, +Node access, +D8MI, +language-content, +Entity Access, +Entity Field API
andypost’s picture

Patch is green and straightforward so +1 to RTBC

Gábor Hojtsy’s picture

Status: Needs review » Needs work
+++ b/core/lib/Drupal/Core/Entity/EntityAccessController.phpundefined
@@ -23,9 +26,61 @@ class EntityAccessController implements EntityAccessControllerInterface {
+      // If the Language module is enabled, try to use the language from content
+      // negotiation.
+      // @todo: Relying on a module in core/lib is not cool.
+      if ($this->moduleHandler->moduleExists('language')) {
+        // Load languages the node exists in.
+        $node_translations = $entity->getTranslationLanguages();
+        // Load the language from content negotiation.
+        $content_negotiation_langcode = $this->languageManager->getLanguage(Language::TYPE_CONTENT)->langcode;
+        // If there is a translation available, use it.
+        if (isset($node_translations[$content_negotiation_langcode])) {
+          $langcode = $content_negotiation_langcode;
+        }
+      }

@berdir asked me to look at this if the language module check is necessary. It does not seem to me that it would be. The negotiated languages are present via bootstrap and entities support getting translations natively. If language module is not enabled, Drupal will understand that the site is in language_default() and even then actively assign language codes from that to things.

blueminds’s picture

Status: Needs work » Needs review
FileSize
12.45 KB

merged with latest 8.x status, rerolled and condition removed.

Status: Needs review » Needs work

The last submitted patch, language-negotation-entity-access-1953892-17.patch, failed testing.

blueminds’s picture

This has two blockers here: https://drupal.org/node/1856976 and here: https://drupal.org/node/1827038 as phpunit will fail. Otherwise unit tests are passing.

plach’s picture

+++ b/core/lib/Drupal/Core/Entity/EntityAccessController.php
@@ -23,11 +26,60 @@ class EntityAccessController implements EntityAccessControllerInterface {
+    // If no language code was provided, default to the entity's langcode.
+    if (empty($langcode)) {
+      $langcode = $entity->language()->langcode;
+      // Load languages the node exists in.
+      $node_translations = $entity->getTranslationLanguages();
+      // Load the language from content negotiation.
+      $content_negotiation_langcode = $this->languageManager->getLanguage(Language::TYPE_CONTENT)->langcode;
+      // If there is a translation available, use it.
+      if (isset($node_translations[$content_negotiation_langcode])) {
+        $langcode = $content_negotiation_langcode;
+      }
+    }

It should be safe to just use the entity language, see #1810370: Entity Translation API improvements. It would be good to remove the langcode parameter altogether.

dawehner’s picture

Status: Needs work » Needs review
Issue tags: -Entity system, -PHPUnit, -Node access, -D8MI, -language-content, -Entity Access, -Entity Field API

Status: Needs review » Needs work
Issue tags: +Entity system, +PHPUnit, +Node access, +D8MI, +language-content, +Entity Access, +Entity Field API

The last submitted patch, language-negotation-entity-access-1953892-17.patch, failed testing.

tim.plunkett’s picture

Priority: Normal » Major

This means it is unsafe to call $node->access() right now, that's a huge problem.
It also blocks #1947880: Replace node_access() by $entity->access() (where I took a different, hackier approach).

jair’s picture

Issue tags: +Needs reroll
Ec1ipsis’s picture

Assigned: Unassigned » Ec1ipsis
Ec1ipsis’s picture

FileSize
13.02 KB

Patch has been rerolled. Submitting for review.

Ec1ipsis’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, language-node-access.patch, failed testing.

Ec1ipsis’s picture

Assigned: Ec1ipsis » Unassigned
FileSize
13.07 KB
1.82 KB

Updating patch with cleanup. Correctly named patch this time!

tim.plunkett’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll

Status: Needs review » Needs work

The last submitted patch, language-negotation-entity-access-32.patch, failed testing.

effulgentsia’s picture

Status: Needs work » Postponed

Per #24, postponing this on #2072945: Remove the $langcode parameter in EntityAccessControllerInterface::access() and friends, unless someone can think of a way to move forward on this without that, in which case, please unpostpone.

YesCT’s picture

Status: Postponed » Needs work

[edit: triaging this as part of major issue triage #2474049: [meta] Major issue triage ]

#2072945: Remove the $langcode parameter in EntityAccessControllerInterface::access() and friends was fixed. let's see if there is still something to do here.

YesCT’s picture

+++ b/core/modules/node/lib/Drupal/node/NodeAccessController.php
@@ -21,7 +20,7 @@ class NodeAccessController extends EntityAccessController {
-  public function access(EntityInterface $entity, $operation, $langcode = Language::LANGCODE_DEFAULT, User $account = NULL) {
+  public function access(EntityInterface $entity, $operation, $langcode = NULL, User $account = NULL) {

the API change here is a change in the default value of the $langcode param.

but #2072945: Remove the $langcode parameter in EntityAccessControllerInterface::access() and friends removed the langcode param... so maybe this means we can do this now without an API change. and it might be ok for https://www.drupal.org/core/d8-allowed-changes#evaluate we should maybe try and do it and see.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.