Kernel.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\App\PageCache;
  7. /**
  8. * Builtin cache processor
  9. */
  10. class Kernel
  11. {
  12. /**
  13. * @var \Magento\PageCache\Model\Cache\Type
  14. *
  15. * @deprecated 100.1.0
  16. */
  17. protected $cache;
  18. /**
  19. * @var Identifier
  20. */
  21. protected $identifier;
  22. /**
  23. * @var \Magento\Framework\App\Request\Http
  24. */
  25. protected $request;
  26. /**
  27. * @var \Magento\PageCache\Model\Cache\Type
  28. */
  29. private $fullPageCache;
  30. /**
  31. * @var \Magento\Framework\Serialize\SerializerInterface
  32. */
  33. private $serializer;
  34. /**
  35. * @var \Magento\Framework\App\Http\Context
  36. */
  37. private $context;
  38. /**
  39. * @var \Magento\Framework\App\Http\ContextFactory
  40. */
  41. private $contextFactory;
  42. /**
  43. * @var \Magento\Framework\App\Response\HttpFactory
  44. */
  45. private $httpFactory;
  46. /**
  47. * @param Cache $cache
  48. * @param Identifier $identifier
  49. * @param \Magento\Framework\App\Request\Http $request
  50. * @param \Magento\Framework\App\Http\Context|null $context
  51. * @param \Magento\Framework\App\Http\ContextFactory|null $contextFactory
  52. * @param \Magento\Framework\App\Response\HttpFactory|null $httpFactory
  53. * @param \Magento\Framework\Serialize\SerializerInterface|null $serializer
  54. */
  55. public function __construct(
  56. \Magento\Framework\App\PageCache\Cache $cache,
  57. \Magento\Framework\App\PageCache\Identifier $identifier,
  58. \Magento\Framework\App\Request\Http $request,
  59. \Magento\Framework\App\Http\Context $context = null,
  60. \Magento\Framework\App\Http\ContextFactory $contextFactory = null,
  61. \Magento\Framework\App\Response\HttpFactory $httpFactory = null,
  62. \Magento\Framework\Serialize\SerializerInterface $serializer = null
  63. ) {
  64. $this->cache = $cache;
  65. $this->identifier = $identifier;
  66. $this->request = $request;
  67. if ($context) {
  68. $this->context = $context;
  69. } else {
  70. $this->context = \Magento\Framework\App\ObjectManager::getInstance()->get(
  71. \Magento\Framework\App\Http\Context::class
  72. );
  73. }
  74. if ($contextFactory) {
  75. $this->contextFactory = $contextFactory;
  76. } else {
  77. $this->contextFactory = \Magento\Framework\App\ObjectManager::getInstance()->get(
  78. \Magento\Framework\App\Http\ContextFactory::class
  79. );
  80. }
  81. if ($httpFactory) {
  82. $this->httpFactory = $httpFactory;
  83. } else {
  84. $this->httpFactory = \Magento\Framework\App\ObjectManager::getInstance()->get(
  85. \Magento\Framework\App\Response\HttpFactory::class
  86. );
  87. }
  88. if ($serializer) {
  89. $this->serializer = $serializer;
  90. } else {
  91. $this->serializer = \Magento\Framework\App\ObjectManager::getInstance()->get(
  92. \Magento\Framework\Serialize\SerializerInterface::class
  93. );
  94. }
  95. }
  96. /**
  97. * Load response from cache
  98. *
  99. * @return \Magento\Framework\App\Response\Http|false
  100. */
  101. public function load()
  102. {
  103. if ($this->request->isGet() || $this->request->isHead()) {
  104. $responseData = $this->getCache()->load($this->identifier->getValue());
  105. if (!$responseData) {
  106. return false;
  107. }
  108. $responseData = $this->serializer->unserialize($responseData);
  109. if (!$responseData) {
  110. return false;
  111. }
  112. return $this->buildResponse($responseData);
  113. }
  114. return false;
  115. }
  116. /**
  117. * Modify and cache application response
  118. *
  119. * @param \Magento\Framework\App\Response\Http $response
  120. * @return void
  121. */
  122. public function process(\Magento\Framework\App\Response\Http $response)
  123. {
  124. if (preg_match('/public.*s-maxage=(\d+)/', $response->getHeader('Cache-Control')->getFieldValue(), $matches)) {
  125. $maxAge = $matches[1];
  126. $response->setNoCacheHeaders();
  127. if (($response->getHttpResponseCode() == 200 || $response->getHttpResponseCode() == 404)
  128. && ($this->request->isGet() || $this->request->isHead())
  129. ) {
  130. $tagsHeader = $response->getHeader('X-Magento-Tags');
  131. $tags = $tagsHeader ? explode(',', $tagsHeader->getFieldValue()) : [];
  132. $response->clearHeader('Set-Cookie');
  133. $response->clearHeader('X-Magento-Tags');
  134. if (!headers_sent()) {
  135. header_remove('Set-Cookie');
  136. }
  137. $this->getCache()->save(
  138. $this->serializer->serialize($this->getPreparedData($response)),
  139. $this->identifier->getValue(),
  140. $tags,
  141. $maxAge
  142. );
  143. }
  144. }
  145. }
  146. /**
  147. * Get prepared data for storage in the cache.
  148. *
  149. * @param \Magento\Framework\App\Response\Http $response
  150. * @return array
  151. */
  152. private function getPreparedData(\Magento\Framework\App\Response\Http $response)
  153. {
  154. return [
  155. 'content' => $response->getContent(),
  156. 'status_code' => $response->getStatusCode(),
  157. 'headers' => $response->getHeaders()->toArray(),
  158. 'context' => $this->context->toArray()
  159. ];
  160. }
  161. /**
  162. * Build response using response data.
  163. *
  164. * @param array $responseData
  165. * @return \Magento\Framework\App\Response\Http
  166. */
  167. private function buildResponse($responseData)
  168. {
  169. $context = $this->contextFactory->create(
  170. [
  171. 'data' => $responseData['context']['data'],
  172. 'default' => $responseData['context']['default']
  173. ]
  174. );
  175. $response = $this->httpFactory->create(
  176. [
  177. 'context' => $context
  178. ]
  179. );
  180. $response->setStatusCode($responseData['status_code']);
  181. $response->setContent($responseData['content']);
  182. foreach ($responseData['headers'] as $headerKey => $headerValue) {
  183. $response->setHeader($headerKey, $headerValue, true);
  184. }
  185. return $response;
  186. }
  187. /**
  188. * TODO: Workaround to support backwards compatibility, will rework to use Dependency Injection in MAGETWO-49547
  189. *
  190. * @return \Magento\PageCache\Model\Cache\Type
  191. */
  192. private function getCache()
  193. {
  194. if (!$this->fullPageCache) {
  195. $this->fullPageCache = \Magento\Framework\App\ObjectManager::getInstance()->get(
  196. \Magento\PageCache\Model\Cache\Type::class
  197. );
  198. }
  199. return $this->fullPageCache;
  200. }
  201. }