diff options
-rw-r--r-- | application/classes/controller/home.php | 8 | ||||
-rw-r--r-- | application/config/core.php | 2 | ||||
-rw-r--r-- | modules/cache/classes/cache.php | 42 | ||||
-rw-r--r-- | modules/cache/classes/cache/abstract.php | 131 | ||||
-rw-r--r-- | modules/cache/classes/cache/apc.php | 26 | ||||
-rw-r--r-- | modules/cache/classes/cache/database.php | 45 | ||||
-rw-r--r-- | modules/cache/classes/cache/file.php | 85 | ||||
-rw-r--r-- | modules/cache/classes/cache/xcache.php | 24 | ||||
-rw-r--r-- | modules/cache/config/cache.php | 6 | ||||
-rw-r--r-- | modules/database/classes/database/result.php | 20 | ||||
-rw-r--r-- | modules/database/classes/driver/mysql/result.php | 8 | ||||
-rw-r--r-- | modules/database/classes/driver/pdo/db.php | 1 | ||||
-rw-r--r-- | modules/database/classes/driver/pdo/result.php | 7 |
13 files changed, 395 insertions, 10 deletions
diff --git a/application/classes/controller/home.php b/application/classes/controller/home.php index 2e353a0..0d4136f 100644 --- a/application/classes/controller/home.php +++ b/application/classes/controller/home.php @@ -4,6 +4,14 @@ class Home_Controller extends Controller { public function action_index(){
$view = View::get('home');
$view->message = 'Have fun coding!';
+ Cache::set('as1d', array(1, 2, 3, 4, 5), 100);
+ Cache::set('as2d', array(1, 2, 3, 4, 5), 100);
+ Cache::set('asd3', array(1,2,3,4,5),100);
+ Cache::garbage_collect();
+ print_r(DB::query('select')->table('cache')->execute()->as_array());
+ Cache::delete_all('asd3');
+ Cache::instance()->set('as1d', array(1, 2, 3, 4, 5), -100);
+ echo Cache::instance()->set('as1d','huj');
$this->response->body=$view->render();
}
diff --git a/application/config/core.php b/application/config/core.php index 557dcd0..51b0840 100644 --- a/application/config/core.php +++ b/application/config/core.php @@ -8,5 +8,5 @@ return array( )
)
),
- 'modules' => array('database', 'orm')
+ 'modules' => array('database', 'orm','cache')
);
diff --git a/modules/cache/classes/cache.php b/modules/cache/classes/cache.php new file mode 100644 index 0000000..caa8593 --- /dev/null +++ b/modules/cache/classes/cache.php @@ -0,0 +1,42 @@ +<?php
+class Cache {
+
+ /**
+ * An associative array of cache instances
+ * @var array
+ * @access private
+ * @static
+ */
+ private static $_instances=array();
+
+ /**
+ * Magic method to call default cache configuration methods.
+ *
+ * @param string $method Method to call
+ * @param array $arguments Arguments passed to the method
+ * @return mixed Returns the result of called mathod
+ * @access public
+ */
+ public static function __callStatic($method, $arguments) {
+ return call_user_func_array(array(static::instance('default'),$method), $arguments);
+ }
+
+ /**
+ * Gets an instance of a cache configuration
+ *
+ * @param string $config Configuration name.
+ * Defaults to 'default'.
+ * @return Abstract_Cache Driver implementation of Abstact_Cache
+ * @access public
+ * @static
+ */
+ public static function instance($config='default'){
+ if (!isset(Cache::$_instances[$config])) {
+ $driver = Config::get("cache.{$config}.driver");
+ $driver="{$driver}_Cache";
+ Cache::$_instances[$config] = new $driver($config);
+ }
+ return Cache::$_instances[$config];
+ }
+
+}
\ No newline at end of file diff --git a/modules/cache/classes/cache/abstract.php b/modules/cache/classes/cache/abstract.php new file mode 100644 index 0000000..069f808 --- /dev/null +++ b/modules/cache/classes/cache/abstract.php @@ -0,0 +1,131 @@ +<?php
+
+/**
+ * Abstract driver class that actual drivers extend.
+ * Defines the basic functionality that each driver must provide and
+ * provides methods that proxy driver calls.
+ * @package Cache
+ */
+abstract class Abstract_Cache {
+
+ /**
+ * Default lifetime for current configuration. Defaults to 3600.
+ * @var int
+ * @access protected
+ */
+ protected $_default_lifetime;
+
+ /**
+ * Creates the cache instance.
+ *
+ * @param string $config Name of the configuration to initialize
+ * @access public
+ */
+ public function __construct($config) {
+ $this->_default_lifetime=Config::get("cache.{$config}.default_lifetime",3600);
+ }
+
+ /**
+ * Caches a value for the duration of the specified lifetime.
+ *
+ * @param string $key Name to store the object under
+ * @param mixed $value Object to store
+ * @param int $lifetime Validity time for this object in seconds.
+ * Default's to the value specified in config, or to 3600
+ * if it was not specified.
+ * @access public
+ */
+ public function set($key, $value, $lifetime = null){
+ if ($lifetime === null)
+ $lifetime = $this->_default_lifetime;
+ $this->_set($this->sanitize($key), $value, $lifetime);
+ }
+
+ /**
+ * Gets a stored cache value.
+ *
+ * @param string $key Name of the object to retrieve
+ * @param mixed $default Default value to return if the object is not found
+ * @return mixed The requested object, or , if it was not found, the default value.
+ * @access public
+ */
+ public function get($key, $default = null) {
+ $data = $this->_get($this->sanitize($key));
+ if ($data !== null)
+ return $data;
+ return $default;
+ }
+
+ /**
+ * Deletes an object from cache
+ *
+ * @param string $key Name of the object to remove
+ * @access public
+ */
+ public function delete($key) {
+ $this->_delete($this->sanitize($key));
+ }
+
+ /**
+ * Deletes all objects from cache.
+ *
+ * @access public
+ */
+ public function delete_all() {
+ $this->_delete_all();
+ }
+
+ /**
+ * Sanitizes the name of the cached object,
+ * preparing it to be passed to the driver.
+ *
+ * @param string $key Name to sanitize
+ * @return string Sanitized name
+ * @access public
+ */
+ protected function sanitize($key) {
+ return str_replace(array('/', '\\', ' '), '_', $key);
+ }
+
+ /**
+ * Driver implementation of the set() method
+ *
+ * @param string $key Sanitized name to store the object under
+ * @param mixed $value Object to store
+ * @param int $lifetime Validity time for this object in seconds.
+ * Default's to the value specified in config, or to 3600
+ * if it was not specified.
+ * @see Abstract_Cache::set()
+ * @access public
+ */
+ protected abstract function _set($key, $value, $lifetime);
+
+ /**
+ * Driver implementation of the get() method.
+ * If it returns NULL a default value will be applied by get().
+ *
+ * @param string $key Sanitized name of the object to retrieve
+ * @return mixed The requested object or NULL if it is not found.
+ * @see Abstract_Cache::get()
+ * @access public
+ */
+ protected abstract function _get($key);
+
+ /**
+ * Driver implementation of the delete() method
+ *
+ * @param string $key Sanitized name of the object to remove
+ * @see Abstract_Cache::delete()
+ * @access public
+ */
+ protected abstract function _delete($key);
+
+ /**
+ * Driver implementation of the delete_all() method
+ *
+ * @see Abstract_Cache::delete_all()
+ * @access public
+ */
+ protected abstract function _delete_all();
+
+}
\ No newline at end of file diff --git a/modules/cache/classes/cache/apc.php b/modules/cache/classes/cache/apc.php new file mode 100644 index 0000000..7c91d8d --- /dev/null +++ b/modules/cache/classes/cache/apc.php @@ -0,0 +1,26 @@ +<?php
+
+/**
+ * APC cache driver.
+ * @package Cache
+ */
+class Apc_Cache extends Abstract_Cache {
+
+ protected function _set($key, $value, $lifetime) {
+ apc_store($key, $value, $lifetime);
+ }
+
+ protected function _get($key) {
+ $data = apc_fetch($key, $success);
+ if ($success)
+ return $data;
+ }
+
+ protected function _delete_all() {
+ apc_clear_cache('user');
+ }
+
+ protected function _delete($key) {
+ apc_delete($key);
+ }
+}
\ No newline at end of file diff --git a/modules/cache/classes/cache/database.php b/modules/cache/classes/cache/database.php new file mode 100644 index 0000000..aa2be63 --- /dev/null +++ b/modules/cache/classes/cache/database.php @@ -0,0 +1,45 @@ +<?php
+
+/**
+ * Database cache driver.
+ * @package Cache
+ */
+class Database_Cache extends Abstract_Cache {
+
+ protected $_db;
+
+ public function __construct($config) {
+ parent::__construct($config);
+ $this->_db = DB::instance(Config::get("cache.{$config}.connection",'default'));
+ $this->_db->execute("CREATE TABLE IF NOT EXISTS cache (
+ name VARCHAR(255) NOT NULL PRIMARY KEY,
+ value TEXT,
+ expires INT
+ )");
+
+ }
+ protected function _set($key, $value, $lifetime) {
+ $this->_db->execute("REPLACE INTO cache(name,value,expires) values (?, ?, ?)", array(
+ $key,serialize($value),time()+$lifetime
+ ));
+ }
+
+ protected function _get($key) {
+ $this->garbage_collect();
+ $data = $this->_db->execute("SELECT value FROM cache where name = ?", array($key))->get('value');
+ if ($data !== null)
+ return unserialize($data);
+ }
+
+ protected function _delete_all() {
+ $this->_db->execute("DELETE FROM cache");
+ }
+
+ protected function _delete($key) {
+ $this->_db->execute("DELETE FROM cache WHERE name = ?",array($key));
+ }
+
+ public function garbage_collect() {
+ $this->_db->execute("DELETE FROM cache WHERE expires < ?",array(time()));
+ }
+}
\ No newline at end of file diff --git a/modules/cache/classes/cache/file.php b/modules/cache/classes/cache/file.php new file mode 100644 index 0000000..05f536d --- /dev/null +++ b/modules/cache/classes/cache/file.php @@ -0,0 +1,85 @@ +<?php
+class File_Cache extends Abstract_Cache {
+
+ protected $_cache_dir;
+
+ public function __construct($config) {
+ parent::__construct($config);
+ $this->_cache_dir = Config::get("cache.{$config}.cache_dir", ROOTDIR.'/modules/cache/cache/');
+ }
+
+ protected function _set($key, $value, $lifetime) {
+ if (!is_dir($key['dir']))
+ mkdir($key['dir'], true);
+ $expires=time()+$lifetime;
+ file_put_contents($key['dir'].$key['file'],$expires."\n".serialize($value));
+ }
+
+ protected function _get($key) {
+ $file = $key['dir'].$key['file'];
+
+ if (file_exists($file) && $this->check_file($file)) {
+ $data = file_get_contents($file);
+ $data = substr($data, strpos($data, "\n")+1);
+ return unserialize($data);
+ }
+
+ if (is_dir($key['dir']))
+ $this->check_dir($key['dir']);
+ }
+
+ protected function _delete_all() {
+ $dirs = array_diff(scandir($this->_cache_dir), array('.', '..'));
+ foreach($dirs as $dir) {
+ $dir=$this->_cache_dir.'/'.$dir;
+ $files=array_diff(scandir($dir), array('.', '..'));
+ foreach($files as $file)
+ unlink($dir.'/'.$file);
+ rmdir($dir);
+ }
+ }
+
+ protected function _delete($key) {
+ if (file_exists($key['dir'].$key['file']))
+ unlink($key['dir'].$key['file']);
+ if(is_dir($key['dir']))
+ $this->check_dir($key['dir']);
+ }
+
+ public function garbage_collect() {
+ $dirs = array_diff(scandir($this->_cache_dir), array('.', '..'));
+ foreach($dirs as $dir) {
+ $dir=$this->_cache_dir.'/'.$dir;
+ $files=array_diff(scandir($dir), array('.', '..'));
+ foreach($files as $file)
+ $this->check_file($dir.'/'.$file);
+ $this->check_dir($dir);
+ }
+ }
+
+ protected function check_dir($dir) {
+ if (count(scandir($dir)) == 2)
+ rmdir($dir);
+ }
+
+ protected function check_file($file) {
+ $fp = fopen($file, 'r');
+ $expires = fgets($fp);
+ fclose($fp);
+
+ if ($expires < time()){
+ unlink($file);
+ return false;
+ }
+
+ return true;
+ }
+
+ protected function sanitize($key) {
+ $key = md5($key);
+ return array(
+ 'dir' => $this->_cache_dir.'/'.substr($key, 0, 2).'/',
+ 'file' => $key
+ );
+ }
+}
\ No newline at end of file diff --git a/modules/cache/classes/cache/xcache.php b/modules/cache/classes/cache/xcache.php new file mode 100644 index 0000000..a5b6888 --- /dev/null +++ b/modules/cache/classes/cache/xcache.php @@ -0,0 +1,24 @@ +<?php
+
+/**
+ * XCache cache driver.
+ * @package Cache
+ */
+class Xcache_Cache extends Abstract_Cache {
+
+ protected function _set($key, $value, $lifetime) {
+ xcache_set($key, $value, $lifetime);
+ }
+
+ protected function _get($key) {
+ return xcache_get($key);
+ }
+
+ protected function _delete_all() {
+ xcache_clear_cache(XC_TYPE_VAR, -1);
+ }
+
+ protected function _delete($key) {
+ xcache_unset($key);
+ }
+}
\ No newline at end of file diff --git a/modules/cache/config/cache.php b/modules/cache/config/cache.php new file mode 100644 index 0000000..f9e07dc --- /dev/null +++ b/modules/cache/config/cache.php @@ -0,0 +1,6 @@ +<?php
+return array(
+ 'default' => array(
+ 'driver' => 'database'
+ )
+);
\ No newline at end of file diff --git a/modules/database/classes/database/result.php b/modules/database/classes/database/result.php index 8b80ac2..5802a96 100644 --- a/modules/database/classes/database/result.php +++ b/modules/database/classes/database/result.php @@ -28,6 +28,12 @@ abstract class Result_Database implements Iterator { */
protected $_row;
+ /**
+ * If at least one row has been fetched
+ * @var object
+ * @access protected
+ */
+ protected $_fetched = false;
/**
* Returns current row
@@ -36,6 +42,7 @@ abstract class Result_Database implements Iterator { * @access public
*/
public function current() {
+ $this->check_fetched();
return $this->_row;
}
@@ -46,6 +53,7 @@ abstract class Result_Database implements Iterator { * @access public
*/
public function key() {
+ $this->check_fetched();
return $this->_position;
}
@@ -56,6 +64,7 @@ abstract class Result_Database implements Iterator { * @access public
*/
public function valid() {
+ $this->check_fetched();
return $this->_row!=null;
}
@@ -72,4 +81,15 @@ abstract class Result_Database implements Iterator { return $arr;
}
+ public function check_fetched() {
+ if (!$this->_fetched)
+ $this->next();
+ $this->_fetched=true;
+ }
+
+ public function get($column) {
+ if ($this->valid() && isset($this->_row->$column))
+ return $this->_row->$column;
+ }
+
}
\ No newline at end of file diff --git a/modules/database/classes/driver/mysql/result.php b/modules/database/classes/driver/mysql/result.php index f058a97..ccbdfcf 100644 --- a/modules/database/classes/driver/mysql/result.php +++ b/modules/database/classes/driver/mysql/result.php @@ -16,8 +16,6 @@ class Result_Mysql_Driver extends Result_Database { */
public function __construct($result) {
$this->_result = $result;
- if(!empty($result))
- $this->_row=$this->_result->fetch_object();
}
/**
@@ -39,11 +37,11 @@ class Result_Mysql_Driver extends Result_Database { * @access public
*/
public function next() {
-
- $this->_position++;
+ if($this->_fetched)
+ $this->_position++;
$this->_row=$this->_result->fetch_object();
if ($this->_row == null)
- $this->_result->free();
+ $this->_result->free();
}
}
\ No newline at end of file diff --git a/modules/database/classes/driver/pdo/db.php b/modules/database/classes/driver/pdo/db.php index ac15258..8390cf0 100644 --- a/modules/database/classes/driver/pdo/db.php +++ b/modules/database/classes/driver/pdo/db.php @@ -34,6 +34,7 @@ class DB_PDO_Driver extends DB{ Config::get("database.{$config}.user",''),
Config::get("database.{$config}.password",'')
);
+ $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->db_type = strtolower(str_replace('PDO_', '', $this->conn->getAttribute(PDO::ATTR_DRIVER_NAME)));
if($this->db_type!='sqlite')
$this->execute("SET NAMES utf8");
diff --git a/modules/database/classes/driver/pdo/result.php b/modules/database/classes/driver/pdo/result.php index fec0652..943dec7 100644 --- a/modules/database/classes/driver/pdo/result.php +++ b/modules/database/classes/driver/pdo/result.php @@ -16,7 +16,6 @@ class Result_PDO_Driver extends Result_Database { */
public function __construct($stmt) {
$this->_result = $stmt;
- $this->_row=$this->_result->fetchObject();
}
/**
@@ -38,11 +37,11 @@ class Result_PDO_Driver extends Result_Database { * @access public
*/
public function next() {
-
- $this->_position++;
+ if($this->_fetched)
+ $this->_position++;
$this->_row=$this->_result->fetchObject();
if ($this->_row == false)
- $this->_result->closeCursor();
+ $this->_result->closeCursor();
}
}
\ No newline at end of file |