Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 4 additions & 4 deletions modules/next/src/Form/NextEntityTypeConfigForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public function form(array $form, FormStateInterface $form_state) {
'#ajax' => [
'callback' => '::ajaxReplaceSettingsForm',
'wrapper' => 'settings-container',
'method' => 'replace',
'method' => 'replaceWith',
],
];

Expand All @@ -120,7 +120,7 @@ public function form(array $form, FormStateInterface $form_state) {
'#ajax' => [
'callback' => '::ajaxReplaceSiteResolverSettingsForm',
'wrapper' => 'site-resolver-settings',
'method' => 'replace',
'method' => 'replaceWith',
],
];

Expand Down Expand Up @@ -167,7 +167,7 @@ public function form(array $form, FormStateInterface $form_state) {
'#ajax' => [
'callback' => '::ajaxReplaceSettingsForm',
'wrapper' => 'settings-container',
'method' => 'replace',
'method' => 'replaceWith',
],
];

Expand All @@ -191,7 +191,7 @@ public function form(array $form, FormStateInterface $form_state) {
'#ajax' => [
'callback' => '::ajaxReplaceRevalidatorSettingsForm',
'wrapper' => 'revalidator-settings',
'method' => 'replace',
'method' => 'replaceWith',
],
];

Expand Down
119 changes: 108 additions & 11 deletions modules/next/src/Plugin/Next/Revalidator/CacheTag.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,95 @@ class CacheTag extends ConfigurableRevalidatorBase implements RevalidatorInterfa
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [];
return [
'entity_tag' => TRUE,
'entity_list_tag' => TRUE,
'additional_tags' => NULL,
];
}

/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
// Get entity type and bundle from form callback object.
$entity_type_id = NULL;
$bundle = NULL;

try {
$entity_bundle_string = $form_state->getBuildInfo()['callback_object']->getEntity()->id();
// Split "node.quote" into entity type and bundle.
if (strpos($entity_bundle_string, '.') !== FALSE) {
[$entity_type_id, $bundle] = explode('.', $entity_bundle_string, 2);
}
}
catch (\Exception) {
Comment thread
senemhartung marked this conversation as resolved.
Outdated
// Fallback if we can't get the entity info.
$entity_type_id = NULL;
$bundle = NULL;
}

$form['entity_tag'] = [
'#title' => $this->t('Revalidate entity cache tag'),
'#description' => $this->t('Revalidate pages with the individual entity cache tag (e.g., @entity_type:123).', [
'@entity_type' => $entity_type_id ?: 'node',
]),
'#type' => 'checkbox',
'#default_value' => $this->configuration['entity_tag'] ?? TRUE,
];

// Generate specific label and description based on detected entity type.
if ($entity_type_id && $bundle) {
if ($entity_type_id === 'node') {
$list_tag_example = 'node_list:' . $bundle;
$next_js_example = 'tags: ["node_list:' . $bundle . '"]';
}
elseif ($entity_type_id === 'taxonomy_term') {
$list_tag_example = 'taxonomy_list:' . $bundle;
Comment thread
senemhartung marked this conversation as resolved.
Outdated
$next_js_example = 'tags: ["taxonomy_list:' . $bundle . '"]';
}
else {
$list_tag_example = $entity_type_id . '_list:' . $bundle;
$next_js_example = 'tags: ["' . $entity_type_id . '_list:' . $bundle . '"]';
}

$title = $this->t('Revalidate @tag cache tags', ['@tag' => $list_tag_example]);
$description = $this->t('Revalidates pages tagged with @tag when @entity_type entities of type @bundle change.<br><br>In Next.js use: <code>@example</code>', [
'@tag' => $list_tag_example,
'@entity_type' => $entity_type_id,
'@bundle' => $bundle,
'@example' => $next_js_example,
]);
}
else {
$title = $this->t('Revalidate [entity_type]_list:[bundle] cache tags');
$description = $this->t('Revalidates pages tagged with entity type and bundle list cache tags when entities change.<br><strong>Node entities:</strong> generates node_list:[bundle] (e.g., node_list:article, node_list:person)<br><strong>Taxonomy terms:</strong> generates taxonomy_list:[vocabulary] (e.g., taxonomy_list:tags)<br><strong>Other entities:</strong> generates [entity_type]_list:[bundle]<br><br>In Next.js use: <code>tags: ["node_list:article"]</code> or <code>tags: ["taxonomy_list:tags"]</code>');
}

$form['entity_list_tag'] = [
'#title' => $title,
'#description' => $description,
'#type' => 'checkbox',
'#default_value' => $this->configuration['entity_list_tag'] ?? TRUE,
];

$form['additional_tags'] = [
'#type' => 'textarea',
'#title' => $this->t('Additional cache tags to revalidate'),
'#default_value' => $this->configuration['additional_tags'] ?? '',
'#description' => $this->t('Additional cache tags to revalidate when this entity type changes. Enter one tag per line. Examples:<br>node_list:all<br>search_results<br>homepage'),
];

return $form;
}

/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
// No configuration form.
$this->configuration['entity_tag'] = $form_state->getValue('entity_tag');
$this->configuration['entity_list_tag'] = $form_state->getValue('entity_list_tag');
$this->configuration['additional_tags'] = $form_state->getValue('additional_tags');
Comment thread
senemhartung marked this conversation as resolved.
}

/**
Expand All @@ -57,26 +131,49 @@ public function revalidate(EntityActionEvent $event): bool {
return FALSE;
}

// Get all available cache tags (including list tags).
$list_tags = $entity->getEntityType()->getListCacheTags();
if ($entity->getEntityType()->hasKey('bundle')) {
$list_tags[] = $entity->getEntityTypeId() . '_list:' . $entity->bundle();
$cache_tags = [];

// Add individual entity cache tags if enabled.
if (!empty($this->configuration['entity_tag'])) {
$cache_tags = array_merge($cache_tags, $entity->getCacheTags());
}

// Add entity list cache tags if enabled.
if (!empty($this->configuration['entity_list_tag'])) {
$list_tags = $entity->getEntityType()->getListCacheTags();
if ($entity->getEntityType()->hasKey('bundle')) {
$list_tags[] = $entity->getEntityTypeId() . '_list:' . $entity->bundle();
}
$cache_tags = array_merge($cache_tags, $list_tags);
}

// Add additional cache tags.
if (!empty($this->configuration['additional_tags'])) {
$additional_tags = array_map('trim', explode("\n", $this->configuration['additional_tags']));
$additional_tags = array_filter($additional_tags);
$cache_tags = array_merge($cache_tags, $additional_tags);
}

if (!count($cache_tags)) {
return FALSE;
Comment thread
senemhartung marked this conversation as resolved.
}
$combined_tags = array_merge($entity->getCacheTags(), $list_tags);
$cache_tags = implode(',', $combined_tags);

// Remove duplicates and convert to comma-separated string.
$cache_tags = array_unique($cache_tags);
$cache_tags_string = implode(',', $cache_tags);

/** @var \Drupal\next\Entity\NextSite $site */
foreach ($sites as $site) {
try {
$revalidate_url = $site->buildRevalidateUrl(['tags' => $cache_tags]);
$revalidate_url = $site->buildRevalidateUrl(['tags' => $cache_tags_string]);
if (!$revalidate_url) {
throw new \Exception('No revalidate url set.');
}

if ($this->nextSettingsManager->isDebug()) {
$this->logger->notice('(@action): Revalidating tags %list for the site %site. URL: %url', [
'@action' => $event->getAction(),
'%list' => $cache_tags,
'%list' => $cache_tags_string,
'%site' => $site->label(),
'%url' => $revalidate_url->toString(),
]);
Expand All @@ -87,7 +184,7 @@ public function revalidate(EntityActionEvent $event): bool {
if ($this->nextSettingsManager->isDebug()) {
$this->logger->notice('(@action): Successfully revalidated tags %list for the site %site. URL: %url', [
'@action' => $event->getAction(),
'%list' => $cache_tags,
'%list' => $cache_tags_string,
'%site' => $site->label(),
'%url' => $revalidate_url->toString(),
]);
Expand Down
Loading