1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114:
<?php
namespace Apptus\Util\Cache;
class SQLite3StateCache implements StateCache {
private $sqlite;
public static function testSQLite($filename, $key = 'sqlitetest', $value = 'sqlitetest') {
if (!extension_loaded('sqlite3')) {
return 'SQLite3 extension is not loaded.';
}
if ($filename !== ':memory:' && !is_writable(dirname($filename))) {
return 'The directory the database file is in must be writable.';
}
$sc = new SQLite3StateCache($filename);
$sc->set($key, $value, 10);
$result = $sc->get($key);
if ($result !== $value) {
return 'SQLite test failed.';
}
return true;
}
public function __construct($filename) {
$sqlite = new \SQLite3($filename, SQLITE3_OPEN_CREATE | SQLITE3_OPEN_READWRITE);
$sqlite->busyTimeout(86400000);
$sqlite->exec('CREATE TABLE IF NOT EXISTS StateCache (key TEXT PRIMARY KEY NOT NULL, value TEXT, expire INTEGER)');
$sqlite->exec("PRAGMA synchronous = 0;");
$this->sqlite = $sqlite;
}
private function cleanOldEntries() {
@$this->sqlite->query('DELETE FROM StateCache WHERE expire < ' . (ceil(microtime(true))));
}
public function add($key, $value, $expire) {
$this->cleanOldEntries();
$stmt = $this->sqlite->prepare('INSERT OR IGNORE INTO StateCache (key, value, expire) VALUES (:key , :value , :expire )');
$stmt->bindValue(':key', (string) $key);
$stmt->bindValue(':value', (string) $value);
if ($expire <= 0) $expire = 31536000;
$stmt->bindValue(':expire', ceil($expire + microtime(true)));
return ($stmt->execute()) !== false && $this->sqlite->changes() > 0;
}
public function delete($key) {
$stmt = $this->sqlite->prepare('DELETE FROM StateCache WHERE key = :key');
$stmt->bindValue(':key', (string) $key);
return ($stmt->execute()) !== false && $this->sqlite->changes() > 0;
}
public function get($key) {
$stmt = $this->sqlite->prepare('SELECT (value) FROM StateCache WHERE key = :key AND expire >= ' . (ceil(microtime(true))));
$stmt->bindValue(':key', (string) $key);
$result = $stmt->execute();
if ($result === false) return false;
$r = $result->fetchArray(SQLITE3_NUM);
if ($r === false) return false;
return count($r) > 0 ? $r[0] : false;
}
public function getMulti($keys) {
$result = array ();
foreach ($keys as $key) {
$key = (string) $key;
$r = $this->get($key);
if ($r !== false) {
$result[$key] = $r;
}
}
return $result;
}
public function replace($key, $value, $expire) {
$this->cleanOldEntries();
$stmt = $this->sqlite->prepare('UPDATE OR IGNORE StateCache SET value = :value , expire = :expire WHERE key = :key');
$stmt->bindValue(':key', (string) $key);
$stmt->bindValue(':value', (string) $value);
if ($expire <= 0) $expire = 31536000;
$stmt->bindValue(':expire', ceil($expire + microtime(true)));
return ($stmt->execute()) !== false && $this->sqlite->changes() > 0;
}
public function set($key, $value, $expire) {
$stmt = $this->sqlite->prepare('INSERT OR REPLACE INTO StateCache (key, value, expire) VALUES (:key , :value , :expire )');
$stmt->bindValue(':key', (string) $key);
$stmt->bindValue(':value', (string) $value);
if ($expire <= 0) $expire = 31536000;
$stmt->bindValue(':expire', ceil($expire + microtime(true)));
return ($stmt->execute()) !== false;
}
public function setMulti($items, $expire) {
$result = true;
foreach ($items as $key => $value) {
$r = $this->set($key, $value, $expire);
$result = $result && $r;
}
return $result;
}
}