@weierophinney
Good morning,
The configuration provider currently provides the \Zend\Cache\Service\StorageCacheAbstractServiceFactory::class abstract factory which make it possible to map pseudo services. For instance:
// Dependencies
...
'factories' => [
\iMPSCP\ApplicationCache::class => \Zend\Cache\Service\StorageCacheAbstractServiceFactory::class
]
...
// Config
...
'caches' => [
\iMSCP\ApplicationCache::class => [
'adapter' => [
'name' => \Zend\Cache\Storage\Adapter\Apcu::class,
'options' => [
'namespace' => \iMSCP\ApplicationCache::class,
]
],
'plugins' => [
\Zend\Cache\Storage\Plugin\ExceptionHandler::class => [
'throw_exceptions' => false,
],
\Zend\Cache\Storage\Plugin\IgnoreUserAbort::class => [
'exit_on_abort' => false
]
]
]
]
...
However, currently, it seem that there is no way to decorate the adapters automatically with a PSR6 or PSR16 implementation. Could it be possible to add a decorator option to the adapters factory and if so, automatically return the decorated adapter? For instance:
// Config
...
'caches' => [
\iMSCP\ApplicationCache::class => [
'adapter' => [
'name' => \Zend\Cache\Storage\Adapter\Apcu::class,
'options' => [
'namespace' => \iMSCP\ApplicationCache::class,
]
],
'plugins' => [
\Zend\Cache\Storage\Plugin\ExceptionHandler::class => [
'throw_exceptions' => false,
],
\Zend\Cache\Storage\Plugin\IgnoreUserAbort::class => [
'exit_on_abort' => false
]
],
decorator' => \Zend\Cache\Psr\SimpleCache\SimpleCacheDecorator::class
]
]
...
For now, I make use of a delegator but...
<?php
declare(strict_types=1);
namespace iMSCP\Foundation\Container;
use Psr\Container\ContainerInterface;
use Psr\SimpleCache\CacheInterface;
use Zend\Cache\Psr\SimpleCache\SimpleCacheDecorator;
use Zend\Cache\Storage\StorageInterface;
class ApplicationCacheDelegatorFactory
{
/**
* Decorate a cache adapter with a PSR16 implementation
*
* @param ContainerInterface $container
* @param string $serviceName
* @param callable $callback
* @return CacheInterface
*/
public function __invoke(ContainerInterface $container, string $serviceName, callable $callback): CacheInterface
{
try {
/** @var StorageInterface $storage */
$storage = $callback();
if($container->get('config')['debug'] ?? false) {
$storage->setOptions([
'readable' => false,
'writable' => false,
]);
}
// PSR-16 implementation
$storage = new SimpleCacheDecorator($storage);
} catch (\Throwable $e) {
// PSR-16 implementation (fallback)
$storage = $this->fallbackPsr16Impl();
}
return $storage;
}
protected function fallbackPsr16Impl()
{
return (new class implements CacheInterface
{
public function get($key, $default = NULL)
{
return false;
}
public function set($key, $value, $ttl = NULL)
{
return false;
}
public function delete($key)
{
return false;
}
public function clear()
{
return false;
}
public function getMultiple($keys, $default = NULL)
{
return [];
}
public function setMultiple($values, $ttl = NULL)
{
return false;
}
public function deleteMultiple($keys)
{
return false;
}
public function has($key)
{
return false;
}
});
}
}