Skip to content

Commit 6178aeb

Browse files
authored
feat: Add Support for App Router Invalidation by Tag in Drupal Module (#812) (#827)
1 parent 74c8dc7 commit 6178aeb

File tree

5 files changed

+118
-17
lines changed

5 files changed

+118
-17
lines changed

modules/next/src/Entity/NextSite.php

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -265,22 +265,15 @@ public function getLiveUrlForEntity(EntityInterface $entity): ?Url {
265265
/**
266266
* {@inheritdoc}
267267
*/
268-
public function getRevalidateUrlForPath(string $path): ?Url {
268+
public function buildRevalidateUrl(array $query = []): ?Url {
269269
$revalidate_url = $this->getRevalidateUrl();
270-
271270
if (!$revalidate_url) {
272271
return NULL;
273272
}
274-
275-
$query = [
276-
'path' => $path,
277-
];
278-
279273
if ($secret = $this->getRevalidateSecret()) {
280274
$query['secret'] = $secret;
281275
}
282-
283-
return Url::fromUri($this->getRevalidateUrl(), [
276+
return Url::fromUri($revalidate_url, [
284277
'query' => $query,
285278
]);
286279
}

modules/next/src/Entity/NextSiteInterface.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,12 @@ public function setRevalidateSecret(string $revalidate_secret): self;
131131
/**
132132
* Returns the revalidate url for given path.
133133
*
134-
* @param string $path
135-
* The path.
134+
* @param array $query
135+
* The revalidate URL query parameters.
136136
*
137137
* @return \Drupal\Core\Url|null
138138
* The revalidate url.
139139
*/
140-
public function getRevalidateUrlForPath(string $path): ?Url;
140+
public function buildRevalidateUrl(array $query = []): ?Url;
141141

142142
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
3+
namespace Drupal\next\Plugin\Next\Revalidator;
4+
5+
use Drupal\Core\Entity\FieldableEntityInterface;
6+
use Drupal\Core\Form\FormStateInterface;
7+
use Drupal\Core\Utility\Error;
8+
use Drupal\next\Event\EntityActionEvent;
9+
use Drupal\next\Plugin\ConfigurableRevalidatorBase;
10+
use Drupal\next\Plugin\RevalidatorInterface;
11+
use Symfony\Component\HttpFoundation\Response;
12+
13+
/**
14+
* Cache tag based on-demand revalidation plugin.
15+
*
16+
* @Revalidator(
17+
* id = "cache_tag",
18+
* label = "Cache Tag",
19+
* description = "Cache tag based on-demand revalidation."
20+
* )
21+
*/
22+
class CacheTag extends ConfigurableRevalidatorBase implements RevalidatorInterface {
23+
24+
/**
25+
* {@inheritdoc}
26+
*/
27+
public function defaultConfiguration() {
28+
return [];
29+
}
30+
31+
/**
32+
* {@inheritdoc}
33+
*/
34+
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
35+
return $form;
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
42+
// No configuration form.
43+
}
44+
45+
/**
46+
* {@inheritdoc}
47+
* @throws \Drupal\Core\Entity\EntityMalformedException
48+
* @throws \GuzzleHttp\Exception\GuzzleException
49+
*/
50+
public function revalidate(EntityActionEvent $event): bool {
51+
$revalidated = FALSE;
52+
$entity = $event->getEntity();
53+
$sites = $event->getSites();
54+
55+
if (!($entity instanceof FieldableEntityInterface)) {
56+
return FALSE;
57+
}
58+
59+
// Get all available cache tags (including list tags).
60+
$list_tags = $entity->getEntityType()->getListCacheTags();
61+
if ($entity->getEntityType()->hasKey('bundle')) {
62+
$list_tags[] = $entity->getEntityTypeId() . '_list:' . $entity->bundle();
63+
}
64+
$combined_tags = array_merge($entity->getCacheTags(), $list_tags);
65+
$cache_tags = implode(',', $combined_tags);
66+
67+
/** @var \Drupal\next\Entity\NextSite $site */
68+
foreach ($sites as $site) {
69+
try {
70+
$revalidate_url = $site->buildRevalidateUrl(['tags' => $cache_tags]);
71+
if (!$revalidate_url) {
72+
throw new \Exception('No revalidate url set.');
73+
}
74+
75+
if ($this->nextSettingsManager->isDebug()) {
76+
$this->logger->notice('(@action): Revalidating tags %list for the site %site. URL: %url', [
77+
'@action' => $event->getAction(),
78+
'%list' => $cache_tags,
79+
'%site' => $site->label(),
80+
'%url' => $revalidate_url->toString(),
81+
]);
82+
}
83+
84+
$response = $this->httpClient->request('GET', $revalidate_url->toString());
85+
if ($response && $response->getStatusCode() === Response::HTTP_OK) {
86+
if ($this->nextSettingsManager->isDebug()) {
87+
$this->logger->notice('(@action): Successfully revalidated tags %list for the site %site. URL: %url', [
88+
'@action' => $event->getAction(),
89+
'%list' => $cache_tags,
90+
'%site' => $site->label(),
91+
'%url' => $revalidate_url->toString(),
92+
]);
93+
}
94+
95+
$revalidated = TRUE;
96+
}
97+
}
98+
catch (\Exception $exception) {
99+
Error::logException($this->logger, $exception);
100+
$revalidated = FALSE;
101+
}
102+
}
103+
104+
return $revalidated;
105+
}
106+
107+
}

modules/next/src/Plugin/Next/Revalidator/Path.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,10 @@ public function revalidate(EntityActionEvent $event): bool {
8484
}
8585

8686
foreach ($paths as $path) {
87+
/** @var \Drupal\next\Entity\NextSite $site */
8788
foreach ($sites as $site) {
8889
try {
89-
$revalidate_url = $site->getRevalidateUrlForPath($path);
90+
$revalidate_url = $site->buildRevalidateUrl(['path' => $path]);
9091

9192
if (!$revalidate_url) {
9293
throw new \Exception('No revalidate url set.');

modules/next/tests/src/Kernel/Entity/NextSiteTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public function test() {
117117
}
118118

119119
/**
120-
* @covers ::getRevalidateUrlForPath
120+
* @covers ::buildRevalidateUrl
121121
*/
122122
public function testGetRevalidateUrlForPath() {
123123
$marketing = NextSite::create([
@@ -129,13 +129,13 @@ public function testGetRevalidateUrlForPath() {
129129
]);
130130
$marketing->save();
131131

132-
$this->assertNull($marketing->getRevalidateUrlForPath('/foo'));
132+
$this->assertNull($marketing->buildRevalidateUrl(['path' => '/foo']));
133133

134134
$marketing->setRevalidateUrl('http://example.com/api/revalidate');
135-
$this->assertSame('http://example.com/api/revalidate?path=/foo', $marketing->getRevalidateUrlForPath('/foo')->toString());
135+
$this->assertSame('http://example.com/api/revalidate?path=/foo', $marketing->buildRevalidateUrl(['path' => '/foo'])->toString());
136136

137137
$marketing->setRevalidateSecret('12345');
138-
$this->assertSame('http://example.com/api/revalidate?path=/foo&secret=12345', $marketing->getRevalidateUrlForPath('/foo')->toString());
138+
$this->assertSame('http://example.com/api/revalidate?path=/foo&secret=12345', $marketing->buildRevalidateUrl(['path' => '/foo'])->toString());
139139
}
140140

141141
}

0 commit comments

Comments
 (0)