sfSQLiteCache.class.php 5.6 KB

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