Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions changelogs/DP-45669.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#
# Write your changelog entry here. Every pull request must have a changelog yml file.
#
# Change types:
# #############################################################################
# You can use one of the following types:
# - Added: For new features.
# - Changed: For changes to existing functionality.
# - Deprecated: For soon-to-be removed features.
# - Removed: For removed features.
# - Fixed: For any bug fixes.
# - Security: In case of vulnerabilities.
#
# Format
# #############################################################################
# The format is crucial. Please follow the examples below. For reference, the requirements are:
# - All 3 parts are required and you must include "Type", "description" and "issue".
# - "Type" must be left aligned and followed by a colon.
# - "description" must be indented with 2 spaces followed by a colon
# - "issue" must be indented with 4 spaces followed by a colon.
# - "issue" is for the Jira ticket number only e.g. DP-1234
# - No extra spaces, indents, or blank lines are allowed.
#
# Example:
# #############################################################################
# Fixed:
# - description: Fixes scrolling on edit pages in Safari.
# issue: DP-13314
#
# You may add more than 1 description & issue for each type using the following format:
# Changed:
# - description: Automating the release branch.
# issue: DP-10166
# - description: Second change item that needs a description.
# issue: DP-19875
# - description: Third change item that needs a description along with an issue.
# issue: DP-19843
#
Fixed:
- description: Fixed missing cache tags from org locations
issue: DP-45669
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?php

namespace Drupal\Tests\mass_caching\ExistingSite;

use Drupal\mass_utility\DebugCachability;
use Drupal\paragraphs\Entity\Paragraph;
use MassGov\Dtt\MassExistingSiteBase;

/**
* Verifies cache tags bubble from referenced content to rendered pages.
*/
class CacheTagCoverageTest extends MassExistingSiteBase {

/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
(new DebugCachability())->requestDebugCachabilityHeaders($this->getSession());
}

/**
* Org location maps should bubble cache tags for referenced locations.
*/
public function testOrgLocationsBubbleReferencedLocationTags(): void {
$location = $this->createNode([
'type' => 'location',
'title' => 'Cache Tag Test Location',
'moderation_state' => 'published',
]);

$org_locations = Paragraph::create([
'type' => 'org_locations',
'field_org_ref_locations' => [$location],
]);
$org_locations->save();

$section = Paragraph::create([
'type' => 'org_section_long_form',
'field_section_long_form_content' => [$org_locations],
]);
$section->save();

$org_page = $this->createNode([
'type' => 'org_page',
'title' => 'Cache Tag Test Org',
'field_organization_sections' => [$section],
'moderation_state' => 'published',
]);

$this->drupalGet($org_page->toUrl()->toString());
$this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'node:' . $location->id());
}

/**
* Event headers should bubble cache tags for unique-address paragraphs.
*/
public function testEventUniqueAddressBubblesParagraphTags(): void {
$parent = $this->createNode([
'type' => 'org_page',
'title' => 'Cache Tag Event Parent',
'moderation_state' => 'published',
]);

$address = Paragraph::create([
'type' => 'address',
'field_label' => 'Unique Event Address',
'field_address_address' => [
'address_line1' => '1 Test Plaza',
'locality' => 'Boston',
'administrative_area' => 'MA',
'postal_code' => '02108',
'country_code' => 'US',
],
]);
$address->save();

$event = $this->createNode([
'type' => 'event',
'title' => 'Cache Tag Test Event',
'field_event_address_type' => 'unique',
'field_event_ref_unique_address' => [$address],
'field_event_date' => [
'value' => '2030-12-31T05:00:00',
'end_value' => '2031-01-01T05:00:00',
],
'field_event_time' => '6AM - 5PM',
'field_event_ref_parents' => [$parent],
'field_organizations' => [$parent],
'moderation_state' => 'published',
]);

$this->drupalGet($event->toUrl()->toString());
$this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'paragraph:' . $address->id());
}

