1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Caching;
13:
14: use Nette;
15:
16:
17:
18: 19: 20: 21: 22:
23: class SqliteJournal extends Nette\Object implements ICacheJournal
24: {
25:
26: private $database;
27:
28:
29:
30: 31: 32: 33:
34: public static function isAvailable()
35: {
36: return extension_loaded('sqlite'); 37: }
38:
39:
40:
41: public function __construct($file)
42: {
43: if (!self::isAvailable()) {
44: throw new \NotSupportedException("SQLite or SQLite3 extension is required for storing tags and priorities.");
45: }
46:
47: $this->database = extension_loaded('sqlite') ? new SQLiteMimic($file) : new \SQLite3($file);
48: @$this->database->exec( 49: 'CREATE TABLE cache (entry VARCHAR NOT NULL, priority INTEGER, tag VARCHAR); '
50: . 'CREATE INDEX IDX_ENTRY ON cache (entry); '
51: . 'CREATE INDEX IDX_PRI ON cache (priority); '
52: . 'CREATE INDEX IDX_TAG ON cache (tag);'
53: );
54: }
55:
56:
57:
58: 59: 60: 61: 62: 63:
64: public function write($key, array $dependencies)
65: {
66: $entry = $this->database->escapeString($key);
67: $query = '';
68: if (!empty($dependencies[Cache::TAGS])) {
69: foreach ((array) $dependencies[Cache::TAGS] as $tag) {
70: $query .= "INSERT INTO cache (entry, tag) VALUES ('$entry', '" . $this->database->escapeString($tag) . "'); ";
71: }
72: }
73: if (!empty($dependencies[Cache::PRIORITY])) {
74: $query .= "INSERT INTO cache (entry, priority) VALUES ('$entry', '" . ((int) $dependencies[Cache::PRIORITY]) . "'); ";
75: }
76:
77: if (!$this->database->exec("BEGIN; DELETE FROM cache WHERE entry = '$entry'; $query COMMIT;")) {
78: $this->database->exec('ROLLBACK');
79: return FALSE;
80: }
81:
82: return TRUE;
83: }
84:
85:
86:
87: 88: 89: 90: 91:
92: public function clean(array $conditions)
93: {
94: if (!empty($conditions[Cache::ALL])) {
95: $this->database->exec('DELETE FROM CACHE;');
96: return;
97: }
98:
99: $query = array();
100: if (!empty($conditions[Cache::TAGS])) {
101: $tags = array();
102: foreach ((array) $conditions[Cache::TAGS] as $tag) {
103: $tags[] = "'" . $this->database->escapeString($tag) . "'";
104: }
105: $query[] = 'tag IN(' . implode(', ', $tags) . ')';
106: }
107:
108: if (isset($conditions[Cache::PRIORITY])) {
109: $query[] = 'priority <= ' . ((int) $conditions[Cache::PRIORITY]);
110: }
111:
112: $entries = array();
113: if (!empty($query)) {
114: $query = implode(' OR ', $query);
115: $result = $this->database->query("SELECT entry FROM cache WHERE $query");
116: if ($result instanceof \SQLiteResult) {
117: while ($entry = $result->fetchSingle()) $entries[] = $entry;
118: } else {
119: while ($entry = $result->fetchArray(SQLITE3_NUM)) $entries[] = $entry[0];
120: }
121: $this->database->exec("DELETE FROM cache WHERE $query");
122: }
123: return $entries;
124: }
125:
126: }
127:
128:
129:
130: if (class_exists('SQLiteDatabase')) {
131: 132: 133: 134: 135: 136:
137: class SQLiteMimic extends \SQLiteDatabase
138: {
139:
140: function exec($sql)
141: {
142: return $this->queryExec($sql);
143: }
144:
145: function escapeString($s)
146: {
147: return sqlite_escape_string($s);
148: }
149:
150: }
151: }
152: