PageRenderTime 50ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/sapphire/cache/Cache.php

https://github.com/benbruscella/vpcounselling.com
PHP | 198 lines | 51 code | 19 blank | 128 comment | 12 complexity | 984a1671b3c27fb40f9a1bc176d1a3cb MD5 | raw file
  1. <?php
  2. /**
  3. * SS_Cache provides a bunch of static functions wrapping the Zend_Cache system in something a little more
  4. * easy to use with the SilverStripe config system.
  5. *
  6. * A Zend_Cache has both a frontend (determines how to get the value to cache, and how to serialize it for storage)
  7. * and a backend (handles the actual storage).
  8. *
  9. * Rather than require library code to specify the backend directly, cache consumers provide a name for the cache
  10. * backend they want. The end developer can then specify which backend to use for each name in their project's
  11. * _config.php. They can also use 'all' to provide a backend for all named caches
  12. *
  13. * End developers provide a set of named backends, then pick the specific backend for each named cache. There is a
  14. * default File cache set up as the 'default' named backend, which is assigned to 'all' named caches
  15. *
  16. * USING A CACHE
  17. *
  18. * $cache = SS_Cache::factory('foo') ; // foo is any name (try to be specific), and is used to get configuration & storage info
  19. *
  20. * if (!($result = $cache->load($cachekey))) {
  21. * $result = caluate some how;
  22. * $cache->save($result);
  23. * }
  24. *
  25. * return $result;
  26. *
  27. * Normally there's no need to remove things from the cache - the cache backends clear out entries based on age & maximum
  28. * allocated storage. If you include the version of the object in the cache key, even object changes don't need any invalidation
  29. *
  30. * DISABLING CACHING IN DEV MOVE
  31. *
  32. * (in _config.php)
  33. *
  34. * if (Director::isDev()) SS_Cache::set_cache_lifetime('any', -1, 100);
  35. *
  36. * USING MEMCACHED AS STORE
  37. *
  38. * (in _config.php)
  39. *
  40. * SS_Cache::add_backend('primary_memcached', 'Memcached',
  41. * array('host' => 'localhost', 'port' => 11211, 'persistent' => true, 'weight' => 1, 'timeout' => 5, 'retry_interval' => 15, 'status' => true, 'failure_callback' => '' )
  42. * );
  43. *
  44. * SS_Cache::pick_backend('primary_memcached', 'any', 10);
  45. * SS_Cache::pick_backend('default', 'aggregate', 20); // Aggregate needs a backend with tag support, which memcached doesn't provide
  46. *
  47. * USING APC AND FILE AS TWO LEVEL STORE
  48. *
  49. * (in _config.php)
  50. *
  51. * SS_Cache::add_backend('two-level', 'TwoLevels' array(
  52. * 'slow_backend' => 'File',
  53. * 'fast_backend' => 'Apc',
  54. * 'slow_backend_options' => array('cache_dir' => TEMP_FOLDER . DIRECTORY_SEPARATOR . 'cache')
  55. * ));
  56. *
  57. * SS_Cache::pick_backend('two-level', 'any', 10); // No need for special backend for aggregate - TwoLevels with a File slow backend supports tags
  58. *
  59. * @author hfried
  60. * @package sapphire
  61. * @subpackage core
  62. */
  63. class SS_Cache {
  64. protected static $backends = array();
  65. protected static $backend_picks = array();
  66. protected static $cache_lifetime = array();
  67. /**
  68. * Initialize the 'default' named cache backend
  69. */
  70. protected static function init(){
  71. if (!isset(self::$backends['default'])) {
  72. $cachedir = TEMP_FOLDER . DIRECTORY_SEPARATOR . 'cache';
  73. if (!is_dir($cachedir)) mkdir($cachedir);
  74. self::$backends['default'] = array('File', array('cache_dir' => TEMP_FOLDER . DIRECTORY_SEPARATOR . 'cache'));
  75. }
  76. }
  77. /**
  78. * Add a new named cache backend
  79. *
  80. * @param string $name The name of this backend as a freeform string
  81. * @param string $type The Zend_Cache backend ('File' or 'Sqlite' or ...)
  82. * @param array $options The Zend_Cache backend options (see http://framework.zend.com/manual/en/zend.cache.html)
  83. * @return none
  84. */
  85. static function add_backend($name, $type, $options=array()) {
  86. self::init();
  87. self::$backends[$name] = array($type, $options);
  88. }
  89. /**
  90. * Pick a named cache backend for a particular named cache
  91. *
  92. * @param string $name The name of the backend, as passed as the first argument to add_backend
  93. * @param string $for The name of the cache to pick this backend for (or 'any' for any backend)
  94. * @param integer $priority The priority of this pick - the call with the highest number will be the actual backend picked.
  95. * A backend picked for a specific cache name will always be used instead of 'any' if it exists, no matter the priority.
  96. * @return none
  97. */
  98. static function pick_backend($name, $for, $priority=1) {
  99. self::init();
  100. $current = -1;
  101. if (isset(self::$backend_picks[$for])) $current = self::$backend_picks[$for]['priority'];
  102. if ($priority >= $current) self::$backend_picks[$for] = array('name' => $name, 'priority' => $priority);
  103. }
  104. /**
  105. * Set the cache lifetime for a particular named cache
  106. *
  107. * @param string $for The name of the cache to set this lifetime for (or 'any' for all backends)
  108. * @param integer $lifetime The lifetime of an item of the cache, in seconds, or -1 to disable caching
  109. * @param integer $priority The priority. The highest priority setting is used. Unlike backends, 'any' is not special in terms of priority.
  110. */
  111. static function set_cache_lifetime($for, $lifetime=600, $priority=1) {
  112. self::init();
  113. $current = -1;
  114. if (isset(self::$cache_lifetime[$for])) $current = self::$cache_lifetime[$for]['priority'];
  115. if ($priority >= $current) self::$cache_lifetime[$for] = array('lifetime' => $lifetime, 'priority' => $priority);
  116. }
  117. /**
  118. * Build a cache object
  119. * @param string $for The name of the cache to build the cache object for
  120. * @param string $frontend (optional) The type of Zend_Cache frontend to use. Output is almost always the best
  121. * @param array $frontendOptions (optional) Any frontend options to use.
  122. *
  123. * @return The cache object. It has been partitioned so that actions on the object
  124. * won't affect cache objects generated with a different $for value, even those using the same Zend_Backend
  125. *
  126. * -- Cache a calculation
  127. *
  128. * if (!($result = $cache->load($cachekey))) {
  129. * $result = caluate some how;
  130. * $cache->save($result);
  131. * }
  132. *
  133. * return $result;
  134. *
  135. * -- Cache captured output
  136. *
  137. * if (!($cache->start($cachekey))) {
  138. *
  139. * // output everything as usual
  140. * echo 'Hello world! ';
  141. * echo 'This is cached ('.time().') ';
  142. *
  143. * $cache->end(); // output buffering ends
  144. * }
  145. *
  146. * -- Invalidate an element
  147. *
  148. * $cache->remove($cachekey);
  149. *
  150. * -- Clear the cache (warning - this clears the entire backend, not just this named cache partition)
  151. *
  152. * $cache->clean(Zend_Cache::CLEANING_MODE_ALL);
  153. *
  154. * See the Zend_Cache documentation at http://framework.zend.com/manual/en/zend.cache.html for more
  155. *
  156. */
  157. static function factory($for, $frontend='Output', $frontendOptions=null) {
  158. self::init();
  159. $backend_name = 'default'; $backend_priority = -1;
  160. $cache_lifetime = 600; $lifetime_priority = -1;
  161. foreach (array('any', $for) as $name) {
  162. if (isset(self::$backend_picks[$name]) && self::$backend_picks[$name]['priority'] > $backend_priority) {
  163. $backend_name = self::$backend_picks[$name]['name'];
  164. $backend_priority = self::$backend_picks[$name]['priority'];
  165. }
  166. if (isset(self::$cache_lifetime[$name]) && self::$cache_lifetime[$name]['priority'] > $lifetime_priority) {
  167. $cache_lifetime = self::$cache_lifetime[$name]['lifetime'];
  168. $lifetime_priority = self::$cache_lifetime[$name]['priority'];
  169. }
  170. }
  171. $backend = self::$backends[$backend_name];
  172. $basicOptions = array('cache_id_prefix' => $for);
  173. if ($cache_lifetime >= 0) $basicOptions['lifetime'] = $cache_lifetime;
  174. else $basicOptions['caching'] = false;
  175. $frontendOptions = $frontendOptions ? array_merge($basicOptions, $frontendOptions) : $basicOptions;
  176. require_once 'Zend/Cache.php';
  177. return Zend_Cache::factory($frontend, $backend[0], $frontendOptions, $backend[1]);
  178. }
  179. }