Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Static.php
Go to the documentation of this file.
1 <?php
26 #require_once 'Zend/Cache/Backend/Interface.php';
27 
31 #require_once 'Zend/Cache/Backend.php';
32 
40  extends Zend_Cache_Backend
42 {
43  const INNER_CACHE_NAME = 'zend_cache_backend_static_tagcache';
44 
49  protected $_options = array(
50  'public_dir' => null,
51  'sub_dir' => 'html',
52  'file_extension' => '.html',
53  'index_filename' => 'index',
54  'file_locking' => true,
55  'cache_file_perm' => 0600,
56  'cache_directory_perm' => 0700,
57  'debug_header' => false,
58  'tag_cache' => null,
59  'disable_caching' => false
60  );
61 
66  protected $_tagCache = null;
67 
72  protected $_tagged = null;
73 
83  public function setOption($name, $value)
84  {
85  if ($name == 'tag_cache') {
86  $this->setInnerCache($value);
87  } else {
88  // See #ZF-12047 and #GH-91
89  if ($name == 'cache_file_umask') {
90  trigger_error(
91  "'cache_file_umask' is deprecated -> please use 'cache_file_perm' instead",
92  E_USER_NOTICE
93  );
94 
95  $name = 'cache_file_perm';
96  }
97  if ($name == 'cache_directory_umask') {
98  trigger_error(
99  "'cache_directory_umask' is deprecated -> please use 'cache_directory_perm' instead",
100  E_USER_NOTICE
101  );
102 
103  $name = 'cache_directory_perm';
104  }
105 
106  parent::setOption($name, $value);
107  }
108  return $this;
109  }
110 
118  public function getOption($name)
119  {
120  $name = strtolower($name);
121 
122  if ($name == 'tag_cache') {
123  return $this->getInnerCache();
124  }
125 
126  return parent::getOption($name);
127  }
128 
138  public function load($id, $doNotTestCacheValidity = false)
139  {
140  if (($id = (string)$id) === '') {
141  $id = $this->_detectId();
142  } else {
143  $id = $this->_decodeId($id);
144  }
145  if (!$this->_verifyPath($id)) {
146  Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
147  }
148  if ($doNotTestCacheValidity) {
149  $this->_log("Zend_Cache_Backend_Static::load() : \$doNotTestCacheValidity=true is unsupported by the Static backend");
150  }
151 
152  $fileName = basename($id);
153  if ($fileName === '') {
154  $fileName = $this->_options['index_filename'];
155  }
156  $pathName = $this->_options['public_dir'] . dirname($id);
157  $file = rtrim($pathName, '/') . '/' . $fileName . $this->_options['file_extension'];
158  if (file_exists($file)) {
159  $content = file_get_contents($file);
160  return $content;
161  }
162 
163  return false;
164  }
165 
172  public function test($id)
173  {
174  $id = $this->_decodeId($id);
175  if (!$this->_verifyPath($id)) {
176  Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
177  }
178 
179  $fileName = basename($id);
180  if ($fileName === '') {
181  $fileName = $this->_options['index_filename'];
182  }
183  if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
184  $this->_tagged = $tagged;
185  } elseif (!$this->_tagged) {
186  return false;
187  }
188  $pathName = $this->_options['public_dir'] . dirname($id);
189 
190  // Switch extension if needed
191  if (isset($this->_tagged[$id])) {
192  $extension = $this->_tagged[$id]['extension'];
193  } else {
194  $extension = $this->_options['file_extension'];
195  }
196  $file = $pathName . '/' . $fileName . $extension;
197  if (file_exists($file)) {
198  return true;
199  }
200  return false;
201  }
202 
215  public function save($data, $id, $tags = array(), $specificLifetime = false)
216  {
217  if ($this->_options['disable_caching']) {
218  return true;
219  }
220  $extension = null;
221  if ($this->_isSerialized($data)) {
222  $data = unserialize($data);
223  $extension = '.' . ltrim($data[1], '.');
224  $data = $data[0];
225  }
226 
227  clearstatcache();
228  if (($id = (string)$id) === '') {
229  $id = $this->_detectId();
230  } else {
231  $id = $this->_decodeId($id);
232  }
233 
234  $fileName = basename($id);
235  if ($fileName === '') {
236  $fileName = $this->_options['index_filename'];
237  }
238 
239  $pathName = realpath($this->_options['public_dir']) . dirname($id);
240  $this->_createDirectoriesFor($pathName);
241 
242  if ($id === null || strlen($id) == 0) {
243  $dataUnserialized = unserialize($data);
244  $data = $dataUnserialized['data'];
245  }
246  $ext = $this->_options['file_extension'];
247  if ($extension) $ext = $extension;
248  $file = rtrim($pathName, '/') . '/' . $fileName . $ext;
249  if ($this->_options['file_locking']) {
250  $result = file_put_contents($file, $data, LOCK_EX);
251  } else {
252  $result = file_put_contents($file, $data);
253  }
254  @chmod($file, $this->_octdec($this->_options['cache_file_perm']));
255 
256  if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
257  $this->_tagged = $tagged;
258  } elseif ($this->_tagged === null) {
259  $this->_tagged = array();
260  }
261  if (!isset($this->_tagged[$id])) {
262  $this->_tagged[$id] = array();
263  }
264  if (!isset($this->_tagged[$id]['tags'])) {
265  $this->_tagged[$id]['tags'] = array();
266  }
267  $this->_tagged[$id]['tags'] = array_unique(array_merge($this->_tagged[$id]['tags'], $tags));
268  $this->_tagged[$id]['extension'] = $ext;
269  $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
270  return (bool) $result;
271  }
272 
276  protected function _createDirectoriesFor($path)
277  {
278  if (!is_dir($path)) {
279  $oldUmask = umask(0);
280  if ( !@mkdir($path, $this->_octdec($this->_options['cache_directory_perm']), true)) {
281  $lastErr = error_get_last();
282  umask($oldUmask);
283  Zend_Cache::throwException("Can't create directory: {$lastErr['message']}");
284  }
285  umask($oldUmask);
286  }
287  }
288 
298  protected function _isSerialized($data)
299  {
300  return preg_match("/a:2:\{i:0;s:\d+:\"/", $data);
301  }
302 
309  public function remove($id)
310  {
311  if (!$this->_verifyPath($id)) {
312  Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
313  }
314  $fileName = basename($id);
315  if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
316  $this->_tagged = $tagged;
317  } elseif (!$this->_tagged) {
318  return false;
319  }
320  if (isset($this->_tagged[$id])) {
321  $extension = $this->_tagged[$id]['extension'];
322  } else {
323  $extension = $this->_options['file_extension'];
324  }
325  if ($fileName === '') {
326  $fileName = $this->_options['index_filename'];
327  }
328  $pathName = $this->_options['public_dir'] . dirname($id);
329  $file = realpath($pathName) . '/' . $fileName . $extension;
330  if (!file_exists($file)) {
331  return false;
332  }
333  return unlink($file);
334  }
335 
344  public function removeRecursively($id)
345  {
346  if (!$this->_verifyPath($id)) {
347  Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
348  }
349  $fileName = basename($id);
350  if ($fileName === '') {
351  $fileName = $this->_options['index_filename'];
352  }
353  $pathName = $this->_options['public_dir'] . dirname($id);
354  $file = $pathName . '/' . $fileName . $this->_options['file_extension'];
355  $directory = $pathName . '/' . $fileName;
356  if (file_exists($directory)) {
357  if (!is_writable($directory)) {
358  return false;
359  }
360  if (is_dir($directory)) {
361  foreach (new DirectoryIterator($directory) as $file) {
362  if (true === $file->isFile()) {
363  if (false === unlink($file->getPathName())) {
364  return false;
365  }
366  }
367  }
368  }
369  rmdir($directory);
370  }
371  if (file_exists($file)) {
372  if (!is_writable($file)) {
373  return false;
374  }
375  return unlink($file);
376  }
377  return true;
378  }
379 
398  public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
399  {
400  $result = false;
401  switch ($mode) {
404  if (empty($tags)) {
405  throw new Zend_Exception('Cannot use tag matching modes as no tags were defined');
406  }
407  if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
408  $this->_tagged = $tagged;
409  } elseif (!$this->_tagged) {
410  return true;
411  }
412  foreach ($tags as $tag) {
413  $urls = array_keys($this->_tagged);
414  foreach ($urls as $url) {
415  if (isset($this->_tagged[$url]['tags']) && in_array($tag, $this->_tagged[$url]['tags'])) {
416  $this->remove($url);
417  unset($this->_tagged[$url]);
418  }
419  }
420  }
421  $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
422  $result = true;
423  break;
425  if ($this->_tagged === null) {
426  $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME);
427  $this->_tagged = $tagged;
428  }
429  if ($this->_tagged === null || empty($this->_tagged)) {
430  return true;
431  }
432  $urls = array_keys($this->_tagged);
433  foreach ($urls as $url) {
434  $this->remove($url);
435  unset($this->_tagged[$url]);
436  }
437  $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
438  $result = true;
439  break;
441  $this->_log("Zend_Cache_Backend_Static : Selected Cleaning Mode Currently Unsupported By This Backend");
442  break;
444  if (empty($tags)) {
445  throw new Zend_Exception('Cannot use tag matching modes as no tags were defined');
446  }
447  if ($this->_tagged === null) {
448  $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME);
449  $this->_tagged = $tagged;
450  }
451  if ($this->_tagged === null || empty($this->_tagged)) {
452  return true;
453  }
454  $urls = array_keys($this->_tagged);
455  foreach ($urls as $url) {
456  $difference = array_diff($tags, $this->_tagged[$url]['tags']);
457  if (count($tags) == count($difference)) {
458  $this->remove($url);
459  unset($this->_tagged[$url]);
460  }
461  }
462  $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
463  $result = true;
464  break;
465  default:
466  Zend_Cache::throwException('Invalid mode for clean() method');
467  break;
468  }
469  return $result;
470  }
471 
482  {
483  $this->_tagCache = $cache;
484  $this->_options['tag_cache'] = $cache;
485  }
486 
492  public function getInnerCache()
493  {
494  if ($this->_tagCache === null) {
495  Zend_Cache::throwException('An Inner Cache has not been set; use setInnerCache()');
496  }
497  return $this->_tagCache;
498  }
499 
506  protected function _verifyPath($path)
507  {
508  $path = realpath($path);
509  $base = realpath($this->_options['public_dir']);
510  return strncmp($path, $base, strlen($base)) !== 0;
511  }
512 
518  protected function _detectId()
519  {
520  return $_SERVER['REQUEST_URI'];
521  }
522 
533  protected static function _validateIdOrTag($string)
534  {
535  if (!is_string($string)) {
536  Zend_Cache::throwException('Invalid id or tag : must be a string');
537  }
538 
539  // Internal only checked in Frontend - not here!
540  if (substr($string, 0, 9) == 'internal-') {
541  return;
542  }
543 
544  // Validation assumes no query string, fragments or scheme included - only the path
545  if (!preg_match(
546  '/^(?:\/(?:(?:%[[:xdigit:]]{2}|[A-Za-z0-9-_.!~*\'()\[\]:@&=+$,;])*)?)+$/',
547  $string
548  )
549  ) {
550  Zend_Cache::throwException("Invalid id or tag '$string' : must be a valid URL path");
551  }
552  }
553 
561  protected function _octdec($val)
562  {
563  if (is_string($val) && decoct(octdec($val)) == $val) {
564  return octdec($val);
565  }
566  return $val;
567  }
568 
575  protected function _decodeId($id)
576  {
577  return pack('H*', $id);
578  }
579 }
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
$id
Definition: fieldset.phtml:14
setInnerCache(Zend_Cache_Core $cache)
Definition: Static.php:481
save($data, $id, $tags=array(), $specificLifetime=false)
Definition: Static.php:215
const CLEANING_MODE_OLD
Definition: Cache.php:73
_log($message, $priority=4)
Definition: Backend.php:273
$fileName
Definition: translate.phtml:15
$value
Definition: gender.phtml:16
static _validateIdOrTag($string)
Definition: Static.php:533
const CLEANING_MODE_NOT_MATCHING_TAG
Definition: Cache.php:75
load($id, $doNotTestCacheValidity=false)
Definition: Static.php:138
if($exist=($block->getProductCollection() && $block->getProductCollection() ->getSize())) $mode
Definition: grid.phtml:15
setOption($name, $value)
Definition: Static.php:83
clean($mode=Zend_Cache::CLEANING_MODE_ALL, $tags=array())
Definition: Static.php:398
const CLEANING_MODE_ALL
Definition: Cache.php:72
static throwException($msg, Exception $e=null)
Definition: Cache.php:205
is_writable($path)
Definition: io.php:25
mkdir($pathname, $mode=0777, $recursive=false, $context=null)
Definition: ioMock.php:25
const CLEANING_MODE_MATCHING_ANY_TAG
Definition: Cache.php:76
const CLEANING_MODE_MATCHING_TAG
Definition: Cache.php:74
if(!isset($_GET['name'])) $name
Definition: log.php:14