From b6be07acde3e70d73e02f8f0e2390882923b651b Mon Sep 17 00:00:00 2001 From: petar_basic <petar_basic@3626336.no-reply.drupal.org> Date: Thu, 21 Jan 2021 15:06:22 +0100 Subject: [PATCH] Issue #3185895 by petar_basic, fago: Add support for via parent invalidation strategy --- composer.json | 4 ++- src/Service/CacheInvalidator.php | 61 ++++++++++++++++++++++++++++---- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index fb50539..6638e88 100644 --- a/composer.json +++ b/composer.json @@ -4,5 +4,7 @@ "type": "drupal-module", "license": "GPL-2.0+", "minimum-stability": "dev", - "require": { } + "require": { + "drunomics/service-utils": "*", + } } diff --git a/src/Service/CacheInvalidator.php b/src/Service/CacheInvalidator.php index f524067..728bdea 100644 --- a/src/Service/CacheInvalidator.php +++ b/src/Service/CacheInvalidator.php @@ -2,6 +2,7 @@ namespace Drupal\cache_tools\Service; +use drunomics\ServiceUtils\Core\Entity\EntityTypeManagerTrait; use Drupal\Core\Cache\CacheTagsInvalidatorInterface; use Drupal\Core\Entity\EntityPublishedInterface; use Drupal\Core\Entity\EntityInterface; @@ -15,6 +16,8 @@ use Drupal\Core\Entity\FieldableEntityInterface; */ class CacheInvalidator { + use EntityTypeManagerTrait; + /** * The cache tag invalidator. * @@ -137,17 +140,18 @@ class CacheInvalidator { $tag_prefix = $this->getPublishedEntityCacheTag($entity) . ':'; foreach ($this->settings['invalidate'][$entity_type] as $cache_parameter) { $parts = explode(':', $cache_parameter); - if (count($parts) != 2 || $parts[0] != $bundle) { + if (count($parts) < 2 || $parts[0] != $bundle) { // This setting is not for the current bundle or not field-based. continue; } $field_name = $parts[1]; + $invalidate_term_parents = isset($parts[2]) && $parts[2] === 'parents' ? TRUE : FALSE; if ($entity->hasField($field_name)) { + $field_definition = $entity->getFieldDefinition($field_name); + $settings = $field_definition->getSettings(); + $target_type = empty($settings['target_type']) ? '' : $settings['target_type']; // The name of the value property, e.g. 'value' or 'target_id'. - $key = $entity - ->getFieldDefinition($field_name) - ->getFieldStorageDefinition() - ->getMainPropertyName(); + $key = $field_definition->getFieldStorageDefinition()->getMainPropertyName(); if (is_null($key)) { // The field has no main value property. continue; @@ -162,7 +166,7 @@ class CacheInvalidator { // Add tag for the original field value. /** @var \Drupal\Core\Field\EntityReferenceFieldItemList $field_items */ foreach ($entity_compare->get($field_name)->getValue() as $value) { - $tags[] = $tag_prefix_field . $value[$key]; + $tags = array_merge($tags, $this->generateTagsBasedOnInvalidationStrategy($target_type, $value[$key], $tag_prefix_field, $invalidate_term_parents)); } } } @@ -170,7 +174,7 @@ class CacheInvalidator { // Add tag for the new field value. /** @var \Drupal\Core\Field\EntityReferenceFieldItemList $field_items */ foreach ($entity->get($field_name)->getValue() as $value) { - $tags[] = $tag_prefix_field . $value[$key]; + $tags = array_merge($tags, $this->generateTagsBasedOnInvalidationStrategy($target_type, $value[$key], $tag_prefix_field, $invalidate_term_parents)); } } } @@ -179,6 +183,49 @@ class CacheInvalidator { return $tags; } + /** + * Returns parent tids for a given tid, or $tid if no parent exists. + * + * @param int $tid + * A taxonomy term id. + * + * @return array + * Returns $tid if no parents are found, else parents tids. + */ + public function taxonomyGetParents($tid) { + $ancestors = $this->getEntityTypeManager()->getStorage('taxonomy_term')->loadAllParents($tid); + return empty($ancestors) ? [$tid] : array_keys($ancestors); + } + + /** + * Returns an array of cache tags to invalidate. + * + * @param string $target_type + * Type of the referenced entity. + * @param mixed $entity_id + * An entity id for which to generate tags. + * @param string $tag_prefix_field + * Prefix for generated tags. + * @param bool $invalidate_term_parents + * Flag to indicate invalidation strategy. + * Only applicable for entities of type taxonomy_term. + * + * @return array + * An array of cache tags to invalidate. + */ + public function generateTagsBasedOnInvalidationStrategy($target_type, $entity_id, $tag_prefix_field, $invalidate_term_parents = FALSE) { + $tags = []; + if ($target_type === 'taxonomy_term' && $invalidate_term_parents) { + foreach ($this->taxonomyGetParents($entity_id) as $parentKey) { + $tags[] = $tag_prefix_field . $parentKey; + } + } + else { + $tags[] = $tag_prefix_field . $entity_id; + } + return $tags; + } + /** * Invalidates published entity field-based cache tags. * -- GitLab