Problem/Motivation

node_is_page() currently doesn't work on revisions and node previews. Revisions and previews are per default displayed in the default theme. So certain preprocessing which is dependent on node_is_page() simply doesn't fire when looking at revisions or previews, for example the following lines are firing a certain CSS grid functionality on node/2 BUT NOT on node/2/revisions/1299/view AND NOT on node/preview/a67cfe71-e7fb-470f-be3a-42e2eac1846a/full:

function MYTHEME_preprocess_node(&$variables) {
  $node = $variables['elements']['#node'];
  $variables['neat_grid'] = node_is_page($node) ? TRUE : FALSE;
}

Proposed resolution

Change code of node_is_page() declaration in core/modules/node/node.module.

BEFORE

function node_is_page(NodeInterface $node) {
  $route_match = \Drupal::routeMatch();
  if ($route_match->getRouteName() == 'entity.node.canonical') {
    $page_node = $route_match->getParameter('node');
  }
  return (!empty($page_node) ? $page_node->id() == $node->id() : FALSE);
}

AFTER

function node_is_page(NodeInterface $node) {
  $route_match = \Drupal::routeMatch();
  $route_name = $route_match->getRouteName();
  if ($route_name == 'entity.node.canonical') {
    $page_node = $route_match->getParameter('node');
  }
  elseif ($route_name == 'entity.node.revision') {
    $revision_id = $route_match->getParameter('node_revision');
    $page_node = node_revision_load($revision_id);
  }
  elseif ($route_name == 'entity.node.preview') {
    $page_node = $route_match->getParameter('node_preview');
  }
  return (!empty($page_node) ? $page_node->id() == $node->id() : FALSE);
}

Remaining tasks

* reviews needed
* tests to be written or run
* documentation to be written

User interface changes

- None -

API changes

Unsure about that ...

Data model changes

- None -

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

leymannx created an issue. See original summary.

leymannx’s picture

Status: Active » Needs review
FileSize
644 bytes
leymannx’s picture

Issue summary: View changes

Fix code highlighting.

leymannx’s picture

Title: Make node_is_page() work on revisions as well » Make node_is_page() work on revisions and previews as well
Issue summary: View changes
FileSize
1.09 KB

Same applies for node previews. So I updated the issue title, description and updated the patch to include previews as well.

The patch also updates wrong code doc where it says it would return an ID of the node, which never happened/happens under any condition in this function.

leymannx’s picture

leymannx’s picture

Version: 8.6.x-dev » 8.7.x-dev
leymannx’s picture

Version: 8.7.x-dev » 8.8.x-dev
tedbow’s picture

  1. +++ b/core/modules/node/node.module
    @@ -507,14 +507,22 @@ function node_revision_delete($revision_id) {
    - * @return int|false
    - *   The ID of the node if this is a full page view, otherwise FALSE.
    + * @return bool
    + *   TRUE if this is a full page view, otherwise FALSE.
    

    We can't change the return type as contrib/custom code could be relying on this return the ID.

    Or actually I guess the return comment is currently wrong.

    So I guess that is fine.

  2. +++ b/core/modules/node/node.module
    @@ -507,14 +507,22 @@ function node_revision_delete($revision_id) {
    +  elseif ($route_name == 'entity.node.revision') {
    +    $revision_id = $route_match->getParameter('node_revision');
    +    $page_node = node_revision_load($revision_id);
    +  }
    +  elseif ($route_name == 'entity.node.preview') {
    +    $page_node = $route_match->getParameter('node_preview');
    +  }
    

    This seems risky to add.

    The docs currently say "the full page view". So there is likely code out there relying on this returning FALSE if this is the preview or revision page.

    So I see that it would be useful but I think it would break functionality on probably a good number of sites.

mikelutz’s picture

Status: Needs review » Needs work

Let me start by saying, I support having the ability to render revisions and previews in the same frame and way that node pages are. I've had to jump through hoops, and make compromises with clients in the past who have complained that 'things are missing' on revision review pages, and the problem is deeper than just node_is_page, it also involves block filters on content types and a whole bunch of other things that come together to render revision views differently from page views for nodes.

That being said, we cannot change the functionality of node_is_page(), because it would constitute a backwards compatibility break. Your use case is well served by this update, but there is going to be other code in contrib that calls this function, expecting it to only return true on node canonical pages, and we can't break their code. You can look into the core code to see the first example as to how this would/could break things.

It seems to be used only 3 times in core code.

Once by the book module to alter the links for the book,
Once by the statistics module to add the statistics to the node render array on the page,

and the big one: in the main node preprocess method, it's used to set the node's 'page' variable to true, which is what a lot of themes and process function and preprocess functions depend on to detect if we are in the node page view. The in-code documentation there says

  // The 'page' variable is set to TRUE in two occasions:
  //   - The view mode is 'full' and we are on the 'node.view' route.
  //   - The node is in preview and view mode is either 'full' or 'default'.
  $variables['page'] = ($variables['view_mode'] == 'full' && (node_is_page($node)) || (isset($node->in_preview) && in_array($node->preview_view_mode, ['full', 'default'])));

(As an aside, we already handle preview mode there. Again, I believe revision pages should have this set, and I often preprocess nodes in my own theme to add the 'page' variable on revision pages to make them appear more like the main node page for my editors.)

Your patch changes the occasions when this variable is set, but doesn't update the documentation here. Even if it did, it's again a backwards incompatible change, as themes in core and contrib expect this variable to be set as currently documented.

From a back-end code perspective, the correct way to do this would be to create a new is_node_page_or_revision_page() method with your logic, and possibly deprecate the is_node_page method in Drupal 8 and require everyone to switch to the new function by Drupal 9. I don't think there would be much support for adding new procedural code in core at this point though. If anything, this feels like it should be abstracted for all entities and generalized into a service somewhere, (see taxonomy_term_is_page()).. It doesn't quite feel right for EntityRepository, but that's the closest I can think of, and I don't think it warrants a new service on it's own, but you could at least have an api to detect if you are on an entity page, and optionally include canonical and revision routes or something like that.

This would provide an api for themes to start using, but it's still going to be an uphill battle to get them to switch over.

mikelutz’s picture

Throwing something against the wall here. This moves the procedural functions node_is_page() and taxonomy_term_is_page() into PathMatcherInterface::isEntityPage(). The new method takes an optional array of link templates to compare to, so you can use it to determine if you are on a canonical, revision, preview, or whatever page, and abstracts to entities.

If we like the approach, we need tests.

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

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). 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.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now 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: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

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

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.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.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.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.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now 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.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now 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: 10.1.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, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.