Config.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\PageCache\Model;
  7. use Magento\Framework\App\ObjectManager;
  8. use Magento\Framework\Filesystem;
  9. use Magento\Framework\Module\Dir;
  10. use Magento\Framework\Serialize\Serializer\Json;
  11. use Magento\PageCache\Model\Varnish\VclGeneratorFactory;
  12. /**
  13. * Model is responsible for replacing default vcl template
  14. * file configuration with user-defined from configuration
  15. *
  16. * @api
  17. * @since 100.0.2
  18. */
  19. class Config
  20. {
  21. /**
  22. * Cache types
  23. */
  24. const BUILT_IN = 1;
  25. const VARNISH = 2;
  26. /**
  27. * XML path to Varnish settings
  28. */
  29. const XML_PAGECACHE_TTL = 'system/full_page_cache/ttl';
  30. const XML_PAGECACHE_TYPE = 'system/full_page_cache/caching_application';
  31. const XML_VARNISH_PAGECACHE_ACCESS_LIST = 'system/full_page_cache/varnish/access_list';
  32. const XML_VARNISH_PAGECACHE_BACKEND_PORT = 'system/full_page_cache/varnish/backend_port';
  33. const XML_VARNISH_PAGECACHE_BACKEND_HOST = 'system/full_page_cache/varnish/backend_host';
  34. const XML_VARNISH_PAGECACHE_GRACE_PERIOD = 'system/full_page_cache/varnish/grace_period';
  35. const XML_VARNISH_PAGECACHE_DESIGN_THEME_REGEX = 'design/theme/ua_regexp';
  36. /**
  37. * @var \Magento\Framework\App\Config\ScopeConfigInterface
  38. */
  39. protected $_scopeConfig;
  40. /**
  41. * XML path to Varnish 5 config template path
  42. */
  43. const VARNISH_5_CONFIGURATION_PATH = 'system/full_page_cache/varnish5/path';
  44. /**
  45. * XML path to Varnish 4 config template path
  46. */
  47. const VARNISH_4_CONFIGURATION_PATH = 'system/full_page_cache/varnish4/path';
  48. /**
  49. * @var \Magento\Framework\App\Cache\StateInterface $_cacheState
  50. */
  51. protected $_cacheState;
  52. /**
  53. * @var Filesystem\Directory\ReadFactory
  54. */
  55. protected $readFactory;
  56. /**
  57. * @var \Magento\Framework\Module\Dir\Reader
  58. */
  59. protected $reader;
  60. /**
  61. * @var Json
  62. */
  63. private $serializer;
  64. /**
  65. * @var VclGeneratorFactory
  66. */
  67. private $vclGeneratorFactory;
  68. /**
  69. * @param Filesystem\Directory\ReadFactory $readFactory
  70. * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
  71. * @param \Magento\Framework\App\Cache\StateInterface $cacheState
  72. * @param Dir\Reader $reader
  73. * @param VclGeneratorFactory $vclGeneratorFactory
  74. * @param Json|null $serializer
  75. */
  76. public function __construct(
  77. \Magento\Framework\Filesystem\Directory\ReadFactory $readFactory,
  78. \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
  79. \Magento\Framework\App\Cache\StateInterface $cacheState,
  80. \Magento\Framework\Module\Dir\Reader $reader,
  81. VclGeneratorFactory $vclGeneratorFactory,
  82. Json $serializer = null
  83. ) {
  84. $this->readFactory = $readFactory;
  85. $this->_scopeConfig = $scopeConfig;
  86. $this->_cacheState = $cacheState;
  87. $this->reader = $reader;
  88. $this->serializer = $serializer ?: ObjectManager::getInstance()->get(Json::class);
  89. $this->vclGeneratorFactory = $vclGeneratorFactory;
  90. }
  91. /**
  92. * Return currently selected cache type: built in or varnish
  93. *
  94. * @return int
  95. * @api
  96. */
  97. public function getType()
  98. {
  99. return $this->_scopeConfig->getValue(self::XML_PAGECACHE_TYPE);
  100. }
  101. /**
  102. * Return page lifetime
  103. *
  104. * @return int
  105. * @api
  106. */
  107. public function getTtl()
  108. {
  109. return $this->_scopeConfig->getValue(self::XML_PAGECACHE_TTL);
  110. }
  111. /**
  112. * Return generated varnish.vcl configuration file
  113. *
  114. * @param string $vclTemplatePath
  115. * @return string
  116. * @deprecated 100.2.0 see \Magento\PageCache\Model\VclGeneratorInterface::generateVcl
  117. * @api
  118. */
  119. public function getVclFile($vclTemplatePath)
  120. {
  121. $accessList = $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_ACCESS_LIST);
  122. $designExceptions = $this->_scopeConfig->getValue(
  123. self::XML_VARNISH_PAGECACHE_DESIGN_THEME_REGEX,
  124. \Magento\Store\Model\ScopeInterface::SCOPE_STORE
  125. );
  126. $version = $vclTemplatePath === self::VARNISH_5_CONFIGURATION_PATH ? 5 : 4;
  127. $sslOffloadedHeader = $this->_scopeConfig->getValue(
  128. \Magento\Framework\HTTP\PhpEnvironment\Request::XML_PATH_OFFLOADER_HEADER
  129. );
  130. $vclGenerator = $this->vclGeneratorFactory->create([
  131. 'backendHost' => $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_BACKEND_HOST),
  132. 'backendPort' => $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_BACKEND_PORT),
  133. 'accessList' => $accessList ? explode(',', $accessList) : [],
  134. 'designExceptions' => $designExceptions ? $this->serializer->unserialize($designExceptions) : [],
  135. 'sslOffloadedHeader' => $sslOffloadedHeader,
  136. 'gracePeriod' => $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_GRACE_PERIOD)
  137. ]);
  138. return $vclGenerator->generateVcl($version);
  139. }
  140. /**
  141. * Prepare data for VCL config
  142. *
  143. * @return array
  144. * @deprecated 100.2.0 see \Magento\PageCache\Model\VclGeneratorInterface::generateVcl
  145. */
  146. protected function _getReplacements()
  147. {
  148. return [
  149. '/* {{ host }} */' => $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_BACKEND_HOST),
  150. '/* {{ port }} */' => $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_BACKEND_PORT),
  151. '/* {{ ips }} */' => $this->_getAccessList(),
  152. '/* {{ design_exceptions_code }} */' => $this->_getDesignExceptions(),
  153. // http headers get transformed by php `X-Forwarded-Proto: https`
  154. // becomes $SERVER['HTTP_X_FORWARDED_PROTO'] = 'https'
  155. // Apache and Nginx drop all headers with underlines by default.
  156. '/* {{ ssl_offloaded_header }} */' => str_replace(
  157. '_',
  158. '-',
  159. $this->_scopeConfig->getValue(\Magento\Framework\HTTP\PhpEnvironment\Request::XML_PATH_OFFLOADER_HEADER)
  160. ),
  161. '/* {{ grace_period }} */' => $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_GRACE_PERIOD)
  162. ];
  163. }
  164. /**
  165. * Get IPs access list that can purge Varnish configuration for config file generation
  166. * and transform it to appropriate view
  167. *
  168. * acl purge{
  169. * "127.0.0.1";
  170. * "127.0.0.2";
  171. *
  172. * @return mixed|null|string
  173. * @deprecated 100.2.0 see \Magento\PageCache\Model\VclGeneratorInterface::generateVcl
  174. */
  175. protected function _getAccessList()
  176. {
  177. $result = '';
  178. $tpl = " \"%s\";";
  179. $accessList = $this->_scopeConfig->getValue(self::XML_VARNISH_PAGECACHE_ACCESS_LIST);
  180. if (!empty($accessList)) {
  181. $result = [];
  182. $ips = explode(',', $accessList);
  183. foreach ($ips as $ip) {
  184. $result[] = sprintf($tpl, trim($ip));
  185. }
  186. return implode("\n", $result);
  187. }
  188. return $result;
  189. }
  190. /**
  191. * Get regexs for design exceptions
  192. * Different browser user-agents may use different themes
  193. * Varnish supports regex with internal modifiers only so
  194. * we have to convert "/pattern/iU" into "(?Ui)pattern"
  195. *
  196. * @return string
  197. * @deprecated 100.2.0 see \Magento\PageCache\Model\VclGeneratorInterface::generateVcl
  198. */
  199. protected function _getDesignExceptions()
  200. {
  201. $result = '';
  202. $tpl = "%s (req.http.user-agent ~ \"%s\") {\n" . " hash_data(\"%s\");\n" . " }";
  203. $expressions = $this->_scopeConfig->getValue(
  204. self::XML_VARNISH_PAGECACHE_DESIGN_THEME_REGEX,
  205. \Magento\Store\Model\ScopeInterface::SCOPE_STORE
  206. );
  207. if ($expressions) {
  208. $rules = array_values($this->serializer->unserialize($expressions));
  209. foreach ($rules as $i => $rule) {
  210. if (preg_match('/^[\W]{1}(.*)[\W]{1}(\w+)?$/', $rule['regexp'], $matches)) {
  211. if (!empty($matches[2])) {
  212. $pattern = sprintf("(?%s)%s", $matches[2], $matches[1]);
  213. } else {
  214. $pattern = $matches[1];
  215. }
  216. $if = $i == 0 ? 'if' : ' elsif';
  217. $result .= sprintf($tpl, $if, $pattern, $rule['value']);
  218. }
  219. }
  220. }
  221. return $result;
  222. }
  223. /**
  224. * Whether a cache type is enabled in Cache Management Grid
  225. *
  226. * @return bool
  227. * @api
  228. */
  229. public function isEnabled()
  230. {
  231. return $this->_cacheState->isEnabled(\Magento\PageCache\Model\Cache\Type::TYPE_IDENTIFIER);
  232. }
  233. }