PageRenderTime 46ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/vendor/yiisoft/yii2/filters/PageCache.php

https://gitlab.com/Sang240892/ecommerce
PHP | 270 lines | 133 code | 12 blank | 125 comment | 22 complexity | 0745d2c31057a51b8c81d5dab38e371e MD5 | raw file
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\filters;
  8. use Yii;
  9. use yii\base\ActionFilter;
  10. use yii\base\Action;
  11. use yii\caching\Cache;
  12. use yii\caching\Dependency;
  13. use yii\di\Instance;
  14. use yii\web\Response;
  15. /**
  16. * PageCache implements server-side caching of whole pages.
  17. *
  18. * It is an action filter that can be added to a controller and handles the `beforeAction` event.
  19. *
  20. * To use PageCache, declare it in the `behaviors()` method of your controller class.
  21. * In the following example the filter will be applied to the `index` action and
  22. * cache the whole page for maximum 60 seconds or until the count of entries in the post table changes.
  23. * It also stores different versions of the page depending on the application language.
  24. *
  25. * ```php
  26. * public function behaviors()
  27. * {
  28. * return [
  29. * 'pageCache' => [
  30. * 'class' => 'yii\filters\PageCache',
  31. * 'only' => ['index'],
  32. * 'duration' => 60,
  33. * 'dependency' => [
  34. * 'class' => 'yii\caching\DbDependency',
  35. * 'sql' => 'SELECT COUNT(*) FROM post',
  36. * ],
  37. * 'variations' => [
  38. * \Yii::$app->language,
  39. * ]
  40. * ],
  41. * ];
  42. * }
  43. * ```
  44. *
  45. * @author Qiang Xue <qiang.xue@gmail.com>
  46. * @since 2.0
  47. */
  48. class PageCache extends ActionFilter
  49. {
  50. /**
  51. * @var boolean whether the content being cached should be differentiated according to the route.
  52. * A route consists of the requested controller ID and action ID. Defaults to true.
  53. */
  54. public $varyByRoute = true;
  55. /**
  56. * @var Cache|array|string the cache object or the application component ID of the cache object.
  57. * After the PageCache object is created, if you want to change this property,
  58. * you should only assign it with a cache object.
  59. * Starting from version 2.0.2, this can also be a configuration array for creating the object.
  60. */
  61. public $cache = 'cache';
  62. /**
  63. * @var integer number of seconds that the data can remain valid in cache.
  64. * Use 0 to indicate that the cached data will never expire.
  65. */
  66. public $duration = 60;
  67. /**
  68. * @var array|Dependency the dependency that the cached content depends on.
  69. * This can be either a [[Dependency]] object or a configuration array for creating the dependency object.
  70. * For example,
  71. *
  72. * ```php
  73. * [
  74. * 'class' => 'yii\caching\DbDependency',
  75. * 'sql' => 'SELECT MAX(updated_at) FROM post',
  76. * ]
  77. * ```
  78. *
  79. * would make the output cache depend on the last modified time of all posts.
  80. * If any post has its modification time changed, the cached content would be invalidated.
  81. *
  82. * If [[cacheCookies]] or [[cacheHeaders]] is enabled, then [[\yii\caching\Dependency::reusable]] should be enabled as well to save performance.
  83. * This is because the cookies and headers are currently stored separately from the actual page content, causing the dependency to be evaluated twice.
  84. */
  85. public $dependency;
  86. /**
  87. * @var array list of factors that would cause the variation of the content being cached.
  88. * Each factor is a string representing a variation (e.g. the language, a GET parameter).
  89. * The following variation setting will cause the content to be cached in different versions
  90. * according to the current application language:
  91. *
  92. * ```php
  93. * [
  94. * Yii::$app->language,
  95. * ]
  96. * ```
  97. */
  98. public $variations;
  99. /**
  100. * @var boolean whether to enable the page cache. You may use this property to turn on and off
  101. * the page cache according to specific setting (e.g. enable page cache only for GET requests).
  102. */
  103. public $enabled = true;
  104. /**
  105. * @var \yii\base\View the view component to use for caching. If not set, the default application view component
  106. * [[\yii\web\Application::view]] will be used.
  107. */
  108. public $view;
  109. /**
  110. * @var boolean|array a boolean value indicating whether to cache all cookies, or an array of
  111. * cookie names indicating which cookies can be cached. Be very careful with caching cookies, because
  112. * it may leak sensitive or private data stored in cookies to unwanted users.
  113. * @since 2.0.4
  114. */
  115. public $cacheCookies = false;
  116. /**
  117. * @var boolean|array a boolean value indicating whether to cache all HTTP headers, or an array of
  118. * HTTP header names (case-insensitive) indicating which HTTP headers can be cached.
  119. * Note if your HTTP headers contain sensitive information, you should white-list which headers can be cached.
  120. * @since 2.0.4
  121. */
  122. public $cacheHeaders = true;
  123. /**
  124. * @inheritdoc
  125. */
  126. public function init()
  127. {
  128. parent::init();
  129. if ($this->view === null) {
  130. $this->view = Yii::$app->getView();
  131. }
  132. }
  133. /**
  134. * This method is invoked right before an action is to be executed (after all possible filters.)
  135. * You may override this method to do last-minute preparation for the action.
  136. * @param Action $action the action to be executed.
  137. * @return boolean whether the action should continue to be executed.
  138. */
  139. public function beforeAction($action)
  140. {
  141. if (!$this->enabled) {
  142. return true;
  143. }
  144. $this->cache = Instance::ensure($this->cache, Cache::className());
  145. if (is_array($this->dependency)) {
  146. $this->dependency = Yii::createObject($this->dependency);
  147. }
  148. $properties = [];
  149. foreach (['cache', 'duration', 'dependency', 'variations'] as $name) {
  150. $properties[$name] = $this->$name;
  151. }
  152. $id = $this->varyByRoute ? $action->getUniqueId() : __CLASS__;
  153. $response = Yii::$app->getResponse();
  154. ob_start();
  155. ob_implicit_flush(false);
  156. if ($this->view->beginCache($id, $properties)) {
  157. $response->on(Response::EVENT_AFTER_SEND, [$this, 'cacheResponse']);
  158. return true;
  159. } else {
  160. $data = $this->cache->get($this->calculateCacheKey());
  161. if (is_array($data)) {
  162. $this->restoreResponse($response, $data);
  163. }
  164. $response->content = ob_get_clean();
  165. return false;
  166. }
  167. }
  168. /**
  169. * Restores response properties from the given data
  170. * @param Response $response the response to be restored
  171. * @param array $data the response property data
  172. * @since 2.0.3
  173. */
  174. protected function restoreResponse($response, $data)
  175. {
  176. if (isset($data['format'])) {
  177. $response->format = $data['format'];
  178. }
  179. if (isset($data['version'])) {
  180. $response->version = $data['version'];
  181. }
  182. if (isset($data['statusCode'])) {
  183. $response->statusCode = $data['statusCode'];
  184. }
  185. if (isset($data['statusText'])) {
  186. $response->statusText = $data['statusText'];
  187. }
  188. if (isset($data['headers']) && is_array($data['headers'])) {
  189. $headers = $response->getHeaders()->toArray();
  190. $response->getHeaders()->fromArray(array_merge($data['headers'], $headers));
  191. }
  192. if (isset($data['cookies']) && is_array($data['cookies'])) {
  193. $cookies = $response->getCookies()->toArray();
  194. $response->getCookies()->fromArray(array_merge($data['cookies'], $cookies));
  195. }
  196. }
  197. /**
  198. * Caches response properties.
  199. * @since 2.0.3
  200. */
  201. public function cacheResponse()
  202. {
  203. $this->view->endCache();
  204. $response = Yii::$app->getResponse();
  205. $data = [
  206. 'format' => $response->format,
  207. 'version' => $response->version,
  208. 'statusCode' => $response->statusCode,
  209. 'statusText' => $response->statusText,
  210. ];
  211. if (!empty($this->cacheHeaders)) {
  212. $headers = $response->getHeaders()->toArray();
  213. if (is_array($this->cacheHeaders)) {
  214. $filtered = [];
  215. foreach ($this->cacheHeaders as $name) {
  216. $name = strtolower($name);
  217. if (isset($headers[$name])) {
  218. $filtered[$name] = $headers[$name];
  219. }
  220. }
  221. $headers = $filtered;
  222. }
  223. $data['headers'] = $headers;
  224. }
  225. if (!empty($this->cacheCookies)) {
  226. $cookies = $response->getCookies()->toArray();
  227. if (is_array($this->cacheCookies)) {
  228. $filtered = [];
  229. foreach ($this->cacheCookies as $name) {
  230. if (isset($cookies[$name])) {
  231. $filtered[$name] = $cookies[$name];
  232. }
  233. }
  234. $cookies = $filtered;
  235. }
  236. $data['cookies'] = $cookies;
  237. }
  238. $this->cache->set($this->calculateCacheKey(), $data, $this->duration, $this->dependency);
  239. echo ob_get_clean();
  240. }
  241. /**
  242. * @return array the key used to cache response properties.
  243. * @since 2.0.3
  244. */
  245. protected function calculateCacheKey()
  246. {
  247. $key = [__CLASS__];
  248. if ($this->varyByRoute) {
  249. $key[] = Yii::$app->requestedRoute;
  250. }
  251. if (is_array($this->variations)) {
  252. foreach ($this->variations as $value) {
  253. $key[] = $value;
  254. }
  255. }
  256. return $key;
  257. }
  258. }