--- /dev/null
+<?php
+// Hoplite
+// Copyright (c) 2013 Blue Static
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program. If not, see <http://www.gnu.org/licenses/>.
+
+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));
+ }
+}
--- /dev/null
+<?php
+// Hoplite
+// Copyright (c) 2013 Blue Static
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation, either version 3 of the License, or any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program. If not, see <http://www.gnu.org/licenses/>.
+
+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,
+ ));
+ }
+}