From 8b915192af86bc78ea252dbe84df59afd7010c76 Mon Sep 17 00:00:00 2001 From: Martijn van der Lee Date: Mon, 3 Aug 2026 22:28:21 +0200 Subject: [PATCH] Add PSR-6 cache adapter --- README.md | 9 +++++ composer.json | 5 ++- src/Cache/Psr6.php | 74 ++++++++++++++++++++++++++++++++++++ tests/src/Cache/Psr6Test.php | 67 ++++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 src/Cache/Psr6.php create mode 100644 tests/src/Cache/Psr6Test.php diff --git a/README.md b/README.md index 1066312..ff55413 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,15 @@ echo $syllable->hyphenateHtmlText('... with highlighted text.'); See the [demo.php](demo.php) file for a working example. +A PSR-6 cache pool can be used without changing the existing Syllable API: + +```php +use Symfony\Component\Cache\Adapter\FilesystemAdapter; +use Vanderlee\Syllable\Cache\Psr6; + +$syllable->setCache(new Psr6(new FilesystemAdapter())); +``` + ## `Syllable` API reference diff --git a/composer.json b/composer.json index c223113..41432bc 100644 --- a/composer.json +++ b/composer.json @@ -26,11 +26,12 @@ "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", - "ext-dom": "*" + "ext-dom": "*", + "psr/cache": "^1.0 || ^2.0 || ^3.0" }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.5" + "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.5 || ^9.6" }, "autoload": { "psr-4": { diff --git a/src/Cache/Psr6.php b/src/Cache/Psr6.php new file mode 100644 index 0000000..92ddb80 --- /dev/null +++ b/src/Cache/Psr6.php @@ -0,0 +1,74 @@ +pool = $pool; + } + + public function __set($key, $value) + { + $this->data[$key] = $value; + } + + public function __get($key) + { + return $this->data[$key]; + } + + public function __isset($key) + { + return isset($this->data[$key]); + } + + public function __unset($key) + { + unset($this->data[$key]); + } + + public function open($language) + { + $this->item = $this->pool->getItem($this->getKey($language)); + $data = $this->item->isHit() ? $this->item->get() : []; + $this->data = is_array($data) ? $data : []; + } + + public function close() + { + if ($this->item === null) { + return; + } + + $this->item->set($this->data); + $this->pool->save($this->item); + } + + private function getKey($language) + { + return 'syllable.'.sha1(strtolower($language)); + } +} diff --git a/tests/src/Cache/Psr6Test.php b/tests/src/Cache/Psr6Test.php new file mode 100644 index 0000000..0c272bf --- /dev/null +++ b/tests/src/Cache/Psr6Test.php @@ -0,0 +1,67 @@ +createMock(CacheItemInterface::class); + $item->expects($this->once()) + ->method('isHit') + ->willReturn(true); + $item->expects($this->once()) + ->method('get') + ->willReturn(['version' => '1.4', 'obsolete' => true]); + $item->expects($this->once()) + ->method('set') + ->with(['version' => '1.4', 'patterns' => ['example'], 'max_pattern' => 7]) + ->willReturnSelf(); + + $pool = $this->createMock(CacheItemPoolInterface::class); + $pool->expects($this->once()) + ->method('getItem') + ->with('syllable.'.sha1('en-us')) + ->willReturn($item); + $pool->expects($this->once()) + ->method('save') + ->with($item) + ->willReturn(true); + + $cache = new Psr6($pool); + $cache->open('EN-US'); + + $this->assertTrue(isset($cache->version)); + $this->assertSame('1.4', $cache->version); + + unset($cache->obsolete); + $cache->patterns = ['example']; + $cache->max_pattern = 7; + $cache->close(); + } + + public function testCacheMissStartsWithEmptyData() + { + $item = $this->createMock(CacheItemInterface::class); + $item->expects($this->once()) + ->method('isHit') + ->willReturn(false); + $item->expects($this->never()) + ->method('get'); + + $pool = $this->createMock(CacheItemPoolInterface::class); + $pool->expects($this->once()) + ->method('getItem') + ->willReturn($item); + + $cache = new Psr6($pool); + $cache->open('en-us'); + + $this->assertFalse(isset($cache->version)); + } +}