120 lines
4.5 KiB
PHP
120 lines
4.5 KiB
PHP
<?php
|
|
// CacheTools.php
|
|
// Created: 2024-04-10
|
|
// Updated: 2024-04-10
|
|
|
|
namespace Index\Cache;
|
|
|
|
use InvalidArgumentException;
|
|
use RuntimeException;
|
|
|
|
/**
|
|
* Common cache actions.
|
|
*
|
|
* DSN documentation:
|
|
*
|
|
* CacheTools only handles the scheme part of the URL,
|
|
* the rest of the URL is described in the documentation of the parseDsn implementation of the respective backend.
|
|
*
|
|
* The scheme can be a PHP classpath to an implementation of ICacheBackend, or any of these aliases:
|
|
* - `array`, `null`: maps to `ArrayCache\ArrayCacheBackend` or `Index-Cache-ArrayCache-ArrayCacheBackend`, uses a simple array backed cache that doesn't get saved.
|
|
* - `memcached`, `memcache`: maps to `Memcached\MemcachedBackend` or `Index-Cache-Memcached-MemcachedBackend`, provides a backend based on the memcached or memcache extension.
|
|
* - `valkey`, `keydb`, `redis`: maps to `Valkey\ValkeyBackend` or `Index-Cache-Valkey-ValkeyBackend`, provides a backend based on the phpredis extension.
|
|
*
|
|
* Short names are currently hardcoded and cannot be expanded.
|
|
*/
|
|
final class CacheTools {
|
|
private const CACHE_PROTOS = [
|
|
'array' => ArrayCache\ArrayCacheBackend::class,
|
|
'null' => ArrayCache\ArrayCacheBackend::class,
|
|
'memcached' => Memcached\MemcachedBackend::class,
|
|
'memcache' => Memcached\MemcachedBackend::class,
|
|
'valkey' => Valkey\ValkeyBackend::class,
|
|
'redis' => Valkey\ValkeyBackend::class,
|
|
'keydb' => 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;
|
|
}
|
|
|
|
/**
|
|
* Retrieves cache provider based on DSN URL.
|
|
*
|
|
* Format of the DSN URLs are described in the documentation of the CacheTools class as a whole.
|
|
*
|
|
* @param string $dsn URL to create cache provider from.
|
|
* @throws InvalidArgumentException if $dsn is not a valid URL.
|
|
* @throws RuntimeException if no cache provider can be made using the URL.
|
|
* @return ICacheBackend Cache backend instance.
|
|
*/
|
|
public static function backend(string $dsn): ICacheBackend {
|
|
return self::resolveBackend(self::parseDsnUri($dsn));
|
|
}
|
|
|
|
/**
|
|
* Parses a DSN URL.
|
|
*
|
|
* Format of the DSN URLs are described in the documentation of the CacheTools class as a whole.
|
|
*
|
|
* @param string $dsn URL to create cache provider from.
|
|
* @throws InvalidArgumentException if $dsn is not a valid URL.
|
|
* @throws RuntimeException if no cache provider can be made using the URL.
|
|
* @return ICacheProviderInfo Cache provider info.
|
|
*/
|
|
public static function parse(string $dsn): ICacheProviderInfo {
|
|
$uri = self::parseDsnUri($dsn);
|
|
return self::resolveBackend($uri)->parseDsn($uri);
|
|
}
|
|
|
|
/**
|
|
* Uses a DSN URL to create a cache provider instance.
|
|
*
|
|
* Format of the DSN URLs are described in the documentation of the CacheTools class as a whole.
|
|
*
|
|
* @param string $dsn URL to create cache provider from.
|
|
* @throws InvalidArgumentException if $dsn is not a valid URL.
|
|
* @throws RuntimeException if no cache provider can be made using the URL.
|
|
* @return ICacheProvider A cache provider.
|
|
*/
|
|
public static function create(string $dsn): ICacheProvider {
|
|
$uri = self::parseDsnUri($dsn);
|
|
$backend = self::resolveBackend($uri);
|
|
return $backend->createProvider($backend->parseDsn($uri));
|
|
}
|
|
}
|