allow vendord
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m3s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 32s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s

This commit is contained in:
2026-03-30 14:54:57 +07:00
parent 66aed7c4e8
commit b5e3a778ce
21316 changed files with 2777892 additions and 13 deletions

View File

@@ -0,0 +1,35 @@
# CHANGELOG
## Unreleased
## 1.4.0 - 2025-09-30
* Added support for PHP 8.5
## 1.3.1 - 2024-08-26
* Made clock argument of `InMemoryCache` constructor explicitly nullable
([#4](https://github.com/beste/in-memory-cache-php/pull/4))
## 1.3.0 - 2024-08-17
* Added support for PHP 8.4
## 1.2.0 - 2024-07-27
* The [PSR-6 definition on what makes a valid cache key](https://www.php-fig.org/psr/psr-6/#definitions), it is said that
keys must support keys consisting of the characters `A-Z`, `a-z`, `0-9`, `_`, and `.` in any order in UTF-8
encoding and a length of up to 64 characters. Implementing libraries MAY support additional characters and encodings
or longer lengths, but must support at least that minimum.
* Dashes (`-`) are now allowed in cache keys.
* The arbitrary maximum key length of 64 characters has been removed.
## 1.1.0 - 2024-03-02
* The Cache can now be instantiated without providing a [PSR-20](https://www.php-fig.org/psr/psr-20/) clock implementation.
* The library doesn't depend on the [`beste/clock` library](https://github.com/beste/clock) anymore.
## 1.0.0 - 2023-12-09
Initial Release

21
vendor/beste/in-memory-cache/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Jérôme Gamez, https://github.com/beste <jerome@gamez.name>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

69
vendor/beste/in-memory-cache/README.md vendored Normal file
View File

@@ -0,0 +1,69 @@
# PSR-6 In-Memory Cache
A [PSR-6](https://www.php-fig.org/psr/psr-6/) In-Memory cache that can be used as a default implementation and in tests.
[![Current version](https://img.shields.io/packagist/v/beste/in-memory-cache.svg?logo=composer)](https://packagist.org/packages/beste/in-memory-cache)
[![Packagist PHP Version Support](https://img.shields.io/packagist/php-v/beste/in-memory-cache)](https://packagist.org/packages/beste/in-memory-cache)
[![Monthly Downloads](https://img.shields.io/packagist/dm/beste/in-memory-cache.svg)](https://packagist.org/packages/beste/in-memory-cache/stats)
[![Total Downloads](https://img.shields.io/packagist/dt/beste/in-memory-cache.svg)](https://packagist.org/packages/beste/in-memory-cache/stats)
[![Tests](https://github.com/beste/in-memory-cache-php/actions/workflows/tests.yml/badge.svg)](https://github.com/beste/in-memory-cache-php/actions/workflows/tests.yml)
## Installation
```shell
composer require beste/in-memory-cache
```
## Usage
```php
use Beste\Cache\InMemoryCache;
$cache = new InMemoryCache();
$item = $cache->getItem('key');
assert($item->isHit() === false);
assert($item->get() === null);
$item->set('value');
$cache->save($item);
// Later...
$item = $cache->getItem('key');
assert($item->isHit() === true);
assert($item->get() === 'value');
```
You can also provide your own [PSR-20](https://www.php-fig.org/psr/psr-20/) clock implementation, for example a frozen
clock for testing, for example from the [`beste/clock` library](https://github.com/beste/clock).
```php
use Beste\Clock\FrozenClock;
use Beste\Cache\InMemoryCache;
$clock = FrozenClock::fromUTC()
$cache = new InMemoryCache();
$item = $cache->getItem('key');
$item->set('value')->expiresAfter(new DateInterval('PT5M'));
$cache->save($item);
$clock->setTo($clock->now()->add(new DateInterval('PT2M')));
assert($cache->getItem('key')->isHit() === true);
$clock->setTo($clock->now()->add(new DateInterval('PT5M')));
assert($cache->getItem('key')->isHit() === false);
```
## Running tests
```shell
composer test
```
## License
This project is published under the [MIT License](LICENSE).

View File

@@ -0,0 +1,67 @@
{
"name": "beste/in-memory-cache",
"description": "A PSR-6 In-Memory cache that can be used as a fallback implementation and/or in tests.",
"keywords": ["cache", "psr-6", "beste"],
"license": "MIT",
"type": "library",
"authors": [
{
"name": "Jérôme Gamez",
"email": "jerome@gamez.name"
}
],
"require": {
"php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
"psr/cache": "^2.0 || ^3.0",
"psr/clock": "^1.0"
},
"require-dev": {
"beste/clock": "^3.0",
"beste/php-cs-fixer-config": "^3.2.0",
"friendsofphp/php-cs-fixer": "^3.62.0",
"phpstan/extension-installer": "^1.4.1",
"phpstan/phpstan": "^2.0.1",
"phpstan/phpstan-deprecation-rules": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^10.5.2 || ^11.3.1",
"symfony/var-dumper": "^6.4 || ^7.1.3"
},
"provide": {
"psr/cache-implementation": "2.0 || 3.0"
},
"suggest": {
"psr/clock-implementation": "Allows injecting a Clock, for example a frozen clock for testing"
},
"autoload": {
"psr-4": {
"Beste\\Cache\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Beste\\Cache\\Tests\\": "tests"
}
},
"config": {
"allow-plugins": {
"phpstan/extension-installer": true
},
"sort-packages": true
},
"scripts": {
"analyse": "vendor/bin/phpstan analyse",
"analyze": "@analyse",
"cs-fix": "vendor/bin/php-cs-fixer fix --diff --verbose",
"test": "vendor/bin/phpunit --testdox",
"test-coverage": [
"Composer\\Config::disableProcessTimeout",
"XDEBUG_MODE=coverage vendor/bin/phpunit --testdox --coverage-html=.build/coverage"
],
"check": [
"@cs-fix",
"@analyse",
"@test"
]
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace Beste\Cache;
use Psr\Cache\CacheItemInterface;
use Psr\Clock\ClockInterface;
/**
* @internal
*/
final class CacheItem implements CacheItemInterface
{
private mixed $value;
private ?\DateTimeInterface $expiresAt;
private bool $isHit;
public function __construct(private readonly CacheKey $key, private readonly ClockInterface $clock)
{
$this->value = null;
$this->expiresAt = null;
$this->isHit = false;
}
public function getKey(): string
{
return $this->key->toString();
}
public function get(): mixed
{
if ($this->isHit()) {
return $this->value;
}
return null;
}
public function isHit(): bool
{
if ($this->isHit === false) {
return false;
}
if ($this->expiresAt === null) {
return true;
}
return $this->clock->now()->getTimestamp() < $this->expiresAt->getTimestamp();
}
public function set(mixed $value): static
{
$this->isHit = true;
$this->value = $value;
return $this;
}
public function expiresAt(?\DateTimeInterface $expiration): static
{
$this->expiresAt = $expiration;
return $this;
}
public function expiresAfter(\DateInterval|int|null $time): static
{
if ($time === null) {
$this->expiresAt = null;
return $this;
}
if (is_int($time)) {
$time = new \DateInterval("PT{$time}S");
}
$this->expiresAt = $this->clock->now()->add($time);
return $this;
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Beste\Cache;
/**
* @internal
*/
final class CacheKey
{
private function __construct(private readonly string $value) {}
public static function fromString(string $value): self
{
if (preg_match('/^[a-zA-Z0-9_.-]+$/u', $value) !== 1) {
throw InvalidArgument::invalidKey();
}
return new self($value);
}
public function toString(): string
{
return $this->value;
}
}

View File

@@ -0,0 +1,119 @@
<?php
namespace Beste\Cache;
use DateTimeImmutable;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Clock\ClockInterface;
final class InMemoryCache implements CacheItemPoolInterface
{
private readonly ClockInterface $clock;
/** @var array<string, CacheItemInterface> */
private array $items;
/** @var array<string, CacheItemInterface> */
private array $deferredItems;
public function __construct(
?ClockInterface $clock = null,
) {
$this->clock = $clock ?? new class implements ClockInterface {
public function now(): DateTimeImmutable
{
return new DateTimeImmutable();
}
};
$this->items = [];
$this->deferredItems = [];
}
public function getItem(string $key): CacheItemInterface
{
$key = CacheKey::fromString($key);
$item = $this->items[$key->toString()] ?? null;
if ($item === null) {
return new CacheItem($key, $this->clock);
}
return clone $item;
}
/**
* @return iterable<CacheItemInterface>
*/
public function getItems(array $keys = []): iterable
{
if ($keys === []) {
return [];
}
$items = [];
foreach ($keys as $key) {
$items[$key] = $this->getItem($key);
}
return $items;
}
public function hasItem(string $key): bool
{
return $this->getItem($key)->isHit();
}
public function clear(): bool
{
$this->items = [];
$this->deferredItems = [];
return true;
}
public function deleteItem(string $key): bool
{
$key = CacheKey::fromString($key);
unset($this->items[$key->toString()]);
return true;
}
public function deleteItems(array $keys): bool
{
foreach ($keys as $key) {
$this->deleteItem($key);
}
return true;
}
public function save(CacheItemInterface $item): bool
{
$this->items[$item->getKey()] = $item;
return true;
}
public function saveDeferred(CacheItemInterface $item): bool
{
$this->deferredItems[$item->getKey()] = $item;
return true;
}
public function commit(): bool
{
foreach ($this->deferredItems as $item) {
$this->save($item);
}
$this->deferredItems = [];
return true;
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace Beste\Cache;
final class InvalidArgument extends \InvalidArgumentException implements \Psr\Cache\InvalidArgumentException
{
public static function invalidKey(): self
{
return new self('The given key is not valid');
}
}