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 2.0.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: * Wincache storage engine for cache
21: *
22: * Supports wincache 1.1.0 and higher.
23: */
24: class WincacheEngine extends CacheEngine
25: {
26:
27: /**
28: * Contains the compiled group names
29: * (prefixed with the global configuration prefix)
30: *
31: * @var array
32: */
33: protected $_compiledGroupNames = [];
34:
35: /**
36: * Initialize the Cache Engine
37: *
38: * Called automatically by the cache frontend
39: *
40: * @param array $config array of setting for the engine
41: * @return bool True if the engine has been successfully initialized, false if not
42: */
43: public function init(array $config = [])
44: {
45: if (!extension_loaded('wincache')) {
46: return false;
47: }
48:
49: parent::init($config);
50:
51: return true;
52: }
53:
54: /**
55: * Write data for key into cache
56: *
57: * @param string $key Identifier for the data
58: * @param mixed $value Data to be cached
59: * @return bool True if the data was successfully cached, false on failure
60: */
61: public function write($key, $value)
62: {
63: $key = $this->_key($key);
64: $duration = $this->_config['duration'];
65:
66: return wincache_ucache_set($key, $value, $duration);
67: }
68:
69: /**
70: * Read a key from the cache
71: *
72: * @param string $key Identifier for the data
73: * @return mixed The cached data, or false if the data doesn't exist,
74: * has expired, or if there was an error fetching it
75: */
76: public function read($key)
77: {
78: $key = $this->_key($key);
79:
80: return wincache_ucache_get($key);
81: }
82:
83: /**
84: * Increments the value of an integer cached key
85: *
86: * @param string $key Identifier for the data
87: * @param int $offset How much to increment
88: * @return bool|int New incremented value, false otherwise
89: */
90: public function increment($key, $offset = 1)
91: {
92: $key = $this->_key($key);
93:
94: return wincache_ucache_inc($key, $offset);
95: }
96:
97: /**
98: * Decrements the value of an integer cached key
99: *
100: * @param string $key Identifier for the data
101: * @param int $offset How much to subtract
102: * @return bool|int New decremented value, false otherwise
103: */
104: public function decrement($key, $offset = 1)
105: {
106: $key = $this->_key($key);
107:
108: return wincache_ucache_dec($key, $offset);
109: }
110:
111: /**
112: * Delete a key from the cache
113: *
114: * @param string $key Identifier for the data
115: * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
116: */
117: public function delete($key)
118: {
119: $key = $this->_key($key);
120:
121: return wincache_ucache_delete($key);
122: }
123:
124: /**
125: * Delete all keys from the cache. This will clear every
126: * item in the cache matching the cache config prefix.
127: *
128: * @param bool $check If true, nothing will be cleared, as entries will
129: * naturally expire in wincache..
130: * @return bool True Returns true.
131: */
132: public function clear($check)
133: {
134: if ($check) {
135: return true;
136: }
137: $info = wincache_ucache_info();
138: $cacheKeys = $info['ucache_entries'];
139: unset($info);
140: foreach ($cacheKeys as $key) {
141: if (strpos($key['key_name'], $this->_config['prefix']) === 0) {
142: wincache_ucache_delete($key['key_name']);
143: }
144: }
145:
146: return true;
147: }
148:
149: /**
150: * Returns the `group value` for each of the configured groups
151: * If the group initial value was not found, then it initializes
152: * the group accordingly.
153: *
154: * @return array
155: */
156: public function groups()
157: {
158: if (empty($this->_compiledGroupNames)) {
159: foreach ($this->_config['groups'] as $group) {
160: $this->_compiledGroupNames[] = $this->_config['prefix'] . $group;
161: }
162: }
163:
164: $groups = wincache_ucache_get($this->_compiledGroupNames);
165: if (count($groups) !== count($this->_config['groups'])) {
166: foreach ($this->_compiledGroupNames as $group) {
167: if (!isset($groups[$group])) {
168: wincache_ucache_set($group, 1);
169: $groups[$group] = 1;
170: }
171: }
172: ksort($groups);
173: }
174:
175: $result = [];
176: $groups = array_values($groups);
177: foreach ($this->_config['groups'] as $i => $group) {
178: $result[] = $group . $groups[$i];
179: }
180:
181: return $result;
182: }
183:
184: /**
185: * Increments the group value to simulate deletion of all keys under a group
186: * old values will remain in storage until they expire.
187: *
188: * @param string $group The group to clear.
189: * @return bool success
190: */
191: public function clearGroup($group)
192: {
193: $success = false;
194: wincache_ucache_inc($this->_config['prefix'] . $group, 1, $success);
195:
196: return $success;
197: }
198: }
199: