1. sfSQLiteCache.class.php
  2. /** * Cache class that stores cached content in a SQLite database. * * @package symfony * @subpackage cache * @author Fabien Potencier * @version SVN: $Id: sfSQLiteCache.class.php 23501 2009-11-01 22:54:37Z FabianLange $ */
  3. class sfSQLiteCache extends sfCache
  4. {
  5. protected
  6. $dbh = null,
  7. $database = '';
  8. /**
  9. * Initializes this sfCache instance.
  10. *
  11. * Available options:
  12. *
  13. * * database: File where to put the cache database (or :memory: to store cache in memory)
  14. *
  15. * * see sfCache for options available for all drivers
  16. *
  17. * @see sfCache
  18. */
  19. public function initialize($options = array())
  20. {
  21. if (!extension_loaded('SQLite') && !extension_loaded('pdo_SQLite'))
  22. {
  23. throw new sfConfigurationException('sfSQLiteCache class needs "sqlite" or "pdo_sqlite" extension to be loaded.');
  24. }
  25. parent::initialize($options);
  26. if (!$this->getOption('database'))
  27. {
  28. throw new sfInitializationException('You must pass a "database" option to initialize a sfSQLiteCache object.');
  29. }
  30. $this->setDatabase($this->getOption('database'));
  31. }
  32. /**
  33. * @see sfCache
  34. */
  35. public function getBackend()
  36. {
  37. return $this->dbh;
  38. }
  39. /**
  40. * @see sfCache
  41. */
  42. public function get($key, $default = null)
  43. {
  44. $data = $this->dbh->singleQuery(sprintf("SELECT data FROM cache WHERE key = '%s' AND timeout > %d", sqlite_escape_string($key), time()));
  45. return null === $data ? $default : $data;
  46. }
  47. /**
  48. * @see sfCache
  49. */
  50. public function has($key)
  51. {
  52. return (boolean) $this->dbh->query(sprintf("SELECT key FROM cache WHERE key = '%s' AND timeout > %d", sqlite_escape_string($key), time()))->numRows();
  53. }
  54. /**
  55. * @see sfCache
  56. */
  57. public function set($key, $data, $lifetime = null)
  58. {
  59. if ($this->getOption('automatic_cleaning_factor') > 0 && rand(1, $this->getOption('automatic_cleaning_factor')) == 1)
  60. {
  61. $this->clean(sfCache::OLD);
  62. }
  63. return (boolean) $this->dbh->query(sprintf("INSERT OR REPLACE INTO cache (key, data, timeout, last_modified) VALUES ('%s', '%s', %d, %d)", sqlite_escape_string($key), sqlite_escape_string($data), time() + $this->getLifetime($lifetime), time()));
  64. }
  65. /**
  66. * @see sfCache
  67. */
  68. public function remove($key)
  69. {
  70. return (boolean) $this->dbh->query(sprintf("DELETE FROM cache WHERE key = '%s'", sqlite_escape_string($key)));
  71. }
  72. /**
  73. * @see sfCache
  74. */
  75. public function removePattern($pattern)
  76. {
  77. return (boolean) $this->dbh->query(sprintf("DELETE FROM cache WHERE REGEXP('%s', key)", sqlite_escape_string(self::patternToRegexp($pattern))));
  78. }
  79. /**
  80. * @see sfCache
  81. */
  82. public function clean($mode = sfCache::ALL)
  83. {
  84. return (boolean) $this->dbh->query("DELETE FROM cache".(sfCache::OLD == $mode ? sprintf(" WHERE timeout < '%s'", time()) : ''))->numRows();
  85. }
  86. /**
  87. * @see sfCache
  88. */
  89. public function getTimeout($key)
  90. {
  91. $rs = $this->dbh->query(sprintf("SELECT timeout FROM cache WHERE key = '%s' AND timeout > %d", sqlite_escape_string($key), time()));
  92. return $rs->numRows() ? intval($rs->fetchSingle()) : 0;
  93. }
  94. /**
  95. * @see sfCache
  96. */
  97. public function getLastModified($key)
  98. {
  99. $rs = $this->dbh->query(sprintf("SELECT last_modified FROM cache WHERE key = '%s' AND timeout > %d", sqlite_escape_string($key), time()));
  100. return $rs->numRows() ? intval($rs->fetchSingle()) : 0;
  101. }
  102. /**
  103. * Sets the database name.
  104. *
  105. * @param string $database The database name where to store the cache
  106. */
  107. protected function setDatabase($database)
  108. {
  109. $this->database = $database;
  110. $new = false;
  111. if (':memory:' == $database)
  112. {
  113. $new = true;
  114. }
  115. else if (!is_file($database))
  116. {
  117. $new = true;
  118. // create cache dir if needed
  119. $dir = dirname($database);
  120. $current_umask = umask(0000);
  121. if (!is_dir($dir))
  122. {
  123. @mkdir($dir, 0777, true);
  124. }
  125. touch($database);
  126. umask($current_umask);
  127. }
  128. if (!$this->dbh = new SQLiteDatabase($this->database, 0644, $errmsg))
  129. {
  130. throw new sfCacheException(sprintf('Unable to connect to SQLite database: %s.', $errmsg));
  131. }
  132. $this->dbh->createFunction('regexp', array($this, 'removePatternRegexpCallback'), 2);
  133. if ($new)
  134. {
  135. $this->createSchema();
  136. }
  137. }
  138. /**
  139. * Callback used when deleting keys from cache.
  140. */
  141. public function removePatternRegexpCallback($regexp, $key)
  142. {
  143. return preg_match($regexp, $key);
  144. }
  145. /**
  146. * @see sfCache
  147. */
  148. public function getMany($keys)
  149. {
  150. $rows = $this->dbh->arrayQuery(sprintf("SELECT key, data FROM cache WHERE key IN ('%s') AND timeout > %d", implode('\', \'', array_map('sqlite_escape_string', $keys)), time()));
  151. $data = array();
  152. foreach ($rows as $row)
  153. {
  154. $data[$row['key']] = $row['data'];
  155. }
  156. return $data;
  157. }
  158. /**
  159. * Creates the database schema.
  160. *
  161. * @throws sfCacheException
  162. */
  163. protected function createSchema()
  164. {
  165. $statements = array(
  166. 'CREATE TABLE [cache] (
  167. [key] VARCHAR(255),
  168. [data] LONGVARCHAR,
  169. [timeout] TIMESTAMP,
  170. [last_modified] TIMESTAMP
  171. )',
  172. 'CREATE UNIQUE INDEX [cache_unique] ON [cache] ([key])',
  173. );
  174. foreach ($statements as $statement)
  175. {
  176. if (!$this->dbh->query($statement))
  177. {
  178. throw new sfCacheException(sqlite_error_string($this->dbh->lastError()));
  179. }
  180. }
  181. }
  182. }

Debug toolbar