19declare(strict_types=1);
41 private const GLUE =
'|||||';
65 private const TRUE =
'true';
82 $this->data_factory =
new Factory();
84 $this->null_trafo = new \ILIAS\Refinery\Custom\Transformation(fn($value):
null =>
null);
85 $this->prefix_pattern =
'(' . implode(
'|', [
86 preg_quote(self::STRING_PREFIX,
'/'),
87 preg_quote(self::ARRAY_PREFIX,
'/'),
88 preg_quote(self::INT_PREFIX,
'/'),
89 preg_quote(self::BOOL_PREFIX,
'/'),
90 preg_quote(self::NULL_PREFIX,
'/')
94 private function pack(mixed $value): string
96 if (is_string($value)) {
97 return self::STRING_PREFIX . self::GLUE . $value;
99 if (is_array($value)) {
102 return self::ARRAY_PREFIX . self::GLUE . json_encode($value, JSON_THROW_ON_ERROR);
104 if (is_int($value)) {
105 return self::INT_PREFIX . self::GLUE . $value;
107 if (is_bool($value)) {
110 if (is_null($value)) {
114 throw new \InvalidArgumentException(
115 'Only strings, integers and arrays containing those values are allowed, ' . gettype($value) .
' given.'
121 array_walk($value,
function (&$item):
void {
129 $str =
'/^' . $this->prefix_pattern . preg_quote(self::GLUE,
'/') .
'(.*)/is';
130 if (!preg_match($str, $value, $matches)) {
134 return [$matches[1], $matches[2]];
137 private function unpack(?
string $value): string|
int|array|bool|null
140 if ($value ===
null) {
143 if ($value === self::NULL_PREFIX . self::GLUE) {
148 [$type, $unprefixed_value] = $this->
unprefix($value);
152 return $unprefixed_value;
156 $unprefixed_value = json_decode((
string) $unprefixed_value,
true, 512);
157 if (!is_array($unprefixed_value)) {
163 return (
int) $unprefixed_value;
173 array_walk($value,
function (&$item):
void {
195 if ($this->lock_cache !==
null && $this->lock_cache > microtime(
true)) {
199 if (!$this->adaptor->has($this->request->getContainerKey(), self::LOCK_UNTIL)) {
200 $this->lock_cache =
null;
205 $lock_until = $this->adaptor->get($this->request->getContainerKey(), self::LOCK_UNTIL);
206 $lock_until = $lock_until ===
null ? null : (float) $lock_until;
208 $this->lock_cache = $lock_until;
210 return $lock_until !==
null && $lock_until > microtime(
true);
213 public function lock(
float $seconds): void
215 if ($seconds > 300.0 || $seconds < 0.0) {
216 throw new \InvalidArgumentException(
'Locking for more than 5 minutes is not allowed.');
218 $lock_until = (string) (microtime(
true) + $seconds);
219 $this->adaptor->set($this->request->getContainerKey(),
self::LOCK_UNTIL, $lock_until, 300);
222 public function has(
string $key): bool
228 return $this->adaptor->has($this->request->getContainerKey(), $key);
231 public function get(
string $key,
Transformation $transformation):
string|
int|array|
bool|
null
236 if (!$this->
has($key)) {
240 $unpacked_values = $this->
unpack(
241 $this->adaptor->get($this->request->getContainerKey(), $key)
247 public function set(
string $key,
string|
int|array|
bool|
null $value, ?
int $ttl =
null):
void
252 $ttl = $ttl ?? $this->config->getDefaultTTL();
255 $this->request->getContainerKey(),
262 public function delete(
string $key):
void
267 $this->adaptor->delete($this->request->getContainerKey(), $key);
272 $this->adaptor->flushContainer($this->request->getContainerKey());
277 return $this->config->getAdaptorName();
282 return $this->request->getContainerKey();
290 $this->adaptor->delete($this->request->getContainerKey(), self::LOCK_UNTIL);
291 $this->lock_cache =
null;
__construct(private Request $request, private Adaptor $adaptor, private Config $config)
packRecursive(array $value)
unpackRecursive(array $value)
getAdaptorName()
Returns the name of the adaptop used (such as apc, memcache, phpstatic)
buildFinalTransformation(Transformation $transformation)
lock(float $seconds)
Locks the container for a given amount of seconds (max 300), in this time, get() will return null and...
Transformation $null_trafo
isLocked()
Returns true if the container is locked.
ILIAS Data Factory $data_factory
getContainerName()
Returns the name of the container.
has(string $key)
Returns true if the container contains a value for the given key.
flush()
Deletes all values in the container.