/**
* Related link lists should bubble tags for linked internal nodes.
*/
public function testRelatedLinkListBubblesLinkedNodeTags(): void {
$related = $this->createNode([
'type' => 'org_page',
'title' => 'Cache Tag Related Org',
'moderation_state' => 'published',
]);

$info_details = $this->createNode([
'type' => 'info_details',
'title' => 'Cache Tag Info Details',
'field_info_details_related' => [
[
'uri' => 'entity:node/' . $related->id(),
'title' => $related->label(),
],
],
'moderation_state' => 'published',
]);

$this->drupalGet($info_details->toUrl()->toString());
$this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'node:' . $related->id());
}

}
7 changes: 6 additions & 1 deletion docroot/modules/custom/mayflower/mayflower.module
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use Composer\InstalledVersions as ComposerInstalledVersions;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Asset\AttachedAssetsInterface;
use Drupal\block\Entity\Block;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\StringTranslation\ByteSizeMarkup;
Expand Down Expand Up @@ -629,6 +630,7 @@ function mayflower_preprocess_paragraph__social_media(&$variables) {
function mayflower_preprocess_paragraph__org_locations(&$variables) {
$paragraph = $variables['paragraph'];
$node = Helper::getParentNode($paragraph);
$cache_tags = [];

if (Helper::isFieldPopulated($paragraph, 'field_org_ref_locations')) {
$mappedLocations_options = [
Expand All @@ -652,13 +654,16 @@ function mayflower_preprocess_paragraph__org_locations(&$variables) {
[
'path' => '@organisms/by-author/mapped-locations.twig',
'data' => [
'mappedLocations' => Organisms::prepareMappedLocations($paragraph->field_org_ref_locations->referencedEntities(), $mappedLocations_options),
'mappedLocations' => Organisms::prepareMappedLocations($paragraph->field_org_ref_locations->referencedEntities(), $mappedLocations_options, $cache_tags),
],
],
],
];

$variables['stackedRowSections'] = $sections;
if (!empty($cache_tags)) {
$variables['#cache']['tags'] = Cache::mergeTags($variables['#cache']['tags'] ?? [], $cache_tags);
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion docroot/modules/custom/mayflower/src/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -1148,12 +1148,13 @@ public static function buildPageHeaderOptionalContentsContactUs($entity, $field,
* ],
* ], ... ]
*/
public static function buildPageHeaderOptionalContentsContactUsAddress($entity, $field, array $options = []) {
public static function buildPageHeaderOptionalContentsContactUsAddress($entity, $field, array $options = [], array &$cache_tags = []) {
$optionalContentsContactUs = [];
$contactUs = [];
$contact_items = Helper::getReferencedEntitiesFromField($entity, $field);
if (!empty($contact_items)) {
foreach ($contact_items as $contact_item) {
$cache_tags = array_merge($cache_tags, $contact_item->getCacheTags());
$contactUs = Molecules::prepareAddress($contact_item, $options);
}

Expand Down
20 changes: 19 additions & 1 deletion docroot/modules/custom/mayflower/src/Prepare/Organisms.php
Original file line number Diff line number Diff line change
Expand Up @@ -350,10 +350,24 @@ public static function prepareEventListing($entity, $field = '', array $options
* ],... ]
* ]
*/
public static function prepareLinkList($entity, $field, array $options = []) {
public static function prepareLinkList($entity, $field, array $options = [], array &$cache_tags = []) {

$linkList = [];

if (Helper::isEntityReferenceField($entity, $field)) {
foreach (Helper::getReferencedEntitiesFromField($entity, $field) as $referenced_entity) {
$cache_tags = array_merge($cache_tags, $referenced_entity->getCacheTags());
}
}
else {
foreach ($entity->get($field) as $link) {
$linked_entity = Helper::entityFromUrl($link->getUrl());
if ($linked_entity instanceof ContentEntityInterface) {
$cache_tags = array_merge($cache_tags, $linked_entity->getCacheTags());
}
}
}

// Build description, if option is set.
if (isset($options['description'])) {
$description = [
Expand Down Expand Up @@ -995,6 +1009,7 @@ public static function prepareMappedLocations(array $locations, array $options,

$contact_ids = [];
foreach ($locations as $location) {
$cache_tags = array_merge($cache_tags, $location->getCacheTags());
foreach ($location->field_ref_contact_info_1 as $contactRef) {
$contactId = $contactRef->target_id;
$contact_ids[] = $contactId;
Expand All @@ -1003,6 +1018,9 @@ public static function prepareMappedLocations(array $locations, array $options,
}
// Batch load contact entities all at once.
$contact_entities = Node::loadMultiple($contact_ids);
foreach ($contact_entities as $contact_entity) {
$cache_tags = array_merge($cache_tags, $contact_entity->getCacheTags());
}

// Override the link to the map of locations if there is only a single
// location listed and instead link directly to that single location's page.
Expand Down
16 changes: 10 additions & 6 deletions docroot/themes/custom/mass_theme/mass_theme.theme
Original file line number Diff line number Diff line change
Expand Up @@ -1467,7 +1467,7 @@ function mass_theme_preprocess_node_topic_page(&$variables) {
],
];

$variables['linkList'] = Organisms::prepareLinkList($node, 'field_topic_ref_related_topics', $linkList_options);
$variables['linkList'] = Organisms::prepareLinkList($node, 'field_topic_ref_related_topics', $linkList_options, $cache_tags);

if (!empty($cache_tags)) {
// Merge arrays of existing and new cache tags and removes duplicates.
Expand Down Expand Up @@ -1509,7 +1509,7 @@ function mass_theme_preprocess_node_binder(&$variables) {
],
'stacked' => TRUE,
];
$sideContent['linkList'] = Organisms::prepareLinkList($node, 'field_binder_related', $linkList_options);
$sideContent['linkList'] = Organisms::prepareLinkList($node, 'field_binder_related', $linkList_options, $cache_tags);
$variables['sideContent'] = $sideContent;

if (!empty($cache_tags)) {
Expand Down Expand Up @@ -1573,7 +1573,7 @@ function mass_theme_preprocess_node_info_details(&$variables) {
],
'stacked' => TRUE,
];
$sideContent['linkList'] = Organisms::prepareLinkList($node, 'field_info_details_related', $linkList_options);
$sideContent['linkList'] = Organisms::prepareLinkList($node, 'field_info_details_related', $linkList_options, $cache_tags);
$variables['sideContent'] = $sideContent;
}

Expand Down Expand Up @@ -2989,7 +2989,7 @@ function mass_theme_preprocess_node_event(&$variables) {
$optionalContents = array_merge($optionalContents, Helper::buildPageHeaderOptionalContentsContactUs($node, 'field_event_ref_contact', $headerContact_options, $cache_tags));
}
if (Helper::isFieldPopulated($node, 'field_event_ref_unique_address') && ($address_type == 'unique')) {
$optionalContents = array_merge($optionalContents, Helper::buildPageHeaderOptionalContentsContactUsAddress($node, 'field_event_ref_unique_address'));
$optionalContents = array_merge($optionalContents, Helper::buildPageHeaderOptionalContentsContactUsAddress($node, 'field_event_ref_unique_address', [], $cache_tags));
}

// Build call out time.
Expand Down Expand Up @@ -3327,7 +3327,7 @@ function mass_theme_preprocess_node_service_page(&$variables) {
$split_columns['columns'][]['items'][] = [
'path' => '@organisms/by-author/link-list.twig',
'data' => [
'linkList' => Organisms::prepareLinkList($node, 'field_service_ref_services_6', $linkList_options),
'linkList' => Organisms::prepareLinkList($node, 'field_service_ref_services_6', $linkList_options, $cache_tags),
],
];
}
Expand Down Expand Up @@ -5456,6 +5456,7 @@ function mass_theme_preprocess_paragraph__related_content(&$variables) {
*/
function mass_theme_preprocess_paragraph__org_related_orgs(&$variables) {
$paragraph = $variables['paragraph'];
$cache_tags = [];

// Add related orgs stack row section.
if (Helper::isFieldPopulated($paragraph, 'field_ref_orgs')) {
Expand All @@ -5468,12 +5469,15 @@ function mass_theme_preprocess_paragraph__org_related_orgs(&$variables) {
[
'path' => '@organisms/by-author/link-list.twig',
'data' => [
'linkList' => Organisms::prepareLinkList($paragraph, 'field_ref_orgs', $linkList_options),
'linkList' => Organisms::prepareLinkList($paragraph, 'field_ref_orgs', $linkList_options, $cache_tags),
],
],
],
];
$variables['stackedRowSections'] = $sections;
if (!empty($cache_tags)) {
$variables['#cache']['tags'] = Cache::mergeTags($variables['#cache']['tags'] ?? [], $cache_tags);
}
}
}

Expand Down