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

  • Working code solution.
  • Test coverage.
  • Reviews.

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:...].

CommentFileSizeAuthor
#113 102-111.txt1.48 KBAjeet Tiwari
#111 919760-111.patch8.9 KBAjeet Tiwari
#102 interdiff_100-102.txt3.84 KBmrinalini9
#102 token-current_page_object_tokens-919760-102.patch8.84 KBmrinalini9
#100 token-current_page_object_tokens-919760-100.patch8.79 KBdshields
#99 token-current_page_object_tokens-919760-99.patch8.89 KBdshields
#93 919760--93.patch8.69 KBweseze
#90 interdiff_83-90.txt8.42 KBdanflanagan8
#90 interdiff_89-90.txt6.36 KBdanflanagan8
#90 token--current_page_object_token--919760--90.patch8.63 KBdanflanagan8
#89 interdiff_83-89.txt7.15 KBdanflanagan8
#89 token--current_page_object_token--919760--89.patch7.41 KBdanflanagan8
#83 interdiff_81-83.txt1.02 KBdanflanagan8
#83 token--current_page_object_token--919760--83.patch4.33 KBdanflanagan8
#81 token--current_page_object_token--919760--81.patch3.31 KBdanflanagan8
#79 interdiff_78-79.txt739 bytesp-neyens
#79 current_page_object_token-919760-79.patch2.59 KBp-neyens
#78 interdiff_74-78.txt1.19 KBRumyanaRuseva
#78 current_page_object_token-919760-78.patch2.59 KBRumyanaRuseva
#74 token-current_page_object_token-919760-74-D8.patch2.29 KBrobertom
#71 token-current_page_object_token-919760-71-D8.patch2.25 KBrobertom
#65 token-current_page_object_token-919760-65.patch2.45 KBShreya Shetty
#16 token-current_page_object_token-919760-16.patch2.33 KBrudiedirkx
#9 token-current_page_object_token-919760-9.patch2.3 KBJohnny vd Laar
#8 token-current_page_object_token-919760-8.patch2.28 KBrudiedirkx
#5 token-current_page_object_token-919760-5.patch2.25 KBrudiedirkx
#1 token.919760.1.patch1.78 KBjamsilver
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jamsilver’s picture

Status: Active » Needs review
FileSize
1.78 KB

Here's a patch which opens up the way for the current page node - but is not generalized to any object.
This patch combines with entity_token, allowing any field / property of the current page node to be accessed.

Status: Needs review » Needs work

The last submitted patch, token.919760.1.patch, failed testing.

Alan D.’s picture

Hi Dave

Any interest or ETA for this? With Webform 7.x-4.x, there is normal token support built-in and this would provide a very nice bridge to provide context between the current page and the webform module.

In saying that, it would be nicer to provide current-[entity name here] like "current-node:nid" rather than "current-page:node:nid". If "current-page:node" pattern is used, maybe the title makes more sense for the default token?

Final point, if this pattern is extended out to multiple entity types, it is going to load up the already heavy token tree a bit, so maybe it is worth making these tokens configurable, even if just a variable_get() with no UI.

Cheers
Alan

greenwork’s picture

This would benefit me as well. Thank you

rudiedirkx’s picture

Status: Needs work » Needs review
FileSize
2.25 KB

I need this too, so here it is.

I've approached it slightly differently, because Token needs a type for it to be any kind of useful. You could make generic entity tokens like object:id, object:type, object:label, but not much else. All others require a token type.

My patch adds one token per entity type to current-page: current-page:node, current-page:taxonomy_term etc. (I've not changed "taxonomy_term" to "term" on purpose, because in this case it's the name of the entity type, which should be literal (like the taxonomy token types should have been too)).

current-page:node:nid will return the nid.
current-page:node and current-page:node:title will return the node title.

It's rolled against dev (72f3d17).

I'm not really satisfied with the switch { default } token_tokens(), but I was trying to reuse as much Token logic as possible, while still being somewhat performant, so there it is. This is the limit of my Token skills.

