mirror of
https://github.com/torrentpier/torrentpier
synced 2025-08-22 22:33:55 -07:00
#90 Refactoring cache
This commit is contained in:
parent
d1d520e086
commit
03bc2dcf49
11 changed files with 598 additions and 29 deletions
|
@ -46,6 +46,10 @@ $di->register(new \TorrentPier\ServiceProviders\LogServiceProvider(), [
|
|||
'config.log.handlers' => $di->config->log->handlers
|
||||
]);
|
||||
|
||||
$di->register(new \TorrentPier\ServiceProviders\CacheServiceProvider(), [
|
||||
'config.services.cache' => $di->config->services->cache->toArray()
|
||||
]);
|
||||
|
||||
$di->register(new \TorrentPier\ServiceProviders\DbServiceProvider, [
|
||||
'config.db' => $di->config->db->toArray()
|
||||
]);
|
||||
|
|
|
@ -42,7 +42,8 @@
|
|||
"zendframework/zend-loader": "^2.5",
|
||||
"zendframework/zend-mail": "^2.5",
|
||||
"zendframework/zend-session": "^2.5",
|
||||
"zendframework/zend-version": "^2.5"
|
||||
"zendframework/zend-version": "^2.5",
|
||||
"doctrine/cache": "^1.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8"
|
||||
|
|
|
@ -19,6 +19,15 @@ $config = [
|
|||
'tp_release_date' => '**/**/2016',
|
||||
'tp_release_state' => 'ALPHA',
|
||||
|
||||
'services' => [
|
||||
'cache' => [
|
||||
'adapter' => \TorrentPier\Cache\FileAdapter::class,
|
||||
'options' => [
|
||||
'directory' => __DIR__ . '/../internal_data/cache',
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
// Database
|
||||
'db' => [
|
||||
'debug' => '{self.debug}',
|
||||
|
|
198
src/Cache/Adapter.php
Normal file
198
src/Cache/Adapter.php
Normal file
|
@ -0,0 +1,198 @@
|
|||
<?php
|
||||
|
||||
namespace TorrentPier\Cache;
|
||||
|
||||
use Doctrine\Common\Cache\CacheProvider;
|
||||
|
||||
/**
|
||||
* Class Adapter
|
||||
* @package TorrentPier\Cache
|
||||
*/
|
||||
abstract class Adapter
|
||||
{
|
||||
const DEFAULT_NAMESPACE = 'default';
|
||||
|
||||
/**
|
||||
* @var CacheProvider
|
||||
*/
|
||||
protected $provider;
|
||||
|
||||
/**
|
||||
* Set options for setting cache provider.
|
||||
*
|
||||
* @param array $options
|
||||
*/
|
||||
public function setOptions(array $options = [])
|
||||
{
|
||||
foreach ($options as $key => $value) {
|
||||
$method = 'set' . ucfirst($key);
|
||||
if (!method_exists($this, $method)) {
|
||||
throw new \InvalidArgumentException('Method ' . $method . ' is undefined.');
|
||||
}
|
||||
|
||||
$this->{$method}($value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get object provider cache.
|
||||
*
|
||||
* @return CacheProvider
|
||||
*/
|
||||
abstract public function getProvider();
|
||||
|
||||
/**
|
||||
* Get type cache.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getType();
|
||||
|
||||
/**
|
||||
* Prepare key.
|
||||
*
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
protected function prepareKey($key)
|
||||
{
|
||||
if (empty($key) || substr($key, -2) === '::') {
|
||||
throw new \InvalidArgumentException('The key is not defined.');
|
||||
}
|
||||
|
||||
$result = explode('::', $key, 2);
|
||||
if (empty($result[1])) {
|
||||
$namespace = self::DEFAULT_NAMESPACE;
|
||||
$id = $result[0];
|
||||
} else {
|
||||
list($namespace, $id) = $result;
|
||||
}
|
||||
|
||||
$this->getProvider()->setNamespace($namespace);
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if an entry exists in the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
$id = $this->prepareKey($key);
|
||||
return $this->getProvider()->contains($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches an entry from the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed|null $defaultValue
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function get($key, $defaultValue = null)
|
||||
{
|
||||
$id = $this->prepareKey($key);
|
||||
$result = $this->getProvider()->fetch($id);
|
||||
|
||||
if ($result === false) {
|
||||
return $defaultValue;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an associative array of values for keys is found in cache.
|
||||
*
|
||||
* @param array $keys
|
||||
* @return array|\string[]
|
||||
*/
|
||||
public function gets(array $keys)
|
||||
{
|
||||
$keys = array_map([$this, 'prepareKey'], $keys);
|
||||
return $this->getProvider()->fetchMultiple([$keys]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts data into the cache.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $data
|
||||
* @param int $timeLeft
|
||||
* @return bool
|
||||
*/
|
||||
public function set($key, $data, $timeLeft = 0)
|
||||
{
|
||||
$id = $this->prepareKey($key);
|
||||
return $this->getProvider()->save($id, $data, $timeLeft);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean value indicating if the operation succeeded.
|
||||
*
|
||||
* @param array $keysAndValues
|
||||
* @param int $timeLeft
|
||||
* @return bool
|
||||
*/
|
||||
public function sets(array $keysAndValues, $timeLeft)
|
||||
{
|
||||
foreach ($keysAndValues as $key => $value) {
|
||||
$id = $this->prepareKey($key);
|
||||
$keysAndValues[$id] = $value;
|
||||
unset($keysAndValues[$key]);
|
||||
}
|
||||
return $this->getProvider()->saveMultiple($keysAndValues, $timeLeft);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a cache entry.
|
||||
*
|
||||
* @param string $id
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$id = $this->prepareKey($id);
|
||||
return $this->getProvider()->delete($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all cache entries in the current cache namespace.
|
||||
*
|
||||
* @param string $namespace
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteAll($namespace = '')
|
||||
{
|
||||
$this->getProvider()->setNamespace($namespace);
|
||||
return $this->getProvider()->deleteAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes all cache entries, globally.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
return $this->getProvider()->flushAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves cached information from the data store.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function stats()
|
||||
{
|
||||
$stats = $this->getProvider()->getStats();
|
||||
if (!$stats) {
|
||||
$stats = [];
|
||||
}
|
||||
$stats['type'] = $this->getType();
|
||||
return $stats;
|
||||
}
|
||||
}
|
77
src/Cache/FileAdapter.php
Normal file
77
src/Cache/FileAdapter.php
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
namespace TorrentPier\Cache;
|
||||
|
||||
use Doctrine\Common\Cache\PhpFileCache;
|
||||
|
||||
/**
|
||||
* Class FileAdapter
|
||||
* @package TorrentPier\Cache
|
||||
*/
|
||||
class FileAdapter extends Adapter
|
||||
{
|
||||
/**
|
||||
* @var string The cache directory.
|
||||
*/
|
||||
protected $directory;
|
||||
|
||||
/**
|
||||
* @var string The cache file extension.
|
||||
*/
|
||||
protected $extension = PhpFileCache::EXTENSION;
|
||||
|
||||
/**
|
||||
* @var int The cache file umask.
|
||||
*/
|
||||
protected $umask = 0002;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getProvider()
|
||||
{
|
||||
if (!$this->provider) {
|
||||
$this->provider = new PhpFileCache($this->directory, $this->extension, $this->umask);
|
||||
}
|
||||
|
||||
return $this->provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getType()
|
||||
{
|
||||
return 'Cache in php file';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set directory path for cache.
|
||||
*
|
||||
* @param $directory
|
||||
*/
|
||||
protected function setDirectory($directory)
|
||||
{
|
||||
$this->directory = $directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set extension file.
|
||||
*
|
||||
* @param $extension
|
||||
*/
|
||||
protected function setExtension($extension)
|
||||
{
|
||||
$this->extension = $extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set umask file.
|
||||
*
|
||||
* @param $umask
|
||||
*/
|
||||
protected function setUmask($umask)
|
||||
{
|
||||
$this->umask = $umask;
|
||||
}
|
||||
}
|
103
src/Cache/MemoryAdapter.php
Normal file
103
src/Cache/MemoryAdapter.php
Normal file
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
|
||||
namespace TorrentPier\Cache;
|
||||
|
||||
use Doctrine\Common\Cache\MemcacheCache;
|
||||
use Doctrine\Common\Cache\MemcachedCache;
|
||||
|
||||
/**
|
||||
* Class MemoryAdapter
|
||||
* @package TorrentPier\Cache
|
||||
*/
|
||||
class MemoryAdapter extends Adapter
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $isMemcached = false;
|
||||
|
||||
/**
|
||||
* @var array Setting servers.
|
||||
*/
|
||||
private $servers = [];
|
||||
|
||||
/**
|
||||
* MemoryAdapter constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->isMemcached = extension_loaded('memcached');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getProvider()
|
||||
{
|
||||
if (!$this->provider) {
|
||||
if ($this->isMemcached) {
|
||||
$this->provider = new MemcachedCache();
|
||||
$this->provider->setMemcached($this->getMemcached());
|
||||
} else {
|
||||
$this->provider = new MemcacheCache();
|
||||
$this->provider->setMemcache($this->getMemcache());
|
||||
}
|
||||
}
|
||||
|
||||
return $this->provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $servers
|
||||
*/
|
||||
protected function setServers(array $servers = [])
|
||||
{
|
||||
$this->servers = $servers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memcached api.
|
||||
*
|
||||
* @return \Memcached
|
||||
*/
|
||||
private function getMemcached()
|
||||
{
|
||||
$mem = new \Memcached();
|
||||
foreach ($this->servers as $server) {
|
||||
$mem->addServer(
|
||||
isset($server['host']) ? $server['host'] : '127.0.0.1',
|
||||
isset($server['port']) ? $server['port'] : 11211,
|
||||
isset($server['weight']) ? $server['weight'] : 100
|
||||
);
|
||||
}
|
||||
return $mem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memcache api.
|
||||
*
|
||||
* @return \Memcache
|
||||
*/
|
||||
private function getMemcache()
|
||||
{
|
||||
$mem = new \Memcache();
|
||||
foreach ($this->servers as $server) {
|
||||
$mem->addserver(
|
||||
isset($server['host']) ? $server['host'] : '127.0.0.1',
|
||||
isset($server['port']) ? $server['port'] : 11211,
|
||||
isset($server['persistent']) ? $server['persistent'] : true,
|
||||
isset($server['weight']) ? $server['weight'] : 100,
|
||||
isset($server['timeout']) ? $server['timeout'] : 1
|
||||
);
|
||||
}
|
||||
return $mem;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getType()
|
||||
{
|
||||
return $this->isMemcached ? 'Cache in memcached' : 'Cache in memcache';
|
||||
}
|
||||
}
|
28
src/ServiceProviders/CacheServiceProvider.php
Normal file
28
src/ServiceProviders/CacheServiceProvider.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace TorrentPier\ServiceProviders;
|
||||
|
||||
use Pimple\Container;
|
||||
use Pimple\ServiceProviderInterface;
|
||||
use TorrentPier\Cache\Adapter;
|
||||
|
||||
/**
|
||||
* Class CacheServiceProvider
|
||||
* @package TorrentPier\ServiceProviders
|
||||
*/
|
||||
class CacheServiceProvider implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container['cache'] = function (Container $container) {
|
||||
$setting = $container['config.services.cache'];
|
||||
/** @var Adapter $adapter */
|
||||
$adapter = new $setting['adapter']();
|
||||
$adapter->setOptions($setting['options']);
|
||||
return $adapter;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -6,13 +6,19 @@ use Pimple\Container;
|
|||
use Pimple\ServiceProviderInterface;
|
||||
use ReCaptcha\ReCaptcha;
|
||||
|
||||
/**
|
||||
* Class CaptchaServiceProvider
|
||||
* @package TorrentPier\ServiceProviders
|
||||
*/
|
||||
class CaptchaServiceProvider implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container['captcha'] = function (Container $container) {
|
||||
$captcha = new ReCaptcha($container['config.captcha.secret_key']);
|
||||
|
||||
return $captcha;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,8 +7,20 @@ require_once __DIR__ . '/common.php';
|
|||
/** @var \TorrentPier\Di $di */
|
||||
$di = \TorrentPier\Di::getInstance();
|
||||
|
||||
/** @var \TorrentPier\Db\Adapter $db */
|
||||
$db = $di->db;
|
||||
/** @var \TorrentPier\Cache\Adapter $cache */
|
||||
$cache = $di->cache;
|
||||
|
||||
//var_dump($cache);
|
||||
//
|
||||
$resultHas = $cache->has('key');
|
||||
$resultGet = $cache->get('key');
|
||||
$resultSet = $cache->set('key', [[1], [2]], 5);
|
||||
$resultStats = $cache->stats();
|
||||
|
||||
var_dump($resultHas, $resultGet, $resultSet, $resultStats);
|
||||
|
||||
///** @var \TorrentPier\Db\Adapter $db */
|
||||
//$db = $di->db;
|
||||
|
||||
///** @var \Symfony\Component\HttpFoundation\Request $request */
|
||||
//$request = $di->request;
|
||||
|
@ -39,26 +51,26 @@ $db = $di->db;
|
|||
//$log = $di->log;
|
||||
//$log->debug('test debug information');
|
||||
|
||||
\TorrentPier\Log::info('You will see the style guide');
|
||||
|
||||
$query = function(\Zend\Db\Sql\Select $select) {
|
||||
$select->columns(['id' => 'user_id', 'name' => 'username']);
|
||||
$select->join(['t' => BB_TOPICS], 't.topic_poster = u.user_id', ['title' => 'topic_title']);
|
||||
// $select->where(['user_id > ?' => 0]);
|
||||
};
|
||||
|
||||
$users = $db->select(['u' => BB_USERS], $query)->all();
|
||||
$usersCount = $db->count(['u' => BB_USERS], $query);
|
||||
|
||||
$content = $di->view->make('styleguide', [
|
||||
'name' => $di->request->get('name', 'Admin'),
|
||||
'users' => $users,
|
||||
'users_count' => $usersCount
|
||||
]);
|
||||
|
||||
/** @var \Symfony\Component\HttpFoundation\Response $response */
|
||||
$response = \Symfony\Component\HttpFoundation\Response::create();
|
||||
$response->setContent($content);
|
||||
|
||||
$response->prepare($di->request);
|
||||
$response->send();
|
||||
//\TorrentPier\Log::info('You will see the style guide');
|
||||
//
|
||||
//$query = function(\Zend\Db\Sql\Select $select) {
|
||||
// $select->columns(['id' => 'user_id', 'name' => 'username']);
|
||||
// $select->join(['t' => BB_TOPICS], 't.topic_poster = u.user_id', ['title' => 'topic_title']);
|
||||
//// $select->where(['user_id > ?' => 0]);
|
||||
//};
|
||||
//
|
||||
//$users = $db->select(['u' => BB_USERS], $query)->all();
|
||||
//$usersCount = $db->count(['u' => BB_USERS], $query);
|
||||
//
|
||||
//$content = $di->view->make('styleguide', [
|
||||
// 'name' => $di->request->get('name', 'Admin'),
|
||||
// 'users' => $users,
|
||||
// 'users_count' => $usersCount
|
||||
//]);
|
||||
//
|
||||
///** @var \Symfony\Component\HttpFoundation\Response $response */
|
||||
//$response = \Symfony\Component\HttpFoundation\Response::create();
|
||||
//$response->setContent($content);
|
||||
//
|
||||
//$response->prepare($di->request);
|
||||
//$response->send();
|
||||
|
|
55
tests/src/Cache/FileAdapterTest.php
Normal file
55
tests/src/Cache/FileAdapterTest.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace TorrentPier\Cache;
|
||||
|
||||
use Doctrine\Common\Cache\PhpFileCache;
|
||||
|
||||
/**
|
||||
* Class FileAdapterTest
|
||||
* @package TorrentPier\Cache
|
||||
*/
|
||||
class FileAdapterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @var Adapter */
|
||||
private $adapter;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
$this->adapter = new FileAdapter();
|
||||
$this->adapter->setOptions([
|
||||
'directory' => __DIR__ . '/../../../internal_data/cache',
|
||||
'extension' => '.torrentpier.php',
|
||||
'umask' => 0644,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check provider.
|
||||
*/
|
||||
public function testAdapterCache()
|
||||
{
|
||||
self::assertInstanceOf(PhpFileCache::class, $this->adapter->getProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test type cache adapter.
|
||||
*/
|
||||
public function testStatsType()
|
||||
{
|
||||
self::assertEquals('Cache in php file', $this->adapter->stats()['type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check handler error for incorrect error.
|
||||
*
|
||||
* @expectedException \InvalidArgumentException
|
||||
* @expectedExceptionMessage Method setIncorrectKey is undefined.
|
||||
*/
|
||||
public function testIncorrectSetting()
|
||||
{
|
||||
$this->adapter->setOptions(['incorrectKey' => 'value']);
|
||||
}
|
||||
}
|
76
tests/src/Cache/MemoryAdapterTest.php
Normal file
76
tests/src/Cache/MemoryAdapterTest.php
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
namespace TorrentPier\Cache;
|
||||
|
||||
use Doctrine\Common\Cache\MemcacheCache;
|
||||
use Doctrine\Common\Cache\MemcachedCache;
|
||||
|
||||
/**
|
||||
* Class FileAdapterTest
|
||||
* @package TorrentPier\Cache
|
||||
*/
|
||||
class MemoryAdapterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @var Adapter */
|
||||
private $adapterMemcache;
|
||||
|
||||
/** @var Adapter */
|
||||
private $adapterMemcached;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
// memcache
|
||||
$this->adapterMemcache = $this->getMockBuilder(MemoryAdapter::class)
|
||||
->setMethods(['getMemcache'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$propMemcache = new \ReflectionProperty(MemoryAdapter::class, 'isMemcached');
|
||||
$propMemcache->setAccessible(true);
|
||||
$propMemcache->setValue($this->adapterMemcache, false);
|
||||
|
||||
$memcacheMock = $this->getMock('\Memcache', ['getStats']);
|
||||
$memcacheMock->method('getStats')->willReturn([]);
|
||||
|
||||
$this->adapterMemcache
|
||||
->method('getMemcache')
|
||||
->willReturn($memcacheMock);
|
||||
|
||||
// memcached
|
||||
$this->adapterMemcached = $this->getMockBuilder(MemoryAdapter::class)
|
||||
->setMethods(['getMemcached'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$propMemcached = new \ReflectionProperty(MemoryAdapter::class, 'isMemcached');
|
||||
$propMemcached->setAccessible(true);
|
||||
$propMemcached->setValue($this->adapterMemcached, true);
|
||||
|
||||
$memcachedMock = $this->getMock('\Memcached', ['getStats', 'getServerList']);
|
||||
$memcachedMock->method('getStats')->willReturn([]);
|
||||
$memcachedMock->method('getServerList')->willReturn([['host' => '127.0.0.1', 'port' => 11211]]);
|
||||
|
||||
$this->adapterMemcached
|
||||
->method('getMemcache')
|
||||
->willReturn($memcachedMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check provider for memcache.
|
||||
*/
|
||||
public function testAdapterCacheMemcache()
|
||||
{
|
||||
self::assertInstanceOf(MemcacheCache::class, $this->adapterMemcache->getProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check provider for memcached.
|
||||
*/
|
||||
public function testAdapterCacheMemcached()
|
||||
{
|
||||
self::assertInstanceOf(MemcachedCache::class, $this->adapterMemcached->getProvider());
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue