HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
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);
        }
    }
}