Skip to content

Commit

Permalink
Merge pull request #2 from charonlab/feature/apcu_adapter
Browse files Browse the repository at this point in the history
Implement APCu Cache Pool Adapter
  • Loading branch information
nulxrd committed Feb 11, 2024
2 parents a50d3e9 + 0e7f963 commit a426aa9
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 0 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"psr/simple-cache-implementation": "1.0"
},
"require": {
"ext-apcu": "*",
"php": "~8.1.0 || ~8.2.0 || ~8.3.0",
"psr/cache": "dev-master",
"psr/simple-cache": "dev-master"
Expand Down
87 changes: 87 additions & 0 deletions src/Adapter/APCu/APCuAdapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

/*
* This file is part of the charonlab/charon-cache.
*
* Copyright (C) 2024 Charon Lab Development Team
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE.md file for details.
*/

namespace Charon\Cache\Adapter\APCu;

use Charon\Cache\Adapter\GenericAdapter;
use Charon\Cache\CacheItem;
use Charon\Cache\Exception\CacheException;

class APCuAdapter extends GenericAdapter
{
public function __construct() {
if (!\extension_loaded('apcu')) {
throw new CacheException('APCu extension is not loaded');
}

parent::__construct();
}

/**
* @inheritDoc
*/
protected function doSave(CacheItem $item): array|bool {
$entry = [
'data' => $item->get(),
'ttl' => $item->getExpirationTime()
];

return \apcu_store(
$item->getKey(),
\serialize($entry),
(int) $item->getExpirationTime()
);
}

/**
* @inheritDoc
*/
protected function doFetch(array $keys): iterable {
$ok = false;
$values = [];

$results = \apcu_fetch($keys, $ok);

if (!\is_array($results)) {
$results = [$results];
}

foreach ($results as $key => $result) {
if ($ok && $result !== null) {
$entry = \unserialize($result);
$values[$key] = $entry['data'];
}
}

return $values;
}

/**
* @inheritDoc
*/
protected function doDelete(array $keys): bool {
return (bool) \apcu_delete($keys);
}

/**
* @inheritDoc
*/
protected function doHave(string $key): bool {
return \apcu_exists($key);
}

/**
* @inheritDoc
*/
protected function doClear(): bool {
return \apcu_clear_cache();
}
}
44 changes: 44 additions & 0 deletions src/Adapter/APCu/Tests/APCuAdapterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

/*
* This file is part of the charonlab/charon-cache.
*
* Copyright (C) 2024 Charon Lab Development Team
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE.md file for details.
*/

namespace Charon\Cache\Adapter\APCu\Tests;

use Charon\Cache\Adapter\APCu\APCuAdapter;
use Charon\Cache\CacheItem;
use Charon\Cache\Exception\CacheException;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\TestCase;

#[Group('unit')]
#[CoversClass(APCuAdapter::class)]
class APCuAdapterTest extends TestCase
{
public function testThrowsExceptionIfAPCuExtensionIsNotLoaded(): void {
self::expectException(CacheException::class);
self::expectExceptionMessage('APCu extension is not loaded');

new APCuAdapter();
}

public function testSerialization(): void {
$mock = $this->createMock(APCuAdapter::class);
$mock->method('get')
->willReturn(new CacheItem('foo', true, 'bar'));

$mock->set('foo', 'bar');

self::assertEquals(
'bar',
$mock->get('foo')->get()
);
}
}
7 changes: 7 additions & 0 deletions src/Exception/CacheException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Charon\Cache\Exception;

class CacheException extends \RuntimeException
{
}

0 comments on commit a426aa9

Please sign in to comment.