PluginProbe
Booking Calendar / 11.8.4
Booking Calendar v11.8.4
11.8.4 11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 All 204 releases
booking / includes / save-load-option / option-save-policies.php

option-save-policies.php in Booking Calendar 11.8.4, at includes/save-load-option/option-save-policies.php

455 lines 15.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Option-specific save policies for the generic WPBC option saver.
4 *
5 * Keep feature-specific permissions and value normalization here so
6 * save-load-option.php can stay focused on transport, nonce checks, and storage.
7 *
8 * @package Booking Calendar
9 */
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 /**
16 * Shared helpers for global option save policies.
17 */
18 class WPBC_Option_Save_Policy_Global_Options {
19
20 /**
21 * Check if current user can save global options.
22 *
23 * In MultiUser regular users do not have access to global options.
24 *
25 * @return bool
26 */
27 public static function can_save_global_options() {
28 return ( ! function_exists( 'wpbc_is_mu_user_can_be_here' ) || wpbc_is_mu_user_can_be_here( 'only_super_admin' ) );
29 }
30
31 /**
32 * Normalize On/Off option values.
33 *
34 * @param mixed $value Raw value.
35 *
36 * @return string
37 */
38 public static function normalize_on_off( $value ) {
39 return ( 'On' === $value ) ? 'On' : 'Off';
40 }
41
42 /**
43 * Normalize a three- or six-digit hexadecimal color.
44 *
45 * @param mixed $value Raw value.
46 * @return string
47 */
48 public static function normalize_hex_color( $value ) {
49
50 $value = sanitize_text_field( (string) $value );
51
52 return preg_match( '/^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i', $value ) ? $value : '#066aab';
53 }
54
55 /**
56 * Normalize the global Booking Form style identifier.
57 *
58 * @param mixed $value Raw value.
59 * @param string $data_name Submitted option name.
60 *
61 * @return string
62 */
63 public static function normalize_form_style( $value, $data_name = '' ) {
64
65 if ( function_exists( 'wpbc_bfb_settings__sanitize_form_style' ) ) {
66 return wpbc_bfb_settings__sanitize_form_style( $value );
67 }
68
69 $value = sanitize_key( (string) $value );
70 $allowed = array( 'light_bordered', 'light_none', 'light_soft', 'dark_bordered', 'dark_none', 'dark_soft', 'custom' );
71
72 return in_array( $value, $allowed, true ) ? $value : 'light_bordered';
73 }
74
75 /**
76 * Get option names belonging to the global Custom Booking Form style.
77 *
78 * @return array
79 */
80 public static function get_custom_form_style_option_names() {
81
82 if ( function_exists( 'wpbc_bfb_settings__get_default_custom_form_style_options' ) ) {
83 return array_keys( wpbc_bfb_settings__get_default_custom_form_style_options() );
84 }
85
86 return array(
87 'booking_form_custom_background_color',
88 'booking_form_custom_border_color',
89 'booking_form_custom_border_width',
90 'booking_form_custom_border_radius',
91 'booking_form_custom_padding_vertical',
92 'booking_form_custom_padding_horizontal',
93 'booking_form_custom_text_color',
94 'booking_form_custom_field_background_color',
95 'booking_form_custom_field_text_color',
96 'booking_form_custom_field_border_color',
97 'booking_form_custom_button_background_color',
98 'booking_form_custom_button_text_color',
99 'booking_form_custom_button_border_color',
100 'booking_form_custom_button_hover_background_color',
101 'booking_form_custom_button_hover_text_color',
102 'booking_form_custom_button_hover_border_color',
103 'booking_form_custom_secondary_button_background_color',
104 'booking_form_custom_secondary_button_text_color',
105 'booking_form_custom_secondary_button_border_color',
106 'booking_form_custom_secondary_button_hover_background_color',
107 'booking_form_custom_secondary_button_hover_text_color',
108 'booking_form_custom_secondary_button_hover_border_color',
109 );
110 }
111
112 /**
113 * Normalize one global Custom Booking Form style option.
114 *
115 * @param mixed $value Raw value.
116 * @param string $data_name Submitted option name.
117 *
118 * @return string
119 */
120 public static function normalize_custom_form_style_option( $value, $data_name = '' ) {
121
122 $data_name = sanitize_key( (string) $data_name );
123
124 if (
125 function_exists( 'wpbc_bfb_settings__get_custom_form_style_options' )
126 && in_array( $data_name, self::get_custom_form_style_option_names(), true )
127 ) {
128 $sanitized = wpbc_bfb_settings__get_custom_form_style_options(
129 array(
130 $data_name => $value,
131 )
132 );
133
134 if ( array_key_exists( $data_name, $sanitized ) ) {
135 return $sanitized[ $data_name ];
136 }
137 }
138
139 return sanitize_text_field( is_scalar( $value ) ? (string) $value : '' );
140 }
141
142 /**
143 * Normalize the pre-check-in hint duration used by the Form Builder setting.
144 *
145 * @param mixed $value Raw value.
146 * @param string $data_name Submitted option name.
147 *
148 * @return string Number of days between 1 and 91.
149 */
150 public static function normalize_pre_checkin_days( $value, $data_name = '' ) {
151
152 $days = is_scalar( $value ) ? absint( $value ) : 14;
153
154 return (string) min( 91, max( 1, $days ) );
155 }
156 }
157
158 /**
159 * Calendar global option policies.
160 */
161 class WPBC_Option_Save_Policy_Global_Calendar {
162
163 /**
164 * Normalize and validate global calendar skin value before saving.
165 *
166 * @param mixed $data_raw Raw calendar skin value.
167 * @param string $data_name Option name.
168 *
169 * @return string
170 */
171 public static function normalize_calendar_skin( $data_raw, $data_name = '' ) {
172
173 $skin_value = is_scalar( $data_raw ) ? (string) $data_raw : '';
174 $replace = array();
175
176 if ( defined( 'WPBC_PLUGIN_DIR' ) ) {
177 $replace[] = WPBC_PLUGIN_DIR;
178 }
179 if ( defined( 'WPBC_PLUGIN_URL' ) ) {
180 $replace[] = WPBC_PLUGIN_URL;
181 }
182
183 $upload_dir = wp_upload_dir();
184 if ( ! empty( $upload_dir['basedir'] ) ) {
185 $replace[] = $upload_dir['basedir'];
186 }
187 if ( ! empty( $upload_dir['baseurl'] ) ) {
188 $replace[] = $upload_dir['baseurl'];
189 }
190
191 $skin_value = str_replace( $replace, '', $skin_value );
192 $skin_value = sanitize_text_field( $skin_value );
193
194 if (
195 '' === $skin_value ||
196 false !== strpos( $skin_value, '..' ) ||
197 ! preg_match( '/\.css$/i', $skin_value ) ||
198 ( 0 !== strpos( $skin_value, '/css/skins/' ) && 0 !== strpos( $skin_value, '/wpbc_skins/' ) )
199 ) {
200 wp_send_json_error( array( 'message' => __( 'Invalid calendar skin.', 'booking' ) ) );
201 }
202
203 $file_path = '';
204 if ( 0 === strpos( $skin_value, '/wpbc_skins/' ) ) {
205 $file_path = ( ! empty( $upload_dir['basedir'] ) ) ? $upload_dir['basedir'] . $skin_value : '';
206 } elseif ( defined( 'WPBC_PLUGIN_DIR' ) ) {
207 $file_path = WPBC_PLUGIN_DIR . $skin_value;
208 }
209
210 if ( empty( $file_path ) || ! file_exists( $file_path ) ) {
211 wp_send_json_error( array( 'message' => __( 'Calendar skin file does not exist.', 'booking' ) ) );
212 }
213
214 return $skin_value;
215 }
216
217 /**
218 * Get allowed global calendar legend option names.
219 *
220 * @return array
221 */
222 public static function get_calendar_legend_option_names() {
223 return array(
224 'booking_is_show_legend',
225 'booking_legend_is_show_item_available',
226 'booking_legend_text_for_item_available',
227 'booking_legend_is_show_item_pending',
228 'booking_legend_text_for_item_pending',
229 'booking_legend_is_show_item_approved',
230 'booking_legend_text_for_item_approved',
231 'booking_legend_is_show_item_partially',
232 'booking_legend_text_for_item_partially',
233 'booking_legend_is_show_item_unavailable',
234 'booking_legend_text_for_item_unavailable',
235 'booking_legend_is_show_numbers',
236 'booking_legend_is_vertical',
237 );
238 }
239
240 /**
241 * Normalize a global calendar legend option before saving.
242 *
243 * @param string $option_key Option name.
244 * @param mixed $value Option value.
245 * @param string $data_name Submitted data name.
246 *
247 * @return string
248 */
249 public static function normalize_calendar_legend_option( $option_key, $value, $data_name = '' ) {
250
251 $on_off_options = array(
252 'booking_is_show_legend',
253 'booking_legend_is_show_item_available',
254 'booking_legend_is_show_item_pending',
255 'booking_legend_is_show_item_approved',
256 'booking_legend_is_show_item_partially',
257 'booking_legend_is_show_item_unavailable',
258 'booking_legend_is_show_numbers',
259 'booking_legend_is_vertical',
260 );
261
262 if ( in_array( $option_key, $on_off_options, true ) ) {
263 return WPBC_Option_Save_Policy_Global_Options::normalize_on_off( $value );
264 }
265
266 return sanitize_text_field( (string) $value );
267 }
268 }
269
270 /**
271 * Time-slot global option policies.
272 */
273 class WPBC_Option_Save_Policy_Global_Time {
274
275 /**
276 * Normalize and validate the global time-picker skin value.
277 *
278 * @param mixed $data_raw Raw value.
279 * @param string $data_name Option name.
280 *
281 * @return string
282 */
283 public static function normalize_time_picker_skin( $data_raw, $data_name = '' ) {
284
285 $skin_value = is_scalar( $data_raw ) ? (string) $data_raw : '';
286 $replace = array();
287
288 if ( defined( 'WPBC_PLUGIN_DIR' ) ) {
289 $replace[] = WPBC_PLUGIN_DIR;
290 }
291 if ( defined( 'WPBC_PLUGIN_URL' ) ) {
292 $replace[] = WPBC_PLUGIN_URL;
293 }
294
295 $upload_dir = wp_upload_dir();
296 if ( ! empty( $upload_dir['basedir'] ) ) {
297 $replace[] = $upload_dir['basedir'];
298 }
299 if ( ! empty( $upload_dir['baseurl'] ) ) {
300 $replace[] = $upload_dir['baseurl'];
301 }
302
303 $skin_value = sanitize_text_field( str_replace( $replace, '', $skin_value ) );
304
305 if (
306 '' === $skin_value ||
307 false !== strpos( $skin_value, '..' ) ||
308 ! preg_match( '/\.css$/i', $skin_value ) ||
309 ( 0 !== strpos( $skin_value, '/css/time_picker_skins/' ) && 0 !== strpos( $skin_value, '/wpbc_time_picker_skins/' ) )
310 ) {
311 wp_send_json_error( array( 'message' => __( 'Invalid time-picker skin.', 'booking' ) ) );
312 }
313
314 if ( 0 === strpos( $skin_value, '/wpbc_time_picker_skins/' ) ) {
315 $file_path = ( ! empty( $upload_dir['basedir'] ) ) ? $upload_dir['basedir'] . $skin_value : '';
316 } else {
317 $file_path = defined( 'WPBC_PLUGIN_DIR' ) ? WPBC_PLUGIN_DIR . $skin_value : '';
318 }
319
320 if ( empty( $file_path ) || ! file_exists( $file_path ) ) {
321 wp_send_json_error( array( 'message' => __( 'Time-picker skin file does not exist.', 'booking' ) ) );
322 }
323
324 return $skin_value;
325 }
326
327 /**
328 * Normalize the global timeslot picker toggle.
329 *
330 * @param mixed $data_raw Raw value.
331 * @param string $data_name Option name.
332 *
333 * @return string
334 */
335 public static function normalize_timeslot_picker( $data_raw, $data_name = '' ) {
336 return WPBC_Option_Save_Policy_Global_Options::normalize_on_off( $data_raw );
337 }
338 }
339
340 /**
341 * Register built-in policies.
342 *
343 * @return void
344 */
345 function wpbc_register_builtin_option_save_policies() {
346
347 if ( ! class_exists( 'wpbc_option_saver_loader' ) ) {
348 return;
349 }
350
351 wpbc_option_saver_loader::register_option_policy(
352 'booking_form_style',
353 array(
354 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
355 'permission_message' => __( 'You do not have permission to save global form appearance options.', 'booking' ),
356 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Options', 'normalize_form_style' ),
357 )
358 );
359
360 foreach ( WPBC_Option_Save_Policy_Global_Options::get_custom_form_style_option_names() as $custom_form_style_option_name ) {
361 wpbc_option_saver_loader::register_option_policy(
362 $custom_form_style_option_name,
363 array(
364 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
365 'permission_message' => __( 'You do not have permission to save global form appearance options.', 'booking' ),
366 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Options', 'normalize_custom_form_style_option' ),
367 )
368 );
369 }
370
371 wpbc_option_saver_loader::register_option_policy(
372 'booking_skin',
373 array(
374 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
375 'permission_message' => __( 'You do not have permission to save global calendar options.', 'booking' ),
376 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Calendar', 'normalize_calendar_skin' ),
377 )
378 );
379
380 wpbc_option_saver_loader::register_option_policy(
381 'wpbc_calendar_legend_options',
382 array(
383 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
384 'permission_message' => __( 'You do not have permission to save global calendar options.', 'booking' ),
385 'force_mode' => 'split',
386 'allowed_keys' => array( 'WPBC_Option_Save_Policy_Global_Calendar', 'get_calendar_legend_option_names' ),
387 'normalize_item' => array( 'WPBC_Option_Save_Policy_Global_Calendar', 'normalize_calendar_legend_option' ),
388 )
389 );
390
391 wpbc_option_saver_loader::register_option_policy(
392 'booking_timeslot_picker',
393 array(
394 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
395 'permission_message' => __( 'You do not have permission to save global time-slot options.', 'booking' ),
396 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Time', 'normalize_timeslot_picker' ),
397 )
398 );
399
400 wpbc_option_saver_loader::register_option_policy(
401 'booking_is_use_autofill_4_logged_user',
402 array(
403 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
404 'permission_message' => __( 'You do not have permission to save global form options.', 'booking' ),
405 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Options', 'normalize_on_off' ),
406 )
407 );
408
409 wpbc_option_saver_loader::register_option_policy(
410 'booking_form_accent_enabled',
411 array(
412 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
413 'permission_message' => __( 'You do not have permission to save global form appearance options.', 'booking' ),
414 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Options', 'normalize_on_off' ),
415 )
416 );
417
418 wpbc_option_saver_loader::register_option_policy(
419 'booking_timeslot_picker_skin',
420 array(
421 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
422 'permission_message' => __( 'You do not have permission to save global time-slot options.', 'booking' ),
423 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Time', 'normalize_time_picker_skin' ),
424 )
425 );
426
427 wpbc_option_saver_loader::register_option_policy(
428 'booking_form_accent_color',
429 array(
430 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
431 'permission_message' => __( 'You do not have permission to save global form appearance options.', 'booking' ),
432 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Options', 'normalize_hex_color' ),
433 )
434 );
435
436 wpbc_option_saver_loader::register_option_policy(
437 'booking_is_use_phone_validation',
438 array(
439 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
440 'permission_message' => __( 'You do not have permission to save global form options.', 'booking' ),
441 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Options', 'normalize_on_off' ),
442 )
443 );
444
445 wpbc_option_saver_loader::register_option_policy(
446 'booking_number_for_pre_checkin_date_hint',
447 array(
448 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
449 'permission_message' => __( 'You do not have permission to save global form options.', 'booking' ),
450 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Options', 'normalize_pre_checkin_days' ),
451 )
452 );
453 }
454 add_action( 'init', 'wpbc_register_builtin_option_save_policies', 5 );
455