mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-19 04:58:41 +00:00
trying to implement acceptable type system
This commit is contained in:
parent
c952489736
commit
be1283d6dc
|
|
@ -16,6 +16,7 @@ namespace phpOMS\DataStorage\Cache\Connection;
|
|||
|
||||
use phpOMS\DataStorage\Cache\CacheStatus;
|
||||
use phpOMS\DataStorage\Cache\CacheType;
|
||||
use phpOMS\DataStorage\Cache\Connection\CacheValueType;
|
||||
|
||||
/**
|
||||
* Cache handler.
|
||||
|
|
@ -163,20 +164,36 @@ abstract class ConnectionAbstract implements ConnectionInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Parse values for cache storage
|
||||
* Analyze caching data type.
|
||||
*
|
||||
* @param mixed $value Value to parse
|
||||
* @param mixed $value Data to cache
|
||||
*
|
||||
* @return mixed
|
||||
* @return int Returns the cache type for a value
|
||||
*
|
||||
* @throws \InvalidArgumentException This exception is thrown if an unsupported datatype is used
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
protected function parseValue($value)
|
||||
protected function dataType($value) : int
|
||||
{
|
||||
if (\is_array($value)) {
|
||||
return \json_encode($value);
|
||||
if (\is_int($value)) {
|
||||
return CacheValueType::_INT;
|
||||
} elseif (\is_float($value)) {
|
||||
return CacheValueType::_FLOAT;
|
||||
} elseif (\is_string($value)) {
|
||||
return CacheValueType::_STRING;
|
||||
} elseif (\is_bool($value)) {
|
||||
return CacheValueType::_BOOL;
|
||||
} elseif (\is_array($value)) {
|
||||
return CacheValueType::_ARRAY;
|
||||
} elseif ($value === null) {
|
||||
return CacheValueType::_NULL;
|
||||
} elseif ($value instanceof \Serializable) {
|
||||
return CacheValueType::_SERIALIZABLE;
|
||||
} elseif ($value instanceof \JsonSerializable) {
|
||||
return CacheValueType::_JSONSERIALIZABLE;
|
||||
}
|
||||
|
||||
return $value;
|
||||
throw new \InvalidArgumentException('Invalid value type.');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,40 +194,6 @@ class FileCache extends ConnectionAbstract
|
|||
return $type . self::DELIM . $expire . self::DELIM . $raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze caching data type.
|
||||
*
|
||||
* @param mixed $value Data to cache
|
||||
*
|
||||
* @return int Returns the cache type for a value
|
||||
*
|
||||
* @throws \InvalidArgumentException This exception is thrown if an unsupported datatype is used
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function dataType($value) : int
|
||||
{
|
||||
if (\is_int($value)) {
|
||||
return CacheValueType::_INT;
|
||||
} elseif (\is_float($value)) {
|
||||
return CacheValueType::_FLOAT;
|
||||
} elseif (\is_string($value)) {
|
||||
return CacheValueType::_STRING;
|
||||
} elseif (\is_bool($value)) {
|
||||
return CacheValueType::_BOOL;
|
||||
} elseif (\is_array($value)) {
|
||||
return CacheValueType::_ARRAY;
|
||||
} elseif ($value === null) {
|
||||
return CacheValueType::_NULL;
|
||||
} elseif ($value instanceof \Serializable) {
|
||||
return CacheValueType::_SERIALIZABLE;
|
||||
} elseif ($value instanceof \JsonSerializable) {
|
||||
return CacheValueType::_JSONSERIALIZABLE;
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Invalid value type.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create string representation of data for storage
|
||||
*
|
||||
|
|
@ -350,6 +316,15 @@ class FileCache extends ConnectionAbstract
|
|||
case CacheValueType::_NULL:
|
||||
return null;
|
||||
case CacheValueType::_JSONSERIALIZABLE:
|
||||
$namespaceStart = (int) \strpos($raw, self::DELIM, $expireEnd);
|
||||
$namespaceEnd = (int) \strpos($raw, self::DELIM, $namespaceStart + 1);
|
||||
$namespace = \substr($raw, $namespaceStart + 1, $namespaceEnd - $namespaceStart - 1);
|
||||
|
||||
if ($namespace === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new $namespace();
|
||||
case CacheValueType::_SERIALIZABLE:
|
||||
$namespaceStart = (int) \strpos($raw, self::DELIM, $expireEnd);
|
||||
$namespaceEnd = (int) \strpos($raw, self::DELIM, $namespaceStart + 1);
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ class MemCached extends ConnectionAbstract
|
|||
return false;
|
||||
}
|
||||
|
||||
$value = $this->parseValue($value);
|
||||
// todo: handle parsing
|
||||
|
||||
return $this->con->replace($key, $value, \max($expire, 0));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ namespace phpOMS\DataStorage\Cache\Connection;
|
|||
use phpOMS\DataStorage\Cache\CacheStatus;
|
||||
use phpOMS\DataStorage\Cache\CacheType;
|
||||
use phpOMS\DataStorage\Cache\Exception\InvalidConnectionConfigException;
|
||||
use phpOMS\Stdlib\Base\Exception\InvalidEnumValue;
|
||||
use phpOMS\DataStorage\Cache\Connection\CacheValueType;
|
||||
|
||||
/**
|
||||
* RedisCache class.
|
||||
|
|
@ -33,6 +35,14 @@ class RedisCache extends ConnectionAbstract
|
|||
*/
|
||||
protected string $type = CacheType::REDIS;
|
||||
|
||||
/**
|
||||
* Delimiter for cache meta data
|
||||
*
|
||||
* @var string
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private const DELIM = '$';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
|
@ -95,21 +105,11 @@ class RedisCache extends ConnectionAbstract
|
|||
return;
|
||||
}
|
||||
|
||||
if (!(\is_scalar($value) || $value === null || \is_array($value) || $value instanceof \JsonSerializable || $value instanceof \Serializable)) {
|
||||
throw new \InvalidArgumentException();
|
||||
}
|
||||
|
||||
if (\is_bool($value)) {
|
||||
$value = $value ? 'true' : 'false';
|
||||
} elseif ($value === null) {
|
||||
$value = 'null';
|
||||
}
|
||||
|
||||
if ($expire > 0) {
|
||||
$this->con->set($key, $value, $expire);
|
||||
$this->con->set($key, $this->build($value), $expire);
|
||||
}
|
||||
|
||||
$this->con->set($key, $value);
|
||||
$this->con->set($key, $this->build($value));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -121,23 +121,11 @@ class RedisCache extends ConnectionAbstract
|
|||
return false;
|
||||
}
|
||||
|
||||
// todo: pull out
|
||||
if (!(\is_scalar($value) || $value === null || \is_array($value) || $value instanceof \JsonSerializable || $value instanceof \Serializable)) {
|
||||
throw new \InvalidArgumentException();
|
||||
}
|
||||
|
||||
// todo: pull out
|
||||
if (\is_bool($value)) {
|
||||
$value = $value ? 'true' : 'false';
|
||||
} elseif ($value === null) {
|
||||
$value = 'null';
|
||||
}
|
||||
|
||||
if ($expire > 0) {
|
||||
return $this->con->setNx($key, $value, $expire);
|
||||
return $this->con->setNx($key, $this->build($value), $expire);
|
||||
}
|
||||
|
||||
return $this->con->setNx($key, $value);
|
||||
return $this->con->setNx($key, $this->build($value));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -151,12 +139,10 @@ class RedisCache extends ConnectionAbstract
|
|||
|
||||
$result = $this->con->get($key);
|
||||
|
||||
if ($result === 'true') {
|
||||
$result = true;
|
||||
} elseif ($result === 'false') {
|
||||
$result = false;
|
||||
} elseif ($result === 'null') {
|
||||
$result = null;
|
||||
if (\is_string($result)) {
|
||||
$type = (int) $result[0];
|
||||
$start = (int) \strpos($result, self::DELIM);
|
||||
$result = $this->reverseValue($type, $result, $start);
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
|
@ -211,10 +197,10 @@ class RedisCache extends ConnectionAbstract
|
|||
return false;
|
||||
}
|
||||
|
||||
$value = $this->parseValue($value);
|
||||
// todo: parse value
|
||||
|
||||
if ($this->con->exists($key) > 0) {
|
||||
$this->set($key, $value, $expire);
|
||||
$this->set($key, $this->build($value), $expire);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -258,4 +244,97 @@ class RedisCache extends ConnectionAbstract
|
|||
{
|
||||
$this->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removing all cache elements larger or equal to the expiration date. Call flushAll for removing persistent cache elements (expiration is negative) as well.
|
||||
*
|
||||
* @param mixed $value Data to cache
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function build($value)
|
||||
{
|
||||
$type = $this->dataType($value);
|
||||
$raw = $this->cachify($value, $type);
|
||||
|
||||
return \is_string($raw) ? $type . self::DELIM . $raw : $raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create string representation of data for storage
|
||||
*
|
||||
* @param mixed $value Value of the data
|
||||
* @param int $type Type of the cache data
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws InvalidEnumValue This exception is thrown if an unsupported cache value type is used
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function cachify($value, int $type)
|
||||
{
|
||||
if (\is_float($value) || \is_int($value)) {
|
||||
return $value;
|
||||
} elseif ($type === CacheValueType::_BOOL) {
|
||||
return (string) ((int) $value);
|
||||
} elseif ($type === CacheValueType::_ARRAY) {
|
||||
return (string) \json_encode($value);
|
||||
} elseif ($type === CacheValueType::_SERIALIZABLE) {
|
||||
return \get_class($value) . self::DELIM . $value->serialize();
|
||||
} elseif ($type === CacheValueType::_JSONSERIALIZABLE) {
|
||||
return \get_class($value) . self::DELIM . ((string) \json_encode($value->jsonSerialize()));
|
||||
} elseif ($type === CacheValueType::_NULL) {
|
||||
return '';
|
||||
}
|
||||
|
||||
throw new InvalidEnumValue($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse cached value
|
||||
*
|
||||
* @param int $type Cached value type
|
||||
* @param mixed $raw Cached value
|
||||
* @param int $start Value start position
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
private function reverseValue(int $type, $raw, int $start)
|
||||
{
|
||||
switch ($type) {
|
||||
case \is_int($raw):
|
||||
case \is_float($raw):
|
||||
return $raw;
|
||||
case CacheValueType::_BOOL:
|
||||
return (bool) \substr($raw, $start + 1);
|
||||
case CacheValueType::_STRING:
|
||||
return \substr($raw, $start + 1);
|
||||
case CacheValueType::_ARRAY:
|
||||
$array = \substr($raw, $start + 1);
|
||||
return \json_decode($array === false ? '[]' : $array, true);
|
||||
case CacheValueType::_NULL:
|
||||
return null;
|
||||
case CacheValueType::_JSONSERIALIZABLE:
|
||||
case CacheValueType::_SERIALIZABLE:
|
||||
$namespaceStart = (int) \strpos($raw, self::DELIM, $start);
|
||||
$namespaceEnd = (int) \strpos($raw, self::DELIM, $namespaceStart + 1);
|
||||
$namespace = \substr($raw, $namespaceStart + 1, $namespaceEnd - $namespaceStart - 1);
|
||||
|
||||
if ($namespace === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$obj = new $namespace();
|
||||
$obj->unserialize(\substr($raw, $namespaceEnd + 1));
|
||||
|
||||
return $obj;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ class FileCacheTest extends \PHPUnit\Framework\TestCase
|
|||
self::assertEquals('abc', $this->cache->get('key7')->val);
|
||||
|
||||
$this->cache->set('key8', new FileCacheJsonSerializable());
|
||||
self::assertEquals('abc', $this->cache->get('key8')->val);
|
||||
self::assertEquals('asdf', $this->cache->get('key8')->val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ class MemCachedTest extends \PHPUnit\Framework\TestCase
|
|||
self::assertEquals('abc', $this->cache->get('key7')->val);
|
||||
|
||||
$this->cache->set('key8', new FileCacheJsonSerializable());
|
||||
self::assertEquals('asdf', $this->cache->get('key8')->val); // @todo: different from file cache fix!
|
||||
self::assertEquals('asdf', $this->cache->get('key8')->val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ class RedisCacheTest extends \PHPUnit\Framework\TestCase
|
|||
self::assertEquals('abc', $this->cache->get('key7')->val);
|
||||
|
||||
$this->cache->set('key8', new FileCacheJsonSerializable());
|
||||
self::assertEquals('asdf', $this->cache->get('key8')->val); // todo: different from file cache fix!
|
||||
self::assertEquals('asdf', $this->cache->get('key8')->val);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user