Actualización

This commit is contained in:
Xes
2025-04-10 12:24:57 +02:00
parent 8969cc929d
commit 45420b6f0d
39760 changed files with 4303286 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\Cache\Adapter\Cache;
/**
* Handles Apc Cache.
*/
class ApcCache extends OpCodeCache
{
}

View File

@@ -0,0 +1,34 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\Cache\Adapter\Cache;
use Sonata\Cache\CacheAdapterInterface;
use Sonata\Cache\CacheElement;
use Sonata\Cache\CacheElementInterface;
abstract class BaseCacheHandler implements CacheAdapterInterface
{
/**
* @param array $keys
* @param mixed $data
*
* @return CacheElementInterface
*/
protected function handleGet(array $keys, $data = null): CacheElementInterface
{
if ($data instanceof CacheElementInterface) {
return $data;
}
return new CacheElement($keys, null, -1000);
}
}

View File

@@ -0,0 +1,120 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\Cache\Adapter\Cache;
use Sonata\Cache\CacheElement;
use Sonata\Cache\CacheElementInterface;
class MemcachedCache extends BaseCacheHandler
{
protected $servers;
protected $prefix;
protected $collection;
/**
* @param $prefix
* @param array $servers
*/
public function __construct(string $prefix, array $servers)
{
$this->prefix = $prefix;
$this->servers = $servers;
}
/**
* {@inheritdoc}
*/
public function flushAll(): bool
{
return $this->getCollection()->flush();
}
/**
* {@inheritdoc}
*/
public function flush(array $keys = []): bool
{
return $this->getCollection()->delete($this->computeCacheKeys($keys));
}
/**
* {@inheritdoc}
*/
public function has(array $keys): bool
{
return false !== $this->getCollection()->get($this->computeCacheKeys($keys));
}
/**
* {@inheritdoc}
*/
public function set(array $keys, $data, int $ttl = CacheElement::DAY, array $contextualKeys = []): CacheElementInterface
{
$cacheElement = new CacheElement($keys, $data, $ttl);
$this->getCollection()->set(
$this->computeCacheKeys($keys),
$cacheElement,
/*
* The driver does not seems to behave as documented, so we provide a timestamp if the ttl > 30d
* http://code.google.com/p/memcached/wiki/NewProgramming#Cache_Invalidation
*/
$cacheElement->getTtl() + ($cacheElement->getTtl() > 2592000 ? time() : 0)
);
return $cacheElement;
}
/**
* {@inheritdoc}
*/
public function get(array $keys): CacheElementInterface
{
return $this->handleGet($keys, $this->getCollection()->get($this->computeCacheKeys($keys)));
}
/**
* {@inheritdoc}
*/
public function isContextual(): bool
{
return false;
}
/**
* {@inheritdoc}
*/
private function getCollection(): \Memcached
{
if (!$this->collection) {
$this->collection = new \Memcached();
foreach ($this->servers as $server) {
$this->collection->addServer($server['host'], $server['port'], $server['weight']);
}
}
return $this->collection;
}
/**
* {@inheritdoc}
*/
private function computeCacheKeys(array $keys): string
{
ksort($keys);
return md5($this->prefix.serialize($keys));
}
}

View File

