Core.php 6.45 KB
Newer Older
Ketan's avatar
Ketan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Framework\Cache;

class Core extends \Zend_Cache_Core
{
    /**
     * Available options
     *
     * ====> (array) backend_decorators :
     * - array of decorators to decorate cache backend. Each element of this array should contain:
     * -- 'class' - concrete decorator, descendant of \Magento\Framework\Cache\Backend\Decorator\AbstractDecorator
     * -- 'options' - optional array of specific decorator options
     * @var array
     */
    protected $_specificOptions = ['backend_decorators' => [], 'disable_save' => false];

    /**
     * Make and return a cache id
     *
     * Checks 'cache_id_prefix' and returns new id with prefix or simply the id if null
     *
     * @param  string $cacheId Cache id
     * @return string Cache id (with or without prefix)
     */
    protected function _id($cacheId)
    {
        if ($cacheId !== null) {
            $cacheId = str_replace('.', '__', $cacheId); //reduce collision chances
            $cacheId = preg_replace('/([^a-zA-Z0-9_]{1,1})/', '_', $cacheId);
            if (isset($this->_options['cache_id_prefix'])) {
                $cacheId = $this->_options['cache_id_prefix'] . $cacheId;
            }
        }
        return $cacheId;
    }

    /**
     * Prepare tags
     *
     * @param string[] $tags
     * @return string[]
     */
    protected function _tags($tags)
    {
        foreach ($tags as $key => $tag) {
            $tags[$key] = $this->_id($tag);
        }
        return $tags;
    }

    /**
     * Save some data in a cache
     *
     * @param  mixed $data                  Data to put in cache (can be another type than string if
     *                                      automatic_serialization is on)
     * @param  null|string $cacheId         Cache id (if not set, the last cache id will be used)
     * @param  string[] $tags               Cache tags
     * @param  bool|int $specificLifetime   If != false, set a specific lifetime for this cache record
     *                                      (null => infinite lifetime)
     * @param  int $priority                integer between 0 (very low priority) and 10 (maximum priority) used by
     *                                      some particular backends
     * @return bool                         True if no problem
     */
    public function save($data, $cacheId = null, $tags = [], $specificLifetime = false, $priority = 8)
    {
        if ($this->getOption('disable_save')) {
            return true;
        }
        $tags = $this->_tags($tags);
        return parent::save($data, $cacheId, $tags, $specificLifetime, $priority);
    }

    /**
     * Clean cache entries
     *
     * Available modes are :
     * 'all' (default)  => remove all cache entries ($tags is not used)
     * 'old'            => remove too old cache entries ($tags is not used)
     * 'matchingTag'    => remove cache entries matching all given tags
     *                     ($tags can be an array of strings or a single string)
     * 'notMatchingTag' => remove cache entries not matching one of the given tags
     *                     ($tags can be an array of strings or a single string)
     * 'matchingAnyTag' => remove cache entries matching any given tags
     *                     ($tags can be an array of strings or a single string)
     *
     * @param string $mode
     * @param string[] $tags
     * @throws \Zend_Cache_Exception
     * @return bool True if ok
     */
    public function clean($mode = 'all', $tags = [])
    {
        $tags = $this->_tags($tags);
        return parent::clean($mode, $tags);
    }

    /**
     * Return an array of stored cache ids which match given tags
     *
     * In case of multiple tags, a logical AND is made between tags
     *
     * @param string[] $tags array of tags
     * @return string[] array of matching cache ids (string)
     */
    public function getIdsMatchingTags($tags = [])
    {
        $tags = $this->_tags($tags);
        return parent::getIdsMatchingTags($tags);
    }

    /**
     * Return an array of stored cache ids which don't match given tags
     *
     * In case of multiple tags, a logical OR is made between tags
     *
     * @param string[] $tags array of tags
     * @return string[] array of not matching cache ids (string)
     */
    public function getIdsNotMatchingTags($tags = [])
    {
        $tags = $this->_tags($tags);
        return parent::getIdsNotMatchingTags($tags);
    }

    /**
     * Set the backend
     *
     * @param  \Zend_Cache_Backend $backendObject
     * @return void
     */
    public function setBackend(\Zend_Cache_Backend $backendObject)
    {
        $backendObject = $this->_decorateBackend($backendObject);
        parent::setBackend($backendObject);
    }

    /**
     * Decorate cache backend with additional functionality
     *
     * @param \Zend_Cache_Backend $backendObject
     * @return \Zend_Cache_Backend
     */
    protected function _decorateBackend(\Zend_Cache_Backend $backendObject)
    {
        if (!is_array($this->_specificOptions['backend_decorators'])) {
            \Zend_Cache::throwException("'backend_decorator' option should be an array");
        }

        foreach ($this->_specificOptions['backend_decorators'] as $decoratorName => $decoratorOptions) {
            if (!is_array($decoratorOptions) || !array_key_exists('class', $decoratorOptions)) {
                \Zend_Cache::throwException(
                    "Concrete decorator options in '" . $decoratorName . "' should be an array containing 'class' key"
                );
            }
            $classOptions = array_key_exists('options', $decoratorOptions) ? $decoratorOptions['options'] : [];
            $classOptions['concrete_backend'] = $backendObject;

            if (!class_exists($decoratorOptions['class'])) {
                \Zend_Cache::throwException(
                    "Class '" . $decoratorOptions['class'] . "' specified in '" . $decoratorName . "' does not exist"
                );
            }

            $backendObject = new $decoratorOptions['class']($classOptions);
            if (!$backendObject instanceof \Magento\Framework\Cache\Backend\Decorator\AbstractDecorator) {
                \Zend_Cache::throwException(
                    "Decorator in '" .
                    $decoratorName .
                    "' should extend \Magento\Framework\Cache\Backend\Decorator\AbstractDecorator"
                );
            }
        }

        return $backendObject;
    }
}