PluginProbe
WP Debugging / 2.11.4
WP Debugging v2.11.4
2.12.6 2.12.5 trunk 2.10.0 2.10.1 2.10.2 2.11.0 2.11.1 2.11.10 2.11.11 2.11.12 2.11.13 2.11.14 2.11.15 2.11.16 2.11.17 2.11.18 2.11.19 2.11.2 2.11.20 2.11.21 2.11.22 2.11.23 2.11.24 2.11.3 All 59 releases
wp-debugging / src / Settings.php

Settings.php in WP Debugging 2.11.4, at src/Settings.php

485 lines 13.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WP Debugging
4 *
5 * @package wp-debugging
6 * @author Andy Fragen
7 * @license MIT
8 */
9
10 namespace Fragen\WP_Debugging;
11
12 // Exit if called directly.
13 if ( ! defined( 'WPINC' ) ) {
14 die;
15 }
16
17 /**
18 * Class Settings
19 */
20 class Settings {
21 /**
22 * Hold plugin options.
23 *
24 * @var array
25 */
26 protected static $options;
27
28 /**
29 * Hold `wp-config.php` file path.
30 *
31 * @var string
32 */
33 protected static $config_path;
34
35 /**
36 * Holds pre-defined constants for `wp-config.php`.
37 *
38 * @var array
39 */
40 protected $defined_constants;
41
42 /**
43 * Holds config args for WPConfigTransformer.
44 *
45 * @var array
46 */
47 protected static $config_args;
48
49 /**
50 * Holds nonce.
51 *
52 * @var $nonce
53 */
54 protected static $nonce;
55
56 /**
57 * Constructor.
58 *
59 * @param array $options Plugin options.
60 * @param string $config_path Path to config file.
61 * @param array $defined_constants Pre-defined constant group.
62 * @return void
63 */
64 public function __construct( $options, $config_path, $defined_constants ) {
65 self::$options = $options;
66 self::$config_path = $config_path;
67 $this->defined_constants = $defined_constants;
68 self::$config_args = [ 'normalize' => true ];
69 static::$nonce = wp_create_nonce( 'wp-debugging' );
70
71 if ( false === strpos( file_get_contents( self::$config_path ), "/* That's all, stop editing!" ) ) {
72 if ( 1 === preg_match( '@\$table_prefix = (.*);@', file_get_contents( self::$config_path ), $matches ) ) {
73 self::$config_args = array_merge(
74 self::$config_args,
75 [
76 'anchor' => "$matches[0]",
77 'placement' => 'after',
78 ]
79 );
80 }
81 }
82 }
83
84 /**
85 * Load hooks for settings.
86 *
87 * @return self
88 */
89 public function load_hooks() {
90 add_action( 'admin_init', [ $this, 'add_settings' ] );
91 add_action( is_multisite() ? 'network_admin_menu' : 'admin_menu', [ $this, 'add_plugin_menu' ] );
92 add_action( 'network_admin_edit_wp_debugging', [ $this, 'update_settings' ] );
93 add_action( 'admin_init', [ $this, 'update_settings' ] );
94 add_filter(
95 is_multisite()
96 ? 'network_admin_plugin_action_links_wp-debugging/wp-debugging.php'
97 : 'plugin_action_links_wp-debugging/wp-debugging.php',
98 [ $this, 'plugin_action_links' ]
99 );
100
101 return $this;
102 }
103
104 /**
105 * Add plugin menu.
106 *
107 * @return void
108 */
109 public function add_plugin_menu() {
110 $parent = is_multisite() ? 'settings.php' : 'tools.php';
111 $capability = is_multisite() ? 'manage_network_options' : 'manage_options';
112
113 add_submenu_page(
114 $parent,
115 esc_html__( 'WP Debugging', 'wp-debugging' ),
116 esc_html_x( 'WP Debugging', 'Menu item', 'wp-debugging' ),
117 $capability,
118 'wp-debugging',
119 [ $this, 'create_settings_page' ]
120 );
121 }
122
123 /**
124 * Update settings on save.
125 *
126 * @return void
127 */
128 public function update_settings() {
129 // Exit if improper privileges.
130 if ( ! current_user_can( 'manage_options' ) || ! wp_verify_nonce( static::$nonce, 'wp-debugging' ) ) {
131 return;
132 }
133
134 if ( isset( $_POST['option_page'] ) &&
135 'wp_debugging' === $_POST['option_page']
136 ) {
137 $options = isset( $_POST['wp-debugging'] )
138 ? array_map( 'sanitize_text_field', wp_unslash( $_POST['wp-debugging'] ) )
139 : [];
140
141 $options = $this->sanitize( $options );
142 $this->update_constants( self::$options, $options );
143 $filtered_options = array_filter(
144 self::$options,
145 function ( $e ) {
146 return '1' !== $e;
147 }
148 );
149 $options = array_merge( $filtered_options, $options );
150 update_site_option( 'wp_debugging', (array) $options );
151 $this->redirect_on_save();
152 }
153 }
154
155 /**
156 * Update constants in wp-config.php.
157 *
158 * @param array $old Current value of self::$options.
159 * @param mixed $new New value of $options.
160 * @return void
161 */
162 private function update_constants( $old, $new ) {
163 $remove = array_diff_assoc( $old, $new );
164 $add = array_diff_assoc( $new, $old );
165
166 if ( ! empty( $add ) ) {
167 $this->add_constants( $add );
168 }
169 if ( ! empty( $remove ) ) {
170 $this->remove_constants( $remove );
171 }
172 }
173
174 /**
175 * Add constants to wp-config.php file.
176 *
177 * @uses https://github.com/wp-cli/wp-config-transformer
178 *
179 * @param array $add Constants to add to wp-config.php.
180 * @return array $added Array of added constants.
181 */
182 public function add_constants( $add ) {
183 $added = [];
184 try {
185 $config_transformer = new \WPConfigTransformer( self::$config_path );
186 foreach ( $add as $constant => $config ) {
187 $value = 'wp_debug_display' === $constant ? 'false' : 'true';
188 $value = isset( $config['value'] ) ? $config['value'] : $value;
189 $raw = isset( $config['raw'] ) ? $config['raw'] : true;
190 self::$config_args = array_merge( self::$config_args, [ 'raw' => $raw ] );
191 $config_transformer->update( 'constant', strtoupper( $constant ), $value, self::$config_args );
192 $added[ $constant ] = $value;
193 }
194
195 return $added;
196 } catch ( \Exception $e ) {
197 $messsage = 'Caught Exception: \Fragen\WP_Debugging\Settings::add_constants() - ' . $e->getMessage();
198 // error_log( $messsage );
199 wp_die( esc_html( $messsage ) );
200 }
201 }
202
203 /**
204 * Process user defined constants added via filter.
205 *
206 * @return void
207 */
208 public function process_filter_constants() {
209 /**
210 * Filter to add user define constants.
211 *
212 * @since 2.5.0
213 *
214 * @param array Array of added constants.
215 * The format for adding constants is to return an array of arrays.
216 * Each array will have the constant as the key with an array of configuration data.
217 * array(
218 * 'my_constant' =>
219 * array(
220 * 'value' => $value, @type string
221 * 'raw' => $raw, // Optional. @type bool $raw is a boolean where false will return the value in quotes and true will return the raw value. Default is true.
222 * ),
223 * )
224 * Default is an empty array.
225 */
226 $filter_constants = apply_filters( 'wp_debugging_add_constants', [] );
227 $remove_user_defined = array_diff( self::$options, array_flip( $this->defined_constants ) );
228
229 // Remove and re-add user defined constants. Clean up for when filter removed or changed.
230 if ( ! empty( $remove_user_defined ) ) {
231 $this->remove_constants( $remove_user_defined );
232 }
233 $added_constants = $this->add_constants( $filter_constants );
234
235 $options = array_diff( self::$options, $remove_user_defined );
236 self::$options = array_merge( $options, $added_constants );
237 update_site_option( 'wp_debugging', (array) self::$options );
238 }
239
240 /**
241 * Remove constants from wp-config.php file.
242 *
243 * @uses https://github.com/wp-cli/wp-config-transformer
244 *
245 * @param array $remove Constants to remove from wp-config.php.
246 * @return void
247 */
248 public function remove_constants( $remove ) {
249 try {
250 $config_transformer = new \WPConfigTransformer( self::$config_path );
251 foreach ( array_keys( $remove ) as $constant ) {
252 $config_transformer->remove( 'constant', strtoupper( $constant ) );
253 }
254 } catch ( \Exception $e ) {
255 $messsage = 'Caught Exception: \Fragen\WP_Debugging\Settings::remove_constants() - ' . $e->getMessage();
256 // error_log( $messsage );
257 wp_die( esc_html( $messsage ) );
258 }
259 }
260
261 /**
262 * Redirect back to settings page on save.
263 *
264 * @return void
265 */
266 private function redirect_on_save() {
267 $update = false;
268 if ( ! wp_verify_nonce( static::$nonce, 'wp-debugging' ) ) {
269 return;
270 }
271
272 if ( ( isset( $_POST['action'] ) && 'update' === $_POST['action'] ) &&
273 ( isset( $_POST['option_page'] ) && 'wp_debugging' === $_POST['option_page'] )
274 ) {
275 $update = true;
276 }
277
278 $redirect_url = is_multisite() ? network_admin_url( 'settings.php' ) : admin_url( 'tools.php' );
279
280 if ( $update ) {
281 $location = add_query_arg(
282 [
283 'page' => 'wp-debugging',
284 'updated' => $update,
285 ],
286 $redirect_url
287 );
288 wp_safe_redirect( $location );
289 exit;
290 }
291 }
292
293 /**
294 * Add notice when settings are saved.
295 *
296 * @return void
297 */
298 private function saved_settings_notice() {
299 if ( ! wp_verify_nonce( static::$nonce, 'wp-debugging' ) ) {
300 return;
301 }
302 if ( ( isset( $_GET['updated'] ) && '1' === $_GET['updated'] ) ||
303 ( isset( $_GET['settings-updated'] ) && '1' === $_GET['settings-updated'] )
304 ) {
305 echo '<div class="updated"><p>';
306 esc_html_e( 'Saved.', 'wp-debugging' );
307 echo '</p></div>';
308 }
309 }
310
311 /**
312 * Register settings.
313 *
314 * @return void
315 */
316 public function add_settings() {
317 register_setting(
318 'wp_debugging',
319 'wp_debugging',
320 [ $this, 'sanitize' ]
321 );
322
323 add_settings_section(
324 'wp_debugging',
325 esc_html__( 'Debugging Constants', 'wp-debugging' ),
326 [ $this, 'print_settings_section' ],
327 'wp_debugging'
328 );
329
330 add_settings_field(
331 'wp_debug',
332 null,
333 [ $this, 'checkbox_setting' ],
334 'wp_debugging',
335 'wp_debugging',
336 [
337 'id' => 'wp_debug',
338 'title' => esc_html__( 'Set WP_DEBUG to true.', 'wp-debugging' ),
339 ]
340 );
341
342 add_settings_field(
343 'wp_debug_display',
344 null,
345 [ $this, 'checkbox_setting' ],
346 'wp_debugging',
347 'wp_debugging',
348 [
349 'id' => 'wp_debug_display',
350 'title' => esc_html__( 'Set WP_DEBUG_DISPLAY to false, default is true.', 'wp-debugging' ),
351 ]
352 );
353
354 add_settings_field(
355 'wp_disable_fatal_error_handler',
356 null,
357 [ $this, 'checkbox_setting' ],
358 'wp_debugging',
359 'wp_debugging',
360 [
361 'id' => 'wp_disable_fatal_error_handler',
362 'title' => esc_html__( 'Set WP_DISABLE_FATAL_ERROR_HANDLER to true.', 'wp-debugging' ),
363 'class' => version_compare( get_bloginfo( 'version' ), '5.2', '>=' ) ? '' : 'hidden',
364 ]
365 );
366 }
367
368 /**
369 * Print settings section information.
370 *
371 * @return void
372 */
373 public function print_settings_section() {
374 esc_html_e( 'The following constants are set with plugin activation and removed with plugin deactivation.', 'wp-debugging' );
375 $this->print_constants();
376 esc_html_e( 'Select the debugging constants.', 'wp-debugging' );
377 }
378
379 /**
380 * Print current constants.
381 *
382 * @return void
383 */
384 private function print_constants() {
385 $added_constants = apply_filters( 'wp_debugging_add_constants', [] );
386 $additional_constants = [];
387 if ( $added_constants ) {
388 foreach ( $added_constants as $constant => $config ) {
389 $additional_constants[ $constant ] = $config['value'];
390 }
391 }
392
393 // Strip user defined constants from $constants array.
394 $constants = [ 'wp_debug_log', 'script_debug', 'savequeries' ];
395 $constants = array_merge( array_keys( self::$options ), $constants );
396 $constants = array_diff( $constants, array_keys( $additional_constants ) );
397
398 echo '<pre>';
399 foreach ( $constants as $constant ) {
400 $value = 'wp_debug_display' === $constant ? 'false' : 'true';
401 $constant = strtoupper( $constant );
402 echo wp_kses_post( "<code>define( '{$constant}', {$value} );</code><br>" );
403 }
404 foreach ( $additional_constants as $constant => $value ) {
405 $value = in_array( $value, [ 'true', 'false' ], true ) ? $value : "'$value'";
406 $constant = strtoupper( $constant );
407 echo wp_kses_post( "<code>define( '{$constant}', {$value} );</code><br>" );
408 }
409 echo '</pre>';
410 }
411
412 /**
413 * Create settings page.
414 *
415 * @return void
416 */
417 public function create_settings_page() {
418 $this->saved_settings_notice();
419 $action = is_multisite() ? 'edit.php?action=wp-debugging' : 'options.php'; ?>
420 <div class="wrap">
421 <h1><?php esc_html_e( 'WP Debugging', 'wp-debugging' ); ?></h1>
422 <div class="updated fade">
423 <p><?php echo wp_kses_post( __( '<strong>Please note:</strong> Your <code>wp-config.php</code> file must be writable by the filesystem. Any errors will result in a PHP Exception being thrown. Debug constants per <a href="https://codex.wordpress.org/Debugging_in_WordPress">Debugging in WordPress</a>.', 'wp-debugging' ) ); ?></p>
424 </div>
425 <div>
426 <form method="post" action="<?php echo esc_attr( $action ); ?>">
427 <?php settings_fields( 'wp_debugging' ); ?>
428 <?php do_settings_sections( 'wp_debugging' ); ?>
429 <?php submit_button(); ?>
430 </form>
431 </div>
432 <?php
433 }
434
435 /**
436 * Sanitize save settings.
437 *
438 * @param array $input Input.
439 * @return array $new_input Sanitized output.
440 */
441 public function sanitize( $input ) {
442 $new_input = [];
443 if ( ! is_array( $input ) ) {
444 $new_input = sanitize_text_field( $input );
445 } else {
446 foreach ( array_keys( (array) $input ) as $id ) {
447 $new_input[ sanitize_text_field( $id ) ] = sanitize_text_field( $input[ $id ] );
448 }
449 }
450
451 return $new_input;
452 }
453
454 /**
455 * Get the settings option array and print one of its values.
456 *
457 * @param array $args 'id' and 'title'.
458 */
459 public function checkbox_setting( $args ) {
460 $checked = isset( self::$options[ $args['id'] ] ) ? self::$options[ $args['id'] ] : null;
461 ?>
462 <style> .form-table th { display:none; } </style>
463 <label for="<?php echo esc_attr( $args['id'] ); ?>">
464 <input type="checkbox" name="wp-debugging[<?php echo esc_attr( $args['id'] ); ?>]" value="1" <?php checked( '1', $checked ); ?> >
465 <?php esc_html_e( $args['title'] ); ?>
466 </label>
467 <?php
468 }
469
470 /**
471 * Add setting link to plugin page.
472 * Applied to the list of links to display on the plugins page (beside the activate/deactivate links).
473 *
474 * @param array $links Plugin links on plugins.php.
475 *
476 * @return array
477 */
478 public function plugin_action_links( $links ) {
479 $settings_page = is_multisite() ? 'settings.php' : 'tools.php';
480 $link = [ '<a href="' . esc_url( network_admin_url( $settings_page ) ) . '?page=wp-debugging">' . esc_html__( 'Settings', 'wp-debugging' ) . '</a>' ];
481
482 return array_merge( $link, $links );
483 }
484 }
485