Skip to content
This repository was archived by the owner on Jan 29, 2020. It is now read-only.
This repository was archived by the owner on Jan 29, 2020. It is now read-only.

Make it possible to decorate cache adapters with PSR6/PSR16 decorators through configuration #179

@nuxwin

Description

@nuxwin

@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;
            }
        });
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions