1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Cache dummy store.
19 *
20 * This dummy store is used when a load has no other stores that it can make use of.
21 * This shouldn't happen in normal operation... I think.
22 *
23 * This file is part of Moodle's cache API, affectionately called MUC.
24 * It contains the components that are requried in order to use caching.
25 *
26 * @package    core
27 * @category   cache
28 * @copyright  2012 Sam Hemelryk
29 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
30 */
31
32defined('MOODLE_INTERNAL') || die();
33
34/**
35 * The cache dummy store.
36 *
37 * @copyright  2012 Sam Hemelryk
38 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 */
40class cachestore_dummy extends cache_store {
41
42    /**
43     * The name of this store.
44     * @var string
45     */
46    protected $name;
47
48    /**
49     * Gets set to true if this store is going to store data.
50     * This happens when the definition doesn't require static acceleration as the loader will not be storing information and
51     * something has to.
52     * @var bool
53     */
54    protected $persist = false;
55
56    /**
57     * The stored data array
58     * @var array
59     */
60    protected $store = array();
61
62    /**
63     * Constructs a dummy store instance.
64     * @param string $name
65     * @param array $configuration
66     */
67    public function __construct($name = 'Dummy store', array $configuration = array()) {
68        $this->name = $name;
69    }
70
71    /**
72     * Returns true if this store plugin is usable.
73     * @return bool
74     */
75    public static function are_requirements_met() {
76        return true;
77    }
78
79    /**
80     * Returns true if the user can add an instance.
81     * @return bool
82     */
83    public static function can_add_instance() {
84        return false;
85    }
86
87    /**
88     * Returns the supported features.
89     * @param array $configuration
90     * @return int
91     */
92    public static function get_supported_features(array $configuration = array()) {
93        return self::SUPPORTS_NATIVE_TTL;
94    }
95
96    /**
97     * Returns the supported mode.
98     * @param array $configuration
99     * @return int
100     */
101    public static function get_supported_modes(array $configuration = array()) {
102        return self::MODE_APPLICATION + self::MODE_REQUEST + self::MODE_SESSION;
103    }
104
105    /**
106     * Initialises the store instance for a definition.
107     * @param cache_definition $definition
108     */
109    public function initialise(cache_definition $definition) {
110        // If the definition isn't using static acceleration then we need to be store data here.
111        // The reasoning behind this is that:
112        //   - If the definition is using static acceleration then the cache loader is going to
113        //     store things in its static array.
114        //   - If the definition is not using static acceleration then the cache loader won't try to store anything
115        //     and we will need to store it here in order to make sure it is accessible.
116        if ($definition->get_mode() !== self::MODE_APPLICATION) {
117            // Neither the request cache nor the session cache provide static acceleration.
118            $this->persist = true;
119        } else {
120            $this->persist = !$definition->use_static_acceleration();
121        }
122    }
123
124    /**
125     * Returns true if this has been initialised.
126     * @return bool
127     */
128    public function is_initialised() {
129        return (!empty($this->definition));
130    }
131
132    /**
133     * Returns true the given mode is supported.
134     * @param int $mode
135     * @return bool
136     */
137    public static function is_supported_mode($mode) {
138        return true;
139    }
140
141    /**
142     * Returns the data for the given key
143     * @param string $key
144     * @return string|false
145     */
146    public function get($key) {
147        if ($this->persist && array_key_exists($key, $this->store)) {
148            return $this->store[$key];
149        }
150        return false;
151    }
152
153    /**
154     * Gets' the values for many keys
155     * @param array $keys
156     * @return bool
157     */
158    public function get_many($keys) {
159        $return = array();
160        foreach ($keys as $key) {
161            if ($this->persist && array_key_exists($key, $this->store)) {
162                $return[$key] = $this->store[$key];
163            } else {
164                $return[$key] = false;
165            }
166        }
167        return $return;
168    }
169
170    /**
171     * Sets an item in the cache
172     * @param string $key
173     * @param mixed $data
174     * @return bool
175     */
176    public function set($key, $data) {
177        if ($this->persist) {
178            $this->store[$key] = $data;
179        }
180        return true;
181    }
182
183    /**
184     * Sets many items in the cache
185     * @param array $keyvaluearray
186     * @return int
187     */
188    public function set_many(array $keyvaluearray) {
189        if ($this->persist) {
190            foreach ($keyvaluearray as $pair) {
191                $this->store[$pair['key']] = $pair['value'];
192            }
193
194        }
195        return count($keyvaluearray);
196    }
197
198    /**
199     * Deletes an item from the cache
200     * @param string $key
201     * @return bool
202     */
203    public function delete($key) {
204        unset($this->store[$key]);
205        return true;
206    }
207    /**
208     * Deletes many items from the cache
209     * @param array $keys
210     * @return bool
211     */
212    public function delete_many(array $keys) {
213        if ($this->persist) {
214            foreach ($keys as $key) {
215                unset($this->store[$key]);
216            }
217        }
218        return count($keys);
219    }
220
221    /**
222     * Deletes all of the items from the cache.
223     * @return bool
224     */
225    public function purge() {
226        $this->store = array();
227        return true;
228    }
229
230    /**
231     * Performs any necessary clean up when the store instance is being deleted.
232     *
233     * @deprecated since 3.2
234     * @see cachestore_dummy::instance_deleted()
235     */
236    public function cleanup() {
237        debugging('cachestore_dummy::cleanup() is deprecated. Please use cachestore_dummy::instance_deleted() instead.',
238            DEBUG_DEVELOPER);
239        $this->instance_deleted();
240    }
241
242    /**
243     * Performs any necessary operation when the store instance is being deleted.
244     *
245     * This method may be called before the store has been initialised.
246     *
247     * @since Moodle 3.2
248     */
249    public function instance_deleted() {
250        $this->purge();
251    }
252
253    /**
254     * Generates an instance of the cache store that can be used for testing.
255     *
256     * @param cache_definition $definition
257     * @return false
258     */
259    public static function initialise_test_instance(cache_definition $definition) {
260        $cache = new cachestore_dummy('Dummy store test');
261        if ($cache->is_ready()) {
262            $cache->initialise($definition);
263        }
264        return $cache;
265    }
266
267    /**
268     * Generates the appropriate configuration required for unit testing.
269     *
270     * @return array Array of unit test configuration data to be used by initialise().
271     */
272    public static function unit_test_configuration() {
273        return [];
274    }
275
276    /**
277     * Returns the name of this instance.
278     * @return string
279     */
280    public function my_name() {
281        return $this->name;
282    }
283}
284