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
1 change: 1 addition & 0 deletions src/HeaderEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ enum HeaderEnum: string
case CACHE_TAG = 'Cache-Tag';
case CACHE_PURGE_TAG = 'Cache-Purge-Tag';
case CACHE_PURGE_PREFIX = 'Cache-Purge-Prefix';
case CACHE_PURGE_URL = 'Cache-Purge-URL';
case CACHE_CONTROL = 'Cache-Control';
case CDN_CACHE_CONTROL = 'CDN-Cache-Control';
case SURROGATE_CONTROL = 'Surrogate-Control';
Expand Down
50 changes: 35 additions & 15 deletions src/StaticCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use craft\web\UrlManager;
use craft\web\View;
use Illuminate\Support\Collection;
use League\Uri\Components\Path;
use samdark\log\PsrMessage;
use yii\base\Event;
use yii\caching\TagDependency;
Expand All @@ -38,12 +37,14 @@ class StaticCache extends \yii\base\Component
private ?int $cacheDuration = null;
private Collection $tags;
private Collection $tagsToPurge;
private Collection $urlsToPurge;
private bool $collectingCacheInfo = false;

public function init(): void
{
$this->tags = Collection::make();
$this->tagsToPurge = Collection::make();
$this->urlsToPurge = Collection::make();
}

public function registerEventHandlers(): void
Expand Down Expand Up @@ -99,6 +100,15 @@ public function registerEventHandlers(): void
Craft::error('Failed to purge tags after request');
}
}

if ($this->urlsToPurge->isNotEmpty()) {
try {
$this->purgeUrls(...$this->urlsToPurge);
} catch (\Throwable $e) {
// TODO: log exception once output payload isn't a concern
Craft::error('Failed to purge tags after request');
}
}
});
}

Expand Down Expand Up @@ -166,12 +176,12 @@ private function handleRegisterCacheOptions(RegisterCacheOptionsEvent $event): v

private function handleSaveElement(ElementEvent $event): void
{
$this->purgeElementUri($event->element);
$this->purgeElementUrl($event->element);
}

private function handleDeleteElement(ElementEvent $event): void
{
$this->purgeElementUri($event->element);
$this->purgeElementUrl($event->element);
}

public function purgeAll(): void
Expand All @@ -198,23 +208,15 @@ public function purgeCdn(): void
$this->tagsToPurge->push($tag);
}

private function purgeElementUri(ElementInterface $element): void
private function purgeElementUrl(ElementInterface $element): void
{
$uri = $element->uri ?? null;
$url = $element->uri ?? null;

if (ElementHelper::isDraftOrRevision($element) || !$uri) {
if (ElementHelper::isDraftOrRevision($element) || !$url) {
return;
}

$uri = $element->getIsHomepage()
? '/'
: Path::new($uri)->withLeadingSlash()->withoutTrailingSlash();

$tag = StaticCacheTag::create($uri)
->withPrefix(Module::getInstance()->getConfig()->environmentId . ':')
->minify(false);

$this->tagsToPurge->prepend($tag);
$this->urlsToPurge->push($url);
}

private function addCacheHeadersToWebResponse(): void
Expand Down Expand Up @@ -298,6 +300,24 @@ public function purgeTags(string|StaticCacheTag ...$tags): void
]);
}

public function purgeUrls(string ...$urls): void
{
$urls = Collection::make($urls)->filter()->unique();

if ($urls->isEmpty()) {
return;
}

Craft::info(new PsrMessage('Purging URLs', [
'urls' => $urls->all(),
]));

// TODO: make sure we don't go over max header size
Helper::makeGatewayApiRequest([
HeaderEnum::CACHE_PURGE_URL->value => $urls->implode(','),
]);
}

public function purgeUrlPrefixes(string ...$urlPrefixes): void
{
$urlPrefixes = Collection::make($urlPrefixes)->filter()->unique();
Expand Down
9 changes: 9 additions & 0 deletions src/cli/controllers/StaticCacheController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ public function actionPurgePrefixes(string ...$prefixes): int
return ExitCode::OK;
}

public function actionPurgeUrls(string ...$urls): int
{
$this->do('Purging URLs', function() use ($urls) {
Module::getInstance()->getStaticCache()->purgeUrls(...$urls);
});

return ExitCode::OK;
}

public function actionPurgeTags(string ...$tags): int
{
$this->do('Purging tags', function() use ($tags) {
Expand Down
Loading