Add a [current-page:object:?] dynamic token

Created on 22 September 2010, over 14 years ago
Updated 5 July 2023, over 1 year ago

Problem/Motivation

In many scenarios it can be useful to access the current page's entity as a token within contexts that would not normally allow it. For example, if a Webform is displayed as a block on a node page, it could be useful to obtain the node's ID to submit in the form.

Proposed resolution

Add the current route's entity available as the token [current-page:ENTITYTYPE], e.g. [current-page:node] for a node, etc.

Remaining tasks

User interface changes

New token structures are added to the [current-page] token structure based upon the current route so that if the current page is the canonical route for an entity that entity will be available as [current-page:ENTITYTYPE] and its child tokens will be available as [current-page:ENTITYTYPE:TOKENNAME], e.g. on a node page [current-page:node:title] would be available, on a taxonomy term page [current-page:taxonomy_term:name] would be available, etc.

API changes

n/a
(new tokens are added, but no new APIs are added)

Data model changes

n/a

Release notes snippet

TBD

Original report by Dave Reid

It might be really cool to add a token for the current object on the page that would use menu_get_object(). That way you could reference the current node on the same page, etc. Something like [current-page:object:node:...].

Feature request
Status

Needs work

Version

1.0

Component

Code

Created by

🇺🇸United States dave reid Nebraska USA

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇺🇸United States DamienMcKenna NH, USA

    I've updated the issue summary, is that workable?

  • Status changed to RTBC over 1 year ago
  • 🇦🇺Australia darvanen Sydney, Australia

    I was about to say we need a change record but then I realised this is for the token module, not core.

    Thanks everyone for your hard work, let's see what the maintainers think.

  • Status changed to Needs work over 1 year ago
  • 🇨🇭Switzerland berdir Switzerland

    Nice work on caching and the tests, I do have a few comments though, some of which you're not going to like I fear :)

    1. +++ b/tests/src/Functional/TokenCurrentPageTest.php
      @@ -64,4 +72,94 @@ class TokenCurrentPageTest extends TokenTestBase {
           $this->assertPageTokens("/node/{$node->id()}", $tokens, [], ['url_options' => ['query' => ['foo' => 'bar']]]);
         }
      +  /*
      +   * Test tokens like [current-page:node:nid].
      +   */
      

      missing empty line.

    2. +++ b/tests/src/Functional/TokenCurrentPageTest.php
      @@ -64,4 +72,94 @@ class TokenCurrentPageTest extends TokenTestBase {
      +        $assert_session->elementContains('css', '#block-token-url-test-block', $test['node1_new_expected']);
      +        // Change to to original title.
      +          $node1->set('title', 'Node the First')->save();
      

      wrong indendation.

    3. +++ b/token.tokens.inc
      @@ -339,6 +339,20 @@ function token_token_info() {
      +  foreach (\Drupal::entityTypeManager()->getDefinitions() as $entity_type_id => $entity_type) {
      +    // Do not generate tokens if the entity doesn't define a token type or is
      +    // not a content entity.
      +    if (!$entity_type->get('token_type') || (!$entity_type instanceof ContentEntityTypeInterface)) {
      +      continue;
      +    }
      +
      +    $info['tokens']['current-page'][$entity_type_id] = [
      +      'name' => t('The current %type', ['%type' => $entity_type->getLabel()]),
      +      'description' => t("The current page object if that's a %type", ['%type' => $entity_type->getLabel()]),
      +      'type' => \Drupal::service('token.entity_mapper')->getTokenTypeForEntityType($entity_type_id),
      +    ];
      

      this will generate a ton of token types and they will all show up in the token UI in most cases, then.

      There's also a risk of conflicts if an entity type were to be called tile, query or another existing token of this type. It will also might result in less experienced users picking the wrong kind of tokens for example for pathauto patterns.

      There's one option that will address most of that, at the loss of token suggestions and it's also going to be a pain for everyone using the patch already. A dynamic token type, like [current-page:entity:?] like :query: already is.

    4. +++ b/token.tokens.inc
      @@ -875,6 +889,52 @@ function token_tokens($type, array $tokens, array $data, array $options, Bubblea
      +
      +          // Load entity if it exists.
      +          $entity_id = \Drupal::routeMatch()->getRawParameter($entity_type);
      +          if ($entity_id) {
      +            $entity = $entity_type_manager->getStorage($entity_type)->load($entity_id);
      +          }
      +          if (!isset($entity)) {
      +            break;
      +          }
      

      There are a number of special routes that will cause problems or not work, what I know:

      * node previews.
      * node revisions. will use the current default revisions and not the revision
      * latest routes from content moderation, will also use the default revision.

      What's the reason for not using the loaded parameter? that would handle the third case.

      For the first two cases, we have this in a project as a helper function. for node_preview, we could support looking that $entity_type . '_preview' although that's currently a node specific thing.

      entity revision routes are becoming more common, we could support $entity_type . '_revision' as well for that.

    5. +++ b/token.tokens.inc
      @@ -875,6 +889,52 @@ function token_tokens($type, array $tokens, array $data, array $options, Bubblea
      +            if (!empty($langcode) && $entity->hasTranslation($langcode)) {
      +              $options['langcode'] = $langcode;
      +            }
      

      This should use $entity = \Drupal::service('entity.repository')->getTranslationFromContext($entity, $langcode);. But if we use the loaded entity from the route context it won't be needed I think because that's already in the correct language.

      Also, it should be further up if not, because the entity label token is not using the correct translation currently.

  • Status changed to Needs review over 1 year ago
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 7.3 & MariaDB 10.3.22
    last update over 1 year ago
    78 pass
  • 🇮🇳India Ajeet Tiwari

    Resolved comments mentioned 1,2 and 5. and uploading patch for the same.

  • 🇦🇺Australia darvanen Sydney, Australia

    @Ajeet Tiwari can you provide an interdiff please?

  • Status changed to Needs work over 1 year ago
  • 🇦🇺Australia darvanen Sydney, Australia

    Thanks @Ajeet Tiwari.

    • #110.1: looks good
    • #110.2: looks good
    • #110.5: Comment is only partially addressed.

    Marking NW for #110 parts 3, 4 and the rest of 5.

Production build 0.71.5 2024