PluginProbe
Booking Calendar / 11.0
Booking Calendar v11.0
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 10.11.2 All 203 releases
booking / includes / save-user-meta / save-user-meta.php

save-user-meta.php in Booking Calendar 11.0, at includes/save-user-meta/save-user-meta.php

253 lines 9.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @version 1.0
4 * @package Booking Calendar
5 * @subpackage User_Custom_Data_Saver
6 * @category Functions
7 * @author wpdevelop
8 * @link https://wpbookingcalendar.com/
9 * @email info@wpbookingcalendar.com
10 * @modified 2025-06-25
11 */
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit; // Exit if accessed directly.
15 }
16
17 class WPBC_User_Custom_Data_Saver {
18
19 private static $ajax_action = 'AJAX_SAVE_USER_META_DATA';
20 private static $user_option_prefix = 'booking_custom_';
21
22 /**
23 * Init hooks
24 */
25 public static function init() {
26 add_action( 'init', array( __CLASS__, 'register_ajax_handler' ) );
27 add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
28 }
29
30 /**
31 * Register AJAX handler
32 */
33 public static function register_ajax_handler() {
34 add_action( 'wp_ajax_' . self::$ajax_action, array( __CLASS__, 'handle_ajax_save' ) );
35 }
36
37 /**
38 * Enqueue JavaScript file and pass AJAX URL
39 */
40 public static function enqueue_scripts() {
41
42 $js_url = function_exists( 'wpbc_plugin_url' ) ? wpbc_plugin_url( '/includes/save-user-meta/_out/save-user-meta.js' ) : plugins_url( '_out/user-data-saver.js', WPBC_FILE );
43
44 wp_register_script( 'wpbc-user-data-saver', $js_url, array( 'jquery' ), '1.1', true );
45 wp_enqueue_script( 'wpbc-user-data-saver' );
46
47 wp_localize_script( 'wpbc-user-data-saver', 'WPBC_UserDataSaver', array(
48 'ajax_url' => admin_url( 'admin-ajax.php' ),
49 'action' => self::$ajax_action,
50 ) );
51 }
52
53 /**
54 * Create nonce
55 */
56 public static function create_nonce( $action_name ) {
57 return wp_create_nonce( $action_name );
58 }
59
60 /**
61 * Render a save button or div with onclick and data attributes
62 */
63 public static function render_save_button( $args = array() ) {
64 $defaults = array(
65 'label' => __( 'Save', 'booking' ),
66 'data_name' => 'custom_data_block',
67 'nonce_action' => 'wpbc_custom_data_nonce',
68 'user_id' => get_current_user_id(),
69 'element' => 'div',
70 'id' => '',
71 'class' => 'wpbc-save-button button button-primary',
72 'data_fields' => array(),
73 );
74 $args = wp_parse_args( $args, $defaults );
75
76 $tag = $args['element'];
77 $id_attr = $args['id'] ? ' id="' . esc_attr( $args['id'] ) . '"' : '';
78 $nonce = self::create_nonce( $args['nonce_action'] );
79 $selectors = implode( ',', $args['data_fields'] );
80 $onclick = 'wpbc_save_custom_user_data_from_element(this);';
81
82 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
83 echo '<' . $tag . $id_attr . ' class="' . esc_attr( $args['class'] ) . '"' . ' data-wpbc-u-save-name="' . esc_attr( $args['data_name'] ) . '"' . ' data-wpbc-u-save-nonce="' . esc_attr( $nonce ) . '"' . ' data-wpbc-u-save-user-id="' . esc_attr( $args['user_id'] ) . '"' . ' data-wpbc-u-save-action="' . esc_attr( $args['nonce_action'] ) . '"' . ' data-wpbc-u-save-fields="' . esc_attr( $selectors ) . '"' . ' onclick="' . esc_attr( $onclick ) . '"' . '>' . esc_html( $args['label'] ) . '</' . $tag . '>';
84 }
85
86 /**
87 * AJAX handler
88 */
89 public static function handle_ajax_save() {
90 $user_id = isset( $_POST['user_id'] ) ? intval( $_POST['user_id'] ) : 0;
91 $data_name = isset( $_POST['data_name'] ) ? sanitize_key( wp_unslash( $_POST['data_name'] ) ) : '';
92 $data_raw = isset( $_POST['data_value'] ) ? wp_unslash( $_POST['data_value'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
93 $nonce_name = isset( $_POST['nonce_action'] ) ? sanitize_key( wp_unslash( $_POST['nonce_action'] ) ) : '';
94 $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
95
96 if ( empty( $nonce_name ) || ! wp_verify_nonce( $nonce, $nonce_name ) ) {
97 wp_send_json_error( array( 'message' => 'Invalid nonce.' ) );
98 }
99
100 if ( empty( $user_id ) || empty( $data_name ) || empty( $data_raw ) ) {
101 wp_send_json_error( array( 'message' => 'Missing required parameters.' ) );
102 }
103 // FixIn: 10.14.15.2.
104 if ( wpbc_get_current_user_id() !== $user_id ) {
105 wp_send_json_error( array( 'message' => 'Unauthorized: You can only modify your own settings.' ) );
106 }
107 parse_str( $data_raw, $parsed_data );
108
109 $sanitized_data = array();
110 foreach ( $parsed_data as $key => $val ) {
111
112 // $key = sanitize_key( $key ); // This strips square brackets and digits for complex input keys (like rows[0][title]) //.
113
114 $key = preg_replace( '/[^a-zA-Z0-9_\[\]]/', '', $key ); // This preserves structure like rows[0][title] (important for array-style inputs), but still sanitizes.
115
116 $sanitized_data[ $key ] = is_array( $val ) ? array_map( 'sanitize_text_field', $val )
117 : sanitize_text_field( $val );
118 }
119
120 update_user_option( $user_id, self::$user_option_prefix . $data_name, $sanitized_data );
121
122 wp_send_json_success( array( 'message' => 'Settings saved successfully.' ) );
123 }
124
125 /**
126 * Get saved data
127 *
128 * Usage for simple values:
129 *
130 * $is_full_screen = WPBC_User_Custom_Data_Saver::get_user_data_value( wpbc_get_current_user_id(), $user_cust_option );
131 * $is_full_screen= ( isset( $is_full_screen_data['value'] ) && $is_full_screen_data['value'] === 'On' );
132 */
133 public static function get_user_data( $user_id, $data_name ) {
134 $option_key = self::$user_option_prefix . sanitize_key( $data_name );
135 $data = get_user_option( $option_key, $user_id );
136
137 return is_array( $data ) ? $data : array();
138 }
139
140 /**
141 * Get simple saved value.
142 *
143 * @param $user_id
144 * @param $data_name
145 * @param $key
146 *
147 * @return mixed|string
148 */
149 public static function get_user_data_value( $user_id, $data_name, $key = 'value' ) {
150 $data = self::get_user_data( $user_id, $data_name );
151
152 return isset( $data[ $key ] ) ? $data[ $key ] : '';
153 }
154 }
155
156 // Register loading JavaScript and Ajax handlers. In initi used other init hooks, that is why we use 'plugins_loaded'.
157 add_action( 'plugins_loaded', array( 'WPBC_User_Custom_Data_Saver', 'init' ) );
158
159 /*
160 if ( 0 ) {
161
162 ?>
163 Example #1:
164 <input type="text" id="my_setting" value="Hello"/>
165 <?php
166 WPBC_User_Custom_Data_Saver::render_save_button( array(
167 'label' => 'Save Setting',
168 'data_name' => 'my_text_value',
169 'nonce_action' => 'wpbc_text_value_nonce',
170 'id' => 'wpbc_save_text_btn',
171 'data_fields' => array( '#my_setting' ),
172 ) );
173 ?>
174
175 Example #2:
176 <input type="text" name="rows[0][title]" id="row_0_title" value="Title 1"/>
177 <input type="text" name="rows[0][value]" id="row_0_value" value="100"/>
178 <input type="text" name="rows[1][title]" id="row_1_title" value="Title 2"/>
179 <input type="text" name="rows[1][value]" id="row_1_value" value="200"/>
180 <?php
181 WPBC_User_Custom_Data_Saver::render_save_button( array(
182 'label' => 'Save Table Rows',
183 'data_name' => 'my_object_array',
184 'nonce_action' => 'wpbc_object_array_nonce',
185 'id' => 'wpbc_save_array_btn',
186 'data_fields' => array( '#row_0_title', '#row_0_value', '#row_1_title', '#row_1_value' ),
187 ) );
188 ?>
189
190 Example #3:
191 <?php
192 $nonce_action = 'wpbc_manual_example_nonce';
193 ?>
194 <input type="text" id="custom_note" value="My note"/>
195 <div class="button button-primary"
196 onclick="wpbc_save_custom_user_data_from_element(this)"
197 data-wpbc-u-save-name="user_note"
198 data-wpbc-u-save-nonce="<?php echo esc_attr( wp_create_nonce( $nonce_action ) ); ?>"
199 data-wpbc-u-save-user-id="<?php echo esc_attr( get_current_user_id() ); ?>"
200 data-wpbc-u-save-action="<?php echo esc_attr( $nonce_action ); ?>"
201 data-wpbc-u-save-fields="#custom_note">
202 Save Note
203 </div>
204
205 Example #4:
206 <?php
207 $nonce_action = 'wpbc_array_rows_nonce';
208 ?>
209 <input type="text" name="rows[0][title]" id="row_0_title" value="Title 1"/>
210 <input type="text" name="rows[0][value]" id="row_0_value" value="100"/>
211 <input type="text" name="rows[1][title]" id="row_1_title" value="Title 2"/>
212 <input type="text" name="rows[1][value]" id="row_1_value" value="200"/>
213 <a href="javascript:void(0);"
214 class="button button-primary"
215 onclick="wpbc_save_custom_user_data_from_element(this)"
216 data-wpbc-u-save-name="object_array_example"
217 data-wpbc-u-save-nonce="<?php echo esc_attr( wp_create_nonce( $nonce_action ) ); ?>"
218 data-wpbc-u-save-user-id="<?php echo esc_attr( get_current_user_id() ); ?>"
219 data-wpbc-u-save-action="<?php echo esc_attr( $nonce_action ); ?>"
220 data-wpbc-u-save-fields="#row_0_title,#row_0_value,#row_1_title,#row_1_value">
221 Save Rows
222 </a>
223
224 Example #5:
225 <?php $nonce_action = 'wpbc_simple_value_nonce'; ?>
226 <a href="javascript:void(0);"
227 class="button button-primary"
228 onclick="wpbc_save_custom_user_data_from_element(this)"
229 data-wpbc-u-save-name="simple_note"
230 data-wpbc-u-save-value="My saved string value"
231 data-wpbc-u-save-nonce="<?php echo esc_attr( wp_create_nonce( $nonce_action ) ); ?>"
232 data-wpbc-u-save-user-id="<?php echo esc_attr( get_current_user_id() ); ?>"
233 data-wpbc-u-save-action="<?php echo esc_attr( $nonce_action ); ?>"
234 >
235 Save Simple Note
236 </a>
237
238 Example #6:
239 <?php $nonce_action = 'wpbc_simple_value_nonce'; ?>
240 <a href="javascript:void(0);"
241 class="button button-primary"
242 onclick="wpbc_save_custom_user_data_from_element(this)"
243 data-wpbc-u-save-name="simple_note"
244 data-wpbc-u-save-value-json='{"title":"Hello","value":42}'
245 data-wpbc-u-save-nonce="<?php echo esc_attr( wp_create_nonce( $nonce_action ) ); ?>"
246 data-wpbc-u-save-user-id="<?php echo esc_attr( get_current_user_id() ); ?>"
247 data-wpbc-u-save-action="<?php echo esc_attr( $nonce_action ); ?>"
248 >
249 Save Simple Note
250 </a>
251 <?php
252 }
253 */