1: <?php
2: /**
3: * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
4: * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
5: *
6: * Licensed under The MIT License
7: * For full copyright and license information, please see the LICENSE.txt
8: * Redistributions of files must retain the above copyright notice.
9: *
10: * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
11: * @link https://cakephp.org CakePHP(tm) Project
12: * @since 3.7.0
13: * @license https://opensource.org/licenses/mit-license.php MIT License
14: */
15: namespace Cake\Cache\Engine;
16:
17: use Cake\Cache\CacheEngine;
18:
19: /**
20: * Array storage engine for cache.
21: *
22: * Not actually a persistent cache engine. All data is only
23: * stored in memory for the duration of a single process. While not
24: * useful in production settings this engine can be useful in tests
25: * or console tools where you don't want the overhead of interacting
26: * with a cache servers, but want the work saving properties a cache
27: * provides.
28: */
29: class ArrayEngine extends CacheEngine
30: {
31: /**
32: * Cached data.
33: *
34: * Structured as [key => [exp => expiration, val => value]]
35: *
36: * @var array
37: */
38: protected $data = [];
39:
40: /**
41: * Write data for key into cache
42: *
43: * @param string $key Identifier for the data
44: * @param mixed $value Data to be cached
45: * @return bool True if the data was successfully cached, false on failure
46: */
47: public function write($key, $value)
48: {
49: $key = $this->_key($key);
50: $expires = time() + $this->_config['duration'];
51: $this->data[$key] = ['exp' => $expires, 'val' => $value];
52:
53: return true;
54: }
55:
56: /**
57: * Read a key from the cache
58: *
59: * @param string $key Identifier for the data
60: * @return mixed The cached data, or false if the data doesn't exist,
61: * has expired, or if there was an error fetching it
62: */
63: public function read($key)
64: {
65: $key = $this->_key($key);
66: if (!isset($this->data[$key])) {
67: return false;
68: }
69: $data = $this->data[$key];
70:
71: // Check expiration
72: $now = time();
73: if ($data['exp'] <= $now) {
74: unset($this->data[$key]);
75:
76: return false;
77: }
78:
79: return $data['val'];
80: }
81:
82: /**
83: * Increments the value of an integer cached key
84: *
85: * @param string $key Identifier for the data
86: * @param int $offset How much to increment
87: * @return int|false New incremented value, false otherwise
88: */
89: public function increment($key, $offset = 1)
90: {
91: if (!$this->read($key)) {
92: $this->write($key, 0);
93: }
94: $key = $this->_key($key);
95: $this->data[$key]['val'] += $offset;
96:
97: return $this->data[$key]['val'];
98: }
99:
100: /**
101: * Decrements the value of an integer cached key
102: *
103: * @param string $key Identifier for the data
104: * @param int $offset How much to subtract
105: * @return int|false New decremented value, false otherwise
106: */
107: public function decrement($key, $offset = 1)
108: {
109: if (!$this->read($key)) {
110: $this->write($key, 0);
111: }
112: $key = $this->_key($key);
113: $this->data[$key]['val'] -= $offset;
114:
115: return $this->data[$key]['val'];
116: }
117:
118: /**
119: * Delete a key from the cache
120: *
121: * @param string $key Identifier for the data
122: * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
123: */
124: public function delete($key)
125: {
126: $key = $this->_key($key);
127: unset($this->data[$key]);
128:
129: return true;
130: }
131:
132: /**
133: * Delete all keys from the cache. This will clear every cache config using APC.
134: *
135: * @param bool $check Unused argument required by interface.
136: * @return bool True Returns true.
137: */
138: public function clear($check)
139: {
140: $this->data = [];
141:
142: return true;
143: }
144:
145: /**
146: * Returns the `group value` for each of the configured groups
147: * If the group initial value was not found, then it initializes
148: * the group accordingly.
149: *
150: * @return array
151: */
152: public function groups()
153: {
154: $result = [];
155: foreach ($this->_config['groups'] as $group) {
156: $key = $this->_config['prefix'] . $group;
157: if (!isset($this->data[$key])) {
158: $this->data[$key] = ['exp' => PHP_INT_MAX, 'val' => 1];
159: }
160: $value = $this->data[$key]['val'];
161: $result[] = $group . $value;
162: }
163:
164: return $result;
165: }
166:
167: /**
168: * Increments the group value to simulate deletion of all keys under a group
169: * old values will remain in storage until they expire.
170: *
171: * @param string $group The group to clear.
172: * @return bool success
173: */
174: public function clearGroup($group)
175: {
176: $key = $this->_config['prefix'] . $group;
177: if (isset($this->data[$key])) {
178: $this->data[$key]['val'] += 1;
179: }
180:
181: return true;
182: }
183: }
184: