PluginProbe
Code Snippets / 3.8.1
Code Snippets v3.8.1
3.10.2 3.10.1 3.10.0 3.10.0-beta.2 3.10.0-beta.1 4.0.0-beta.1 3.9.6 trunk 2.10.0 2.10.1 2.12.0 2.12.1 2.13.0 2.13.1 2.13.2 2.13.3 2.14.0 2.14.1 2.14.2 2.14.3 2.14.4 2.14.5 2.14.6 3.0.0 3.0.1 All 64 releases
code-snippets / php / settings / settings.php

settings.php in Code Snippets 3.8.1, at php/settings/settings.php

350 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * This file registers the settings
4 *
5 * @package Code_Snippets
6 * @subpackage Settings
7 */
8
9 namespace Code_Snippets\Settings;
10
11 use Code_Snippets\Welcome_API;
12 use function Code_Snippets\clean_snippets_cache;
13 use function Code_Snippets\code_snippets;
14
15 const CACHE_KEY = 'code_snippets_settings';
16 const OPTION_GROUP = 'code-snippets';
17 const OPTION_NAME = 'code_snippets_settings';
18
19 /**
20 * Add a new option for either the current site or the current network
21 *
22 * @param bool $network Whether to add a network-wide option.
23 * @param string $option Name of option to add. Expected to not be SQL-escaped.
24 * @param mixed $value Option value, can be anything. Expected to not be SQL-escaped.
25 *
26 * @return bool False if the option was not added. True if the option was added.
27 */
28 function add_self_option( bool $network, string $option, $value ): bool {
29 return $network ? add_site_option( $option, $value ) : add_option( $option, $value );
30 }
31
32 /**
33 * Retrieves an option value based on an option name from either the current site or the current network
34 *
35 * @param bool $network Whether to get a network-wide option.
36 * @param string $option Name of option to retrieve. Expected to not be SQL-escaped.
37 * @param mixed $default_value Optional value to return if option doesn't exist. Default false.
38 *
39 * @return mixed Value set for the option.
40 */
41 function get_self_option( bool $network, string $option, $default_value = false ) {
42 return $network ? get_site_option( $option, $default_value ) : get_option( $option, $default_value );
43 }
44
45 /**
46 * Update the value of an option that was already added on the current site or the current network
47 *
48 * @param bool $network Whether to update a network-wide option.
49 * @param string $option Name of option. Expected to not be SQL-escaped.
50 * @param mixed $value Option value. Expected to not be SQL-escaped.
51 *
52 * @return bool False if value was not updated. True if value was updated.
53 */
54 function update_self_option( bool $network, string $option, $value ): bool {
55 return $network ? update_site_option( $option, $value ) : update_option( $option, $value );
56 }
57
58 /**
59 * Returns 'true' if plugin settings are unified on a multisite installation
60 * under the Network Admin settings menu
61 *
62 * This option is controlled by the "Enable administration menus" setting on the Network Settings menu
63 *
64 * @return bool
65 */
66 function are_settings_unified(): bool {
67 if ( ! is_multisite() ) {
68 return false;
69 }
70
71 $menu_perms = get_site_option( 'menu_items', array() );
72 return empty( $menu_perms['snippets_settings'] );
73 }
74
75 /**
76 * Retrieve the setting values from the database.
77 * If a setting does not exist in the database, the default value will be returned.
78 *
79 * @return array<string, array<string, mixed>>
80 */
81 function get_settings_values(): array {
82 $settings = wp_cache_get( CACHE_KEY );
83 if ( $settings ) {
84 return $settings;
85 }
86
87 $settings = get_default_settings();
88 $saved = get_self_option( are_settings_unified(), OPTION_NAME, array() );
89
90 foreach ( $settings as $section => $fields ) {
91 if ( isset( $saved[ $section ] ) ) {
92 $settings[ $section ] = array_replace( $fields, $saved[ $section ] );
93 }
94 }
95
96 wp_cache_set( CACHE_KEY, $settings );
97 return $settings;
98 }
99
100 /**
101 * Retrieve an individual setting field value
102 *
103 * @param string $section ID of the section the setting belongs to.
104 * @param string $field ID of the setting field.
105 *
106 * @return mixed
107 */
108 function get_setting( string $section, string $field ) {
109 $settings = get_settings_values();
110
111 return $settings[ $section ][ $field ] ?? null;
112 }
113
114 /**
115 * Update a single setting to a new value.
116 *
117 * @param string $section ID of the section the setting belongs to.
118 * @param string $field ID of the setting field.
119 * @param mixed $new_value Setting value. Expected to not be SQL-escaped.
120 *
121 * @return bool False if value was not updated. True if value was updated.
122 */
123 function update_setting( string $section, string $field, $new_value ): bool {
124 $settings = get_settings_values();
125
126 $settings[ $section ][ $field ] = $new_value;
127
128 wp_cache_set( CACHE_KEY, $settings );
129 return update_self_option( are_settings_unified(), OPTION_NAME, $settings );
130 }
131
132 /**
133 * Retrieve the settings sections
134 *
135 * @return array<string, string> Settings sections.
136 */
137 function get_settings_sections(): array {
138 $sections = array(
139 'general' => __( 'General', 'code-snippets' ),
140 'editor' => __( 'Code Editor', 'code-snippets' ),
141 'debug' => __( 'Debug', 'code-snippets' ),
142 );
143
144 // Only show the Version section when the debug setting to enable version changes is enabled.
145 $enable_version = get_setting( 'debug', 'enable_version_change' );
146 if ( $enable_version ) {
147 $sections['version-switch'] = __( 'Version', 'code-snippets' );
148 }
149
150 return apply_filters( 'code_snippets_settings_sections', $sections );
151 }
152
153 /**
154 * Register settings sections, fields, etc
155 */
156 function register_plugin_settings() {
157 if ( are_settings_unified() ) {
158 if ( ! get_site_option( OPTION_NAME ) ) {
159 add_site_option( OPTION_NAME, get_default_settings() );
160 }
161 } elseif ( ! get_option( OPTION_NAME ) ) {
162 add_option( OPTION_NAME, get_default_settings() );
163 }
164
165 // Register the setting.
166 register_setting(
167 OPTION_GROUP,
168 OPTION_NAME,
169 [ 'sanitize_callback' => __NAMESPACE__ . '\\sanitize_settings' ]
170 );
171
172 // Register settings sections.
173 foreach ( get_settings_sections() as $section_id => $section_name ) {
174 add_settings_section( $section_id, $section_name, '__return_empty_string', 'code-snippets' );
175 }
176
177 // Register settings fields. Only register fields for sections that exist (some sections may be gated by settings).
178 $registered_sections = get_settings_sections();
179 foreach ( get_settings_fields() as $section_id => $fields ) {
180 if ( ! isset( $registered_sections[ $section_id ] ) ) {
181 continue;
182 }
183
184 foreach ( $fields as $field_id => $field ) {
185 $field_object = new Setting_Field( $section_id, $field_id, $field );
186 add_settings_field( $field_id, $field['name'], [ $field_object, 'render' ], 'code-snippets', $section_id );
187 }
188 }
189
190 // Add editor preview as a field.
191 add_settings_field(
192 'editor_preview',
193 __( 'Editor Preview', 'code-snippets' ),
194 __NAMESPACE__ . '\\render_editor_preview',
195 'code-snippets',
196 'editor'
197 );
198 }
199
200 add_action( 'admin_init', __NAMESPACE__ . '\\register_plugin_settings' );
201
202 /**
203 * Sanitize a single setting value.
204 *
205 * @param array<string, mixed> $field Setting field information.
206 * @param mixed $input_value User input setting value, or null if missing.
207 *
208 * @return mixed Sanitized setting value, or null if unset.
209 */
210 function sanitize_setting_value( array $field, $input_value ) {
211 switch ( $field['type'] ) {
212
213 case 'checkbox':
214 return 'on' === $input_value;
215
216 case 'number':
217 return intval( $input_value );
218
219 case 'select':
220 $select_options = array_map( 'strval', array_keys( $field['options'] ) );
221 return in_array( strval( $input_value ), $select_options, true ) ? $input_value : null;
222
223 case 'checkboxes':
224 $results = [];
225
226 if ( ! empty( $input_value ) ) {
227 foreach ( $field['options'] as $option_id => $option_label ) {
228 if ( isset( $input_value[ $option_id ] ) && 'on' === $input_value[ $option_id ] ) {
229 $results[] = $option_id;
230 }
231 }
232 }
233
234 return $results;
235
236 case 'text':
237 case 'hidden':
238 return trim( sanitize_text_field( $input_value ) );
239
240 case 'callback':
241 return isset( $field['sanitize_callback'] ) && is_callable( $field['sanitize_callback'] ) ?
242 call_user_func( $field['sanitize_callback'], $input_value ) :
243 null;
244
245 default:
246 return null;
247 }
248 }
249
250 /**
251 * Process settings actions.
252 *
253 * @param array $input Provided settings input.
254 *
255 * @return array|null New $input value to return, or null to continue with settings update process.
256 */
257 function process_settings_actions( array $input ): ?array {
258
259 if ( isset( $input['reset_settings'] ) ) {
260 add_settings_error(
261 OPTION_NAME,
262 'settings_reset',
263 __( 'All settings have been reset to their defaults.', 'code-snippets' ),
264 'updated'
265 );
266
267 delete_option( 'code_snippets_cloud_settings' );
268 return [];
269 }
270
271 if ( isset( $input['debug']['database_update'] ) ) {
272 code_snippets()->db->create_or_upgrade_tables();
273
274 add_settings_error(
275 OPTION_NAME,
276 'database_update_done',
277 __( 'Successfully performed database table upgrade.', 'code-snippets' ),
278 'updated'
279 );
280 }
281
282 if ( isset( $input['debug']['reset_caches'] ) ) {
283 Welcome_API::clear_cache();
284 clean_snippets_cache( code_snippets()->db->get_table_name( false ) );
285
286 if ( is_multisite() ) {
287 clean_snippets_cache( code_snippets()->db->get_table_name( true ) );
288 }
289
290 add_settings_error(
291 OPTION_NAME,
292 'snippet_caches_reset',
293 __( 'Successfully reset snippets caches.', 'code-snippets' ),
294 'updated'
295 );
296 }
297
298 return null;
299 }
300
301 /**
302 * Validate the settings
303 *
304 * @param array<string, array<string, mixed>> $input The received settings.
305 *
306 * @return array<string, array<string, mixed>> The validated settings.
307 */
308 function sanitize_settings( array $input ): array {
309 wp_cache_delete( CACHE_KEY );
310 $result = process_settings_actions( $input );
311
312 if ( ! is_null( $result ) ) {
313 return $result;
314 }
315
316 $settings = get_settings_values();
317 $updated = false;
318
319 // Don't directly loop through $input as it does not include as deselected checkboxes.
320 foreach ( get_settings_fields() as $section_id => $fields ) {
321 foreach ( $fields as $field_id => $field ) {
322
323 // Fetch the corresponding input value from the posted data.
324 $input_value = $input[ $section_id ][ $field_id ] ?? null;
325
326 // Attempt to sanitize the setting value.
327 $sanitized_value = sanitize_setting_value( $field, $input_value );
328
329 if ( ! is_null( $sanitized_value ) && $settings[ $section_id ][ $field_id ] !== $sanitized_value ) {
330 $settings[ $section_id ][ $field_id ] = $sanitized_value;
331 $updated = true;
332 }
333 }
334 }
335
336 // Add an updated message.
337 if ( $updated ) {
338 add_settings_error(
339 OPTION_NAME,
340 'settings-saved',
341 __( 'Settings saved.', 'code-snippets' ),
342 'updated'
343 );
344
345 do_action( 'code_snippets/settings_updated', $settings, $input );
346 }
347
348 return $settings;
349 }
350