From 35564ea016b3eea5b85dcaec1e398b18ac6ec3ea Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Mon, 3 Jun 2013 21:54:00 -0400 Subject: [PATCH] Write a CacheBackend implementation for PDO. --- .../tests/views/pdo_cache_backend_test.php | 69 +++++++++++++ views/pdo_cache_backend.php | 96 +++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 testing/tests/views/pdo_cache_backend_test.php create mode 100644 views/pdo_cache_backend.php diff --git a/testing/tests/views/pdo_cache_backend_test.php b/testing/tests/views/pdo_cache_backend_test.php new file mode 100644 index 0000000..699a4d4 --- /dev/null +++ b/testing/tests/views/pdo_cache_backend_test.php @@ -0,0 +1,69 @@ +. + +namespace hoplite\test; +use hoplite\views as views; + +require_once HOPLITE_ROOT . '/views/pdo_cache_backend.php'; + +class PDOCacheBackendTest extends \PHPUnit_Framework_TestCase +{ + private $db; + private $cache; + + public function setUp() + { + $this->db = new \PDO('sqlite::memory:'); + $this->db->Exec(" + CREATE TABLE test_template_cache ( + filename string PRIMARY KEY, + data string, + mtime int + ); + "); + + $this->cache = new views\PDOCacheBackend( + $this->db, 'test_template_cache', 'filename', 'data', 'mtime'); + } + + private function _GetCount() + { + $stmt = $this->db->Query("SELECT COUNT(*) AS count FROM test_template_cache"); + return $stmt->FetchObject()->count; + } + + public function testCacheMiss() + { + $this->assertNull($this->cache->GetTemplateDataForName('test', 100)); + $this->db->Exec("INSERT INTO test_template_cache (filename, data, mtime) VALUES ('test', 'hello world', 100)"); + $this->assertEquals('hello world', $this->cache->GetTemplateDataForName('test', 100)); + $this->assertEquals(1, $this->_GetCount()); + + $this->assertNull($this->cache->GetTemplateDataForName('test', 200)); + $this->assertEquals(0, $this->_GetCount()); + } + + public function testCacheStore() + { + $this->cache->StoreCompiledTemplate('name', 400, 'abcdefgh'); + $this->assertEquals(1, $this->_GetCount()); + + $this->assertEquals('abcdefgh', $this->cache->GetTemplateDataForName('name', 400)); + $this->assertEquals(1, $this->_GetCount()); + + $this->assertNull($this->cache->GetTemplateDataForName('name', 500)); + } +} diff --git a/views/pdo_cache_backend.php b/views/pdo_cache_backend.php new file mode 100644 index 0000000..da3f093 --- /dev/null +++ b/views/pdo_cache_backend.php @@ -0,0 +1,96 @@ +. + +namespace hoplite\views; + +require_once HOPLITE_ROOT . '/views/cache_backend.php'; + +/*! + An instance of CacheBackend that stores compiled templates in a database + table accessed through a PDO object. +*/ +class PDOCacheBackend implements CacheBackend +{ + /*! @var \PDOStatement Used to query for cached templates. */ + protected $fetch_statement = NULL; + + /*! @var \PDOStatement Used to insert new templates. */ + protected $insert_statement = NULL; + + /*! @var \PDOStatement Used to expire out-of-date templates. */ + protected $delete_statement = NULL; + + /*! + Constructor that prepares the database statements. + + @param \PDO The connected database object. + @param string Name of the database table to store templates in. + @param string Column in which the template name is stored. + @param string Column in which the template data is stored. + @param string Column in which the template last modified time is stored. + */ + public function __construct(\PDO $db, + $table_name, + $name_column_name = 'name', + $data_column_name = 'template', + $timestamp_column_name = 'timestamp') + { + $this->fetch_statement = $db->Prepare(" + SELECT `$data_column_name` AS template, + `$timestamp_column_name` AS timestamp + FROM $table_name + WHERE `$name_column_name` IN (:name) + "); + + $this->insert_statement = $db->Prepare(" + INSERT INTO `$table_name` + (`$name_column_name`, `$data_column_name`, `$timestamp_column_name`) + VALUES + (:name, :template, :timestamp) + "); + + $this->delete_statement = $db->Prepare(" + DELETE FROM `$table_name` + WHERE `$name_column_name` = :name + "); + } + + public function GetTemplateDataForName($name, $modification_time) + { + if (!$this->fetch_statement->Execute(array('name' => $name))) + return NULL; + + $tpl = $this->fetch_statement->FetchObject(); + if (!$tpl) + return NULL; + + if ($tpl->timestamp < $modification_time) { + $this->delete_statement->Execute(array('name' => $name)); + return NULL; + } + + return $tpl->template; + } + + public function StoreCompiledTemplate($name, $modification_time, $data) + { + $this->insert_statement->Execute(array( + 'name' => $name, + 'timestamp' => $modification_time, + 'template' => $data, + )); + } +} -- 2.22.5