rudiedirkx’s picture

And I actually can't seem to load them into my token tree... I tried #token_types => array('current-page') but there's no current-page in the resulting tree.

Status: Needs review » Needs work

The last submitted patch, token-current_page_object_token-919760-5.patch, failed testing.

rudiedirkx’s picture

Status: Needs work » Needs review
FileSize
2.28 KB

Oh wow stupid n00b bug!

Fixed.

Johnny vd Laar’s picture

I think there is an access check missing. When you don't have access to the menu item then there is no $item['map'].

rudiedirkx’s picture

Issue summary: View changes
quicksketch’s picture

I realized I've never commented on this issue, so I wanted to say this would be a huge benefit to Webform users. A *very* common request is being able to make a Webform into a block that is displayed on certain node types. Then users want to prepopulate Webform fields with values from the node on which the block is displayed. This is super-helpful for doing things like feedback forms, contacting the author of the node, recording relevant information, prepopulating node titles in textfields, etc.

How common is this request? Probably a few people every month. Since these requests always end up in the Webform, I thought I'd list the relevant issues to emphasize the commonality of this problem.

#2149463: Setting hidden field to [node:field_email] or [current-page:field_email] - neither work
#2163791: How to use Webform as a replacement for User Contact form: Tokens for User Email?
#1589100: Get the node title into a webform block and change the destination mail address for each node. Is this the right way?
#1620652: I want to create form on each content type "Event"
#1692026: [current-page:url:args] returns "node, 25"
#2061503: Using node field data in emails using tokens?
#2199435: Webform Mail
#2087177: Webform: [node:title] or [current-page:title] tokens display title of webform instead of current page
#1224130: %title token in Webform
#2129199: Node tokes
#2058065: Node Reference form filled in Form
#2213857: Node Tokens from Node into Webform Fields
#1617086: Webform > E-mails: Add "Content values" (ie: node field) support

Needless to say, I would be thrilled if this functionality would be added as it would help a lot of Webform users, and stop the support requests. ;)

rudiedirkx’s picture

Did #9 do it for you?

JayShoe’s picture

quicksketch,

You are right. This is a pretty common requirement and would be an amazing addition to webform. I'll be paying attention to this post to see what happens. Fingers crossed.

In the meantime, for other users searching for this functionality - You can still do it in code. Here is a snippet that worked for me.

<?php

function webform_insert_default_form_alter(&$form, &$form_state, $form_id) {
// you'll want to limit your altering to specific forms
 if ($form_id == 'webform_client_form_2151') {
    // load the current node into $node2
    if ($node2 = menu_get_object()) {
                // populate the venue_email field of the form with field_email of the node. 
		$form['submitted']['venue_email']['#default_value'] = $node2->field_email['und'][0]['email'];
	}
 }	
}

Jay

pingwin4eg’s picture

Status: Needs review » Reviewed & tested by the community

Patch in #9 works. Tested with nodes ([current-page:node:...]) in custom block's body (using token_filter module).

knalstaaf’s picture

I'm using it with Webform, which has on its own a Webform block. This webform block uses a token (of an Entity Reference field) from the node it's being displayed in, and works perfectly on these nodes themselves.

This Webform block also appears on the homepage, which is not a node, nor does it have the token that goes as a default value in the hidden field (contrary to the node described above). As a result I'm getting these errors, only on the homepage:

Warning: array_search() expects parameter 2 to be array, string given in token_tokens() (line 700 of /sites/all/modules/token/token.tokens.inc).
Notice: Undefined index: in token_tokens() (line 703 of /sites/all/modules/token/token.tokens.inc).

The token itself looks like this: [current-page:node:field-sector]

Clearing the Drupal cache does not help.

rudiedirkx’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
2.33 KB

Yes, bug, sometimes load_functions is a string. Weird.

Try this one.

knalstaaf’s picture

#16 gets rid of the errors, thanks!

One more thing is that the ampersands (and probably other special characters, like in French) are displayed as html-code (&amp;) in the results pages of webform (screen). Not sure if this is something that should be addressed in #1665818: Ampersands and other characters are not displayed correctly in <select> widgets instead (applied patch #69, no result).