@@ -0,0 +1,154 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\Cache\Adapter\Cache;
use Sonata\Cache\CacheElement;
use Sonata\Cache\CacheElementInterface;
class MongoCache extends BaseCacheHandler
{
protected $collection;
private $servers;
private $databaseName;
private $collectionName;
/**
* @param array $servers
* @param $database
* @param $collection
*/
public function __construct(array $servers, string $database, string $collection)
{
$this->servers = $servers;
$this->databaseName = $database;
$this->collectionName = $collection;
}
/**
* {@inheritdoc}
*/
public function flushAll(): bool
{
return $this->flush([]);
}
/**
* {@inheritdoc}
*/
public function flush(array $keys = []): bool
{
$result = $this->getCollection()->remove($keys, [
'w' => 1,
]);
return 1 == $result['ok'] && null === $result['err'];
}
/**
* {@inheritdoc}
*/
public function has(array $keys): bool
{
$keys['_timeout'] = ['$gt' => time()];
return $this->getCollection()->count($keys) > 0;
}
/**
* Returns the valid Mongo class client for the current php driver.
*
* @return string
*/
public static function getMongoClass()
{
if (class_exists('\MongoClient')) {
return '\MongoClient';
}
return '\Mongo';
}
/**
* {@inheritdoc}
*/
public function set(array $keys, $data, int $ttl = CacheElement::DAY, array $contextualKeys = []): CacheElementInterface
{
$time = time();
$cacheElement = new CacheElement($keys, $data, $ttl, $contextualKeys);
$keys = $cacheElement->getContextualKeys() + $cacheElement->getKeys();
$keys['_value'] = new \MongoBinData(serialize($cacheElement), \MongoBinData::BYTE_ARRAY);
$keys['_updated_at'] = $time;
$keys['_timeout'] = $time + $cacheElement->getTtl();
$this->getCollection()->save($keys);
return $cacheElement;
}
/**
* {@inheritdoc}
*/
public function get(array $keys): CacheElementInterface
{
$record = $this->getRecord($keys);
return $this->handleGet($keys, $record ? unserialize($record['_value']->bin) : null);
}
/**
* {@inheritdoc}
*/
public function isContextual(): bool
{
return true;
}
/**
* @return \MongoCollection
*/
private function getCollection(): \MongoCollection
{
if (!$this->collection) {
$class = self::getMongoClass();
$mongo = new $class(sprintf('mongodb://%s', implode(',', $this->servers)));
$this->collection = $mongo
->selectDB($this->databaseName)
->selectCollection($this->collectionName);
}
return $this->collection;
}
/**
* @param array $keys
*
* @return array|null
*/
private function getRecord(array $keys)
{
$keys['_timeout'] = ['$gt' => time()];
$results = $this->getCollection()->find($keys);
if ($results->hasNext()) {
return $results->getNext();
}
return;
}
}

View File

@@ -0,0 +1,67 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\Cache\Adapter\Cache;
use Sonata\Cache\CacheElement;
use Sonata\Cache\CacheElementInterface;
use Sonata\Cache\Exception\UnsupportedException;
class NoopCache extends BaseCacheHandler
{
/**
* {@inheritdoc}
*/
public function flushAll(): bool
{
return true;
}
/**
* {@inheritdoc}
*/
public function flush(array $keys = []): bool
{
return true;
}
/**
* {@inheritdoc}
*/
public function has(array $keys): bool
{
return false;
}
/**
* {@inheritdoc}
*/
public function set(array $keys, $data, int $ttl = CacheElement::DAY, array $contextualKeys = []): CacheElementInterface
{
return new CacheElement($keys, $data, $ttl, $contextualKeys);
}
/**
* {@inheritdoc}
*/
public function get(array $keys): CacheElementInterface
{
throw new UnsupportedException('The NoopCache::get() cannot called');
}
/**
* {@inheritdoc}
*/
public function isContextual(): bool
{
return false;
}
}

View File

