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

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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