rudiedirkx’s picture

HTML encoding where it shouldn't is another issue. This issue only adds the objects, not the properties or replacements.

ret5’s picture

#16 Worked well for me!

rudiedirkx’s picture

Status: Needs review » Reviewed & tested by the community
jasom’s picture

#16 worked for me. May you please commit this patch to the latest token release?

scareyclott’s picture

#17 Worked for me too. Please commit patch to latest token release

VISIOS’s picture

#16 works for me too. Thanks to all contributors. :)

Anonymous’s picture

Also confirming that #16 is working. Thanks for the patch!

Germanix’s picture

Works for me too. Thanks to all contributors !! :)

mvillares’s picture

Not working, [current-page:node:author:mail] doesn´t working.

jasom’s picture

@mvillares I disagree, you did something wrong. I have just checked if there was any update which broke the functionality. No, there was none. Everything works as it should (mails are generated and delivered).

mvillares’s picture

Oops my mistake! User role problem. Thanks!!!

marcoka’s picture

[current-page:node:author:mail] works if you display the form on the user page like /user/2
confirmed. works. love it. thank you.

caw67’s picture

patch works!

marcoka’s picture

ok i teste that with another site and i updated the system first. now [current-page:node:author:mail] doesnt work when shwoing the form on the /user/2 page.

[current-page:title] works. not sure what happened.

@mvillares what was your role problem?

Alan D.’s picture

ok i teste that with another site and i updated the system first. now [current-page:node:author:mail] doesnt work when shwoing the form on the /user/2 page.

On a user page, (user/%) there will be no context to a content item (node/%) so [current-page:node:author:mail] is a valid token, but current-page:node is undefined, so you will not get anything shown. If it did, technically you have found a bug :)

Try on a node/NID page and it should work.

Without looking up the token tree [current-page:user:mail] is probably what you are after, the email address of the user being displayed.

[edit]
PS: The forums are probably a better place for help rather than issue threads too.

marcoka’s picture

Yes of course you are right, my bad. My brain thought i used [current-page:user:mail] my hand clicked [current-page:node:author:mail] and my eyes saw [current-page:user:mail] :)

I wasnt looking for like "how to support stuff". I was testing the patch, and it works. I hope they will commit it. Thank you for you work.

Alan D.’s picture

Excellent, and sorry for some reason I assumed this was committed already :)

miloshito’s picture

Hello,

I've patched my token module, but now when i got my rule for example and "send email to address" i can't find [current-page:node:author:mail] in the list. Any suggestions?

Thanks!

jasom’s picture

miloshito’s picture

@jasom

can you fix images on your site? Also your solution worked! Thanks

AgentJay’s picture

#16 works great for me. It's using the syntax: [current-page:node:field_name]

Needs to be committed. Awesome work!

GiorgosK’s picture

#16 works great, should be committed

jimmynash’s picture

Chiming in. #16 worked perfectly for me to get a current page token into a hidden secure webform component value.

Thanks!

JayShoe’s picture

I just tested this and it works for me too.

Please commit this old issue!

mairoulhs’s picture

#16 worked for me too! I agree, should be committed.

rwilson0429’s picture

Patch at #16 works great and is a huge benefit to the token module users.

Summit’s picture

Hi,
Please commit the patch #16!
Greetings, Martijn

Maurice M.’s picture

#16 worked! Thanks alot! Please include this in the next version.

Bijanzn’s picture

When i enable WEBORM AJAX module, emails will not send !!
Do you have any suggestions ?!

Bijanzn’s picture

When i use WEBORM AJAX module, emails will not send !!
Do you have any suggestions ?!?????

JayShoe’s picture

Bijanzand, don't hijack this thread. Please create a new thread.

kylebehse’s picture

#16 worked first try. Thanks so much!

redsky’s picture

I'd love to see this committed. It would work well for a bunch of our use cases.

cmseasy’s picture

