index/src/Cache/CacheTools.php
2024-04-10 22:23:34 +00:00

78 lines
2.4 KiB
PHP

<?php
// CacheTools.php
// Created: 2024-04-10
// Updated: 2024-04-10
namespace Index\Cache;
use InvalidArgumentException;
use RuntimeException;
/**
* Common cache actions.
*/
final class CacheTools {
private const CACHE_PROTOS = [
'null' => ArrayCache\ArrayCacheBackend::class,
'array' => ArrayCache\ArrayCacheBackend::class,
'memcache' => Memcached\MemcachedBackend::class,
'memcached' => Memcached\MemcachedBackend::class,
'redis' => Valkey\ValkeyBackend::class,
'keydb' => Valkey\ValkeyBackend::class,
'valkey' => Valkey\ValkeyBackend::class,
];
private static function parseDsnUri(string $dsn): array {
$uri = parse_url($dsn);
if($uri === false)
throw new InvalidArgumentException('$dsn is not a valid uri.');
return $uri;
}
private static function resolveBackend(array $uri): ICacheBackend {
static $backends = [];
$scheme = $uri['scheme'];
if(in_array($scheme, $backends))
$backend = $backends[$scheme];
else {
$backend = null;
if(array_key_exists($scheme, self::CACHE_PROTOS))
$name = self::CACHE_PROTOS[$scheme];
else
$name = str_replace('-', '\\', $scheme);
if(class_exists($name) && is_subclass_of($name, ICacheBackend::class)) {
$backend = new $name;
$name = get_class($backend);
}
if($backend === null)
throw new RuntimeException('No implementation is available for the specified scheme.');
if(!$backend->isAvailable())
throw new RuntimeException('Requested cache backend is not available, likely due to missing dependencies.');
$backends[$name] = $backend;
}
return $backend;
}
public static function backend(string $dsn): ICacheBackend {
return self::resolveBackend(self::parseDsnUri($dsn));
}
public static function parse(string $dsn): ICacheProviderInfo {
$uri = self::parseDsnUri($dsn);
return self::resolveBackend($uri)->parseDsn($uri);
}
public static function create(string $dsn): ICacheProvider {
$uri = self::parseDsnUri($dsn);
$backend = self::resolveBackend($uri);
return $backend->createProvider($backend->parseDsn($uri));
}
}