Laravel 13 + Filament 5 admin panel and REST API for a non-profit developer collective, backed by the Pireon OAuth identity server. The public site is a separate, server-rendered application consuming /api/public/v1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
58 lines
1.7 KiB
PHP
58 lines
1.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Support;
|
|
|
|
use App\Models\Setting;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
/**
|
|
* A number that changes whenever published content does.
|
|
*
|
|
* The public API is cached with `s-maxage` and a long
|
|
* `stale-while-revalidate`, which is right for an SSR frontend and wrong for
|
|
* an urgent correction: a fix can sit behind a stale copy for minutes. The
|
|
* frontend cannot know something changed without asking, and asking is the
|
|
* thing the cache exists to avoid.
|
|
*
|
|
* So it is told. `/site` carries this number, the frontend keeps it as part of
|
|
* its cache key, and the moment it moves everything downstream is stale by
|
|
* definition — no purge webhook, no shared secret, nothing to deploy.
|
|
*/
|
|
final class ContentVersion
|
|
{
|
|
public const KEY = 'content.version';
|
|
|
|
public static function current(): int
|
|
{
|
|
return (int) Setting::get(self::KEY, 0);
|
|
}
|
|
|
|
/**
|
|
* Move it on. Cheap on purpose: this runs on every content save.
|
|
*/
|
|
public static function bump(): void
|
|
{
|
|
Setting::set(self::KEY, self::current() + 1);
|
|
}
|
|
|
|
/**
|
|
* Whether a change to this record is one a visitor could notice.
|
|
*
|
|
* A draft nobody can see moving does not invalidate anybody's cache, and
|
|
* bumping on every keystroke of a half-written page would make the number
|
|
* meaningless.
|
|
*/
|
|
public static function shouldBumpFor(Model $record): bool
|
|
{
|
|
if (method_exists($record, 'isPublishedNow')) {
|
|
// Either it is on the site now, or it was a moment ago — going
|
|
// away is exactly as visible as arriving.
|
|
return $record->isPublishedNow() || (bool) $record->getOriginal('published_at');
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|