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