PluginProbe
Docket Cache – Object Cache Accelerator / 22.07.01
Docket Cache – Object Cache Accelerator v22.07.01
26.04.05 trunk 22.07.01 22.07.02 22.07.03 22.07.04 22.07.05 23.08.01 23.08.02 24.07.01 24.07.02 24.07.03 24.07.04 24.07.05 24.07.06 24.07.07 26.04.03 26.04.04
docket-cache / includes / src / WpConfig.php

WpConfig.php in Docket Cache – Object Cache Accelerator 22.07.01, at includes/src/WpConfig.php

435 lines 13.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Docket Cache.
4 *
5 * @author Nawawi Jamili
6 * @license MIT
7 *
8 * @see https://github.com/nawawi/docket-cache
9 */
10
11 namespace Nawawi\DocketCache;
12
13 \defined('ABSPATH') || exit;
14
15 final class WpConfig
16 {
17 private static function canopt()
18 {
19 static $inst;
20 if (!\is_object($inst)) {
21 $inst = new Canopt();
22 }
23
24 return $inst;
25 }
26
27 private static function normalize_eol($content)
28 {
29 return str_replace(["\r\n", "\n\r", "\r"], "\n", $content);
30 }
31
32 private static function keys()
33 {
34 return [
35 'rtpostautosave' => 'AUTOSAVE_INTERVAL',
36 'rtpostrevision' => 'WP_POST_REVISIONS',
37 'rtpostemptytrash' => 'EMPTY_TRASH_DAYS',
38 'rtpluginthemeeditor' => 'DISALLOW_FILE_EDIT',
39 'rtpluginthemeinstall' => 'DISALLOW_FILE_MODS',
40 'rtimageoverwrite' => 'IMAGE_EDIT_OVERWRITE',
41 'rtwpdebug' => 'WP_DEBUG',
42 'rtwpdebugdisplay' => 'WP_DEBUG_DISPLAY',
43 'rtwpdebuglog' => 'WP_DEBUG_LOG',
44 'rtwpcoreupdate' => 'WP_AUTO_UPDATE_CORE',
45 ];
46 }
47
48 public static function is_bedrock()
49 {
50 return class_exists('\\Roots\\Bedrock\\Autoloader');
51 }
52
53 public static function get_file()
54 {
55 $file = false;
56 $abspath = wp_normalize_path(ABSPATH);
57 $parent_dir = \dirname($abspath);
58
59 if (@is_file($abspath.'wp-config.php')) {
60 $file = $abspath.'wp-config.php';
61 } elseif (@is_file($parent_dir.'/wp-config.php') && !@is_file($parent_dir.'/wp-settings.php')) {
62 $file = $parent_dir.'/wp-config.php';
63 }
64
65 if (!$file) {
66 return false;
67 }
68
69 return $file;
70 }
71
72 public static function is_writable()
73 {
74 $file = self::get_file();
75
76 return @is_file($file) && is_writable($file);
77 }
78
79 public static function strip_marker($content)
80 {
81 if (!empty($content) && false !== strpos($content, '/*@DOCKETCACHE-RUNTIME-BEGIN*/') && false !== strpos($content, '/*@DOCKETCACHE-RUNTIME-END*/')) {
82 try {
83 $content_r = @preg_replace('#/\*@DOCKETCACHE-RUNTIME-BEGIN\*/.*/\*@DOCKETCACHE-RUNTIME-END\*/(\n|'.\PHP_EOL.')?#sm', '', $content, -1, $cnt);
84 if (!empty($content_r) && $cnt > 0) {
85 $content = $content_r;
86 }
87 } catch (\Throwable $e) {
88 nwdcx_throwable(__METHOD__, $e);
89 }
90 }
91
92 return $content;
93 }
94
95 public static function runtime_remove()
96 {
97 $wpconfig = self::get_contents();
98 if (!$wpconfig) {
99 return false;
100 }
101
102 $wpconfig = self::strip_marker($wpconfig);
103 if (false !== strpos($wpconfig, '/*@DOCKETCACHE-RUNTIME-BEGIN*/')) {
104 return false;
105 }
106
107 self::canopt()->opcache_flush(self::get_file());
108
109 if (self::put_contents($wpconfig)) {
110 $config = self::canopt()->read_config();
111 if (!empty($config) && \is_array($config)) {
112 $keys = self::keys();
113 $ok = false;
114 foreach ($keys as $k => $v) {
115 $nk = nwdcx_constfx($k);
116 if (!empty($config[$nk])) {
117 unset($config[$nk]);
118 $ok = true;
119 }
120 }
121
122 if ($ok) {
123 self::canopt()->put_config($config);
124 }
125 }
126
127 self::unlink_runtime();
128
129 return true;
130 }
131
132 return false;
133 }
134
135 public static function runtime_code()
136 {
137 $data_path = self::canopt()->path;
138 $code = '/*@DOCKETCACHE-RUNTIME-BEGIN*/'.\PHP_EOL;
139 $code .= "if(!\\function_exists('docketcache_runtime')){".\PHP_EOL;
140 $code .= ' function docketcache_runtime(){'.\PHP_EOL;
141 $code .= ' if(!(\PHP_VERSION_ID >= 70205)) {return;}'.\PHP_EOL;
142 $code .= ' try{'.\PHP_EOL;
143 $code .= ' $path="'.$data_path.'";'.\PHP_EOL;
144 $code .= ' $runtime=$path."/runtime.php";'.\PHP_EOL;
145 $code .= ' if(is_file($runtime)){include_once $runtime;}'.\PHP_EOL;
146 $code .= ' }catch(\\Throwable $e){}'.\PHP_EOL;
147 $code .= ' }'.\PHP_EOL;
148 $code .= ' docketcache_runtime();'.\PHP_EOL;
149 $code .= '}'.\PHP_EOL;
150 $code .= '/*@DOCKETCACHE-RUNTIME-END*/'.\PHP_EOL;
151
152 return $code;
153 }
154
155 public static function runtime_install()
156 {
157 $wpconfig = self::get_contents();
158 if (!$wpconfig) {
159 return false;
160 }
161
162 $wpconfig = self::strip_marker($wpconfig);
163 if (false !== strpos($wpconfig, '/*@DOCKETCACHE-RUNTIME-BEGIN*/')) {
164 return false;
165 }
166
167 $code = self::runtime_code();
168
169 $wpconfig_r = false;
170 $cnt = 0;
171
172 // find placeholder
173 if (@preg_match("@^(require_once\s+ABSPATH\s+?\.\s+?'wp-settings\.php';)@m", $wpconfig, $mm)) {
174 $placeholder = $mm[1];
175 $wpconfig_r = str_replace($placeholder, $code.$placeholder, $wpconfig, $cnt);
176 } elseif (@preg_match('@^(/\*\* Sets up WordPress vars and included files\. \*/)@m', $wpconfig, $mm)) {
177 $placeholder = $mm[1];
178 $wpconfig_r = str_replace($placeholder, $placeholder.$code, $wpconfig, $cnt);
179 }
180
181 if (!empty($wpconfig_r) && $cnt > 0) {
182 self::canopt()->opcache_flush(self::get_file());
183
184 if (self::put_contents($wpconfig_r)) {
185 $results = Crawler::fetch_home_nocache(['blocking' => true]);
186 if (!is_wp_error($results) && (isset($results['response']['code']) && '50' !== substr($results['response']['code'], 0, 2))) {
187 self::write_runtime();
188
189 return true;
190 }
191
192 self::put_contents($wpconfig);
193 }
194 }
195
196 return false;
197 }
198
199 public static function get_contents()
200 {
201 $file = self::get_file();
202 if (!$file || !@is_readable($file)) {
203 return false;
204 }
205
206 $content = @file_get_contents($file);
207 if (!empty($content) && \is_string($content)) {
208 return self::normalize_eol($content);
209 }
210
211 return false;
212 }
213
214 public static function put_contents($content)
215 {
216 if (empty($content)) {
217 return $content;
218 }
219
220 $file = self::get_file();
221 if (!$file || !@is_writable($file)) {
222 return false;
223 }
224
225 self::put_backup();
226
227 return @file_put_contents($file, $content, \LOCK_EX);
228 }
229
230 private static function put_backup()
231 {
232 $path = self::canopt()->path;
233 $fm = glob($path.'/wp-config-bak*.php');
234
235 $cnt = 0;
236 if (!empty($fm)) {
237 $cnt = \count($fm);
238 }
239
240 if ($cnt >= 3) {
241 $cnt = 0;
242 foreach ($fm as $k => $f) {
243 if (@is_file($f) && @is_writable($f)) {
244 @unlink($f);
245 }
246 }
247 }
248
249 clearstatcache();
250
251 $src = self::get_file();
252 $dst = $path.'/wp-config-bak'.$cnt.'.php';
253
254 return @copy($src, $dst);
255 }
256
257 public static function has($name)
258 {
259 if (!empty($GLOBALS[nwdcx_constfx($name.'_false')])) {
260 return true;
261 }
262
263 static $found = [];
264
265 if (empty($found) || !\is_array($found)) {
266 $config = self::get_contents();
267 if (empty($config)) {
268 return false;
269 }
270
271 try {
272 $tokens = token_get_all($config);
273 } catch (\Throwable $e) {
274 nwdcx_throwable(__METHOD__, $e);
275
276 return false;
277 }
278
279 if (empty($tokens) || !\is_array($tokens)) {
280 return false;
281 }
282
283 $keys = self::keys();
284 foreach ($tokens as $token) {
285 if (!empty($token) && \is_array($token)) {
286 $token_name = token_name($token[0]);
287 $token_value = trim($token[1], '"\'');
288 $token_value = strtoupper($token_value);
289 if ('T_CONSTANT_ENCAPSED_STRING' === $token_name && ('DOCKET_CACHE_' === substr($token_value, 0, 13) || \in_array($token_value, array_values($keys)))) {
290 $found[$token_value] = 1;
291 }
292 }
293 }
294 }
295
296 return \array_key_exists(nwdcx_constfx($name), $found) || (isset($keys[$name]) && \array_key_exists($keys[$name], $found));
297 }
298
299 public static function is_runtimeconst($name)
300 {
301 return \array_key_exists($name, self::keys());
302 }
303
304 public static function is_runtimefalse()
305 {
306 return !\function_exists('docketcache_runtime');
307 }
308
309 public static function write_runtime()
310 {
311 $file = self::canopt()->path.'/runtime.php';
312 $config = self::canopt()->read_config();
313 $runtime = [
314 'contentpath' => nwdcx_constval('CONTENT_PATH'),
315 'pluginpath' => realpath(plugin_dir_path(nwdcx_constval('FILE'))),
316 'configpath' => self::canopt()->path,
317 ];
318
319 $cons = '';
320 $keys = self::keys();
321 foreach ($keys as $k => $v) {
322 $ka = nwdcx_constfx($k);
323 if (!empty($config[$ka])) {
324 $val = $config[$ka];
325 if ('default' === $val) {
326 continue;
327 }
328
329 if ('on' === $val) {
330 $val = 'true';
331 } elseif ('off' === $val) {
332 $val = 'false';
333 } elseif (@preg_match('@^\d+$@', $val)) {
334 $val = (int) $val;
335
336 if ('rtpostautosave' === $k) {
337 $val = 60 * $val;
338 }
339 }
340
341 $cons .= "if(!defined('".$v."')){define('".$v."', ".$val.");}else{\$GLOBALS['".$ka."_FALSE']=1;}".\PHP_EOL;
342 }
343 }
344
345 $code = '<?php '.\PHP_EOL;
346 $code .= "if(!defined('ABSPATH')){return;}".\PHP_EOL;
347 $code .= '$runtime=(object)'.var_export($runtime, 1).';'.\PHP_EOL;
348 $code .= 'if(!@is_dir($runtime->configpath)){return;}'.\PHP_EOL;
349 $code .= 'if(!@is_file($runtime->pluginpath.\'/docket-cache.php\')){return;}'.\PHP_EOL;
350 if (!empty($cons)) {
351 $code .= $cons;
352 }
353
354 $data = apply_filters('docketcache/filter/wpconfig/runtime', $code, $runtime);
355 if (empty($data)) {
356 $data = $code;
357 }
358
359 $data = rtrim($data).\PHP_EOL.'/*@DOCKET_CACHE_EOF*/'.\PHP_EOL;
360
361 self::canopt()->opcache_flush($file);
362
363 return @file_put_contents($file, $data, \LOCK_EX);
364 }
365
366 public static function unlink_runtime()
367 {
368 $file = self::canopt()->path.'/runtime.php';
369 if (@is_file($file)) {
370 @unlink($file);
371 }
372 }
373
374 public static function notice_filter($name, $value, $key)
375 {
376 if ('default' === $value) {
377 /* translators: %s = option name */
378 return sprintf(esc_html__('%s resets to WordPress default.', 'docket-cache'), $name);
379 }
380
381 $notice = '';
382 switch ($key) {
383 case 'rtpostautosave':
384 if ('off' === $value) {
385 /* translators: %s = option name */
386 $notice = sprintf(esc_html__('%s set to disable.', 'docket-cache'), $name);
387 } elseif ($value > 1) {
388 /* translators: %1$s = option name, %2$s = option_value */
389 $notice = sprintf(esc_html__('%1$s set to every %2$s minutes.', 'docket-cache'), $name, $value);
390 } else {
391 /* translators: %s = option name */
392 $notice = sprintf(esc_html__('%s set to every minute.', 'docket-cache'), $name);
393 }
394 break;
395 case 'rtpostrevision':
396 if ('off' === $value) {
397 /* translators: %s = option name */
398 $notice = sprintf(esc_html__('%s set to disable.', 'docket-cache'), $name);
399 } elseif ('on' === $value) {
400 /* translators: %s = option name */
401 $notice = sprintf(esc_html__('%s set to no limit.', 'docket-cache'), $name);
402 } else {
403 /* translators: %1$s = option name, %2$s = option_value */
404 $notice = sprintf(esc_html__('%1$s set limit to %2$s revisions.', 'docket-cache'), $name, $value);
405 }
406 break;
407 case 'rtpostemptytrash':
408 if ('off' === $value) {
409 /* translators: %s = option name */
410 $notice = sprintf(esc_html__('%s set to disable.', 'docket-cache'), $name);
411 } else {
412 /* translators: %1$s = option name, %2$s = option_value */
413 $notice = sprintf(esc_html__('%1$s set to empty in %2$s days.', 'docket-cache'), $name, $value);
414 }
415 break;
416 case 'rtimageoverwrite':
417 case 'rtpluginthemeeditor':
418 case 'rtpluginthemeinstall':
419 case 'rtwpdebug':
420 case 'rtwpdebugdisplay':
421 case 'rtwpdebuglog':
422 if ('off' === $value) {
423 /* translators: %s = option name */
424 $notice = sprintf(esc_html__('%s set to disable.', 'docket-cache'), $name);
425 } elseif ('on' === $value) {
426 /* translators: %s = option name */
427 $notice = sprintf(esc_html__('%s set to enable.', 'docket-cache'), $name);
428 }
429 break;
430 }
431
432 return $notice;
433 }
434 }
435