PluginProbe
Booking Calendar / 11.5
Booking Calendar v11.5
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.5, at includes/save-load-option/option-save-policies.php

413 lines 13.3 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 /**
144 * Calendar global option policies.
145 */
146 class WPBC_Option_Save_Policy_Global_Calendar {
147
148 /**
149 * Normalize and validate global calendar skin value before saving.
150 *
151 * @param mixed $data_raw Raw calendar skin value.
152 * @param string $data_name Option name.
153 *
154 * @return string
155 */
156 public static function normalize_calendar_skin( $data_raw, $data_name = '' ) {
157
158 $skin_value = is_scalar( $data_raw ) ? (string) $data_raw : '';
159 $replace = array();
160
161 if ( defined( 'WPBC_PLUGIN_DIR' ) ) {
162 $replace[] = WPBC_PLUGIN_DIR;
163 }
164 if ( defined( 'WPBC_PLUGIN_URL' ) ) {
165 $replace[] = WPBC_PLUGIN_URL;
166 }
167
168 $upload_dir = wp_upload_dir();
169 if ( ! empty( $upload_dir['basedir'] ) ) {
170 $replace[] = $upload_dir['basedir'];
171 }
172 if ( ! empty( $upload_dir['baseurl'] ) ) {
173 $replace[] = $upload_dir['baseurl'];
174 }
175
176 $skin_value = str_replace( $replace, '', $skin_value );
177 $skin_value = sanitize_text_field( $skin_value );
178
179 if (
180 '' === $skin_value ||
181 false !== strpos( $skin_value, '..' ) ||
182 ! preg_match( '/\.css$/i', $skin_value ) ||
183 ( 0 !== strpos( $skin_value, '/css/skins/' ) && 0 !== strpos( $skin_value, '/wpbc_skins/' ) )
184 ) {
185 wp_send_json_error( array( 'message' => __( 'Invalid calendar skin.', 'booking' ) ) );
186 }
187
188 $file_path = '';
189 if ( 0 === strpos( $skin_value, '/wpbc_skins/' ) ) {
190 $file_path = ( ! empty( $upload_dir['basedir'] ) ) ? $upload_dir['basedir'] . $skin_value : '';
191 } elseif ( defined( 'WPBC_PLUGIN_DIR' ) ) {
192 $file_path = WPBC_PLUGIN_DIR . $skin_value;
193 }
194
195 if ( empty( $file_path ) || ! file_exists( $file_path ) ) {
196 wp_send_json_error( array( 'message' => __( 'Calendar skin file does not exist.', 'booking' ) ) );
197 }
198
199 return $skin_value;
200 }
201
202 /**
203 * Get allowed global calendar legend option names.
204 *
205 * @return array
206 */
207 public static function get_calendar_legend_option_names() {
208 return array(
209 'booking_is_show_legend',
210 'booking_legend_is_show_item_available',
211 'booking_legend_text_for_item_available',
212 'booking_legend_is_show_item_pending',
213 'booking_legend_text_for_item_pending',
214 'booking_legend_is_show_item_approved',
215 'booking_legend_text_for_item_approved',
216 'booking_legend_is_show_item_partially',
217 'booking_legend_text_for_item_partially',
218 'booking_legend_is_show_item_unavailable',
219 'booking_legend_text_for_item_unavailable',
220 'booking_legend_is_show_numbers',
221 'booking_legend_is_vertical',
222 );
223 }
224
225 /**
226 * Normalize a global calendar legend option before saving.
227 *
228 * @param string $option_key Option name.
229 * @param mixed $value Option value.
230 * @param string $data_name Submitted data name.
231 *
232 * @return string
233 */
234 public static function normalize_calendar_legend_option( $option_key, $value, $data_name = '' ) {
235
236 $on_off_options = array(
237 'booking_is_show_legend',
238 'booking_legend_is_show_item_available',
239 'booking_legend_is_show_item_pending',
240 'booking_legend_is_show_item_approved',
241 'booking_legend_is_show_item_partially',
242 'booking_legend_is_show_item_unavailable',
243 'booking_legend_is_show_numbers',
244 'booking_legend_is_vertical',
245 );
246
247 if ( in_array( $option_key, $on_off_options, true ) ) {
248 return WPBC_Option_Save_Policy_Global_Options::normalize_on_off( $value );
249 }
250
251 return sanitize_text_field( (string) $value );
252 }
253 }
254
255 /**
256 * Time-slot global option policies.
257 */
258 class WPBC_Option_Save_Policy_Global_Time {
259
260 /**
261 * Normalize and validate the global time-picker skin value.
262 *
263 * @param mixed $data_raw Raw value.
264 * @param string $data_name Option name.
265 *
266 * @return string
267 */
268 public static function normalize_time_picker_skin( $data_raw, $data_name = '' ) {
269
270 $skin_value = is_scalar( $data_raw ) ? (string) $data_raw : '';
271 $replace = array();
272
273 if ( defined( 'WPBC_PLUGIN_DIR' ) ) {
274 $replace[] = WPBC_PLUGIN_DIR;
275 }
276 if ( defined( 'WPBC_PLUGIN_URL' ) ) {
277 $replace[] = WPBC_PLUGIN_URL;
278 }
279
280 $upload_dir = wp_upload_dir();
281 if ( ! empty( $upload_dir['basedir'] ) ) {
282 $replace[] = $upload_dir['basedir'];
283 }
284 if ( ! empty( $upload_dir['baseurl'] ) ) {
285 $replace[] = $upload_dir['baseurl'];
286 }
287
288 $skin_value = sanitize_text_field( str_replace( $replace, '', $skin_value ) );
289
290 if (
291 '' === $skin_value ||
292 false !== strpos( $skin_value, '..' ) ||
293 ! preg_match( '/\.css$/i', $skin_value ) ||
294 ( 0 !== strpos( $skin_value, '/css/time_picker_skins/' ) && 0 !== strpos( $skin_value, '/wpbc_time_picker_skins/' ) )
295 ) {
296 wp_send_json_error( array( 'message' => __( 'Invalid time-picker skin.', 'booking' ) ) );
297 }
298
299 if ( 0 === strpos( $skin_value, '/wpbc_time_picker_skins/' ) ) {
300 $file_path = ( ! empty( $upload_dir['basedir'] ) ) ? $upload_dir['basedir'] . $skin_value : '';
301 } else {
302 $file_path = defined( 'WPBC_PLUGIN_DIR' ) ? WPBC_PLUGIN_DIR . $skin_value : '';
303 }
304
305 if ( empty( $file_path ) || ! file_exists( $file_path ) ) {
306 wp_send_json_error( array( 'message' => __( 'Time-picker skin file does not exist.', 'booking' ) ) );
307 }
308
309 return $skin_value;
310 }
311
312 /**
313 * Normalize the global timeslot picker toggle.
314 *
315 * @param mixed $data_raw Raw value.
316 * @param string $data_name Option name.
317 *
318 * @return string
319 */
320 public static function normalize_timeslot_picker( $data_raw, $data_name = '' ) {
321 return WPBC_Option_Save_Policy_Global_Options::normalize_on_off( $data_raw );
322 }
323 }
324
325 /**
326 * Register built-in policies.
327 *
328 * @return void
329 */
330 function wpbc_register_builtin_option_save_policies() {
331
332 if ( ! class_exists( 'wpbc_option_saver_loader' ) ) {
333 return;
334 }
335
336 wpbc_option_saver_loader::register_option_policy(
337 'booking_form_style',
338 array(
339 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
340 'permission_message' => __( 'You do not have permission to save global form appearance options.', 'booking' ),
341 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Options', 'normalize_form_style' ),
342 )
343 );
344
345 foreach ( WPBC_Option_Save_Policy_Global_Options::get_custom_form_style_option_names() as $custom_form_style_option_name ) {
346 wpbc_option_saver_loader::register_option_policy(
347 $custom_form_style_option_name,
348 array(
349 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
350 'permission_message' => __( 'You do not have permission to save global form appearance options.', 'booking' ),
351 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Options', 'normalize_custom_form_style_option' ),
352 )
353 );
354 }
355
356 wpbc_option_saver_loader::register_option_policy(
357 'booking_skin',
358 array(
359 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
360 'permission_message' => __( 'You do not have permission to save global calendar options.', 'booking' ),
361 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Calendar', 'normalize_calendar_skin' ),
362 )
363 );
364
365 wpbc_option_saver_loader::register_option_policy(
366 'wpbc_calendar_legend_options',
367 array(
368 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
369 'permission_message' => __( 'You do not have permission to save global calendar options.', 'booking' ),
370 'force_mode' => 'split',
371 'allowed_keys' => array( 'WPBC_Option_Save_Policy_Global_Calendar', 'get_calendar_legend_option_names' ),
372 'normalize_item' => array( 'WPBC_Option_Save_Policy_Global_Calendar', 'normalize_calendar_legend_option' ),
373 )
374 );
375
376 wpbc_option_saver_loader::register_option_policy(
377 'booking_timeslot_picker',
378 array(
379 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
380 'permission_message' => __( 'You do not have permission to save global time-slot options.', 'booking' ),
381 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Time', 'normalize_timeslot_picker' ),
382 )
383 );
384
385 wpbc_option_saver_loader::register_option_policy(
386 'booking_form_accent_enabled',
387 array(
388 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
389 'permission_message' => __( 'You do not have permission to save global form appearance options.', 'booking' ),
390 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Options', 'normalize_on_off' ),
391 )
392 );
393
394 wpbc_option_saver_loader::register_option_policy(
395 'booking_timeslot_picker_skin',
396 array(
397 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
398 'permission_message' => __( 'You do not have permission to save global time-slot options.', 'booking' ),
399 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Time', 'normalize_time_picker_skin' ),
400 )
401 );
402
403 wpbc_option_saver_loader::register_option_policy(
404 'booking_form_accent_color',
405 array(
406 'can_save' => array( 'WPBC_Option_Save_Policy_Global_Options', 'can_save_global_options' ),
407 'permission_message' => __( 'You do not have permission to save global form appearance options.', 'booking' ),
408 'normalize_raw' => array( 'WPBC_Option_Save_Policy_Global_Options', 'normalize_hex_color' ),
409 )
410 );
411 }
412 add_action( 'init', 'wpbc_register_builtin_option_save_policies', 5 );
413