PluginProbe
WP Debugging / 2.9.0
WP Debugging v2.9.0
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.9.0, at src/Settings.php

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