Files
portal-legacy/lib/symfony/cache/sfSQLiteCache.class.php
Chris Sewell cf140a2e97 initial commit
2012-11-28 03:55:08 -05:00

318 lines
8.1 KiB
PHP
Executable File

<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Cache class that stores content in a sqlite database.
*
* @package symfony
* @subpackage cache
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfSQLiteCache.class.php 3935 2007-05-06 10:07:08Z fabien $
*/
class sfSQLiteCache extends sfCache
{
const DEFAULT_NAMESPACE = '';
protected $conn = null;
/**
* File where to put the cache database (or :memory: to store cache in memory)
*/
protected $database = '';
/**
* Disable / Tune the automatic cleaning process
*
* The automatic cleaning process destroy too old (for the given life time)
* cache files when a new cache file is written.
* 0 => no automatic cache cleaning
* 1 => systematic cache cleaning
* x (integer) > 1 => automatic cleaning randomly 1 times on x cache write
*/
protected $automaticCleaningFactor = 500;
/**
* Constructor.
*
* @param string The database name
*/
public function __construct($database = null)
{
if (!extension_loaded('sqlite'))
{
throw new sfConfigurationException('sfSQLiteCache class needs "sqlite" extension');
}
$this->setDatabase($database);
}
/**
* Initializes the cache.
*
* @param array An array of options
* Available options:
* - database: database name
* - automaticCleaningFactor: disable / tune automatic cleaning process (int)
*
*/
public function initialize($options = array())
{
if (isset($options['database']))
{
$this->setDatabase($options['database']);
unset($options['database']);
}
$availableOptions = array('automaticCleaningFactor');
foreach ($options as $key => $value)
{
if (!in_array($key, $availableOptions) && sfConfig::get('sf_logging_enabled'))
{
sfLogger::getInstance()->err(sprintf('sfSQLiteCache cannot take "%s" as an option', $key));
}
$this->$key = $value;
}
}
/**
* Sets the database name.
*
* @param string The database name where to store the cache
*/
public function setDatabase($database)
{
if (!$database)
{
return;
}
$this->database = $database;
$new = false;
if (':memory:' == $database)
{
$new = true;
}
elseif (!is_file($database))
{
$new = true;
// create cache dir if needed
$dir = dirname($database);
$current_umask = umask(0000);
if (!is_dir($dir))
{
@mkdir($dir, 0777, true);
}
touch($database);
umask($current_umask);
}
if (!($this->conn = @sqlite_open($this->database, 0644, $errmsg)))
{
throw new sfException(sprintf("Unable to connect to SQLite database: %s", $errmsg));
}
if ($new)
{
$this->createSchema();
}
}
/**
* Creates the database schema.
*
* @throws sfException
*/
protected function createSchema()
{
$statements = array(
"CREATE TABLE [cache] (
[id] VARCHAR(255),
[namespace] VARCHAR(255),
[data] LONGVARCHAR,
[created_at] TIMESTAMP
)",
"CREATE UNIQUE INDEX [cache_unique] ON [cache] ([namespace], [id])",
);
foreach ($statements as $statement)
{
if (!sqlite_query($statement, $this->conn))
{
throw new sfException(sqlite_error_string(sqlite_last_error($this->database)));
}
}
}
/**
* Destructor.
*/
public function __destruct()
{
sqlite_close($this->conn);
}
/**
* Gets the database name.
*
* @return string The database name
*/
public function getDatabase()
{
return $this->database;
}
/**
* Tests if a cache is available and (if yes) returns it.
*
* @param string The cache id
* @param string The name of the cache namespace
* @param boolean If set to true, the cache validity won't be tested
*
* @return string The data in the cache (or null if no cache available)
*
* @see sfCache
*/
public function get($id, $namespace = self::DEFAULT_NAMESPACE, $doNotTestCacheValidity = false)
{
$statement = sprintf("SELECT data FROM cache WHERE id = '%s' AND namespace = '%s'", sqlite_escape_string($id), sqlite_escape_string($namespace));
if (!$doNotTestCacheValidity)
{
$statement .= sprintf(" AND created_at > '%s'", sqlite_escape_string($this->refreshTime));
}
$rs = sqlite_query($statement, $this->conn);
return sqlite_num_rows($rs) ? sqlite_fetch_single($rs) : null;
}
/**
* Returns true if there is a cache for the given id and namespace.
*
* @param string The cache id
* @param string The name of the cache namespace
* @param boolean If set to true, the cache validity won't be tested
*
* @return boolean true if the cache exists, false otherwise
*
* @see sfCache
*/
public function has($id, $namespace = self::DEFAULT_NAMESPACE, $doNotTestCacheValidity = false)
{
$statement = sprintf("SELECT id FROM cache WHERE id = '%s' AND namespace = '%s'", sqlite_escape_string($id), sqlite_escape_string($namespace));
if (!$doNotTestCacheValidity)
{
$statement .= sprintf(" AND created_at > '%s'", sqlite_escape_string($this->refreshTime));
}
return sqlite_num_rows(sqlite_query($statement, $this->conn)) ? true : false;
}
/**
* Saves some data in the cache.
*
* @param string The cache id
* @param string The name of the cache namespace
* @param string The data to put in cache
*
* @return boolean true if no problem
*
* @see sfCache
*/
public function set($id, $namespace = self::DEFAULT_NAMESPACE, $data)
{
if ($this->automaticCleaningFactor > 0)
{
$rand = rand(1, $this->automaticCleaningFactor);
if ($rand == 1)
{
$this->clean(false, 'old');
}
}
if (!$this->has($id, $namespace, true))
{
$statement = sprintf("INSERT INTO cache (id, namespace, data, created_at) VALUES ('%s', '%s', '%s', %d)", sqlite_escape_string($id), sqlite_escape_string($namespace), sqlite_escape_string($data), time());
}
else
{
$statement = sprintf("UPDATE cache SET data = '%s', created_at = %s WHERE id = '%s' AND namespace = '%s'", sqlite_escape_string($data), time(), sqlite_escape_string($id), sqlite_escape_string($namespace));
}
if (sqlite_query($statement, $this->conn))
{
return true;
}
return false;
}
/**
* Removes an element from the cache.
*
* @param string The cache id
* @param string The name of the cache namespace
*
* @return boolean true if no problem
*
* @see sfCache
*/
public function remove($id, $namespace = self::DEFAULT_NAMESPACE)
{
$statement = sprintf("DELETE FROM cache WHERE id = '%s' AND namespace = '%s'", sqlite_escape_string($id), sqlite_escape_string($namespace));
if (sqlite_query($statement, $this->conn))
{
return true;
}
return false;
}
/**
* Cleans the cache.
*
* If no namespace is specified all cache files will be destroyed
* else only cache files of the specified namespace will be destroyed.
*
* @param string The name of the cache namespace
*
* @return boolean true if no problem
*/
public function clean($namespace = null, $mode = 'all')
{
if (!$namespace)
{
$statement = "DELETE FROM cache";
}
else
{
$statement = sprintf("DELETE FROM cache WHERE namespace LIKE '%s%%'", $namespace);
}
if ('old' == $mode)
{
$statement .= sprintf(" %s created_at < '%s'", $namespace ? 'AND' : 'WHERE', sqlite_escape_string($this->refreshTime));
}
return sqlite_num_rows(sqlite_query($statement, $this->conn)) ? true : false;
}
public function lastModified($id, $namespace = self::DEFAULT_NAMESPACE)
{
$statement = sprintf("SELECT created_at FROM cache WHERE id = '%s' AND namespace = '%s'", sqlite_escape_string($id), sqlite_escape_string($namespace));
$rs = sqlite_query($statement, $this->conn);
return sqlite_num_rows($rs) ? intval(sqlite_fetch_single($rs)) : 0;
}
}