File: /home/xedaptot/be.naniguide.com/app/Library/Cache/CacheScope.php
<?php
namespace App\Library\Cache;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
final class CacheScope
{
/** @var array<string, CacheEntry> */
protected array $entries = [];
public function __construct(
protected string $scope,
protected ?\Closure $onWrite = null,
) {}
public function register(CacheEntry $entry): void
{
$this->entries[$entry->name] = $entry;
}
public function hasEntries(): bool
{
return !empty($this->entries);
}
/** @return list<string> */
public function entryNames(): array
{
return array_keys($this->entries);
}
public function scope(): string
{
return $this->scope;
}
private function assertKnownEntry(string $name): void
{
if (isset($this->entries[$name])) {
return;
}
$registered = array_keys($this->entries);
$details = empty($registered)
? ' No cache entries are registered for this scope.'
: ' Registered entries: ' . implode(', ', $registered) . '.';
throw new \InvalidArgumentException(
"Unknown cache entry '{$name}' in scope '{$this->scope}'." . $details
);
}
public function read(string $name, mixed $default = null): mixed
{
$this->assertKnownEntry($name);
$blob = Cache::get(CacheKey::build($this->scope, $name));
if ($blob === null) {
return $default;
}
return is_array($blob) && array_key_exists('value', $blob) ? $blob['value'] : $default;
}
/**
* $ttl null → forever. Int → seconds until expiry.
* refresh() forwards $entry->ttl here so manifest-declared TTLs apply.
*/
public function put(string $name, mixed $value, ?int $ttl = null): void
{
$this->assertKnownEntry($name);
$key = CacheKey::build($this->scope, $name);
$blob = ['value' => $value, 'updated_at' => now()->timestamp];
if ($ttl === null) {
Cache::forever($key, $blob);
} else {
Cache::put($key, $blob, $ttl);
}
if ($this->onWrite !== null) {
($this->onWrite)();
}
}
public function forget(string $name): void
{
$this->assertKnownEntry($name);
Cache::forget(CacheKey::build($this->scope, $name));
}
public function lastUpdatedAt(string $name): ?Carbon
{
$this->assertKnownEntry($name);
$blob = Cache::get(CacheKey::build($this->scope, $name));
$ts = is_array($blob) ? ($blob['updated_at'] ?? null) : null;
return $ts ? Carbon::createFromTimestamp($ts) : null;
}
public function refresh(?string $name = null): void
{
if (empty($this->entries)) {
return;
}
if ($name !== null) {
$this->assertKnownEntry($name);
}
$targets = $name !== null ? [$this->entries[$name]] : array_values($this->entries);
foreach ($targets as $entry) {
$this->put($entry->name, ($entry->compute)(), $entry->ttl);
}
}
public function clear(): void
{
if (empty($this->entries)) {
return;
}
foreach ($this->entries as $entry) {
$this->forget($entry->name);
}
}
}