PluginProbe
Docket Cache – Object Cache Accelerator / trunk
Docket Cache – Object Cache Accelerator vtrunk
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 trunk, at includes/src/WpConfig.php

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