Files
newznab-tmux/app/Services/Search/SearchCursorCodec.php
T

50 lines
1.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Services\Search;
use App\Services\Search\DTO\SearchCursor;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Contracts\Encryption\Encrypter;
use InvalidArgumentException;
final readonly class SearchCursorCodec
{
public function __construct(private Encrypter $encrypter) {}
public function encode(SearchCursor $cursor): string
{
return $this->encrypter->encryptString(json_encode([
'sort' => $cursor->sortValues,
'total' => $cursor->total,
'query' => $cursor->queryHash,
'driver' => $cursor->driver,
'generation' => $cursor->indexGeneration,
'expires' => $cursor->expiresAt,
], JSON_THROW_ON_ERROR));
}
public function decode(string $token): SearchCursor
{
try {
$payload = json_decode($this->encrypter->decryptString($token), true, flags: JSON_THROW_ON_ERROR);
} catch (DecryptException|\JsonException $e) {
throw new InvalidArgumentException('Invalid search cursor.', previous: $e);
}
if (! is_array($payload) || ! is_array($payload['sort'] ?? null) || (int) ($payload['expires'] ?? 0) < time()) {
throw new InvalidArgumentException('Invalid or expired search cursor.');
}
return new SearchCursor(
sortValues: array_values($payload['sort']),
total: (int) ($payload['total'] ?? 0),
queryHash: (string) ($payload['query'] ?? ''),
driver: (string) ($payload['driver'] ?? ''),
indexGeneration: (string) ($payload['generation'] ?? ''),
expiresAt: (int) $payload['expires'],
);
}
}