- Added an ArrayCache (for dev), an HandleCacheTrait and a CacheInvalidator
This commit is contained in:
		
							parent
							
								
									a6ea7b9cce
								
							
						
					
					
						commit
						8665e97a19
					
				@ -2,32 +2,47 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Kash;
 | 
					namespace Kash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Psr\SimpleCache\CacheException;
 | 
				
			||||||
use Psr\SimpleCache\CacheInterface;
 | 
					use Psr\SimpleCache\CacheInterface;
 | 
				
			||||||
 | 
					use Psr\SimpleCache\InvalidArgumentException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use function apcu_fetch, apcu_store, apcu_delete, apcu_clear_cache, apcu_exists, apcu_enabled;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ApcuCache implements CacheInterface
 | 
					class ApcuCache implements CacheInterface
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const DEFAULT_NS_SEPARATOR = ':';
 | 
					    const DEFAULT_NS_SEPARATOR = ':';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function __construct(
 | 
					    public function __construct(
 | 
				
			||||||
 | 
					        protected CacheInvalidator $invalidator,
 | 
				
			||||||
        protected string $namespace,
 | 
					        protected string $namespace,
 | 
				
			||||||
        protected int $ttl,
 | 
					        protected int $ttl = 3600,
 | 
				
			||||||
    ) {}
 | 
					    ) {
 | 
				
			||||||
 | 
					        if (! apcu_enabled() ) {
 | 
				
			||||||
 | 
					            throw new class extends \Exception implements CacheException{
 | 
				
			||||||
 | 
					                public function __construct(string $message = "APCu extension is required to operate this class.", int $code = 0, ? \Throwable $previous = null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    parent::__construct($message, $code, $previous);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function get(string $key, mixed $default = null) : mixed
 | 
					    public function get(string $key, mixed $default = null) : mixed
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $value = apcu_fetch($this->fullkey($key), $status);
 | 
					        $value = apcu_fetch($this->fullKey($key), $status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $status === true ? $value : $default;
 | 
					        return $status === true ? $value : $default;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function set(string $key, mixed $value, null|int|\DateInterval $ttl = null) : bool
 | 
					    public function set(string $key, mixed $value, null|int|\DateInterval $ttl = null) : bool
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return apcu_store($this->fullkey($key), $value, $this->handleTTL($ttl));
 | 
					        return apcu_store($this->fullKey($key), $value, $this->handleTTL($ttl));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function delete(string $key) : bool
 | 
					    public function delete(string $key) : bool
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return apcu_delete($this->fullkey($key));
 | 
					        return apcu_delete($this->fullKey($key));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function clear() : bool
 | 
					    public function clear() : bool
 | 
				
			||||||
@ -37,30 +52,34 @@ class ApcuCache implements CacheInterface
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function getMultiple(iterable $keys, mixed $default = null) : iterable
 | 
					    public function getMultiple(iterable $keys, mixed $default = null) : iterable
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $nsKeys = $this->fullkey($keys);
 | 
					        $arr = iterator_to_array($keys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $nsKeys = $this->fullKey($keys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $result = apcu_fetch($nsKeys);
 | 
					        $result = apcu_fetch($nsKeys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return array_combine(array_map(fn($e) => substr($e, strlen($this->namespace) + strlen(static::DEFAULT_NS_SEPARATOR)), $nsKeys), $result) + array_fill_keys($keys, $default);
 | 
					        return array_combine(array_map(fn($e) => substr($e, strlen($this->namespace) + strlen(static::DEFAULT_NS_SEPARATOR)), $nsKeys), $result) + array_fill_keys($arr, $default);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null): bool
 | 
					    public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null): bool
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $list = array_combine(array_map( [$this, 'prependNamespace' ], array_keys($values), $values);
 | 
					        $arr = iterator_to_array($values);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $result = apcu_store($list, $this->ttl($ttl));
 | 
					        $list = array_combine(array_map( [$this, 'prependNamespace' ], array_keys($arr)), $arr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $result = apcu_store($list, $this->handleTTL($ttl));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return in_array($result, [ [], true ], true);
 | 
					        return in_array($result, [ [], true ], true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function deleteMultiple(iterable $keys) : bool
 | 
					    public function deleteMultiple(iterable $keys) : bool
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return apcu_delete($this->fullkey($keys)) === [];
 | 
					        return apcu_delete($this->fullKey($keys)) === [];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function has(string $key) : bool
 | 
					    public function has(string $key) : bool
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return apcu_exists($this->fullkey($key));
 | 
					        return apcu_exists($this->fullKey($key));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected function handleTTL(null|int|\DateInterval $ttl) : int
 | 
					    protected function handleTTL(null|int|\DateInterval $ttl) : int
 | 
				
			||||||
@ -74,13 +93,13 @@ class ApcuCache implements CacheInterface
 | 
				
			|||||||
        return (int) $ttl;
 | 
					        return (int) $ttl;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected function fullkey(string|array $key) : string|array
 | 
					    protected function fullKey(string|array $key) : string|array
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return is_array($key) ? array_map([ $this, 'prependNamespace' ], $key) : $this->prependNamespace($key);
 | 
					        return is_array($key) ? array_map([ $this, 'prependNamespace' ], $key) : $this->prependNamespace($key);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected function prependNamespace(string $key) : string
 | 
					    protected function prependNamespace(string $key) : string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->namespace . static::DEFAULT_NS_SEPARATOR . $key;
 | 
					        return $this->invalidator . $this->namespace . static::DEFAULT_NS_SEPARATOR . $key;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										112
									
								
								src/ArrayCache.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/ArrayCache.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,112 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Kash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Psr\SimpleCache\CacheException;
 | 
				
			||||||
 | 
					use Psr\SimpleCache\CacheInterface;
 | 
				
			||||||
 | 
					use Psr\SimpleCache\InvalidArgumentException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use function apcu_fetch, apcu_store, apcu_delete, apcu_clear_cache, apcu_exists, apcu_enabled;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ArrayCache implements CacheInterface
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const DEFAULT_NS_SEPARATOR = ':';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected array $storage = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected array $storageTTL = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct(
 | 
				
			||||||
 | 
					        protected CacheInvalidator $invalidator,
 | 
				
			||||||
 | 
					        protected string $namespace,
 | 
				
			||||||
 | 
					        protected int $ttl = -1,
 | 
				
			||||||
 | 
					    ) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function get(string $key, mixed $default = null) : mixed
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->storage[$this->fullKey($key)] ?? $default;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function set(string $key, mixed $value, null|int|\DateInterval $ttl = null) : bool
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $key = $this->fullKey($key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->storage[$key] = $value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->storageTTL[$key] = $this->handleTTL($ttl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function delete(string $key) : bool
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        unset($this->storage[$this->fullKey($key)]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function clear() : bool
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        unset($this->storage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getMultiple(iterable $keys, mixed $default = null) : iterable
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $list = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach($this->fullKey($keys) as $key => $value) {
 | 
				
			||||||
 | 
					            $list[$key] = $this->get($key, $default);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $list;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function setMultiple(iterable $values, null|int|\DateInterval $ttl = null): bool
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        foreach($values as $key => $value) {
 | 
				
			||||||
 | 
					            $this->set($key, $value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function deleteMultiple(iterable $keys) : bool
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach($keys as $key => $unused) {
 | 
				
			||||||
 | 
					            $this->delete($key);
 | 
				
			||||||
 | 
					            $i++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (bool) $i;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function has(string $key) : bool
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return isset($this->storage[$this->fullKey($key)]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function handleTTL(null|int|\DateInterval $ttl) : int
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($ttl instanceof \DateInterval) {
 | 
				
			||||||
 | 
					            $ttl = (new \DateTime)->add($ttl)->getTimestamp() - (new \DateTime)->getTimestamp();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $ttl ??= $this->ttl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (int) $ttl;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function fullKey(string|array $key) : string|array
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return is_array($key) ? array_map([ $this, 'prependNamespace' ], $key) : $this->prependNamespace($key);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function prependNamespace(string $key) : string
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->invalidator . $this->namespace . static::DEFAULT_NS_SEPARATOR . $key;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										33
									
								
								src/CacheInvalidator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/CacheInvalidator.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Kash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CacheInvalidator
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const CACHE_KEY_TEMPLATE = "v:%s_";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public string $version;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __construct(
 | 
				
			||||||
 | 
					        protected string $filePath,
 | 
				
			||||||
 | 
					        protected bool $updateVersion = false,
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        if ($this->updateVersion) {
 | 
				
			||||||
 | 
					            $this->version = $this->generateVersion();
 | 
				
			||||||
 | 
					            file_put_contents($this->filePath, $this->version);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            $this->version = file_get_contents($this->filePath);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function generateVersion() : string
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return sprintf(static::CACHE_KEY_TEMPLATE, substr(md5(uniqid()), random_int(0, 20), random_int(6,8)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function __toString() : string
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->version;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								src/HandleCacheTrait.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/HandleCacheTrait.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Kash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Psr\SimpleCache\CacheInterface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					trait HandleCacheTrait
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    protected ? CacheInterface $cache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function handleCaching(string $key, callable $callback, null|int|\DateInterval $ttl = null) : mixed
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        static $internalCache = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ( isset($internalCache[$key]) ) {
 | 
				
			||||||
 | 
					            return $internalCache[$key];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($this->cache !== null) {
 | 
				
			||||||
 | 
					            if (null === ($internalCache[$key] = $this->cache->get($key, null))) {
 | 
				
			||||||
 | 
					                $internalCache[$key] = call_user_func($callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $this->cache->set($key, $internalCache[$key], $ttl);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            $internalCache[$key] = call_user_func($callback);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $internalCache[$key];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user