#16 works perfect, please commit.

berenddeboer’s picture

Please commit, great patch.

Vincent_Jo’s picture

#16 essential for following use case: (for those who are looking for solutions)

Webform (as block) - assigned to content-type ( + email-field)
Add email-field from content type as token to the recipient-field (E-mail to address) in the webform:
In my case:
[current-page:node:field_e_mail]

I can then add the form block to the NID-page (panels in my case) and can send mails to the mail address provided by the node of the content-type (to mention that, because I´ve been confused by the term "node" which is used for the available tokens in webforms too: [node:field_e_mail] )

thanks for the patch, please commit

regards

Vincent

alison’s picture

+1 would love to have this committed :) Are there any blockers I might be able to help with? Thank you!

[EDIT: Still applies fine against 7.x-1.7, fwiw]

ConradFlashback’s picture

#16 works with 1.7.
Please commit.

JayShoe’s picture

#16 works.
Very old issue. Very useful feature.
Please commit.

dherbold’s picture

#16 saves the day. Please commit already.

giupenni’s picture

Awesome, #16 save my day. The patch works for me.

Summit’s picture

Please..please commit #16! thanks in advance. Greetings, Martijn

goodmuyis’s picture

+1 for #16: Even thought its should be committed

chegor’s picture

Can we commit this at least to the dev branch?

JayShoe’s picture

Nah, they'll probably just continue to ignore us. :-)

JayShoe’s picture

@quicksketch

You said it yourself that this is an important feature. Since you are well regarded in this community, maybe you can suggest number 16 get committed.

alison’s picture

Hear hear! And thank you, everyone :)

Shreya Shetty’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
2.45 KB

Just a minor fix while using multistep the current node object is not reflected from menu_get_item(). So made some changes to the code so we can get the updated node or any entity on the current page

Alan D.’s picture

At a guess, this doesn't work in all cases as it assumes arg(0) = entity type & arg(1) is the ID, as per the comment in the patch.

Not always in arg(1)

+              // That's where the object resides. Not always in arg(1).
+              $object_load = entity_load($entity_type, array($item['original_map'][1]));

So this patch needs work and maybe best left as a followup if yr issue isn't triggering actual PHP errors (as opposed to not working in this use case)?

Patch #16 still rtbtc (as of forever ago)

Bensbury’s picture

I would like this to be committed too.
Currently using the custom module snippet from #13 but that does appear to work for the secure hidden fields so leaving email addresses vulnerable is not ideal.

Any suggestions to tweak #13 to get it into the secure field?

I'll try the patch but be nice if it can be added to Dev so won't have to worry about it getting wiped when doing updates.
This functionality is a pretty common request.

Thanks.

frazac’s picture

Hello, applying this patch with webform 4.17 does not work... Any idea on alternatives?

Alan D.’s picture

Patch #65 or #16?

Patch #65 will not work in many cases, as it assumes something/ID/something.

frazac’s picture

Both!
Edit: #16 works!
I had problem passing CCK Email field because it is passing the tag <a href="mailto:mail@domain.com...>eccetera and not the simple email mail@domain.com
But I have substitued the email field with a simple text field. Not elegant but it works!

robertom’s picture

Version: 7.x-1.x-dev » 8.x-1.x-dev
Assigned: Dave Reid » Unassigned
FileSize
2.25 KB

Hi sorry for my bad english.

I need this capability also for Drupal 8... attached a proposed patch.

the patch seems to work properly with the nodes and terms, but I have not done any further tests with other entities

P.S. as said by Alan D in #66, the working patch for d7 is #16

Status: Needs review » Needs work

The last submitted patch, 71: token-current_page_object_token-919760-71-D8.patch, failed testing. View results

robertom’s picture

Status: Needs work » Needs review

reset to need review because the bot performed the test on drupal 7

robertom’s picture

added a slightly modified version that uses getTokenTypeForEntityType also on token_token_info()

jwilson3’s picture

Confirming that #74 works great on Drupal 8, with webforms, where I'm embedding a contact form on a Profile page. On this site, user accounts are not publicly visible, but profiles are, and profiles may or may not be related to user accounts, but all profiles have the ability to specify their own email address. With this patch I've setup the webform email handler to send to token: [current-page:profile:field_user_email], then I embedded the webform into the profile twig template with {{ drupal_entity('webform', profile_contact_form') }} (via Twig Tweak module). Et voila! It Just Worked™! Thanks to everyone who's put hours into getting this working.

Grayle’s picture

Was this tested with page manager? I'm getting Call to a member function id() on string in node_tokens() on a content type that uses page manager.

osopolar’s picture

Tested with Token Filter module, patch from #74 works great for tokens like [current-page:taxonomy_term:vocabulary:machine-name] or [current-page:node:content-type:machine-name].

RumyanaRuseva’s picture

Thank you for the patch, it's really helpful.

Some routes do not have loaded objects as attributes, they have only the ID. That is why Grayle got an error on Page Manager pages, and the same error applies when viewing node revisions for example.

Here is an updated patch which loads the entity object from the ID.

p-neyens’s picture

Fix PHP 7.3 compliance warnings

"continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? token.tokens.inc:810
"continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? token.tokens.inc:822

manuel.adan’s picture

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

Feature added to several projects and working fine in multiple scenarios, would be RTBC adding test converage.

danflanagan8’s picture

I've been using the patch from #79 and I think it's not handing cacheable metadata quite right. Here's the same patch but with the [url.path] context added to the bubbleable metadata at the start of the code that handles the current-page:object token. This is important if we're imagining this token being used in a block that might appear on many different pages.

jrochate’s picture

Patch from #81
Working fine at Drupal 8.9.4, Token 1.7

Thanks.

danflanagan8’s picture

Here's a patch that attempts to add basic test coverage for this new token. I don't think there's much more that we could do without adding a new test class. Is this sufficient?

danflanagan8’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
dat deaf drupaler’s picture

Can confirm patch #83 worked beautifully for me - now I am able to populate ECK title field using Automatic Entity Label within an IEF container on a parent node without the need to rely on populating from the URL.

This is amazing contribuition to token module!! :) :) I've been looking for a solution to handle this kind of approach for a very long time.. very much appreciated! Thank you all for making this possible.

chegor’s picture

Status: Needs review » Reviewed & tested by the community
Cosmin Hodis-Mindras’s picture

Patch #83 works like a charm with fields deeply buried into Paragraphs - catching the parent content type name, note title, etc. and allowing for meaningful file names and folder structure for uploaded images using File (Field) Paths. That's amazing.

Berdir’s picture

Status: Reviewed & tested by the community » Needs work