@@ -0,0 +1,239 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\Cache\Adapter\Cache;
use Sonata\Cache\CacheElement;
use Sonata\Cache\CacheElementInterface;
use Sonata\Cache\Exception\UnsupportedException;
/**
* Handles OpCode cache.
*
* For user cache this Adapter use this extensions:
* - Apc extension for PHP version < 5.5.0 (see http://php.net/manual/fr/book.apc.php)
* - Apcu extension for PHP version >= 5.5.0 (see https://github.com/krakjoe/apcu)
* And for opcode cache use the Apc extension for PHP version < 5.5.0 and opcache instead (see http://php.net/manual/fr/book.opcache.php)
*
* @author Amine Zaghdoudi <amine.zaghdoudi@ekino.com>
*/
class OpCodeCache extends BaseCacheHandler
{
/**
* @var string
*/
protected $url;
/**
* @var string
*/
protected $prefix;
/**
* @var array
*/
protected $servers;
/**
* @var bool
*/
protected $currentOnly;
/**
* @var array
*/
protected $timeout = [];
/**
* Constructor.
*
* @param string $url A router instance
* @param string $prefix A prefix to avoid clash between instances
* @param array $servers An array of servers
* @param array $timeout An array of timeout options
*/
public function __construct(string $url, string $prefix, array $servers, array $timeout = [])
{
$this->url = $url;
$this->prefix = $prefix;
$this->servers = $servers;
$defaultTimeout = [
'sec' => 5,
'usec' => 0,
];
$this->timeout['RCV'] = isset($timeout['RCV']) ? array_merge($defaultTimeout, $timeout['RCV']) : $defaultTimeout;
$this->timeout['SND'] = isset($timeout['SND']) ? array_merge($defaultTimeout, $timeout['SND']) : $defaultTimeout;
}
/**
* @param bool $bool
*/
public function setCurrentOnly($bool): void
{
$this->currentOnly = $bool;
}
/**
* {@inheritdoc}
*/
public function flushAll(): bool
{
if ($this->currentOnly) {
if (version_compare(PHP_VERSION, '5.5.0', '>=') && function_exists('opcache_reset')) {
opcache_reset();
}
if (function_exists('apc_clear_cache')) {
apc_clear_cache('user') && apc_clear_cache();
}
return true;
}
$result = true;
foreach ($this->servers as $server) {
if (4 == count(explode('.', $server['ip']))) {
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
} else {
$socket = socket_create(AF_INET6, SOCK_STREAM, SOL_TCP);
}
// generate the raw http request
$command = sprintf("GET %s HTTP/1.1\r\n", $this->getUrl());
$command .= sprintf("Host: %s\r\n", $server['domain']);
if ($server['basic']) {
$command .= sprintf("Authorization: Basic %s\r\n", $server['basic']);
}
$command .= "Connection: Close\r\n\r\n";
// setup the default timeout (avoid max execution time)
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, $this->timeout['SND']);
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, $this->timeout['RCV']);
socket_connect($socket, $server['ip'], $server['port']);
socket_write($socket, $command);
$content = '';
do {
$buffer = socket_read($socket, 1024);
$content .= $buffer;
} while (!empty($buffer));
if ($result) {
$result = 'ok' == substr($content, -2);
}
}
return $result;
}
/**
* {@inheritdoc}
*/
public function flush(array $keys = []): bool
{
if ($this->currentOnly) {
$this->checkApc();
return apc_delete($this->computeCacheKeys($keys));
}
return $this->flushAll();
}
/**
* {@inheritdoc}
*/
public function has(array $keys): bool
{
$this->checkApc();
return apc_exists($this->computeCacheKeys($keys));
}
/**
* {@inheritdoc}
*/
public function set(array $keys, $data, int $ttl = CacheElement::DAY, array $contextualKeys = []): CacheElementInterface
{
$this->checkApc();
$cacheElement = new CacheElement($keys, $data, $ttl);
apc_store(
$this->computeCacheKeys($keys),
$cacheElement,
$cacheElement->getTtl()
);
return $cacheElement;
}
/**
* {@inheritdoc}
*/
public function get(array $keys): CacheElementInterface
{
$this->checkApc();
return $this->handleGet($keys, apc_fetch($this->computeCacheKeys($keys)));
}
/**
* {@inheritdoc}
*/
public function isContextual(): bool
{
return false;
}
/**
* @return string
*/
protected function getUrl()
{
return $this->url;
}
/**
* Check that Apc is enabled.
*
* @return bool
*
* @throws UnsupportedException
*/
protected function checkApc()
{
if (!extension_loaded('apc') || !ini_get('apc.enabled')) {
throw new UnsupportedException(__CLASS__.' does not support data caching. you should install APC or APCu to use it');
}
}
/**
* Computes the given cache keys.
*
* @param array $keys
*
* @return string
*/
protected function computeCacheKeys($keys)
{
ksort($keys);
return md5($this->prefix.serialize($keys));
}
}

View File

@@ -0,0 +1,153 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\Cache\Adapter\Cache;
use Predis\Client;
use Predis\Connection\PredisCluster;
use Sonata\Cache\CacheElement;
use Sonata\Cache\CacheElementInterface;
class PRedisCache extends BaseCacheHandler
{
protected $parameters;
protected $options;
/**
* @var Client
*/
protected $client;
/**
* @param array $parameters
* @param array $options
*/
public function __construct(array $parameters = [], array $options = [])
{
$this->parameters = $parameters;
$this->options = $options;
}
/**
* {@inheritdoc}
*/
public function flushAll(): bool
{
$command = $this->getClient()->createCommand('flushdb');
$connection = $this->getClient()->getConnection();
if ($connection instanceof PredisCluster) {
foreach ($connection->executeCommandOnNodes($command) as $status) {
if (!$status) {
return false;
}
}
return true;
}
return $this->getClient()->executeCommand($command);
}
/**
* {@inheritdoc}
*/
public function flush(array $keys = []): bool
{
$this->getClient()->del($this->computeCacheKeys($keys));
// http://redis.io/commands/del
// it is not possible to know is the command succeed as the del command returns
// the number of row deleted.
// we can flush an non existant row
return true;
}
/**
* {@inheritdoc}
*/
public function has(array $keys): bool
{
return $this->getClient()->exists($this->computeCacheKeys($keys));
}
/**
* {@inheritdoc}
*/
public function set(array $keys, $data, int $ttl = CacheElement::DAY, array $contextualKeys = []): CacheElementInterface
{
$cacheElement = new CacheElement($keys, $data, $ttl);
$key = $this->computeCacheKeys($keys);
$this->getClient()->hset($key, 'sonata__data', serialize($cacheElement));
foreach ($contextualKeys as $name => $value) {
if (!is_scalar($value)) {
$value = serialize($value);
}
$this->getClient()->hset($key, $name, $value);
}
foreach ($keys as $name => $value) {
if (!is_scalar($value)) {
$value = serialize($value);
}
$this->getClient()->hset($key, $name, $value);
}
$this->getClient()->expire($key, $cacheElement->getTtl());
return $cacheElement;
}
/**
* {@inheritdoc}
*/
public function get(array $keys): CacheElementInterface
{
return $this->handleGet($keys, unserialize($this->getClient()->hget($this->computeCacheKeys($keys), 'sonata__data')));
}
/**
* {@inheritdoc}
*/
public function isContextual(): bool
{
return false;
}
/**
* @return Client
*/
protected function getClient(): Client
{
if (!$this->client) {
$this->client = new Client($this->parameters, $this->options);
}
return $this->client;
}
/**
* {@inheritdoc}
*/
private function computeCacheKeys(array $keys): string
{
ksort($keys);
return md5(serialize($keys));
}
}

View File

@@ -0,0 +1,77 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\Cache\Adapter\Counter;
use Sonata\Cache\Counter;
/**
* Handles APC cache.
*/
class ApcCounter extends BaseCounter
{
/**
* @var string
*/
protected $prefix;
/**
* Constructor.
*
* @param string $prefix A prefix to avoid clash between instances
*/
public function __construct(string $prefix)
{
$this->prefix = $prefix;
}
/**
* {@inheritdoc}
*/
public function increment(Counter $counter, int $number = 1): Counter
{
$counter = $this->transform($counter);
$value = apc_inc($this->prefix.'/'.$counter->getName(), $number);
return $this->handleIncrement($value, $counter, $number);
}
/**
* {@inheritdoc}
*/
public function decrement(Counter $counter, int $number = 1): Counter
{
$counter = $this->transform($counter);
$value = apc_dec($this->prefix.'/'.$counter->getName(), $number);
return $this->handleDecrement($value, $counter, $number);
}
/**
* {@inheritdoc}
*/
public function set(Counter $counter): Counter
{
apc_store($this->prefix.'/'.$counter->getName(), $counter->getValue());
return $counter;
}
/**
* {@inheritdoc}
*/
public function get(string $name): Counter
{
return Counter::create($name, (int) apc_fetch($this->prefix.'/'.$name));
}
}

View File

@@ -0,0 +1,68 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\Cache\Adapter\Counter;
use Sonata\Cache\Counter;
use Sonata\Cache\CounterAdapterInterface;
abstract class BaseCounter implements CounterAdapterInterface
{
/**
* @param $counter
*
* @return Counter
*/
protected function transform($counter): Counter
{
if ($counter instanceof Counter) {
return $counter;
}
return Counter::create($counter);
}
/**
* @param mixed $value
* @param Counter $counter
* @param int $number
*
* @return Counter
*/
protected function handleIncrement($value, Counter $counter, int $number): Counter
{
if (false === $value) {
$counter = $this->set(Counter::create($counter->getName(), $counter->getValue() + $number));
} else {
$counter = Counter::create($counter->getName(), $value);
}
return $counter;
}
/**
* @param mixed $value
* @param Counter $counter
* @param int $number
*
* @return Counter
*/
protected function handleDecrement($value, Counter $counter, int $number): Counter
{
if (false === $value) {
$counter = $this->set(Counter::create($counter->getName(), $counter->getValue() + (-1 * $number)));
} else {
$counter = Counter::create($counter->getName(), $value);
}
return $counter;
}
}

View File

@@ -0,0 +1,91 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\Cache\Adapter\Counter;
use Sonata\Cache\Counter;
class MemcachedCounter extends BaseCounter
{
protected $servers;
protected $prefix;
protected $collection;
/**
* @param $prefix
* @param array $servers
*/
public function __construct(string $prefix, array $servers)
{
$this->prefix = $prefix;
$this->servers = $servers;
}
/**
* {@inheritdoc}
*/
public function increment(Counter $counter, int $number = 1): Counter
{
$counter = $this->transform($counter);
$value = $this->getCollection()->increment($this->prefix.'.'.$counter->getName(), $number);
return $this->handleIncrement(0 !== $this->getCollection()->getResultCode() ? false : $value, $counter, $number);
}
/**
* {@inheritdoc}
*/
public function decrement(Counter $counter, int $number = 1): Counter
{
$counter = $this->transform($counter);
$value = $this->getCollection()->decrement($this->prefix.'.'.$counter->getName(), $number);
return $this->handleDecrement(0 !== $this->getCollection()->getResultCode() ? false : $value, $counter, $number);
}
/**
* {@inheritdoc}
*/
public function set(Counter $counter): Counter
{
$this->getCollection()->add($this->prefix.'.'.$counter->getName(), $counter->getValue());
return $counter;
}
/**
* {@inheritdoc}
*/
public function get(string $name): Counter
{
return Counter::create($name, (int) $this->getCollection()->get($this->prefix.'.'.$name));
}
/**
* {@inheritdoc}
*/
private function getCollection(): \Memcached
{
if (!$this->collection) {
$this->collection = new \Memcached();
foreach ($this->servers as $server) {
$this->collection->addServer($server['host'], $server['port'], $server['weight']);
}
}
return $this->collection;
}
}

View File

@@ -0,0 +1,114 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\Cache\Adapter\Counter;
use Sonata\Cache\Adapter\Cache\MongoCache;
use Sonata\Cache\Counter;
class MongoCounter extends BaseCounter
{
protected $collection;
private $servers;
private $databaseName;
private $collectionName;
/**
* @param array $servers
* @param $database
* @param $collection
*/
public function __construct(array $servers, string $database, string $collection)
{
$this->servers = $servers;
$this->databaseName = $database;
$this->collectionName = $collection;
}
/**
* {@inheritdoc}
*/
public function increment(Counter $counter, int $number = 1): Counter
{
$counter = $this->transform($counter);
$result = $this->getCollection()->findAndModify(
['counter' => $counter->getName()],
['$inc' => ['value' => $number]],
[],
['new' => true]
);
return $this->handleIncrement(0 === count($result) ? false : $result['value'], $counter, $number);
}
/**
* {@inheritdoc}
*/
public function decrement(Counter $counter, int $number = 1): Counter
{
$counter = $this->transform($counter);
$result = $this->getCollection()->findAndModify(
['counter' => $counter->getName()],
['$inc' => ['value' => -1 * $number]],
[],
['new' => true]
);
return $this->handleDecrement(0 === count($result) ? false : $result['value'], $counter, $number);
}
/**
* {@inheritdoc}
*/
public function set(Counter $counter): Counter
{
$result = $this->getCollection()->findAndModify(
['counter' => $counter->getName()],
['$setOnInsert' => ['value' => $counter->getValue()]],
[],
['upsert' => true, 'new' => true]
);
return Counter::create($counter->getName(), $result['value']);
}
/**
* {@inheritdoc}
*/
public function get(string $name): Counter
{
$result = $this->getCollection()->findOne(['counter' => $name]);
return Counter::create($name, $result ? (int) $result['value'] : 0);
}
/**
* @return \MongoCollection
*/
private function getCollection(): \MongoCollection
{
if (!$this->collection) {
$class = MongoCache::getMongoClass();
$mongo = new $class(sprintf('mongodb://%s', implode(',', $this->servers)));
$this->collection = $mongo
->selectDB($this->databaseName)
->selectCollection($this->collectionName);
}
return $this->collection;
}
}

View File

@@ -0,0 +1,96 @@
<?php
/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sonata\Cache\Adapter\Counter;
use Predis\Client;
use Sonata\Cache\Counter;
class PRedisCounter extends BaseCounter
{
protected $options;
protected $parameters;
protected $client;
/**
* @param array $parameters
* @param array $options
*/
public function __construct(array $parameters = [], array $options = [])
{
$this->parameters = $parameters;
$this->options = $options;
}
/**
* {@inheritdoc}
*/
public function increment(Counter $counter, int $number = 1): Counter
{
$counter = $this->transform($counter);
if (null === $this->getClient()->get($counter->getName())) {
$this->getClient()->set($counter->getName(), $value = $counter->getValue() + $number);
} else {
$value = $this->getClient()->incrby($counter->getName(), $number);
}
return Counter::create($counter->getName(), $value);
}
/**
* {@inheritdoc}
*/
public function decrement(Counter $counter, int $number = 1): Counter
{
$counter = $this->transform($counter);
if (null === $this->getClient()->get($counter->getName())) {
$this->getClient()->set($counter->getName(), $value = $counter->getValue() - $number);
} else {
$value = $this->getClient()->decrby($counter->getName(), $number);
}
return Counter::create($counter->getName(), $value);
}
/**
* {@inheritdoc}
*/
public function set(Counter $counter): Counter
{
$this->getClient()->set($counter->getName(), $counter->getValue());
return $counter;
}
/**
* {@inheritdoc}
*/
public function get(string $name): Counter
{
return Counter::create($name, (int) $this->getClient()->get($name));
}
/**
* @return Client
*/
private function getClient(): Client
{
if (!$this->client) {
$this->client = new Client($this->parameters, $this->options);
}
return $this->client;
}
}