Improve code, fix filesystem test failing after first run

This commit is contained in:
2018-03-25 12:48:54 +02:00
parent 5b94961691
commit d992c767e8
12 changed files with 68 additions and 43 deletions

View File

@@ -1,13 +1,13 @@
{ {
"name": "iqparts/cache", "name": "iqparts/cache",
"type": "library", "type": "library",
"description": "Simple cache library with Redis and Filesystem adapters.",
"license": "MIT", "license": "MIT",
"require": { "require": {
"predis/predis": "^1.1" "predis/predis": "^1.1"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.3", "phpunit/phpunit": "^6.3"
"phpstan/phpstan": "^0.9.1"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View File

@@ -17,7 +17,7 @@ interface CacheAdapterInterface
* @param int|null $ttl * @param int|null $ttl
* @return void * @return void
*/ */
public function set(string $key, $value, int $ttl = null); public function set(string $key, $value, int $ttl = null): void;
/** /**
* @param string $key * @param string $key

View File

@@ -49,21 +49,21 @@ class FilesystemAdapter implements CacheAdapterInterface
* @param SerializerInterface $serializer * @param SerializerInterface $serializer
* @param int|null $chmod * @param int|null $chmod
* @param int|null $ttl * @param int|null $ttl
* @param string|null $directorySeperator * @param string|null $directorySeparator
*/ */
public function __construct( public function __construct(
string $directory, string $directory,
SerializerInterface $serializer, SerializerInterface $serializer,
int $chmod = null, int $chmod = null,
int $ttl = null, int $ttl = null,
string $directorySeperator = null string $directorySeparator = null
) )
{ {
$this->indexLocation = $directory . '/' . md5($directory) . 'index'; $this->indexLocation = $directory . '/' . md5($directory) . 'index';
$this->ttlLocation = $directory . '/' . md5($directory) . 'ttl'; $this->ttlLocation = $directory . '/' . md5($directory) . 'ttl';
$this->directory = $directory; $this->directory = $directory;
$this->serializer = $serializer; $this->serializer = $serializer;
$this->directorySeparator = $directorySeperator; $this->directorySeparator = $directorySeparator;
$this->chmod = $chmod; $this->chmod = $chmod;
$this->ttl = $ttl; $this->ttl = $ttl;
@@ -106,7 +106,7 @@ class FilesystemAdapter implements CacheAdapterInterface
* @param int|null $ttl * @param int|null $ttl
* @return void * @return void
*/ */
public function set(string $key, $value, int $ttl = null) public function set(string $key, $value, int $ttl = null): void
{ {
$file = $this->getFilename($key); $file = $this->getFilename($key);
file_put_contents($file, $this->serializer->serialize($value)); file_put_contents($file, $this->serializer->serialize($value));
@@ -136,8 +136,7 @@ class FilesystemAdapter implements CacheAdapterInterface
if ($this->exists($file)) { if ($this->exists($file)) {
unlink($file); unlink($file);
} }
unset($this->index[$key]); unset($this->index[$key], $this->timeToLive[$key]);
unset($this->timeToLive[$key]);
$this->saveIndex(); $this->saveIndex();
} }
} }
@@ -175,7 +174,7 @@ class FilesystemAdapter implements CacheAdapterInterface
/** /**
* @param $pattern * @param $pattern
*/ */
private function deleteGlob($pattern) private function deleteGlob($pattern): void
{ {
foreach ($this->index as $key => $value) { foreach ($this->index as $key => $value) {
if (fnmatch($pattern, $key)) { if (fnmatch($pattern, $key)) {
@@ -188,7 +187,7 @@ class FilesystemAdapter implements CacheAdapterInterface
* @param $file * @param $file
* @return bool * @return bool
*/ */
private function exists(string $file) private function exists(string $file): bool
{ {
return file_exists($file); return file_exists($file);
} }
@@ -197,9 +196,9 @@ class FilesystemAdapter implements CacheAdapterInterface
* @param $key * @param $key
* @return string * @return string
*/ */
private function getFilename(string $key) private function getFilename(string $key): string
{ {
list($directory, $file) = $this->getDirectoryAndFile($key); [$directory, $file] = $this->getDirectoryAndFile($key);
return $directory . '/' . md5($file); return $directory . '/' . md5($file);
} }
@@ -207,7 +206,7 @@ class FilesystemAdapter implements CacheAdapterInterface
* @param string $key * @param string $key
* @return array * @return array
*/ */
private function getDirectoryAndFile(string $key) private function getDirectoryAndFile(string $key): array
{ {
$directory = $this->directory; $directory = $this->directory;
if ($this->directorySeparator !== null) { if ($this->directorySeparator !== null) {
@@ -224,17 +223,19 @@ class FilesystemAdapter implements CacheAdapterInterface
/** /**
* @param $directory * @param $directory
*/ */
private function createSubDirectoryIfNotExists($directory) private function createSubDirectoryIfNotExists($directory): void
{ {
if (file_exists($directory) === false) { if (file_exists($directory) === false) {
mkdir($directory); if (!mkdir($directory) && !is_dir($directory)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $directory));
}
if ($this->chmod !== null) { if ($this->chmod !== null) {
chmod($directory, $this->chmod); chmod($directory, $this->chmod);
} }
} }
} }
private function saveIndex() private function saveIndex(): void
{ {
file_put_contents($this->indexLocation, json_encode($this->index)); file_put_contents($this->indexLocation, json_encode($this->index));
file_put_contents($this->ttlLocation, json_encode($this->timeToLive)); file_put_contents($this->ttlLocation, json_encode($this->timeToLive));

View File

@@ -32,8 +32,7 @@ final class MemoryAdapter implements CacheAdapterInterface
return $this->data[$key]; return $this->data[$key];
} }
unset($this->timeToLive[$key]); unset($this->timeToLive[$key], $this->data[$key]);
unset($this->data[$key]);
return null; return null;
} }
@@ -43,7 +42,7 @@ final class MemoryAdapter implements CacheAdapterInterface
* @param int|null $ttl * @param int|null $ttl
* @return void * @return void
*/ */
public function set(string $key, $value, int $ttl = null) public function set(string $key, $value, int $ttl = null): void
{ {
$this->data[$key] = $value; $this->data[$key] = $value;
if ($ttl !== null) { if ($ttl !== null) {
@@ -53,13 +52,11 @@ final class MemoryAdapter implements CacheAdapterInterface
/** /**
* @param string $key * @param string $key
* @return mixed * @return void
*/ */
public function delete(string $key) public function delete(string $key): void
{ {
unset($this->data[$key]); unset($this->data[$key], $this->timeToLive[$key]);
unset($this->timeToLive[$key]);
return 1;
} }
/** /**

View File

@@ -48,7 +48,7 @@ final class NamespaceAdapter implements CacheAdapterInterface
* @param string $key * @param string $key
* @return void * @return void
*/ */
public function delete(string $key) public function delete(string $key): void
{ {
$this->cacheAdapter->delete($this->namespace . $key); $this->cacheAdapter->delete($this->namespace . $key);
} }
@@ -57,19 +57,20 @@ final class NamespaceAdapter implements CacheAdapterInterface
* @param string $key * @param string $key
* @return array * @return array
*/ */
public function keys($key = '*') public function keys($key = '*'): array
{ {
if (substr($key, -1) !== '*') { if (substr($key, -1) !== '*') {
$key = $key . '*'; $key .= '*';
} }
/** @var string[] $keys */
$keys = $this->cacheAdapter->keys($this->namespace . $key); $keys = $this->cacheAdapter->keys($this->namespace . $key);
$allowed = []; $allowed = [];
$len = strlen($this->namespace); $len = \strlen($this->namespace);
foreach ($keys as $key) { foreach ($keys as $cacheKey) {
if (substr($key, 0, $len) === $this->namespace) { if (0 === strpos($cacheKey, $this->namespace)) {
$allowed[] = substr($key, $len); $allowed[] = substr($cacheKey, $len);
} }
} }

View File

@@ -20,7 +20,7 @@ final class NullAdapter implements CacheAdapterInterface
* @param int|null $ttl * @param int|null $ttl
* @return void * @return void
*/ */
public function set(string $key, $value, int $ttl = null) public function set(string $key, $value, int $ttl = null): void
{ {
} }
@@ -28,7 +28,7 @@ final class NullAdapter implements CacheAdapterInterface
* @param string $key * @param string $key
* @return void * @return void
*/ */
public function delete(string $key) public function delete(string $key): void
{ {
} }

View File

@@ -48,7 +48,7 @@ final class PredisAdapter implements CacheAdapterInterface
* @param $value * @param $value
* @param int|null $ttl TTL in seconds * @param int|null $ttl TTL in seconds
*/ */
public function set(string $key, $value, int $ttl = null) public function set(string $key, $value, int $ttl = null): void
{ {
if ($ttl !== null && $ttl !== 0) { if ($ttl !== null && $ttl !== 0) {
$this->client->setex($key, $ttl ?? $this->defaultTtl, $this->serializer->serialize($value)); $this->client->setex($key, $ttl ?? $this->defaultTtl, $this->serializer->serialize($value));

View File

@@ -4,9 +4,9 @@ namespace IQParts\Cache\Serializer;
final class JsonSerializer implements SerializerInterface final class JsonSerializer implements SerializerInterface
{ {
public function serialize($input) public function serialize($input): string
{ {
if (is_array($input)) { if (\is_array($input)) {
return json_encode($input); return json_encode($input);
} }

View File

@@ -6,11 +6,14 @@ use PHPUnit\Framework\TestCase;
abstract class AbstractTestCase extends TestCase abstract class AbstractTestCase extends TestCase
{ {
public function getTmpDirectory() /**
* @return string
*/
public function getTmpDirectory(): string
{ {
$location = __DIR__ . '/../tmp'; $location = __DIR__ . '/../tmp';
if (!file_exists($location)) { if (!file_exists($location)) {
if (!mkdir($location)) { if (!mkdir($location) && !is_dir($location)) {
throw new \RuntimeException('Could not create directory: ' . $location); throw new \RuntimeException('Could not create directory: ' . $location);
} }
chmod($location, 0777); chmod($location, 0777);

View File

@@ -6,6 +6,8 @@ namespace IQParts\CacheTest\Unit\Adapter;
use IQParts\Cache\Adapter\FilesystemAdapter; use IQParts\Cache\Adapter\FilesystemAdapter;
use IQParts\Cache\Serializer\JsonSerializer; use IQParts\Cache\Serializer\JsonSerializer;
use IQParts\CacheTest\AbstractTestCase; use IQParts\CacheTest\AbstractTestCase;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
final class FilesystemAdapterTest extends AbstractTestCase final class FilesystemAdapterTest extends AbstractTestCase
{ {
@@ -27,7 +29,7 @@ final class FilesystemAdapterTest extends AbstractTestCase
$adapter->set('ttl', 'b', 200); $adapter->set('ttl', 'b', 200);
$this->assertTrue($adapter->ttl('ttl') > 0); $this->assertTrue($adapter->ttl('ttl') > 0);
$this->assertTrue($adapter->ttl('b') === $adapter::NO_TTL); $this->assertSame($adapter->ttl('b'), $adapter::NO_TTL);
$adapter->set('a-keys', 'a'); $adapter->set('a-keys', 'a');
$adapter->set('b-keys', 'a'); $adapter->set('b-keys', 'a');
@@ -118,4 +120,22 @@ final class FilesystemAdapterTest extends AbstractTestCase
$this->assertEquals('a', $adapter->get('a/b')); $this->assertEquals('a', $adapter->get('a/b'));
$adapter->delete('a/b'); $adapter->delete('a/b');
} }
protected function tearDown()
{
parent::tearDown();
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($this->getTmpDirectory(), RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($files as $file) {
if ($file->isDir()) {
rmdir($file->getRealPath());
} else {
unlink($file->getRealPath());
}
}
}
} }

View File

@@ -8,6 +8,9 @@ use IQParts\CacheTest\AbstractTestCase;
final class MemoryAdapterTest extends AbstractTestCase final class MemoryAdapterTest extends AbstractTestCase
{ {
/**
*
*/
public function testAdapter() public function testAdapter()
{ {
$adapter = new MemoryAdapter(); $adapter = new MemoryAdapter();
@@ -25,7 +28,7 @@ final class MemoryAdapterTest extends AbstractTestCase
$adapter->set('a', 'b', 200); $adapter->set('a', 'b', 200);
$this->assertTrue($adapter->ttl('a') > 0); $this->assertTrue($adapter->ttl('a') > 0);
$this->assertTrue($adapter->ttl('c') === MemoryAdapter::NO_TTL); $this->assertSame($adapter->ttl('c'), MemoryAdapter::NO_TTL);
} }
public function testTtl() public function testTtl()

View File

@@ -10,10 +10,10 @@ final class JsonSerializerTest extends AbstractTestCase
public function testSerialize() public function testSerialize()
{ {
$serializer = new JsonSerializer(); $serializer = new JsonSerializer();
$string = "myString"; $string = 'myString';
$array = [0 => '1', 1 => '2', 2 => '3']; $array = [0 => '1', 1 => '2', 2 => '3'];
$this->assertTrue(is_string($serializer->serialize($array))); $this->assertInternalType('string', $serializer->serialize($array));
$this->assertEquals($string, $serializer->serialize($string)); $this->assertEquals($string, $serializer->serialize($string));
$this->assertEquals($array, $serializer->deserialize($serializer->serialize($array))); $this->assertEquals($array, $serializer->deserialize($serializer->serialize($array)));