PluginProbe
WP Debugging / 2.7.1
WP Debugging v2.7.1
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.1, at src/Settings.php

443 lines 12.2 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 $added = [];
150 $config_transformer = new \WPConfigTransformer( self::$config_path );
151 foreach ( $add as $constant => $config ) {
152 $value = 'wp_debug_display' === $constant ? 'false' : 'true';
153 $value = isset( $config['value'] ) ? $config['value'] : $value;
154 $raw = isset( $config['raw'] ) ? $config['raw'] : true;
155 $config_args = [
156 'raw' => $raw,
157 'normalize' => true,
158 ];
159 $config_transformer->update( 'constant', strtoupper( $constant ), $value, $config_args );
160 $added[ $constant ] = $value;
161 }
162
163 return $added;
164 }
165
166 /**
167 * Process user defined constants added via filter.
168 *
169 * @return void
170 */
171 public function process_filter_constants() {
172 /**
173 * Filter to add user define constants.
174 *
175 * @since 2.5.0
176 *
177 * @param array Array of added constants.
178 * The format for adding constants is to return an array of arrays.
179 * Each array will have the constant as the key with an array of configuration data.
180 * array(
181 * 'my_constant' =>
182 * array(
183 * 'value' => $value, @type string
184 * '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.
185 * ),
186 * )
187 * Default is an empty array.
188 */
189 $filter_constants = apply_filters( 'wp_debugging_add_constants', [] );
190 $remove_user_defined = array_diff( self::$options, array_flip( $this->defined_constants ) );
191
192 // Remove and re-add user defined constants. Clean up for when filter removed or changed.
193 if ( ! empty( $remove_user_defined ) ) {
194 $this->remove_constants( $remove_user_defined );
195 }
196 $added_constants = $this->add_constants( $filter_constants );
197
198 $options = array_diff( self::$options, $remove_user_defined );
199 self::$options = array_merge( $options, $added_constants );
200 update_site_option( 'wp_debugging', (array) self::$options );
201 }
202
203 /**
204 * Remove constants from wp-config.php file.
205 *
206 * @uses https://github.com/wp-cli/wp-config-transformer
207 *
208 * @param array $remove Constants to remove from wp-config.php.
209 * @return void
210 */
211 public function remove_constants( $remove ) {
212 $config_transformer = new \WPConfigTransformer( self::$config_path );
213 foreach ( array_keys( $remove ) as $constant ) {
214 $config_transformer->remove( 'constant', strtoupper( $constant ) );
215 }
216 }
217
218 /**
219 * Redirect back to settings page on save.
220 *
221 * phpcs:disable WordPress.Security.NonceVerification.Missing
222 *
223 * @return void
224 */
225 private function redirect_on_save() {
226 $update = false;
227 if ( ( isset( $_POST['action'] ) && 'update' === $_POST['action'] ) &&
228 ( isset( $_POST['option_page'] ) && 'wp_debugging' === $_POST['option_page'] )
229 ) {
230 $update = true;
231 }
232 // phpcs:enable
233
234 $redirect_url = is_multisite() ? network_admin_url( 'settings.php' ) : admin_url( 'tools.php' );
235
236 if ( $update ) {
237 $location = add_query_arg(
238 [
239 'page' => 'wp-debugging',
240 'updated' => $update,
241 ],
242 $redirect_url
243 );
244 wp_safe_redirect( $location );
245 exit;
246 }
247 }
248
249 /**
250 * Add notice when settings are saved.
251 *
252 * phpcs:disable WordPress.PHP.StrictComparisons.LooseComparison
253 * phpcs:disable WordPress.Security.NonceVerification.Recommended
254 *
255 * @return void
256 */
257 private function saved_settings_notice() {
258 if ( ( isset( $_GET['updated'] ) && true == $_GET['updated'] ) ||
259 ( isset( $_GET['settings-updated'] ) && true == $_GET['settings-updated'] )
260 ) {
261 echo '<div class="updated"><p>';
262 esc_html_e( 'Saved.', 'wp-debugging' );
263 echo '</p></div>';
264 }
265 // phpcs:enable
266 }
267
268 /**
269 * Register settings.
270 *
271 * @return void
272 */
273 public function add_settings() {
274 register_setting(
275 'wp_debugging',
276 'wp_debugging',
277 [ $this, 'sanitize' ]
278 );
279
280 add_settings_section(
281 'wp_debugging',
282 esc_html__( 'Debugging Constants', 'wp-debugging' ),
283 [ $this, 'print_settings_section' ],
284 'wp_debugging'
285 );
286
287 add_settings_field(
288 'wp_debug',
289 null,
290 [ $this, 'checkbox_setting' ],
291 'wp_debugging',
292 'wp_debugging',
293 [
294 'id' => 'wp_debug',
295 'title' => esc_html__( 'Set WP_DEBUG to true.', 'wp-debugging' ),
296 ]
297 );
298
299 add_settings_field(
300 'wp_debug_display',
301 null,
302 [ $this, 'checkbox_setting' ],
303 'wp_debugging',
304 'wp_debugging',
305 [
306 'id' => 'wp_debug_display',
307 'title' => esc_html__( 'Set WP_DEBUG_DISPLAY to false, default is true.', 'wp-debugging' ),
308 ]
309 );
310
311 if ( version_compare( get_bloginfo( 'version' ), '5.2-beta', '>=' ) ) {
312 add_settings_field(
313 'wp_disable_fatal_error_handler',
314 null,
315 [ $this, 'checkbox_setting' ],
316 'wp_debugging',
317 'wp_debugging',
318 [
319 'id' => 'wp_disable_fatal_error_handler',
320 'title' => esc_html__( 'Set WP_DISABLE_FATAL_ERROR_HANDLER to true.', 'wp-debugging' ),
321 ]
322 );
323 }
324 }
325
326 /**
327 * Print settings section information.
328 *
329 * @return void
330 */
331 public function print_settings_section() {
332 esc_html_e( 'The following constants are set with plugin activation and removed with plugin deactivation.', 'wp-debugging' );
333 $this->print_constants();
334 esc_html_e( 'Select the debugging constants.', 'wp-debugging' );
335 }
336
337 /**
338 * Print current constants.
339 *
340 * @return void
341 */
342 private function print_constants() {
343 $added_constants = apply_filters( 'wp_debugging_add_constants', [] );
344 $additional_constants = [];
345 if ( $added_constants ) {
346 foreach ( $added_constants as $constant => $config ) {
347 $additional_constants[ $constant ] = $config['value'];
348 }
349 }
350
351 // Strip user defined constants from $constants array.
352 $constants = [ 'wp_debug_log', 'script_debug', 'savequeries' ];
353 $constants = array_merge( array_keys( self::$options ), $constants );
354 $constants = array_diff( $constants, array_keys( $additional_constants ) );
355
356 echo '<pre>';
357 foreach ( $constants as $constant ) {
358 $value = 'wp_debug_display' === $constant ? 'false' : 'true';
359 $constant = strtoupper( $constant );
360 echo wp_kses_post( "<code>define( '{$constant}', {$value} );</code><br>" );
361 }
362 foreach ( $additional_constants as $constant => $value ) {
363 $value = in_array( $value, [ 'true', 'false' ], true ) ? $value : "'$value'";
364 $constant = strtoupper( $constant );
365 echo wp_kses_post( "<code>define( '{$constant}', {$value} );</code><br>" );
366 }
367 echo '</pre>';
368 }
369
370 /**
371 * Create settings page.
372 *
373 * @return void
374 */
375 public function create_settings_page() {
376 $this->saved_settings_notice();
377 $action = is_multisite() ? 'edit.php?action=wp-debugging' : 'options.php'; ?>
378 <div class="wrap">
379 <h1><?php esc_html_e( 'WP Debugging', 'wp-debugging' ); ?></h1>
380 <div class="updated fade">
381 <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>
382 </div>
383 <div>
384 <form method="post" action="<?php esc_attr_e( $action ); ?>">
385 <?php settings_fields( 'wp_debugging' ); ?>
386 <?php do_settings_sections( 'wp_debugging' ); ?>
387 <?php submit_button(); ?>
388 </form>
389 </div>
390 <?php
391 }
392
393 /**
394 * Sanitize save settings.
395 *
396 * @param array $input Input.
397 * @return array $new_input Sanitized output.
398 */
399 public function sanitize( $input ) {
400 $new_input = [];
401 if ( ! is_array( $input ) ) {
402 $new_input = sanitize_text_field( $input );
403 } else {
404 foreach ( array_keys( (array) $input ) as $id ) {
405 $new_input[ sanitize_text_field( $id ) ] = sanitize_text_field( $input[ $id ] );
406 }
407 }
408
409 return $new_input;
410 }
411
412 /**
413 * Get the settings option array and print one of its values.
414 *
415 * @param array $args 'id' and 'title'.
416 */
417 public function checkbox_setting( $args ) {
418 $checked = isset( self::$options[ $args['id'] ] ) ? self::$options[ $args['id'] ] : null;
419 ?>
420 <style> .form-table th { display:none; } </style>
421 <label for="<?php esc_attr_e( $args['id'] ); ?>">
422 <input type="checkbox" name="wp-debugging[<?php esc_attr_e( $args['id'] ); ?>]" value="1" <?php checked( '1', $checked ); ?> >
423 <?php esc_html_e( $args['title'] ); ?>
424 </label>
425 <?php
426 }
427
428 /**
429 * Add setting link to plugin page.
430 * Applied to the list of links to display on the plugins page (beside the activate/deactivate links).
431 *
432 * @param array $links Plugin links on plugins.php.
433 *
434 * @return array
435 */
436 public function plugin_action_links( $links ) {
437 $settings_page = is_multisite() ? 'settings.php' : 'tools.php';
438 $link = [ '<a href="' . esc_url( network_admin_url( $settings_page ) ) . '?page=wp-debugging">' . esc_html__( 'Settings', 'wp-debugging' ) . '</a>' ];
439
440 return array_merge( $link, $links );
441 }
442 }
443