Thanks for working on this. Conceptually, this seems fine, just comments on how to improve the code. Should be a relatively simple task to address this.

  1. +++ b/token.tokens.inc
    @@ -293,6 +293,19 @@ 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_id]),
    +      'description' => t("The current page object if that's a %type", ['%type' => $entity_type_id]),
    +      'type' => \Drupal::service('token.entity_mapper')->getTokenTypeForEntityType($entity_type_id),
    +    ];
    

    The type below does use the api through the entity mapper but the first check doesn't, why?

    the name and description should use $entity_type->label(), not the ID.

  2. +++ b/token.tokens.inc
    @@ -782,6 +795,52 @@ function token_tokens($type, array $tokens, array $data = [], array $options = [
    +        default:
    +          /*
    +           * This is the case that can handle the current-page:object token.
    +           * We need to start by adding the url.path cache context. We need
    +           * to do this regardless of whether or not the object actually exists.
    +           * Otherwise, we could imagine a block that is first rendered on a
    +           * custom route for which there is no current-page:object. If we then
    +           * viewed a node that has this same block, we could see a cached version
    +           * of the block instead of seeing a new rendering of the block that has the
    +           * current-page:object token replaced with the new current page's node.
    +           */
    +          $bubbleable_metadata->addCacheContexts(['url.path']);
    

    AFAIK, the coding standard requires that inline comments use //, also for multi-line comments.

  3. +++ b/token.tokens.inc
    @@ -782,6 +795,52 @@ function token_tokens($type, array $tokens, array $data = [], array $options = [
    +          $parts = explode(':', $name);
    +          $entity_type = $parts[0];
    +          $entities = $entity_type_manager->getDefinitions();
    +
    +          if (!isset($entities[$entity_type])) {
    +            break;
    +          }
    +
    +          /** @var \Drupal\Core\Entity\EntityInterface $entity */
    +          $entity = $request->attributes->get($entity_type);
    +
    +          // Load the entity object if only entity ID was retrieved.
    +          if (is_numeric($entity)) {
    +            $entity = $entity_type_manager->getStorage($entity_type)->load($entity);
    +          }
    +
    +          if (!is_object($entity)) {
    +            break;
    +          }
    +
    

    Variable names could be improved here a bit.

    Instead of getDefinitions() and isset, we could just do a hasDefinition($entity_type_id).

    Instead of $request->attributes, the recommended API to fetch route parameters is \Drupal::routeMatch()->getRawParameter()

    That should also avoid the dynamic cases for being a number or an entity, a raw parameter is always an ID.

    Even for content entities, the id could be a string, so I don't think we need to check for an integer, just non-empty. Same for the is object check, a !$entity should be sufficient.

danflanagan8’s picture

Status: Needs work » Needs review
FileSize
7.41 KB
7.15 KB

Here's an updated patch with (most of) those comments addressed. I also added better test coverage primarily focused on asserting everything is cached right.

The type below does use the api through the entity mapper but the first check doesn't, why?

I can't speak to the initial author's intentions, but I'm hesitant to change it at this point. With taxonomy as the example, currently people can use [current-page:taxonomy_term:field_foo]. If we start using the mapper the supported token would be [current-page:term:field_foo].

I wonder what people think about that. Anyone?

danflanagan8’s picture

Here's a better patch. This one has expanded test that exposed a bug where cache metadata was not being added for unchained current-page:object tokens like [current-page:node]. I also updated the test to explicitly show the existing behavior of [current-page:taxonomy_term] and [current-page:term] which is relevant to comments in #88 and #89.

I also reduced the big comment since the test coverage is increased, and moved the place where the url.path cache context is being added.

I'm attaching a couple interdiffs. Not sure which one will be more helpful.

danflanagan8’s picture

Issue summary: View changes
cmseasy’s picture

I am missing patch #16 in the file list for Drupal-7.
Patch #16 has a lot of 'please commit' reactions, so it does not needs a 'needs review' status: please commit patch #16 for D7.

weseze’s picture

Had issues with the patch from #90 not applying correctly against 9.3.0 because of different line numbers.
Rerolled patch without any changes.

kazah’s picture

Confirm, patch #93 works!

mxh’s picture

Sorry for being OT, but maybe this can be helpful: I'm working on a Context Stack, which provides Tokens to access current, parent and root context from entity view and current account scope. If you'd need something even more complicated than retrieving the current node of the page, feel free to try this one out.

Dajka’s picture

#93 works with 9.3.2 just as before! Thanks weseze!

Mitsuko’s picture

hi, just to share my successful experience with this patch

My goal was to build a newsletter (node) with several articles (other nodes).
Newsletter content type has 2 fields : body and "articles" which is an entity reference content field accepting node of type article.
The "articles" field use inline entity formwith the "complex" widget, so articles are created "inside/through" the newsletter edit form.

Article's path inherit of the newsletter/parent path with the following pattern :
/[current-page:node:url:relative]/article/[node:title]

So thank you for this feature.

Maybe we could change the status issue for "Reviewed & tested by the community"...?

cmseasy’s picture

Status: Needs review » Reviewed & tested by the community

Maybe we could change the status issue for "Reviewed & tested by the community"...?

Done
#93 for Drupal 8 (and 9)
#16 for Drupal 7

dshields’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
8.89 KB

#93 wasn't working for me on a multilingual site. This extends #93 to return entity tokens in the active language.

dshields’s picture

Sorry, it seems something has changed upstream and the patch in #99 no longer applies. This seems to apply to the latest dev.

darvanen’s picture

Status: Needs review » Needs work

A couple of nits:

  1. +++ b/token.tokens.inc
    @@ -339,6 +339,20 @@ function token_token_info() {
    +      'description' => t("The current page object if that's a %type", ['%type' => $entity_type_id]),
    

    See #88.1, this should use the label not the id.

  2. +++ b/token.tokens.inc
    @@ -875,6 +889,52 @@ function token_tokens($type, array $tokens, array $data, array $options, Bubblea
    +
    +        default:
    +          // This is the case that handles the current-page:object token.
    +          // Things like [current-page:node:field_foo].
    +
    +          // Parse token to determine entity type.
    +          $entity_type_manager = \Drupal::entityTypeManager();
    +          $parts = explode(':', $name);
    +          $entity_type = $parts[0];
    +          if (!$entity_type_manager->hasDefinition($entity_type)) {
    +            break;
    +         }
    +
    +         // Entity type is valid. Add url.path cache context. We need to
    +         // do this regardless of whether or not the entity in question
    +         // exists for the current page.
    +         $bubbleable_metadata->addCacheContexts(['url.path']);
    +
    +         // 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;
    +        }
    +
    +        // No child properties, so load the entity label.
    +        // For example [current-page:node].
    +        if ($name == $entity_type) {
    +          $label = $entity->label();
    +          $replacements[$original] = $label;
    +          $bubbleable_metadata->addCacheableDependency($entity);
    +        }
    +        // Load child properties via recursive tokens.
    +        // For example [current-page:node:nid].
    +        else {
    +          $entity_tokens = \Drupal::token()->findWithPrefix($tokens, $entity_type);
    +          $token_type = \Drupal::service('token.entity_mapper')->getTokenTypeForEntityType($entity_type);
    +          if (!empty($langcode) && $entity->hasTranslation($langcode)) {
    +            $options['langcode'] = $langcode;
    +          }
    +          $replacements += \Drupal::token()->generate($token_type, $entity_tokens, [$token_type => $entity], $options, $bubbleable_metadata);
    +        }
    +
    +        break;
    

    Code alignment creeping to the left here. That 'break;' should be four spaces to the right of the closing brace for the switch. (The creeping happens at line 904 and 918)

mrinalini9’s picture

Updated patch #100 by addressing #101, please review it.

darvanen’s picture

Status: Needs review » Needs work
Issue tags: +Needs issue summary update

Reviewed the code, looks good to me.

Core team are going to want a clear issue summary so tagging for IS update and setting NW for that. After that I think it might just be ready for the core team to look at.

kazah’s picture

Patch #102 works like a charm.

For some reason all my tokens stopped working.
Child [term:name] - start showing parent name.
I just updated the metatag module - and thought it was because of it.

Thank you very much.

ThuleNB’s picture

Patch #102 works well for me. Will this be committed soon?

cmseasy’s picture

Status: Needs work » Reviewed & tested by the community

I agree with ThuleNB.
Maybe we could change the status issue for "Reviewed & tested by the community"...?

...Done
#102 for Drupal 8 (and 9)
#16 for Drupal 7

darvanen’s picture

Thanks @cmseasy, but for an issue to be considered RTBC it needs to pass the whole review process, a working patch is not enough by itself :)

Per #103 this issue still needs an issue summary update.

DamienMcKenna’s picture

Issue summary: View changes
Status: Needs work » Needs review

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

darvanen’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs issue summary update

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.

Berdir’s picture

Status: Reviewed & tested by the community » Needs work

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.

Ajeet Tiwari’s picture

Status: Needs work » Needs review
FileSize
8.9 KB

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

darvanen’s picture

@Ajeet Tiwari can you provide an interdiff please?

Ajeet Tiwari’s picture

FileSize
1.48 KB

@darvanen

darvanen’s picture

Status: Needs review » Needs work

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.