PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.15.0
Independent Analytics – WordPress Analytics Plugin v2.15.0
2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / vendor / eftec / bladeone / lib / BladeOneCache.php
independent-analytics / vendor / eftec / bladeone / lib Last commit date
BladeOne.php 4 days ago BladeOneCache.php 4 days ago BladeOneCacheRedis.php 2 years ago BladeOneCustom.php 4 days ago bladeonecli 2 years ago
BladeOneCache.php
317 lines
1 <?php
2
3 /** @noinspection UnknownInspectionInspection */
4 /** @noinspection TypeUnsafeComparisonInspection */
5 namespace IAWPSCOPED\eftec\bladeone;
6
7 use Exception;
8 use JsonException;
9 use function fclose;
10 use function file_put_contents;
11 use function filemtime;
12 use function filesize;
13 use function fopen;
14 use function fwrite;
15 use function is_array;
16 use function is_object;
17 use function ob_get_contents;
18 use function print_r;
19 use function strlen;
20 use function substr;
21 use function time;
22 /**
23 * trait BladeOneCache
24 * Copyright (c) 2016 Jorge Patricio Castro Castillo MIT License. Don't delete this comment, its part of the license.
25 * Extends the tags of the class BladeOne. Its optional
26 * It adds the next tags to the template
27 * <code>
28 * @ cache([cacheid],[duration=86400]). The id is optional. The duration of the cache is in seconds
29 * // content here
30 * @ endcache()
31 * </code>
32 * It also adds a new function (optional) to the business or logic layer
33 * <code>
34 * if ($blade->cacheExpired('hellocache',1,5)) { //'helloonecache' =template, =1 id cache, 5=duration (seconds)
35 * // cache expired, so we should do some stuff (such as read from the database)
36 * }
37 * </code>
38 *
39 * @package BladeOneCache
40 * @version 3.43.1 2025-09-03
41 * @link https://github.com/EFTEC/BladeOne
42 * @author Jorge Patricio Castro Castillo <jcastro arroba eftec dot cl>
43 * @internal
44 */
45 trait BladeOneCache
46 {
47 protected int $curCacheId = 0;
48 protected int $curCacheDuration = 0;
49 protected int $curCachePosition = 0;
50 protected bool $cacheRunning = \false;
51 protected bool $cachePageRunning = \false;
52 /** @var string|null where the log file will be stored */
53 protected ?string $cacheLog;
54 /**
55 * @var array avoids comparing the file different times. It also avoids race conditions.
56 */
57 private array $cacheExpired = [];
58 /**
59 * @var string=['get','post','getpost','request',null][$i]
60 */
61 private string $cacheStrategy;
62 /** @var array|null */
63 private ?array $cacheStrategyIndex;
64 /**
65 * @return null|string $cacheStrategy=['get','post','getpost','request',null][$i]
66 */
67 public function getCacheStrategy() : ?string
68 {
69 return $this->cacheStrategy;
70 }
71 /**
72 * It sets the cache log. If not cache log then it does not generate a log file<br>
73 * The cache log stores each time a template is created or expired.<br>
74 *
75 * @param string $file
76 */
77 public function setCacheLog($file) : void
78 {
79 $this->cacheLog = $file;
80 }
81 /**
82 * @throws JsonException
83 */
84 public function writeCacheLog($txt, $nivel) : void
85 {
86 if (!$this->cacheLog) {
87 return;
88 // if there is not a file assigned then it skips saving.
89 }
90 $fz = @filesize($this->cacheLog);
91 if (is_object($txt) || is_array($txt)) {
92 $txt = print_r($txt, \true);
93 }
94 // Rewrite file if more than 100000 bytes
95 $mode = $fz > 100000 ? 'w' : 'a';
96 $fp = fopen($this->cacheLog, $mode);
97 if ($fp === \false) {
98 return;
99 }
100 switch ($nivel) {
101 case 1:
102 $txtNivel = 'expired';
103 break;
104 case 2:
105 $txtNivel = 'new';
106 break;
107 default:
108 $txtNivel = 'other';
109 }
110 $txtarg = \json_encode($this->cacheUniqueGUID(\false), \JSON_THROW_ON_ERROR);
111 fwrite($fp, \date('c') . "\t{$txt}\t{$txtNivel}\t{$txtarg}\n");
112 fclose($fp);
113 }
114 /**
115 * It sets the strategy of the cache page.
116 *
117 * @param null|string $cacheStrategy =['get','post','getpost','request',null][$i]
118 * @param array|null $index if null then it reads all indexes. If not, it reads an indexes.
119 */
120 public function setCacheStrategy($cacheStrategy, $index = null) : void
121 {
122 $this->cacheStrategy = $cacheStrategy;
123 $this->cacheStrategyIndex = $index;
124 }
125 /**
126 * It obtains a unique GUID based in:<br>
127 * **get**= parameters from the url<br>
128 * **post**= parameters sends via post<br>
129 * **getpost** = a mix between get and post<br>
130 * **request** = get, post and cookies (including sessions)<br>
131 * MD5 could generate colisions (2^64 = 18,446,744,073,709,551,616) but the end hash is the sum of the hash of
132 * the page + this GUID.
133 *
134 * @param bool $serialize if true then it serializes using md5
135 * @return string|null
136 */
137 private function cacheUniqueGUID($serialize = \true) : ?string
138 {
139 switch ($this->cacheStrategy) {
140 case 'get':
141 $r = $_GET;
142 break;
143 case 'post':
144 $r = $_POST;
145 break;
146 case 'getpost':
147 $arr = \array_merge($_GET, $_POST);
148 $r = $arr;
149 break;
150 case 'request':
151 $r = $_REQUEST;
152 break;
153 default:
154 $r = null;
155 }
156 if ($this->cacheStrategyIndex === null || !is_array($r)) {
157 $r = \serialize($r);
158 } else {
159 $copy = \array_filter($r, function ($key) {
160 return \in_array($key, $this->cacheStrategyIndex, \true);
161 }, \ARRAY_FILTER_USE_KEY);
162 $r = \serialize($copy);
163 }
164 return $serialize === \true ? \md5($r) : $r;
165 }
166 public function compileCache($expression) : string
167 {
168 // get id of template
169 // if the file exists then
170 // compare date.
171 // if the date is too old then re-save.
172 // else
173 // save for the first time.
174 return $this->phpTag . "echo \$this->cacheStart{$expression}; if(!\$this->cacheRunning) { ?>";
175 }
176 public function compileEndCache($expression) : string
177 {
178 return $this->phpTag . "} // if cacheRunning\necho \$this->cacheEnd{$expression}; ?>";
179 }
180 /**
181 * It gets the filename of the compiled file (cached). If cache is not enabled, then it
182 * returns the regular file.
183 *
184 * @param string $view
185 * @return string The full filename
186 */
187 private function getCompiledFileCache($view) : string
188 {
189 $id = $this->cacheUniqueGUID();
190 if ($id !== null) {
191 return \str_replace($this->compileExtension, '_cache' . $id . $this->compileExtension, $this->getCompiledFile($view));
192 }
193 return $this->getCompiledFile($view);
194 }
195 /**
196 * run the blade engine. It returns the result of the code.
197 *
198 * @param string $view The name of the cache. Ex: "folder.folder.view" ("/folder/folder/view.blade")
199 * @param array $variables An associative arrays with the values to display.
200 * @param int $ttl time to live (in second).
201 * @return string
202 * @throws Exception
203 */
204 public function runCache($view, $variables = [], $ttl = 86400) : string
205 {
206 $this->cachePageRunning = \true;
207 $cacheStatus = $this->cachePageExpired($view, $ttl);
208 if ($cacheStatus !== 0) {
209 $this->writeCacheLog($view, $cacheStatus);
210 $this->cacheStart('_page_', $ttl);
211 $content = $this->run($view, $variables);
212 // if no cache, then it runs normally.
213 $this->fileName = $view;
214 // sometimes the filename is replaced (using the tag include), so we restore it
215 $this->cacheEnd($content);
216 // and it stores as a cache paged.
217 } else {
218 $content = $this->getFile($this->getCompiledFileCache($view));
219 }
220 $this->cachePageRunning = \false;
221 return $content;
222 }
223 /**
224 * Returns true if the block cache expired (or doesn't exist), otherwise false.
225 *
226 * @param string $templateName name of the template to use (such hello for template hello.blade.php)
227 * @param string $id (id of cache, optional, if not id then it adds automatically a number)
228 * @param int $cacheDuration (duration of the cache in seconds)
229 * @return int 0=cache exists, 1= cache expired, 2=not exists, string= the cache file (if any)
230 */
231 public function cacheExpired($templateName, $id, $cacheDuration) : int
232 {
233 if ($this->getMode() & 1) {
234 return 2;
235 // forced mode, hence it always expires. (fast mode is ignored).
236 }
237 $compiledFile = $this->getCompiledFile($templateName) . '_cache' . $id;
238 return $this->cacheExpiredInt($compiledFile, $cacheDuration);
239 }
240 /**
241 * It returns true if the whole page expired.
242 *
243 * @param string $templateName
244 * @param int $cacheDuration is seconds.
245 * @return int 0=cache exists, 1= cache expired, 2=not exists, string= the cache content (if any)
246 */
247 public function cachePageExpired($templateName, $cacheDuration) : int
248 {
249 if ($this->getMode() & 1) {
250 return 2;
251 // forced mode, hence it always expires. (fast mode is ignored).
252 }
253 $compiledFile = $this->getCompiledFileCache($templateName);
254 return $this->CacheExpiredInt($compiledFile, $cacheDuration);
255 }
256 /**
257 * This method is used by cacheExpired() and cachePageExpired()
258 *
259 * @param string $compiledFile
260 * @param int $cacheDuration is seconds.
261 * @return int|mixed 0=cache exists, 1= cache expired, 2=not exists, string= the cache content (if any)
262 */
263 private function cacheExpiredInt($compiledFile, $cacheDuration)
264 {
265 if (isset($this->cacheExpired[$compiledFile])) {
266 // if the information is already in the array then returns it.
267 return $this->cacheExpired[$compiledFile];
268 }
269 $date = @filemtime($compiledFile);
270 if ($date) {
271 if ($date + $cacheDuration < time()) {
272 $this->cacheExpired[$compiledFile] = 1;
273 return 2;
274 // time-out.
275 }
276 } else {
277 $this->cacheExpired[$compiledFile] = 2;
278 return 1;
279 // no file
280 }
281 $this->cacheExpired[$compiledFile] = 0;
282 return 0;
283 // cache active.
284 }
285 public function cacheStart($id = '', $cacheDuration = 86400) : void
286 {
287 $this->curCacheId = $id == '' ? $this->curCacheId + 1 : $id;
288 $this->curCacheDuration = $cacheDuration;
289 $this->curCachePosition = strlen(ob_get_contents());
290 if ($this->cachePageRunning) {
291 $compiledFile = $this->getCompiledFileCache($this->fileName);
292 } else {
293 $compiledFile = $this->getCompiledFile() . '_cache' . $this->curCacheId;
294 }
295 if ($this->cacheExpired('', $id, $cacheDuration) !== 0) {
296 $this->cacheRunning = \false;
297 } else {
298 $this->cacheRunning = \true;
299 $content = $this->getFile($compiledFile);
300 echo $content;
301 }
302 }
303 public function cacheEnd($txt = null) : void
304 {
305 if (!$this->cacheRunning) {
306 $txt = $txt ?? substr(ob_get_contents(), $this->curCachePosition);
307 if ($this->cachePageRunning) {
308 $compiledFile = $this->getCompiledFileCache($this->fileName);
309 } else {
310 $compiledFile = $this->getCompiledFile() . '_cache' . $this->curCacheId;
311 }
312 file_put_contents($compiledFile, $txt);
313 }
314 $this->cacheRunning = \false;
315 }
316 }
317