-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #237 from WebFiori/cache
feat: Cache
- Loading branch information
Showing
7 changed files
with
702 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
<?php | ||
namespace webfiori\framework\test\cache; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use webfiori\framework\cache\Cache; | ||
/** | ||
*/ | ||
class CacheTest extends TestCase { | ||
/** | ||
* @test | ||
*/ | ||
public function test00() { | ||
$key = 'first'; | ||
$data = Cache::get($key, function () { | ||
return 'This is a test.'; | ||
}); | ||
$this->assertEquals('This is a test.', $data); | ||
$this->assertEquals('This is a test.', Cache::get($key)); | ||
$this->assertNull(Cache::get('not_cached')); | ||
} | ||
/** | ||
* @test | ||
*/ | ||
public function test01() { | ||
$key = 'test_2'; | ||
$this->assertFalse(Cache::has($key)); | ||
$data = Cache::get($key, function () { | ||
return 'This is a test.'; | ||
}, 5); | ||
$this->assertEquals('This is a test.', $data); | ||
$this->assertTrue(Cache::has($key)); | ||
sleep(6); | ||
$this->assertFalse(Cache::has($key)); | ||
$this->assertNull(Cache::get($key)); | ||
} | ||
/** | ||
* @test | ||
*/ | ||
public function test03() { | ||
$key = 'ok_test'; | ||
$this->assertFalse(Cache::has($key)); | ||
$data = Cache::get($key, function () { | ||
return 'This is a test.'; | ||
}, 600); | ||
$this->assertEquals('This is a test.', $data); | ||
$this->assertTrue(Cache::has($key)); | ||
Cache::delete($key); | ||
$this->assertFalse(Cache::has($key)); | ||
$this->assertNull(Cache::get($key)); | ||
} | ||
/** | ||
* @test | ||
*/ | ||
public function test04() { | ||
$key = 'test_3'; | ||
$this->assertFalse(Cache::has($key)); | ||
$data = Cache::get($key, function () { | ||
return 'This is a test.'; | ||
}, 600); | ||
$this->assertEquals('This is a test.', $data); | ||
$item = Cache::getItem($key); | ||
$this->assertNotNull($item); | ||
$this->assertEquals(600, $item->getTTL()); | ||
Cache::setTTL($key, 1000); | ||
$item = Cache::getItem($key); | ||
$this->assertEquals(1000, $item->getTTL()); | ||
Cache::delete($key); | ||
$this->assertNull(Cache::getItem($key)); | ||
} | ||
public function test05() { | ||
$keys = []; | ||
for ($x = 0 ; $x < 10 ; $x++) { | ||
$key = 'item_'.$x; | ||
Cache::get($key, function () { | ||
return 'This is a test.'; | ||
}, 600); | ||
$keys[] = $key; | ||
} | ||
foreach ($keys as $key) { | ||
$this->assertTrue(Cache::has($key)); | ||
} | ||
Cache::flush(); | ||
foreach ($keys as $key) { | ||
$this->assertFalse(Cache::has($key)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
<?php | ||
/** | ||
* This file is licensed under MIT License. | ||
* | ||
* Copyright (c) 2024 Ibrahim BinAlshikh and Contributors | ||
* | ||
* For more information on the license, please visit: | ||
* https://github.com/WebFiori/.github/blob/main/LICENSE | ||
* | ||
*/ | ||
namespace webfiori\framework\cache; | ||
|
||
/** | ||
* A class which is used to manage cache related operations | ||
*/ | ||
class Cache { | ||
/** | ||
* | ||
* @var Storage | ||
*/ | ||
private $driver; | ||
private static $inst; | ||
/** | ||
* Removes an item from the cache given its unique identifier. | ||
* | ||
* @param string $key | ||
*/ | ||
public static function delete(string $key) { | ||
self::getDriver()->delete($key); | ||
} | ||
/** | ||
* Removes all items from the cache. | ||
*/ | ||
public static function flush() { | ||
self::getDriver()->flush(); | ||
} | ||
/** | ||
* Returns or creates a cache item given its key. | ||
* | ||
* | ||
* @param string $key The unique identifier of the item. | ||
* | ||
* @param callable $generator A callback which is used as a fallback to | ||
* create new cache entry or re-create an existing one if it was expired. | ||
* This callback must return the data that will be cached. | ||
* | ||
* @param int $ttl Time to live of the item in seconds. | ||
* | ||
* @param array $params Any additional parameters to be passed to the callback | ||
* which is used to generate cache data. | ||
* @return null | ||
*/ | ||
public static function get(string $key, callable $generator = null, int $ttl = 60, array $params = []) { | ||
$data = self::getDriver()->read($key); | ||
|
||
if ($data !== null && $data !== false) { | ||
return $data; | ||
} | ||
|
||
if (!is_callable($generator)) { | ||
return null; | ||
} | ||
$newData = call_user_func_array($generator, $params); | ||
$item = new Item($key, $newData, $ttl, defined('CACHE_SECRET') ? CACHE_SECRET : ''); | ||
self::getDriver()->cache($item); | ||
|
||
return $newData; | ||
} | ||
/** | ||
* Returns storage engine which is used to store, read, update and delete items | ||
* from the cache. | ||
* | ||
* @return Storage | ||
*/ | ||
public static function getDriver() : Storage { | ||
return self::getInst()->driver; | ||
} | ||
/** | ||
* Reads an item from the cache and return its information. | ||
* | ||
* @param string $key The unique identifier of the item. | ||
* | ||
* @return Item|null If such item exist and not yet expired, an object | ||
* of type 'Item' is returned which has all cached item information. Other | ||
* than that, null is returned. | ||
*/ | ||
public static function getItem(string $key) { | ||
return self::getDriver()->readItem($key); | ||
} | ||
/** | ||
* Checks if the cache has in item given its unique identifier. | ||
* | ||
* @param string $key | ||
* | ||
* @return bool If the item exist and is not yet expired, true is returned. | ||
* Other than that, false is returned. | ||
*/ | ||
public static function has(string $key) : bool { | ||
return self::getDriver()->has($key); | ||
} | ||
/** | ||
* Creates new item in the cache. | ||
* | ||
* Note that the item will only be added if it does not exist or already | ||
* expired or the override option is set to true in case it was already | ||
* created and not expired. | ||
* | ||
* @param string $key The unique identifier of the item. | ||
* | ||
* @param mixed $data The data that will be cached. | ||
* | ||
* @param int $ttl The time at which the data will be kept in the cache (in seconds). | ||
* | ||
* @param bool $override If cache item already exist which has given key and not yet | ||
* expired and this one is set to true, the existing item will be overridden by | ||
* provided data and ttl. | ||
* | ||
* @return bool If successfully added, the method will return true. False | ||
* otherwise. | ||
*/ | ||
public static function set(string $key, $data, int $ttl = 60, bool $override = false) : bool { | ||
if (!self::has($key) || $override === true) { | ||
$item = new Item($key, $data, $ttl, defined('CACHE_SECRET') ? CACHE_SECRET : ''); | ||
self::getDriver()->cache($item); | ||
} | ||
|
||
return false; | ||
} | ||
/** | ||
* Sets storage engine which is used to store, read, update and delete items | ||
* from the cache. | ||
* | ||
* @param Storage $driver | ||
*/ | ||
public static function setDriver(Storage $driver) { | ||
self::getInst()->driver = $driver; | ||
} | ||
/** | ||
* Updates TTL of specific cache item. | ||
* | ||
* @param string $key The unique identifier of the item. | ||
* | ||
* @param int $ttl The new value for TTL. | ||
* | ||
* @return bool If item is updated, true is returned. Other than that, false | ||
* is returned. | ||
*/ | ||
public static function setTTL(string $key, int $ttl) { | ||
$item = self::getItem($key); | ||
|
||
if ($item === null) { | ||
return false; | ||
} | ||
$item->setTTL($ttl); | ||
self::getDriver()->cache($item); | ||
|
||
return true; | ||
} | ||
/** | ||
* Creates and returns a single instance of the class. | ||
* | ||
* @return Cache | ||
*/ | ||
private static function getInst() : Cache { | ||
if (self::$inst === null) { | ||
self::$inst = new Cache(); | ||
self::setDriver(new FileStorage()); | ||
} | ||
|
||
return self::$inst; | ||
} | ||
} |
Oops, something went wrong.