mirror of
https://github.com/atlanticbiomedical/portal-legacy.git
synced 2025-07-02 01:47:28 -04:00
318 lines
8.1 KiB
PHP
318 lines
8.1 KiB
PHP
![]() |
<?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;
|
||
|
}
|
||
|
}
|