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

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