token.inc contains procedural code that cannot be lazy-loaded. It should be converted to a utility or a service. It's small and simple enough to be a utility, and I have not yet seen a need to override the functionality. However, it depends on ModuleHandler, which is a service, and which makes the token API harder to test if it's not a service (with dependency injection) itself.

The conversion to either a utility or a service would be fairly straightforward, as it's mostly a case of find and replace and there are no behavioral changes needed.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Dave Reid’s picture

Service probably makes sense since we'd want to inject the ModuleHandler and eventually caching as well.

Xano’s picture

Assigned: Unassigned » Xano

Yep, that's what I realized: they're not mutually exclusive.

ParisLiakos’s picture

Issue tags: +PHPUnit Blocker

tagging

Xano’s picture

Status: Active » Needs review
Issue tags: -PHPUnit Blocker
FileSize
74.84 KB

Status: Needs review » Needs work

The last submitted patch, drupal_1969540_00.patch, failed testing.

Dave Reid’s picture

- If we're using a service, we can't use static methods anymore. Needs to be all regular function calls.
- Needs to be registered at /Drupal::Token for shorthand and DX

Xano’s picture

Status: Needs work » Needs review
Issue tags: +PHPUnit Blocker
FileSize
75.58 KB

Fixed all of the above, and the installation failure, and re-tagging.

Status: Needs review » Needs work

The last submitted patch, drupal_1969540_01.patch, failed testing.

Xano’s picture

Status: Needs work » Needs review
FileSize
696 bytes
75.59 KB

Status: Needs review » Needs work

The last submitted patch, drupal_1969540_02.patch, failed testing.

Dave Reid’s picture

+++ b/core/lib/Drupal/Core/Utility/Token.phpundefined
@@ -0,0 +1,291 @@
+    $data = &drupal_static(__FUNCTION__);

Using __FUNCTION__ here means that this static will be stored as 'info' which is not desired. We should manually use 'token_info' as the static key instead of __FUNCTION__ until we replace this with injected caching.

Dave Reid’s picture

Crazy thought, what if instead of having to declare \Drupal::token() in every instance of hook_tokens and hook_tokens_alter(), what if we passed $this into the hook as well?

Xano’s picture

Status: Needs work » Needs review
FileSize
38.22 KB
76.3 KB

Crazy thought, what if instead of having to declare \Drupal::token() in every instance of hook_tokens and hook_tokens_alter(), what if we passed $this into the hook as well?

Interesting. I'm not sure whether it will actually improve DX, as most implementations will need other services as well, but it should be worth checking out. We'll need to do this in a follow-up issue, though.

The patch fixes the drupal_static(__FUNCTION__) issue, and a problem in a Views test which was caused by naming collisions. I opted to refer to the token service using $token_service rather than $token.

Xano’s picture

Title: Convert token.inc to a utility class » Convert token.inc to a service
Xano’s picture

Status: Needs review » Needs work

Token::info() should be explicitly made public.

Xano’s picture

Status: Needs work » Needs review
FileSize
76.31 KB

Token::info() is now public. No other changes.

Status: Needs review » Needs work
Issue tags: -PHPUnit Blocker

The last submitted patch, drupal_1969540_04.patch, failed testing.

Xano’s picture

Status: Needs work » Needs review
Issue tags: +PHPUnit Blocker

#16: drupal_1969540_04.patch queued for re-testing.

Re-testing, as the failed test passed locally and it seems like an unrelated issue.

ParisLiakos’s picture

looks very good to me:)
just one biggie and two minors

+++ b/core/lib/Drupal/Core/Utility/Token.phpundefined
@@ -0,0 +1,291 @@
+    $data = &drupal_static('token_info');

why not turn this into a class property? Then we could unit test it

+++ b/core/lib/Drupal/Core/Utility/Token.phpundefined
@@ -0,0 +1,291 @@
+  function __construct(ModuleHandlerInterface $module_handler) {

should be public function

+++ b/core/modules/action/action.moduleundefined
@@ -581,7 +581,7 @@ function action_send_email_action($entity, $context) {
+  $recipient = \Drupal::token()->replace($context['recipient'], $context);

@@ -647,7 +647,7 @@ function action_message_action(&$entity, $context = array()) {
+  $context['message'] = \Drupal::token()->replace(filter_xss_admin($context['message']), $context);

@@ -688,11 +688,11 @@ function action_goto_action_submit($form, $form_state) {
+  drupal_goto(\Drupal::token()->replace($context['url'], $context));

+++ b/core/modules/comment/comment.tokens.incundefined
@@ -103,6 +103,8 @@ function comment_token_info() {
+  $token_service = \Drupal::token();

+++ b/core/modules/file/file.field.incundefined
@@ -352,18 +352,19 @@ function file_field_widget_upload_validators($field, $instance) {
+  $destination = \Drupal::token()->replace($destination, $data);

+++ b/core/modules/link/link.moduleundefined
@@ -362,7 +362,7 @@ function link_field_formatter_view(EntityInterface $entity, $field, $instance, $
+      $link_title = \Drupal::token()->replace($item['title'], array($entity->entityType() => $entity), array('sanitize' => FALSE, 'clear' => TRUE));

+++ b/core/modules/node/node.tokens.incundefined
@@ -90,6 +90,8 @@ function node_token_info() {
+  $token_service = \Drupal::token();

+++ b/core/modules/statistics/statistics.tokens.incundefined
@@ -32,6 +32,8 @@ function statistics_token_info() {
+  $token_service = \Drupal::token();

+++ b/core/modules/system/system.api.phpundefined
@@ -3225,6 +3227,8 @@ function hook_url_outbound_alter(&$path, &$options, $original_path) {
+  $token_service = \Drupal::token();

+++ b/core/modules/system/system.moduleundefined
@@ -3591,10 +3591,12 @@ function system_cron() {
+  $token_service = \Drupal::token();

+++ b/core/modules/taxonomy/taxonomy.tokens.incundefined
@@ -89,6 +89,8 @@ function taxonomy_token_info() {
+  $token_service = \Drupal::token();

+++ b/core/modules/user/user.moduleundefined
@@ -1731,6 +1731,7 @@ function user_view_multiple($accounts, $view_mode = 'full', $langcode = NULL) {
+  $token_service = \Drupal::token();

+++ b/core/modules/user/user.tokens.incundefined
@@ -62,6 +62,8 @@ function user_token_info() {
+  $token_service = \Drupal::token();

+++ b/core/modules/views/views.tokens.incundefined
@@ -67,6 +67,8 @@ function views_token_info() {
+  $token_service = \Drupal::token();

No need to prefix Drupal in procedural, non namespaced code

Xano’s picture

FileSize
76.64 KB

This patch addresses those issues. It adds Token:setInfo() and Token::resetInfo() methods, and renames Token::info() to Token::getInfo().

Status: Needs review » Needs work

The last submitted patch, drupal_1969540_05.patch, failed testing.

Xano’s picture

Status: Needs work » Needs review
FileSize
76.64 KB
839 bytes
ParisLiakos’s picture

Thanks! looks really good now:)

+++ b/core/lib/Drupal/Core/Utility/Token.phpundefined
@@ -0,0 +1,313 @@
+  protected $moduleHandler = NULL;

we dont do this elsewhere in core.
protected $moduleHandler;
should be enough

+++ b/core/lib/Drupal/Core/Utility/Token.phpundefined
@@ -0,0 +1,313 @@
+   * @return NULL
...
+   * @return NULL

same here..you can completely remove the @return

besides those this seems ready to fly, good job!

Xano’s picture

FileSize
1.03 KB
76.58 KB
ParisLiakos’s picture

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

Title: Convert token.inc to a service » Change notice: Convert token.inc to a service
Priority: Normal » Critical
Status: Reviewed & tested by the community » Active
Issue tags: +Needs change record
FileSize
4.2 KB

Attaching the diff with all whitespace changes removed of the new Token class and token.inc... all changes look good to me. And this patch completely converts all usages. Nice!

Committed c014519 and pushed to 8.x.Thanks!

Xano’s picture

Title: Change notice: Convert token.inc to a service » Convert token.inc to a service
Priority: Critical » Normal
Status: Active » Fixed

Status: Fixed » Closed (fixed)

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

Xano’s picture

Assigned: Xano » Unassigned
xjm’s picture

Issue tags: -Needs change record

Untagging. Please remove the tag when the change notification task is completed.