Support from Acquia helps fund testing for Drupal Acquia logo

Comments

ekes’s picture

Status: Active » Needs review
FileSize
4.86 KB

Patch replaces all uses of menu_get_object('node') which are not in views arguments.

Views arguments should probably follow the same pattern as #2095961: Remove instances of menu_get_object('user') should that one make sense.

One function to note in this patch node_block_access() also replaces the existing arg() code. It would be nice to also use $request->attributes but the original logic covers any page where there is a node object, but only the node/add/{node_type} page not other instances with {node_type} (ie content type admin pages). Hence the ugly call to get the route.

Status: Needs review » Needs work

The last submitted patch, menu_get_object_node.2095959-01.patch, failed testing.

tim.plunkett’s picture

+++ b/core/modules/node/node.module
@@ -621,8 +622,12 @@ function node_show(EntityInterface $node, $message = FALSE) {
+  if ($request->attributes->has('node')) {

You can't do this for node_is_page(), because on something like a comment page that has the node in the request context, this will be a false positive. In some of these places, you actually need to check the route name.

If you reread the "menu_get_object() is used for two main reasons:" from the parent/meta issue, this is #1

ekes’s picture

There are a few more complicated instances on this one (than the user, and taxo ones). First node_is_page(), which then uses menu_get_object, is now only used three times in core.

Once by statistics module:

function statistics_node_view(EntityInterface $node, EntityDisplay $display, $view_mode) {
if (!$node->isNew() && $view_mode == 'full' && node_is_page($node) && empty($node->in_preview))

This actually wants specifically the route node.view and nothing else.

Once in book module:

// Adds relevant book links to the node's links.
function book_node_view_link(NodeInterface $node, $view_mode) {
...
  if (isset($node->book['depth'])) {
    if ($view_mode == 'full' && node_is_page($node)) {

I'm not sure here if fixing this to the route makes sense? Should the links be made available even if the site is configured to show the full node on some other route?

And finally in the node module itself:

// Prepares variables for node templates. 
function template_preprocess_node(&$variables) {
...
$variables['page'] = $variables['view_mode'] == 'full' && node_is_page($node);

I guess this wants the route node.view; and again no others?

ekes’s picture

Issue summary: View changes
Status: Needs work » Needs review
FileSize
9.06 KB

So working on the common cases.

ekes’s picture

Updating for dependency injection where possible.

The last submitted patch, 5: menu_get_object_node.2095959-05.patch, failed testing.

The last submitted patch, 5: menu_get_object_node.2095959-05.patch, failed testing.

The last submitted patch, 6: menu_get_object_node.2095959-06.patch, failed testing.

ekes’s picture

Previous patch is failing because the test was passing with the block shown on a 403 page.

The test has an admin user with 'administer content' privs, but no 'create * content' access. The test was checking with this user if the block was shown on the front page - correctly no; and then on the 'node/add/article' page which is returning a 403 access denied. Previous code still showed the block. Updating the test to check on the 'node/add/article' page with the webuser which does have access to 'create article content'.

dawehner’s picture

  1. +++ b/core/modules/views/lib/Drupal/views/Plugin/views/argument/Date.php
    @@ -42,16 +45,53 @@ class Date extends Formula {
    +    $form['default_argument_type']['#options'] += array('node_changed' => t("Current node's update time"));
    

    If we change this line anyway we should use $this->t() instead.

  2. +++ b/core/modules/views/lib/Drupal/views/Plugin/views/argument/Date.php
    @@ -62,18 +102,11 @@ public function getDefaultArgument($raw = FALSE) {
    -      foreach (range(1, 3) as $i) {
    -        $node = menu_get_object('node', $i);
    -        if (!empty($node)) {
    -          continue;
    -        }
    -      }
    -
    -      if (arg(0) == 'node' && is_numeric(arg(1))) {
    -        $node = node_load(arg(1));
    +      if ($this->request->attributes->has('node')) {
    +        $node = $this->request->attributes->get('node');
           }
    

    What a win if you compare the two ones.

ekes’s picture

Adding in swapping t() for $this->t() in the Date Argument class.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +WSCCI Conversions

Thank you

catch’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/modules/book/lib/Drupal/book/Plugin/Block/BookNavigationBlock.php
    @@ -63,7 +63,9 @@ public function blockSubmit($form, &$form_state) {
    +      $node = $request->attributes->get('node');
    

    This is quite ugly, and another good reason to do #2124749: [meta] Stop using $request->attributes->get(MAGIC_KEY) as a public API, but it's not the fault of this patch.

  2. +++ b/core/modules/node/lib/Drupal/node/Plugin/views/argument_default/Node.php
    @@ -10,6 +10,9 @@
      * Default argument plugin to extract a node via menu_get_object
    

    This reference should be removed.

jmuzz’s picture

Yes a function's comment shouldn't explain implementation issues like what functions it calls.

Also updated the patch to apply to the most recent version of the repository.

jmuzz’s picture

star-szr’s picture

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

Tagging for reroll.

InternetDevels’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
14.34 KB

rerolled patch

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Thank you for taking the time to inject things properly.

catch’s picture

  1. +++ b/core/modules/node/lib/Drupal/node/Plugin/views/argument_default/Node.php
    @@ -21,17 +24,51 @@
    +      if ($node instanceof NodeInterface) {
    

    What else would $node be?

  2. +++ b/core/modules/node/node.module
    @@ -577,7 +579,10 @@ function node_revision_delete($revision_id) {
    +  if ($request->attributes->get(RouteObjectInterface::ROUTE_NAME) == 'node.view') {
    

    Not sure I like exposing the Symfony CMF RouteObjectInterface for such a common operation here.

webchick’s picture

Status: Reviewed & tested by the community » Needs work
InternetDevels’s picture

Status: Needs work » Needs review
  1. see point 1 here https://drupal.org/comment/7937111#comment-7937111 :)
  2. $request->attributes->get(RouteObjectInterface::ROUTE_NAME) is used in couple places
    block_page_build
    TermBreadcrumbBuilder::applies
    menu_link_system_breadcrumb_alter
    \Drupal\forum\ForumBreadcrumbBuilder
    and few more.
    And these are in core. Why is usage of RouteObjectInterface common in node.module?
dawehner’s picture

Yeah technically the code previous did just checked whether the nid at position 1 in the path agrees with the nid passed in, so yeah I guess we can keep the same logic, too.

dawehner’s picture

Status: Needs review » Needs work

So needs work, let's just check whether the node object exists and confirms with the passed in one.

Berdir’s picture

Priority: Major » Critical
Issue tags: +beta blocker

According to #2177041: Remove all implementations of hook_menu, that issue is blocked by this, which makes this a beta blocker?

Berdir’s picture

+++ b/core/includes/theme.inc
@@ -2241,8 +2241,9 @@ function template_preprocess_page(&$variables) {
 
-  if ($node = menu_get_object()) {
-    $variables['node'] = $node;
+  $request = \Drupal::request();
+  if ($request->attributes->has('node')) {
+    $variables['node'] = $request->attributes->get('node');
   }

+++ b/core/modules/node/node.module
@@ -577,7 +579,10 @@ function node_revision_delete($revision_id) {
+  $request = \Drupal::request();
+  if ($request->attributes->get(RouteObjectInterface::ROUTE_NAME) == 'node.view') {
+    $page_node = $request->attributes->get('node');
+  }

Am I the only one that thinks the Request object has a weird API? :)

Berdir’s picture

+++ b/core/includes/theme.inc
@@ -2241,8 +2241,9 @@ function template_preprocess_page(&$variables) {
 
-  if ($node = menu_get_object()) {
-    $variables['node'] = $node;
+  $request = \Drupal::request();
+  if ($request->attributes->has('node')) {
+    $variables['node'] = $request->attributes->get('node');
   }

Actually, get() returns NULL by default (you can even control what is returned by default), that would be much easier than the conditionals that we have here?

Instead of this, we just write:

if ($node = \Drupal::request()->attributes->get('node')) {
  ...
}

Which is almost as easy as before, unlike the current change?

Would also save some of the introduced !empty($node) checks, which I always find weird (having a defined variable and if ($node) is imho easier to read, what is an "empty" $node ;)).

dawehner’s picture

Status: Needs work » Needs review
FileSize
15.49 KB
7.32 KB

Good ideas, seriously.

Status: Needs review » Needs work

The last submitted patch, 28: menu_get_object-2095959.patch, failed testing.

Berdir’s picture

That looks much better I think :)

Those default argument plugins are pretty crazy, how they just fall back to the node fields and try ti find some term ID's in whatever way they can :)

dawehner’s picture

Status: Needs work » Needs review
FileSize
15.09 KB
1.39 KB

embarrassing

Status: Needs review » Needs work

The last submitted patch, 31: menu_get_object-node-2095959-31.patch, failed testing.

dawehner’s picture

Berdir’s picture

+++ b/core/modules/node/node.module
@@ -1159,26 +1163,23 @@ function node_block_access($block) {
-      return FALSE;
+    // This is a node creation page.
+    // $request->attributes->has('node_type') would also match administration
+    // configuration pages, which the previous URI path options did not.
+    if ($request->attributes->get(RouteObjectInterface::ROUTE_NAME) == 'node.add') {
+      $node_type = $request->attributes->get('node_type');
+      return in_array($node_type->id(), $allowed_types);
     }

I'm not sure about having comments that reference previous code. It might make sense in the interdiff, but for someone looking at the resulting code (in a year, or two), it won't.

So maybe simply move the first comment line into the if or rewrite (Check if this is...) and then replace the second part of the second sentence with "so check specifically for the node.add route" ?

Ok, that's too complicated, I mean something like this:

// Only looking for node_type request parameter would also match
// administration configuration pages, specifically limit it to the node.add route.
if ($request->attributes->get(RouteObjectInterface::ROUTE_NAME) == 'node.add') {
  // This is a node creation page.
  $node_type = $request->attributes->get('node_type');
  return in_array($node_type->id(), $allowed_types);
}

And as ugly as that route name check is, I agree with #22 that it's already used in HEAD and shouldn't block this, but maybe we can open a followup issue? I think it's really unfortunate that we have to expose the fact that we are using Symfony/Cmf for the routing for a simple (?) check like this.

twistor’s picture

  1. +++ b/core/modules/book/lib/Drupal/book/Plugin/Block/BookNavigationBlock.php
    @@ -18,7 +21,44 @@
    +   * Constructs a Drupal\Component\Plugin\PluginBase object.
    

    BookNavigationBlock

  2. +++ b/core/modules/node/lib/Drupal/node/Plugin/views/argument_default/Node.php
    @@ -21,17 +24,49 @@
    +   * Constructs a default argument User object.
    

    Node object.

  3. +++ b/core/modules/node/node.module
    @@ -590,7 +594,7 @@ function node_is_page(EntityInterface $node) {
    +  if (($node = \Drupal::request()->attributes->get('node')) && $node instanceof NodeInterface) {
    

    How come we check for instanceof NodeInterface some places and not others?

  4. +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/views/argument_default/Tid.php
    @@ -22,6 +25,42 @@
    +   * Constructs a default argument User object.
    

    Tid object.

  5. +++ b/core/modules/views/lib/Drupal/views/Plugin/views/argument/Date.php
    @@ -41,16 +44,53 @@ class Date extends Formula {
    +   * Constructs a default argument User object.
    

    Date object.

catch’s picture

And as ugly as that route name check is, I agree with #22 that it's already used in HEAD and shouldn't block this, but maybe we can open a followup issue?

I'm not sure this is really the same as the existing usages.

menu_get_object() is a commonly used API in contrib/custom modules, and we're replacing it with something that is extremely ugly here. If we open a follow-up to fix that, it'll be two API changes instead of one (and that follow-up would probably need to be critical/beta-blocker). The current usages are at least mostly implementation details/crept in - i.e. I don't think we have this in a change notice yet.

dawehner’s picture

menu_get_object() is a commonly used API in contrib/custom modules, and we're replacing it with something that is extremely ugly here. If we open a follow-up to fix that, it'll be two API changes instead of one (and that follow-up would probably need to be critical/beta-blocker). The current usages are at least mostly implementation details/crept in - i.e. I don't think we have this in a change notice yet.

This issue is blocking #2177041: Remove all implementations of hook_menu and so a full chain of related issues. Afaik there was an issue which did nothing else then provide a service which allows you to fetch the route name for example from a service instead from the request object.

tim.plunkett’s picture

Issue tags: +MenuSystemRevamp
dawehner’s picture

Status: Needs work » Needs review
FileSize
14.97 KB
2.61 KB

How come we check for instanceof NodeInterface some places and not others?

This makes it both safer but also more suitable for static code analyze tools/IDEs.

tim.plunkett’s picture

Status: Needs review » Reviewed & tested by the community

We have #2124749: [meta] Stop using $request->attributes->get(MAGIC_KEY) as a public API. That doesn't actually encompass these constants, but it could.

This is why I originally opened #2103301: Add a helper class to introspect a given request.

But I don't think we should hold this issue up on that, this is a huge blocker for the menu system changes.

xjm’s picture

Hm, I'm not sure #36 is addressed entirely. I can understand the desire to get this in and unblock the rest of the MenuSystemRevamp, but I'd want, at a minimum, an explicit beta blocker followup if we're not going to fix it here.

Edit: I missed that catch tagged #2124749-15: [meta] Stop using $request->attributes->get(MAGIC_KEY) as a public API. On the fence as to whether that covers entirely though.

xjm’s picture

Assigned: Unassigned » catch

Let's do this.

Berdir’s picture

Looks like we forgot two calls, one of them was actually converted below :)

Given that these were the last usages of that function, let's just drop it and close the meta?

Berdir’s picture

Status: Reviewed & tested by the community » Needs review

Didn't mean to leave it at RTBC.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Good catch!

catch’s picture

Title: Remove instances of menu_get_object('node') » Change notice: Remove instances of menu_get_object('node')
Priority: Critical » Major
Status: Reviewed & tested by the community » Active
Issue tags: +Missing change record

I'm OK doing this in the other issue - exactly the same lines of code need to be touched, even if it's not quite the same problem with exposing the Symfony CMF interface. Committed/pushed to 8.x, thanks!

Needs a change notice, we should explicitly state that the API might change when #2124749: [meta] Stop using $request->attributes->get(MAGIC_KEY) as a public API is resolved though.

dawehner’s picture

Status: Active » Needs review

Thank you, here is a change notice: https://drupal.org/node/2192317

Berdir’s picture

Title: Change notice: Remove instances of menu_get_object('node') » Remove instances of menu_get_object('node')
Status: Needs review » Fixed
Issue tags: -Missing change record

Slightly updated and published.

star-szr’s picture

Assigned: catch » Unassigned
Priority: Major » Critical

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.