Problem/Motivation

The link text of the link field does allow to use tokens, but the url does not.

A use case example is using the link for a sharing function where the link is

http://twitter.com/share?url=[current-page:url:absolute]&text=[current-page:title]

and the link text "Twitter".

It does not appear logical why I can use tokens for the link text and not for the title. Therefore I marked this as a bug.

Steps to reproduce

  1. Enable token module
  2. Enable link module
  3. Create content type
  4. Add link field to content type form display. Allow unlimited values so we can test lots of things.
  5. Go to /node/add/ to create a new piece of content and to test tokens in the url input of a link field.
  6. Enter title
  7. Enter link title in your newly created link field
  8. Enter url with a token in it.
    • http://twitter.com/share?url=[current-page:url:absolute]&text=[current-page:title]
    • /node/[node:id]
  9. Save the content and see how this doesn't replace the token

Proposed resolution

Optionally allow tokens to be used in the url field of link fields

Remaining tasks

This currently only works on form submissions, tested with a migration and it seems more work is needed to make this work in a migration, my assumption is that it probably won't work in other non-form related entity creations either. example JSON API
links are rendered correctly on the front end, but they are not tied to the context in the database, and are instead tied to the node itself.
The contrib module: https://www.drupal.org/project/field_group_link does not render link properly which leads to other questions about how these types of links should be rendered.
Additionally, this does not account for entity references via token.

User interface changes

Maybe allow tokens on the link field creation form.

API changes

Add new method for generating links with tokens.
Add new scheme:// type for tokens token://

Data model changes

Adds token context array to url options array in database so that contextual tokens can validate on form submission.
a:1:{s:7:"context";a:1:{s:4:"node";s:3:"193";}}

Release notes snippet

Issue fork drupal-2903336

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

demonde created an issue. See original summary.

demonde’s picture

Title: Allow tokens for url of Link field » Allow tokens for url of the Link field
dawehner’s picture

Category: Bug report » Feature request

Why I totally get why you need this particular feature, its less easy as you think it is.

When you expose the data in REST, what do you return?

  1. Replace the tokens ... saving the data again then destroy things. When you replace stuff, you also need to take into account caching
  2. Not replacing tokens in REST, well, then the field is completely broken

This is just a short example of questions one might need to answer. Given that, at least for me personally, it feels like a contrib module you could work on, and well, maybe figure out all the various problems, that might come up.

Even if you disagree with these problems, I think this is at least a clear feature request :)

demonde’s picture

The Drupal 7 Link module would allow Token by a checkbox in the backend.

If the problems like caching and REST requests are grave, why is there a token allowed for the link text but not for the link itself?

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

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now 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.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now 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.

lucas cavalcante’s picture

Version: 8.7.x-dev » 8.6.x-dev
StatusFileSize
new1.41 KB

When we tried to use token inside a link field it broken, concatenating the right URI with the token in front of it.

We made a patch to solve this issue in the link module.

hypertext200’s picture

I think you can easily extend the LinkFormatter class and add token replace function to the viewElements method to make it work, so while you are working on that you can add an additional setting. Not sure how this is going to impact on caching since cache tags aren't aware of dynamic tokens.

eahonet’s picture

Came across this as I was researching the same request. I was able to leverage this module to solve: https://www.drupal.org/project/token_filter

Amit Dwivedi’s picture

@heshanlk @eahonet,

I want to replace whole URL with some custom token. (As Url is different for all environments)
I tried with creating a custom LinkFormatter for that purpose and Token is working fine when I put it after http:// or https://.
But that doesn't seems a good solution as I need to trim it in LinkFormatter.

When token is filled in link field (without prefixing http:// or https://) it throws invalid path error.
So how can I skip that validation in case of token is there in link field.

Thank you.

freed_paris’s picture

Hi,

This patch is not working actually, I'm not sure but I think 8.6.1 updated things about validations of URLs

Unable to validate the field with a token, it says : "Manually entered paths should start with /, ? or #."

Any solution ?

Thanks

Freed

brooke_heaton’s picture

This patch does not work fully due to two problems:

1. validateUriElement in LinkWidget.php is going to throw a validation error because a token will start with '[' and not with the other allowed elements. I think this can be fixed by allowing [ but it might be best to validate the actual token here before saving.

2. LinkNotExistingInternalConstraintValidator will throw an invalid exception on getUrl since a token will not validate as a url - the token should be identified and rendered here as well.

Ultimately we likely need a new 'token' url scheme that differs from 'base', 'internal' and 'external' and it should get its own formatter and validation.

brooke_heaton’s picture

This is a pretty meaty patch against 8.7 and adds a new method to get urls from tokens as well as a token property to define the url as a token. It also includes validation and replacement via the token service. Non-url tokens will not validate.

brooke_heaton’s picture

Version: 8.6.x-dev » 8.7.x-dev
Assigned: Unassigned » brooke_heaton
Status: Active » Needs review

The last submitted patch, 7: allow-token-707484-7.patch, failed testing. View results

alison’s picture

Applies cleanly on 8.7.0 and 8.7.1! I can't test the actual functionality right now, but, just wanted to chime in that it applies cleanly for me.

demonde’s picture

I applied the patch in #13 against 8.7 cleanly but I have no token replacement for the link using

http://twitter.com/share?url=[current-page:url:absolute]&text=[current-page:title]

while token replacement for the title works. Not sure if I did sth wrong.

brooke_heaton’s picture

@demonde - I think the issue is that my patch currently replaces entire tokens but not tokens within strings. I will refactor the patch to replace tokens within strings.

ccasals’s picture

+++ b/core/modules/link/src/Plugin/Field/FieldType/LinkItem.php
@@ -158,6 +158,13 @@ public function isExternal() {
+        return $this->getUrl()->isToken();

@brooke_heaton The 'isToken()' method appears to be missing from Drupal\Core\Url. It looks like everything else is wired up though. This is a nice approach that will let other modules extend this logic. (for example: https://www.drupal.org/project/rabbit_hole/issues/3060274)

edit: after manual testing this further I found a couple of other places that are missing some logic.
elseif (empty($uri_parts['scheme'])) on line 280 fails the check since there's no token scheme returned from parse_url()
This causes the later on 'if $scheme is token' check you have to fail as well (it's never set).

brooke_heaton’s picture

@ccasals. I'll take a look at that and test it with the rabbit_hole issue. I'm still needing to get back to this and to ensure that multiple tokens within strings can be replaced. I've just been swamped.

ccasals’s picture

Yeah I hear you! Thanks for your work on this (I added a few other notes to #19 as well). We may need to manually set the scheme using internal logic(presumably the missing 'isToken' method). Were you planning on using Token's scan method for that check? https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Utility%2...

Cheers

yogeshmpawar’s picture

yogeshmpawar’s picture

Assigned: yogeshmpawar » Unassigned
StatusFileSize
new4.53 KB
new5.97 KB

Resolved all coding standard issues & added an interdiff as well.

demonde’s picture

I applied the patch in #23 which works with the URL [current-page:url:absolute] but it does not work with http://twitter.com/share?url=[current-page:url:absolute]&text=[current-page:title]

Also sth like https://[current-page:title] does not work.

bramdriesen’s picture

Status: Needs review » Needs work

I tested the patch in #23 and this does seem to work in my case when I put

<a href="https://[my:token]">bla bla</a>

But it doesn't work for without the https:// in front of it like so:

<a href="[my:token]">bla bla</a>

bramdriesen’s picture

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

Drupal 8.7.9 was released on November 6 and is the final full bugfix release for the Drupal 8.7.x series. Drupal 8.7.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.8.0 on December 4, 2019. (Drupal 8.8.0-beta1 is available for testing.)

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.

VishalKumarSahu’s picture

#9 How were you able to achieve it using token_filter module?

ctrladel’s picture

StatusFileSize
new53.13 KB
new2.09 KB

I've updated the token finding logic to use \Drupal\Core\Utility\Token::scan() instead of regex, this should address the issues where full tokens worked but tokens in strings were not.

There was also a couple issues with the fromToken() method, the first being that it didn't set a scheme for the parsed uri that was passed to Url::fromUri(). This is why https://[some:token] worked but just [some:token]token did not. I set it to always to use internal:, based on the description this seems correct but perhaps we need some extra logic in fromToken() to determine the true scheme. The other issue I noticed was that options passed with token paths were not making it to the render array so I added $options as an argument to the fromToken() method and pass it through for the call it does to Url::fromUri()

ctrladel’s picture

Status: Needs work » Needs review
ctrladel’s picture

StatusFileSize
new4.72 KB
new2.55 KB

Lets try this again without random files included in the patch.

This is functionally identical to #29 and also addresses 2 coding standard issues.

kenton.r’s picture

I have tested the patch #31 and I get the following error while trying to save a link with a token:
"The path 'token:/user/[user:uid]/requests/new' is invalid."

if I dump the $uri variable on line 154 of LinkWidget.php, it looks like it is geting called twice and the second time it is the following:
"token:token:/user/[user:uid]/requests/new"

When instead of exploding the string I changed it to what is being done with the "route:" scheme with ltrim like:
elseif ($scheme === 'token') {
$displayable_string = ltrim($displayable_string, 'token:');
}
I am able to get it to save and display correctly, but the tokens are never processed.

Were the tokens being processed in "checkTokens"? This "checkTokens" is now being totally bypassed. It should be removed if not needed.

kenton.r’s picture

With looking into this more I found that since there are no entity contexts many of the tokens are not available for use in the links url.

array $data: (optional) An array of keyed objects. For simple replacement scenarios 'node', 'user', and others are common keys, with an accompanying node or user object being the value. Some token types, like 'site', do not require any explicit information from $data and can be replaced even if it is empty.

Token::replace API

So the tokens that are available are the [site:], [current-page:], [current-user:], and [current-date:]. With any of those token it works. but not with [user:] because it is not aware of the user entity.

The attached patch adds only a workaround for the double token being added to the Uri string. I think this is coming from somewhere in the formvalidtion.

There are also checks for being empty in the URL.php and a removal of the unused "checkTokens" in the linkWidget.php.

Add support for entities

Would there be the possibility of adding support for the current node, user, view, group, comment, term, vocabulary, URL, menu, and file to be collected and made available to this replacement of tokens?

In addition to raw text containing placeholders, modules may pass in an array of objects to be used when performing the replacement. The objects should be keyed by the token type they correspond to. For example:

// Load a node and a user, then replace tokens in the text.
$text = 'On [date:short], [user:name] read [node:title].';
$node = Node::load(1);
$user = User::load(1);

// [date:...] tokens use the current date automatically.
$data = array(
'node' => $node,
'user' => $user,
);
return Token::replace($text, $data);

It would be great to be able to use more of the tokens related to entities.

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.

mepperly’s picture

?[current-page:URL] work in the link UI to get the Current Page as link.

Does anyone know the token for the original node URL when the content is in a view? When I use ?[current-page:URL], it goes to the view page itself (naturally).

Thanks,

Meg

Sorry--this should be in a forum, but I don't see how to delete!

mandclu’s picture

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

+1 for getting this functionality added to core url fields

jamiep’s picture

Created a new patch from #33 that allows external URLs to be constructed. Also removes 2 lines that were commented out

bramdriesen’s picture

Status: Needs review » Needs work

There is still code in comment which doesn't pass the quality check.

mandclu’s picture

I re-rolled the patch from #37 to remove the line that was commented out.

mandclu’s picture

StatusFileSize
new4.31 KB

Hmmm the last patch wouldn't apply, trying a manual update to the paths.

bramdriesen’s picture

Status: Needs work » Needs review

Setting it to needs review for #40

trackleft2 made their first commit to this issue’s fork.

trackleft2’s picture

StatusFileSize
new5.85 KB

Interdiff between patch @comment 40 and MR1076 https://www.drupal.org/files/issues/2021-08-18/interdiff_40_MR1076.txt

vikashsoni’s picture

StatusFileSize
new56.97 KB

Appied patch but not working when trying to add url like [current-page:URL] not working if missing some tell me

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.

effortdee’s picture

How do i get this to work? I want the exact same, thanks.

fernly’s picture

Applying the patch in #40 works for me. In the URL field of a Link field, fill in any available token. There is no "browse tokens" link, so you should look up the tokens somewhere else and paste them into the URL field.

I don't think it's possible to use a token only in the URL field because of URL validation. In my case it was just a GET parameter at the end of a fixed URL.

mradcliffe’s picture

I added the Needs issue summary update tag so that the issue summary can be formatted with the issue summary template.

trackleft2’s picture

Issue summary: View changes
trackleft2’s picture

Issue summary: View changes
trackleft2’s picture

Issue summary: View changes
trackleft2’s picture

Issue summary: View changes
mradcliffe’s picture

Thank you for the issue summary update! That really helps a subsystem or core maintainer when reviewing the issue. I removed the issue summary update tag and added subsystem maintainer review tag since there are some changes that need discussion (maybe Needs product manager review instead?).

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.

trackleft2’s picture

I might be wrong about this, but I think if we change the core/modules/link/src/LinkItemInterface.php interface, all implementing classes downstream will have to add the same new method isToken() or be invalid?

abhijith s’s picture

StatusFileSize
new119.72 KB

Applied MR !1076 in 9.5.x and its not working. I've tried the url like this http://twitter.com/share?url=[current-page:url:absolute]&text=[current-page:title]/node/[node:id]

After patch:
after

Needs work

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.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new2.54 KB

The Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

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.

abhishek.kumar’s picture

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

Can this be reviewed by core maintainers and suggest their view on this ?

bramdriesen’s picture

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

Version should always target the latest version and be back ported when needed.

alt.dev made their first commit to this issue’s fork.

alt.dev’s picture

StatusFileSize
new20.18 KB

We faced an issue with this patch.

If the page title has an apostrophe symbol, the \Drupal::service('token')->replace() method will run the Html::escape() method which will convert the apostrophe to the &#39; HTML symbol. After that, the \Drupal::request()->query->get() function won't be able to extract the whole param and will trim everything after the # symbol since it will be considered as an anchor, and not the query param.

I made changes so the patch will use the "replacePlain()" method instead.

alt.dev’s picture

StatusFileSize
new8.73 KB

Adding the patch with the current state of the branch. Works with 10.4.3.

fromme made their first commit to this issue’s fork.

fromme changed the visibility of the branch 2903336-allow-tokens-for to hidden.

junaidpv’s picture

StatusFileSize
new8.21 KB

Re-rolled #65 for 10.4.5

voleger made their first commit to this issue’s fork.

voleger’s picture

StatusFileSize
new8.73 KB

rebased `9.2.0` against latest `11.x` branch and pushed to `2903336-allow_tokens_for_url` fork branch. I suggest closing MR !1076 and hiding the `9.2.0` fork branch to avoid confusion.
Attaching the patch from the new MR

dcam changed the visibility of the branch 9.2.x to hidden.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

a.hover’s picture

StatusFileSize
new7.07 KB

Re-based #71 patch against D11 latest (11.4.6).