PageRenderTime 62ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Cache/Frontend/Page.php

https://bitbucket.org/baruffaldi/webapp-urltube
PHP | 395 lines | 236 code | 16 blank | 143 comment | 37 complexity | 8b5f962ad5eacce3fb9a7c01da884eee MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0, MIT
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Cache
  17. * @subpackage Zend_Cache_Frontend
  18. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. */
  21. /**
  22. * @see Zend_Cache_Core
  23. */
  24. require_once 'Zend/Cache/Core.php';
  25. /**
  26. * @package Zend_Cache
  27. * @subpackage Zend_Cache_Frontend
  28. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. */
  31. class Zend_Cache_Frontend_Page extends Zend_Cache_Core
  32. {
  33. /**
  34. * This frontend specific options
  35. *
  36. * ====> (boolean) http_conditional :
  37. * - if true, http conditional mode is on
  38. * WARNING : http_conditional OPTION IS NOT IMPLEMENTED FOR THE MOMENT (TODO)
  39. *
  40. * ====> (boolean) debug_header :
  41. * - if true, a debug text is added before each cached pages
  42. *
  43. * ====> (boolean) content_type_memorization :
  44. * - deprecated => use memorize_headers instead
  45. * - if the Content-Type header is sent after the cache was started, the
  46. * corresponding value can be memorized and replayed when the cache is hit
  47. * (if false (default), the frontend doesn't take care of Content-Type header)
  48. *
  49. * ====> (array) memorize_headers :
  50. * - an array of strings corresponding to some HTTP headers name. Listed headers
  51. * will be stored with cache datas and "replayed" when the cache is hit
  52. *
  53. * ====> (array) default_options :
  54. * - an associative array of default options :
  55. * - (boolean) cache : cache is on by default if true
  56. * - (boolean) cacheWithXXXVariables (XXXX = 'Get', 'Post', 'Session', 'Files' or 'Cookie') :
  57. * if true, cache is still on even if there are some variables in this superglobal array
  58. * if false, cache is off if there are some variables in this superglobal array
  59. * - (boolean) makeIdWithXXXVariables (XXXX = 'Get', 'Post', 'Session', 'Files' or 'Cookie') :
  60. * if true, we have to use the content of this superglobal array to make a cache id
  61. * if false, the cache id won't be dependent of the content of this superglobal array
  62. * - (int) specific_lifetime : cache specific lifetime
  63. * (false => global lifetime is used, null => infinite lifetime,
  64. * integer => this lifetime is used), this "lifetime" is probably only
  65. * usefull when used with "regexps" array
  66. * - (array) tags : array of tags (strings)
  67. * - (int) priority : integer between 0 (very low priority) and 10 (maximum priority) used by
  68. * some particular backends
  69. *
  70. * ====> (array) regexps :
  71. * - an associative array to set options only for some REQUEST_URI
  72. * - keys are (pcre) regexps
  73. * - values are associative array with specific options to set if the regexp matchs on $_SERVER['REQUEST_URI']
  74. * (see default_options for the list of available options)
  75. * - if several regexps match the $_SERVER['REQUEST_URI'], only the last one will be used
  76. *
  77. * @var array options
  78. */
  79. protected $_specificOptions = array(
  80. 'http_conditional' => false,
  81. 'debug_header' => false,
  82. 'content_type_memorization' => false,
  83. 'memorize_headers' => array(),
  84. 'default_options' => array(
  85. 'cache_with_get_variables' => false,
  86. 'cache_with_post_variables' => false,
  87. 'cache_with_session_variables' => false,
  88. 'cache_with_files_variables' => false,
  89. 'cache_with_cookie_variables' => false,
  90. 'make_id_with_get_variables' => true,
  91. 'make_id_with_post_variables' => true,
  92. 'make_id_with_session_variables' => true,
  93. 'make_id_with_files_variables' => true,
  94. 'make_id_with_cookie_variables' => true,
  95. 'cache' => true,
  96. 'specific_lifetime' => false,
  97. 'tags' => array(),
  98. 'priority' => null
  99. ),
  100. 'regexps' => array()
  101. );
  102. /**
  103. * Internal array to store some options
  104. *
  105. * @var array associative array of options
  106. */
  107. protected $_activeOptions = array();
  108. /**
  109. * If true, the page won't be cached
  110. *
  111. * @var boolean
  112. */
  113. private $_cancel = false;
  114. /**
  115. * Constructor
  116. *
  117. * @param array $options Associative array of options
  118. * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
  119. * @throws Zend_Cache_Exception
  120. * @return void
  121. */
  122. public function __construct(array $options = array())
  123. {
  124. while (list($name, $value) = each($options)) {
  125. $name = strtolower($name);
  126. switch ($name) {
  127. case 'regexps':
  128. $this->_setRegexps($value);
  129. break;
  130. case 'default_options':
  131. $this->_setDefaultOptions($value);
  132. break;
  133. case 'content_type_memorization':
  134. $this->_setContentTypeMemorization($value);
  135. break;
  136. default:
  137. $this->setOption($name, $value);
  138. }
  139. }
  140. if (isset($this->_specificOptions['http_conditional'])) {
  141. if ($this->_specificOptions['http_conditional']) {
  142. Zend_Cache::throwException('http_conditional is not implemented for the moment !');
  143. }
  144. }
  145. $this->setOption('automatic_serialization', true);
  146. }
  147. /**
  148. * Specific setter for the 'default_options' option (with some additional tests)
  149. *
  150. * @param array $options Associative array
  151. * @throws Zend_Cache_Exception
  152. * @return void
  153. */
  154. protected function _setDefaultOptions($options)
  155. {
  156. if (!is_array($options)) {
  157. Zend_Cache::throwException('default_options must be an array !');
  158. }
  159. foreach ($options as $key=>$value) {
  160. $key = strtolower($key);
  161. if (!isset($this->_specificOptions['default_options'][$key])) {
  162. Zend_Cache::throwException("unknown option [$key] !");
  163. } else {
  164. $this->_specificOptions['default_options'][$key] = $value;
  165. }
  166. }
  167. }
  168. /**
  169. * Set the deprecated contentTypeMemorization option
  170. *
  171. * @param boolean $value value
  172. * @return void
  173. * @deprecated
  174. */
  175. protected function _setContentTypeMemorization($value)
  176. {
  177. $found = null;
  178. foreach ($this->_specificOptions['memorize_headers'] as $key => $value) {
  179. if (strtolower($value) == 'content-type') {
  180. $found = $key;
  181. }
  182. }
  183. if ($value) {
  184. if (!$found) {
  185. $this->_specificOptions['memorize_headers'][] = 'Content-Type';
  186. }
  187. } else {
  188. if ($found) {
  189. unset($this->_specificOptions['memorize_headers'][$found]);
  190. }
  191. }
  192. }
  193. /**
  194. * Specific setter for the 'regexps' option (with some additional tests)
  195. *
  196. * @param array $options Associative array
  197. * @throws Zend_Cache_Exception
  198. * @return void
  199. */
  200. protected function _setRegexps($regexps)
  201. {
  202. if (!is_array($regexps)) {
  203. Zend_Cache::throwException('regexps option must be an array !');
  204. }
  205. foreach ($regexps as $regexp=>$conf) {
  206. if (!is_array($conf)) {
  207. Zend_Cache::throwException('regexps option must be an array of arrays !');
  208. }
  209. $validKeys = array_keys($this->_specificOptions['default_options']);
  210. foreach ($conf as $key=>$value) {
  211. $key = strtolower($key);
  212. if (!in_array($key, $validKeys)) {
  213. Zend_Cache::throwException("unknown option [$key] !");
  214. }
  215. }
  216. }
  217. $this->setOption('regexps', $regexps);
  218. }
  219. /**
  220. * Start the cache
  221. *
  222. * @param string $id (optional) A cache id (if you set a value here, maybe you have to use Output frontend instead)
  223. * @param boolean $doNotDie For unit testing only !
  224. * @return boolean True if the cache is hit (false else)
  225. */
  226. public function start($id = false, $doNotDie = false)
  227. {
  228. $this->_cancel = false;
  229. $lastMatchingRegexp = null;
  230. foreach ($this->_specificOptions['regexps'] as $regexp => $conf) {
  231. if (preg_match("`$regexp`", $_SERVER['REQUEST_URI'])) {
  232. $lastMatchingRegexp = $regexp;
  233. }
  234. }
  235. $this->_activeOptions = $this->_specificOptions['default_options'];
  236. if (!is_null($lastMatchingRegexp)) {
  237. $conf = $this->_specificOptions['regexps'][$lastMatchingRegexp];
  238. foreach ($conf as $key=>$value) {
  239. $this->_activeOptions[$key] = $value;
  240. }
  241. }
  242. if (!($this->_activeOptions['cache'])) {
  243. return false;
  244. }
  245. if (!$id) {
  246. $id = $this->_makeId();
  247. if (!$id) {
  248. return false;
  249. }
  250. }
  251. $array = $this->load($id);
  252. if ($array !== false) {
  253. $data = $array['data'];
  254. $headers = $array['headers'];
  255. if ($this->_specificOptions['debug_header']) {
  256. echo 'DEBUG HEADER : This is a cached page !';
  257. }
  258. if (!headers_sent()) {
  259. foreach ($headers as $key=>$headerCouple) {
  260. $name = $headerCouple[0];
  261. $value = $headerCouple[1];
  262. header("$name: $value");
  263. }
  264. }
  265. echo $data;
  266. if ($doNotDie) {
  267. return true;
  268. }
  269. die();
  270. }
  271. ob_start(array($this, '_flush'));
  272. ob_implicit_flush(false);
  273. return false;
  274. }
  275. /**
  276. * Cancel the current caching process
  277. */
  278. public function cancel()
  279. {
  280. $this->_cancel = true;
  281. }
  282. /**
  283. * callback for output buffering
  284. * (shouldn't really be called manually)
  285. *
  286. * @param string $data Buffered output
  287. * @return string Data to send to browser
  288. */
  289. public function _flush($data)
  290. {
  291. if ($this->_cancel) {
  292. return $data;
  293. }
  294. $contentType = null;
  295. $storedHeaders = array();
  296. $headersList = headers_list();
  297. foreach($this->_specificOptions['memorize_headers'] as $key=>$headerName) {
  298. foreach ($headersList as $headerSent) {
  299. $tmp = split(':', $headerSent);
  300. $headerSentName = trim(array_shift($tmp));
  301. if (strtolower($headerName) == strtolower($headerSentName)) {
  302. $headerSentValue = trim(implode(':', $tmp));
  303. $storedHeaders[] = array($headerSentName, $headerSentValue);
  304. }
  305. }
  306. }
  307. $array = array(
  308. 'data' => $data,
  309. 'headers' => $storedHeaders
  310. );
  311. $this->save($array, null, $this->_activeOptions['tags'], $this->_activeOptions['specific_lifetime'], $this->_activeOptions['priority']);
  312. return $data;
  313. }
  314. /**
  315. * Make an id depending on REQUEST_URI and superglobal arrays (depending on options)
  316. *
  317. * @return mixed|false a cache id (string), false if the cache should have not to be used
  318. */
  319. protected function _makeId()
  320. {
  321. $tmp = $_SERVER['REQUEST_URI'];
  322. foreach (array('Get', 'Post', 'Session', 'Files', 'Cookie') as $arrayName) {
  323. $tmp2 = $this->_makePartialId($arrayName, $this->_activeOptions['cache_with_' . strtolower($arrayName) . '_variables'], $this->_activeOptions['make_id_with_' . strtolower($arrayName) . '_variables']);
  324. if ($tmp2===false) {
  325. return false;
  326. }
  327. $tmp = $tmp . $tmp2;
  328. }
  329. return md5($tmp);
  330. }
  331. /**
  332. * Make a partial id depending on options
  333. *
  334. * @param string $arrayName Superglobal array name
  335. * @param bool $bool1 If true, cache is still on even if there are some variables in the superglobal array
  336. * @param bool $bool2 If true, we have to use the content of the superglobal array to make a partial id
  337. * @return mixed|false Partial id (string) or false if the cache should have not to be used
  338. */
  339. protected function _makePartialId($arrayName, $bool1, $bool2)
  340. {
  341. switch ($arrayName) {
  342. case 'Get':
  343. $var = $_GET;
  344. break;
  345. case 'Post':
  346. $var = $_POST;
  347. break;
  348. case 'Session':
  349. if (isset($_SESSION)) {
  350. $var = $_SESSION;
  351. } else {
  352. $var = null;
  353. }
  354. break;
  355. case 'Cookie':
  356. if (isset($_COOKIE)) {
  357. $var = $_COOKIE;
  358. } else {
  359. $var = null;
  360. }
  361. break;
  362. case 'Files':
  363. $var = $_FILES;
  364. break;
  365. default:
  366. return false;
  367. }
  368. if ($bool1) {
  369. if ($bool2) {
  370. return serialize($var);
  371. }
  372. return '';
  373. }
  374. if (count($var) > 0) {
  375. return false;
  376. }
  377. return '';
  378. }
  379. }