Bearsampp 2026.7.11
Loading...
Searching...
No Matches
class.cachemanager.php
Go to the documentation of this file.
1<?php
2/*
3 * Copyright (c) 2021-2024 Bearsampp
4 * License: GNU General Public License version 3 or later; see LICENSE.txt
5 * Website: https://bearsampp.com
6 * Github: https://github.com/Bearsampp
7 */
8
18{
19 private static $cacheDir;
20 private static $enabled = true;
21 private static $stats = [
22 'hits' => 0,
23 'misses' => 0,
24 'writes' => 0
25 ];
26
27 const CACHE_VERSION = '1.0';
28
36 public static function init(string $cacheDir): void
37 {
38 self::$cacheDir = $cacheDir;
39
40 // Create cache directory if needed
41 if (!is_dir(self::$cacheDir)) {
42 @mkdir(self::$cacheDir, 0755, true);
43 }
44
45 // Check if cache directory is writable
46 if (!is_writable(self::$cacheDir)) {
47 Log::warning('Cache directory not writable, caching disabled: ' . self::$cacheDir);
48 self::$enabled = false;
49 }
50 }
51
61 public static function load(
62 string $sourcePath,
63 callable $parser,
64 ?string $cacheKey = null
65 ) {
66 if (!self::$enabled || !self::$cacheDir) {
67 return call_user_func($parser, $sourcePath);
68 }
69
70 if ($cacheKey === null) {
71 $cacheKey = md5($sourcePath);
72 }
73
74 $cacheFile = self::getCacheFile($cacheKey);
75
76 // Try cache first (warm start optimization)
77 if (self::isCacheValid($sourcePath, $cacheFile)) {
78 $cached = @json_decode(file_get_contents($cacheFile), true);
79 if (is_array($cached)) {
80 self::$stats['hits']++;
81 return $cached;
82 }
83 }
84
85 // Cache miss or invalid - parse and save
86 self::$stats['misses']++;
87 $data = call_user_func($parser, $sourcePath);
88
89 if (is_array($data)) {
90 self::writeCache($cacheFile, $data);
91 }
92
93 return $data;
94 }
95
103 private static function isCacheValid(
104 string $sourcePath,
105 string $cacheFile
106 ): bool {
107 if (!file_exists($cacheFile) || !file_exists($sourcePath)) {
108 return false;
109 }
110
111 // Cache valid only if newer than source
112 return filemtime($cacheFile) > filemtime($sourcePath);
113 }
114
123 private static function writeCache(string $cacheFile, array $data): bool
124 {
125 if (!self::$enabled) {
126 return false;
127 }
128
129 $json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
130 $written = @file_put_contents($cacheFile, $json);
131
132 if ($written !== false) {
133 self::$stats['writes']++;
134 return true;
135 }
136
137 Log::warning('Failed to write cache: ' . $cacheFile);
138 return false;
139 }
140
147 private static function getCacheFile(string $cacheKey): string
148 {
149 return self::$cacheDir . '/' . $cacheKey . '.cache';
150 }
151
159 public static function invalidate(string $sourcePath): void
160 {
161 if (!self::$enabled || !self::$cacheDir) {
162 return;
163 }
164
165 $cacheKey = md5($sourcePath);
166 $cacheFile = self::getCacheFile($cacheKey);
167
168 if (file_exists($cacheFile)) {
169 @unlink($cacheFile);
170 }
171 }
172
179 public static function clearAll(): int
180 {
181 if (!self::$enabled || !self::$cacheDir) {
182 return 0;
183 }
184
185 // Clear in-memory caches of related classes
186 if (class_exists('Module')) {
188 }
189
190 // Clear general cache if it exists
191 if (class_exists('Cache')) {
192 $cache = new Cache();
193 $cache->clear();
194 }
195
196 $files = @glob(self::$cacheDir . '/*.cache');
197 $deleted = 0;
198
199 if (is_array($files)) {
200 foreach ($files as $file) {
201 if (@unlink($file)) {
202 $deleted++;
203 }
204 }
205 }
206
207 return $deleted;
208 }
209
216 public static function getStats(): array
217 {
218 $files = @glob(self::$cacheDir . '/*.cache');
219 $totalSize = 0;
220
221 if (is_array($files)) {
222 foreach ($files as $file) {
223 $totalSize += filesize($file);
224 }
225 }
226
227 return [
228 'enabled' => self::$enabled,
229 'cacheDir' => self::$cacheDir,
230 'filesCount' => count($files ?? []),
231 'totalSize' => $totalSize,
232 'cacheHits' => self::$stats['hits'],
233 'cacheMisses' => self::$stats['misses'],
234 'cachewrites' => self::$stats['writes'],
235 'hitRate' => (self::$stats['hits'] + self::$stats['misses']) > 0
236 ? round((self::$stats['hits'] / (self::$stats['hits'] + self::$stats['misses'])) * 100, 2)
237 : 0
238 ];
239 }
240
248 public static function setEnabled(bool $enable): void
249 {
250 self::$enabled = $enable;
251 }
252
258 public static function isEnabled(): bool
259 {
260 return self::$enabled;
261 }
262}
static load(string $sourcePath, callable $parser, ?string $cacheKey=null)
static invalidate(string $sourcePath)
static isCacheValid(string $sourcePath, string $cacheFile)
static setEnabled(bool $enable)
static getCacheFile(string $cacheKey)
static init(string $cacheDir)
static writeCache(string $cacheFile, array $data)
static warning($data, $file=null)
static clearMemoryCache()
if(!defined("APPPREFIX")) define("APPPREFIX"