From 900ea3f68c0d3510e51a490b4313a479b9e6b874 Mon Sep 17 00:00:00 2001
From: Dave Long <dave@longwaveconsulting.com>
Date: Sat, 3 Feb 2024 18:39:47 +0000
Subject: [PATCH] Issue #3161892 by Abhijith S, purushotam.rai, smustgrave:
 Taxonomy term [term:changed] token not available

---
 core/modules/taxonomy/taxonomy.tokens.inc     | 25 +++++++++++++++++++
 .../tests/src/Kernel/TokenReplaceTest.php     |  6 +++++
 2 files changed, 31 insertions(+)

diff --git a/core/modules/taxonomy/taxonomy.tokens.inc b/core/modules/taxonomy/taxonomy.tokens.inc
index f6cfc6292ac5..f80c83abb13c 100644
--- a/core/modules/taxonomy/taxonomy.tokens.inc
+++ b/core/modules/taxonomy/taxonomy.tokens.inc
@@ -5,6 +5,8 @@
  * Builds placeholder replacement tokens for taxonomy terms and vocabularies.
  */
 
+use Drupal\Core\Datetime\Entity\DateFormat;
+use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Render\BubbleableMetadata;
 use Drupal\taxonomy\Entity\Vocabulary;
 
@@ -78,6 +80,11 @@ function taxonomy_token_info() {
     'description' => t("The parent term of the taxonomy term, if one exists."),
     'type' => 'term',
   ];
+  $term['changed'] = [
+    'name' => t("Date changed"),
+    'description' => t("The date the taxonomy was most recently updated."),
+    'type' => 'date',
+  ];
 
   return [
     'types' => $types,
@@ -94,6 +101,14 @@ function taxonomy_token_info() {
 function taxonomy_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
   $token_service = \Drupal::token();
 
+  if (isset($options['langcode'])) {
+    $url_options['language'] = \Drupal::languageManager()->getLanguage($options['langcode']);
+    $langcode = $options['langcode'];
+  }
+  else {
+    $langcode = LanguageInterface::LANGCODE_DEFAULT;
+  }
+
   $replacements = [];
   if ($type == 'term' && !empty($data['term'])) {
     $term = $data['term'];
@@ -140,6 +155,12 @@ function taxonomy_tokens($type, $tokens, array $data, array $options, Bubbleable
             $replacements[$original] = $parent->getName();
           }
           break;
+
+        case 'changed':
+          $date_format = DateFormat::load('medium');
+          $bubbleable_metadata->addCacheableDependency($date_format);
+          $replacements[$original] = \Drupal::service('date.formatter')->format($term->getChangedTime(), 'medium', '', NULL, $langcode);
+          break;
       }
     }
 
@@ -155,6 +176,10 @@ function taxonomy_tokens($type, $tokens, array $data, array $options, Bubbleable
         $replacements += $token_service->generate('term', $vocabulary_tokens, ['term' => $parent], $options, $bubbleable_metadata);
       }
     }
+
+    if ($changed_tokens = $token_service->findWithPrefix($tokens, 'changed')) {
+      $replacements += $token_service->generate('date', $changed_tokens, ['date' => $term->getChangedTime()], $options, $bubbleable_metadata);
+    }
   }
 
   elseif ($type == 'vocabulary' && !empty($data['vocabulary'])) {
diff --git a/core/modules/taxonomy/tests/src/Kernel/TokenReplaceTest.php b/core/modules/taxonomy/tests/src/Kernel/TokenReplaceTest.php
index 70682693073d..f59ae6b9b903 100644
--- a/core/modules/taxonomy/tests/src/Kernel/TokenReplaceTest.php
+++ b/core/modules/taxonomy/tests/src/Kernel/TokenReplaceTest.php
@@ -120,6 +120,9 @@ public function testTaxonomyTokenReplacement() {
     $tests['[term:url]'] = $term1->toUrl('canonical', ['absolute' => TRUE])->toString();
     $tests['[term:node-count]'] = 0;
     $tests['[term:parent:name]'] = '[term:parent:name]';
+    /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
+    $date_formatter = $this->container->get('date.formatter');
+    $tests['[term:changed:since]'] = $date_formatter->formatTimeDiffSince($term1->getChangedTime(), ['langcode' => $language_interface->getId()]);
     $tests['[term:vocabulary:name]'] = $this->vocabulary->label();
     $tests['[term:vocabulary]'] = $this->vocabulary->label();
 
@@ -135,6 +138,8 @@ public function testTaxonomyTokenReplacement() {
     $bubbleable_metadata = clone $base_bubbleable_metadata;
     $metadata_tests['[term:vocabulary:name]'] = $bubbleable_metadata->addCacheTags($this->vocabulary->getCacheTags());
     $metadata_tests['[term:vocabulary]'] = $bubbleable_metadata->addCacheTags($this->vocabulary->getCacheTags());
+    $bubbleable_metadata = clone $base_bubbleable_metadata;
+    $metadata_tests['[term:changed:since]'] = $bubbleable_metadata->setCacheMaxAge(0);
 
     foreach ($tests as $input => $expected) {
       $bubbleable_metadata = new BubbleableMetadata();
@@ -153,6 +158,7 @@ public function testTaxonomyTokenReplacement() {
     $tests['[term:parent:name]'] = $term1->getName();
     $tests['[term:parent:url]'] = $term1->toUrl('canonical', ['absolute' => TRUE])->toString();
     $tests['[term:parent:parent:name]'] = '[term:parent:parent:name]';
+    $tests['[term:changed:since]'] = $date_formatter->formatTimeDiffSince($term2->getChangedTime(), ['langcode' => $language_interface->getId()]);
     $tests['[term:vocabulary:name]'] = $this->vocabulary->label();
 
     // Test to make sure that we generated something for each token.
-- 
GitLab