Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php/*** PDO Cache Handler* Allows you to store Smarty Cache files into your db.* Example table :* CREATE TABLE `smarty_cache` (* `id` char(40) NOT NULL COMMENT 'sha1 hash',* `name` varchar(250) NOT NULL,* `cache_id` varchar(250) DEFAULT NULL,* `compile_id` varchar(250) DEFAULT NULL,* `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,* `expire` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',* `content` mediumblob NOT NULL,* PRIMARY KEY (`id`),* KEY `name` (`name`),* KEY `cache_id` (`cache_id`),* KEY `compile_id` (`compile_id`),* KEY `modified` (`modified`),* KEY `expire` (`expire`)* ) ENGINE=InnoDB* Example usage :* $cnx = new PDO("mysql:host=localhost;dbname=mydb", "username", "password");* $smarty->setCachingType('pdo');* $smarty->loadPlugin('Smarty_CacheResource_Pdo');* $smarty->registerCacheResource('pdo', new Smarty_CacheResource_Pdo($cnx, 'smarty_cache'));** @author Beno!t POLASZEK - 2014*/class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom{/*** @var string[]*/protected $fetchStatements = array('default' => 'SELECT %2$sFROM %1$sWHERE 1AND id = :idAND cache_id IS NULLAND compile_id IS NULL','withCacheId' => 'SELECT %2$sFROM %1$sWHERE 1AND id = :idAND cache_id = :cache_idAND compile_id IS NULL','withCompileId' => 'SELECT %2$sFROM %1$sWHERE 1AND id = :idAND compile_id = :compile_idAND cache_id IS NULL','withCacheIdAndCompileId' => 'SELECT %2$sFROM %1$sWHERE 1AND id = :idAND cache_id = :cache_idAND compile_id = :compile_id');/*** @var string*/protected $insertStatement = 'INSERT INTO %sSET id = :id,name = :name,cache_id = :cache_id,compile_id = :compile_id,modified = CURRENT_TIMESTAMP,expire = DATE_ADD(CURRENT_TIMESTAMP, INTERVAL :expire SECOND),content = :contentON DUPLICATE KEY UPDATEname = :name,cache_id = :cache_id,compile_id = :compile_id,modified = CURRENT_TIMESTAMP,expire = DATE_ADD(CURRENT_TIMESTAMP, INTERVAL :expire SECOND),content = :content';/*** @var string*/protected $deleteStatement = 'DELETE FROM %1$s WHERE %2$s';/*** @var string*/protected $truncateStatement = 'TRUNCATE TABLE %s';/*** @var string*/protected $fetchColumns = 'modified, content';/*** @var string*/protected $fetchTimestampColumns = 'modified';/*** @var \PDO*/protected $pdo;/*** @var*/protected $table;/*** @var null*/protected $database;/*** Constructor** @param PDO $pdo PDO : active connection* @param string $table : table (or view) name* @param string $database : optional - if table is located in another db** @throws \SmartyException*/public function __construct(PDO $pdo, $table, $database = null){if (is_null($table)) {throw new SmartyException("Table name for caching can't be null");}$this->pdo = $pdo;$this->table = $table;$this->database = $database;$this->fillStatementsWithTableName();}/*** Fills the table name into the statements.** @return $this Current Instance* @access protected*/protected function fillStatementsWithTableName(){foreach ($this->fetchStatements as &$statement) {$statement = sprintf($statement, $this->getTableName(), '%s');}$this->insertStatement = sprintf($this->insertStatement, $this->getTableName());$this->deleteStatement = sprintf($this->deleteStatement, $this->getTableName(), '%s');$this->truncateStatement = sprintf($this->truncateStatement, $this->getTableName());return $this;}/*** Gets the fetch statement, depending on what you specify** @param string $columns : the column(s) name(s) you want to retrieve from the database* @param string $id unique cache content identifier* @param string|null $cache_id cache id* @param string|null $compile_id compile id** @access protected* @return \PDOStatement*/protected function getFetchStatement($columns, $id, $cache_id = null, $compile_id = null){$args = array();if (!is_null($cache_id) && !is_null($compile_id)) {$query = $this->fetchStatements[ 'withCacheIdAndCompileId' ] and$args = array('id' => $id, 'cache_id' => $cache_id, 'compile_id' => $compile_id);} elseif (is_null($cache_id) && !is_null($compile_id)) {$query = $this->fetchStatements[ 'withCompileId' ] and$args = array('id' => $id, 'compile_id' => $compile_id);} elseif (!is_null($cache_id) && is_null($compile_id)) {$query = $this->fetchStatements[ 'withCacheId' ] and $args = array('id' => $id, 'cache_id' => $cache_id);} else {$query = $this->fetchStatements[ 'default' ] and $args = array('id' => $id);}$query = sprintf($query, $columns);$stmt = $this->pdo->prepare($query);foreach ($args as $key => $value) {$stmt->bindValue($key, $value);}return $stmt;}/*** fetch cached content and its modification time from data source** @param string $id unique cache content identifier* @param string $name template name* @param string|null $cache_id cache id* @param string|null $compile_id compile id* @param string $content cached content* @param integer $mtime cache modification timestamp (epoch)** @return void* @access protected*/protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime){$stmt = $this->getFetchStatement($this->fetchColumns, $id, $cache_id, $compile_id);$stmt->execute();$row = $stmt->fetch();$stmt->closeCursor();if ($row) {$content = $this->outputContent($row[ 'content' ]);$mtime = strtotime($row[ 'modified' ]);} else {$content = null;$mtime = null;}}/*** Fetch cached content's modification timestamp from data source* {@internal implementing this method is optional.* Only implement it if modification times can be accessed faster than loading the complete cached content.}}** @param string $id unique cache content identifier* @param string $name template name* @param string|null $cache_id cache id* @param string|null $compile_id compile id** @return integer|boolean timestamp (epoch) the template was modified, or false if not found* @access protected*/// protected function fetchTimestamp($id, $name, $cache_id = null, $compile_id = null) {// $stmt = $this->getFetchStatement($this->fetchTimestampColumns, $id, $cache_id, $compile_id);// $stmt -> execute();// $mtime = strtotime($stmt->fetchColumn());// $stmt -> closeCursor();// return $mtime;// }/*** Save content to cache** @param string $id unique cache content identifier* @param string $name template name* @param string|null $cache_id cache id* @param string|null $compile_id compile id* @param integer|null $exp_time seconds till expiration time in seconds or null* @param string $content content to cache** @return boolean success* @access protected*/protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content){$stmt = $this->pdo->prepare($this->insertStatement);$stmt->bindValue('id', $id);$stmt->bindValue('name', $name);$stmt->bindValue('cache_id', $cache_id, (is_null($cache_id)) ? PDO::PARAM_NULL : PDO::PARAM_STR);$stmt->bindValue('compile_id', $compile_id, (is_null($compile_id)) ? PDO::PARAM_NULL : PDO::PARAM_STR);$stmt->bindValue('expire', (int)$exp_time, PDO::PARAM_INT);$stmt->bindValue('content', $this->inputContent($content));$stmt->execute();return !!$stmt->rowCount();}/*** Encodes the content before saving to database** @param string $content** @return string $content* @access protected*/protected function inputContent($content){return $content;}/*** Decodes the content before saving to database** @param string $content** @return string $content* @access protected*/protected function outputContent($content){return $content;}/*** Delete content from cache** @param string|null $name template name* @param string|null $cache_id cache id* @param string|null $compile_id compile id* @param integer|null|-1 $exp_time seconds till expiration or null** @return integer number of deleted caches* @access protected*/protected function delete($name = null, $cache_id = null, $compile_id = null, $exp_time = null){// delete the whole cacheif ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) {// returning the number of deleted caches would require a second query to count them$this->pdo->query($this->truncateStatement);return -1;}// build the filter$where = array();// equal test nameif ($name !== null) {$where[] = 'name = ' . $this->pdo->quote($name);}// equal test cache_id and match sub-groupsif ($cache_id !== null) {$where[] ='(cache_id = ' .$this->pdo->quote($cache_id) .' OR cache_id LIKE ' .$this->pdo->quote($cache_id . '|%') .')';}// equal test compile_idif ($compile_id !== null) {$where[] = 'compile_id = ' . $this->pdo->quote($compile_id);}// for clearing expired cachesif ($exp_time === Smarty::CLEAR_EXPIRED) {$where[] = 'expire < CURRENT_TIMESTAMP';} // range test expiration timeelseif ($exp_time !== null) {$where[] = 'modified < DATE_SUB(NOW(), INTERVAL ' . intval($exp_time) . ' SECOND)';}// run delete query$query = $this->pdo->query(sprintf($this->deleteStatement, join(' AND ', $where)));return $query->rowCount();}/*** Gets the formatted table name** @return string* @access protected*/protected function getTableName(){return (is_null($this->database)) ? "`{$this->table}`" : "`{$this->database}`.`{$this->table}`";}}