Skip to content

Commit f2c6fd3

Browse files
committed
feat: Add Support for App Router Invalidation by Tag in Drupal Module (#812)
1 parent f8561b1 commit f2c6fd3

File tree

1 file changed

+139
-0
lines changed

1 file changed

+139
-0
lines changed
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
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\Url;
8+
use Drupal\Core\Utility\Error;
9+
use Drupal\next\Entity\NextSite;
10+
use Drupal\next\Event\EntityActionEvent;
11+
use Drupal\next\Plugin\ConfigurableRevalidatorBase;
12+
use Drupal\next\Plugin\RevalidatorInterface;
13+
use Symfony\Component\HttpFoundation\Response;
14+
15+
/**
16+
* Provides a revalidator for revalidating Next Site references by cache tags.
17+
*
18+
* @Revalidator(
19+
* id = "cache_tag",
20+
* label = "Cache Tag",
21+
* description = "Cache tag based on-demand revalidation."
22+
* )
23+
*/
24+
class CacheTag extends ConfigurableRevalidatorBase implements RevalidatorInterface {
25+
26+
/**
27+
* {@inheritdoc}
28+
*/
29+
public function defaultConfiguration() {
30+
return [];
31+
}
32+
33+
/**
34+
* {@inheritdoc}
35+
*/
36+
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
37+
return $form;
38+
}
39+
40+
/**
41+
* {@inheritdoc}
42+
*/
43+
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
44+
// No configuration form.
45+
}
46+
47+
/**
48+
* {@inheritdoc}
49+
* @throws \Drupal\Core\Entity\EntityMalformedException
50+
* @throws \GuzzleHttp\Exception\GuzzleException
51+
*/
52+
public function revalidate(EntityActionEvent $event): bool {
53+
$revalidated = FALSE;
54+
$entity = $event->getEntity();
55+
$sites = $event->getSites();
56+
57+
if (!($entity instanceof FieldableEntityInterface)) {
58+
return FALSE;
59+
}
60+
61+
$tags = [];
62+
$tags[] = $entity->getEntityTypeId() . ':' . $entity->id();
63+
if ($entity->getEntityTypeId() == 'menu_link_content') {
64+
$tags[] = $entity->getEntityTypeId() . ':' . $entity->getMenuName();
65+
}
66+
else {
67+
$tags[] = $entity->getEntityTypeId() . '_list';
68+
$tags[] = $entity->getEntityTypeId() . '_list:' . $entity->bundle();
69+
}
70+
71+
/** @var \Drupal\next\Entity\NextSite $site */
72+
foreach ($sites as $site) {
73+
try {
74+
$tags_string = implode(',', $tags);
75+
$revalidate_url = $this->getRevalidateUrlForTags($site, $tags_string);
76+
77+
if (!$revalidate_url) {
78+
throw new \Exception('No revalidate url set.');
79+
}
80+
81+
if ($this->nextSettingsManager->isDebug()) {
82+
$this->logger->notice('(@action): Revalidating tags %tags for the site %site. URL: %url', [
83+
'@action' => $event->getAction(),
84+
'%tags' => $tags_string,
85+
'%site' => $site->label(),
86+
'%url' => $revalidate_url->toString(),
87+
]);
88+
}
89+
90+
$response = $this->httpClient->request('GET', $revalidate_url->toString());
91+
if ($response && $response->getStatusCode() === Response::HTTP_OK) {
92+
if ($this->nextSettingsManager->isDebug()) {
93+
$this->logger->notice('(@action): Successfully revalidated tags %path for the site %site. URL: %url', [
94+
'@action' => $event->getAction(),
95+
'%tags' => $tags_string,
96+
'%site' => $site->label(),
97+
'%url' => $revalidate_url->toString(),
98+
]);
99+
}
100+
101+
$revalidated = TRUE;
102+
}
103+
}
104+
catch (\Exception $exception) {
105+
Error::logException($this->logger, $exception);
106+
$revalidated = FALSE;
107+
}
108+
}
109+
110+
return $revalidated;
111+
}
112+
113+
/**
114+
* Returns the revalidate url for given cache tags.
115+
*
116+
* @param NextSite $site
117+
* @param string $cache_tags
118+
* The cache tags as string.
119+
*
120+
* @return \Drupal\Core\Url|null
121+
* The revalidate url.
122+
*/
123+
protected function getRevalidateUrlForTags(NextSite $site, string $cache_tags): ?Url {
124+
$revalidate_url = $site->getRevalidateUrl();
125+
if (!$revalidate_url) {
126+
return NULL;
127+
}
128+
$query = [
129+
'tags' => $cache_tags,
130+
];
131+
if ($secret = $site->getRevalidateSecret()) {
132+
$query['secret'] = $secret;
133+
}
134+
return Url::fromUri($site->getRevalidateUrl(), [
135+
'query' => $query,
136+
]);
137+
}
138+
139+
}

0 commit comments

Comments
 (0)