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
← All changes | includes/page-form-builder/save-load/bfb-form-manager.php +133 -265 11.3 → 11.8.4 View file →
@@ -1,4 +1,4 @@
1 1 <?php
2 2 if ( ! defined( 'ABSPATH' ) ) {
3 3 exit; // Exit if accessed directly.
4 4 }
@@ -5,19 +5,18 @@
5 5
6 6 /**
7 7 * Helper functions for saving / loading between different versions of booking forms.
8 8 *
9 - * This file is the bridge between:
9 + * This file manages Booking Form Builder form configuration stored in
10 + * booking_form_structures. Legacy option readers live in the import-only
11 + * module: includes/page-form-builder/legacy-import/.
10 12 *
11 - * - Old world: booking_form, booking_form_show, booking_forms_extended, etc.
12 - * - New world: booking_form_structures table.
13 - *
14 13 * It introduces a normalized FormConfig array:
15 14 *
16 15 * [
17 16 * 'id' => booking_form_id,
18 17 * 'form_name' => 'standard' or custom key (maps to form_slug),
19 - * 'engine' => 'bfb' | 'legacy_advanced' | 'legacy_simple',
18 + * 'engine' => 'bfb' | 'advanced_mode',
20 19 * 'engine_version' => '1.0',
21 20 * 'title' => string,
22 21 * 'description' => string,
23 22 * 'scope' => string,
@@ -33,27 +32,20 @@
33 32 * 'created_at' => string,
34 33 * 'updated_at' => string,
35 34 * ]
36 35 *
37 - * What we do:
38 - * - Re-use booking_form_structures as canonical FormConfig storage.
39 - * Each row now carries:
40 - * - form_slug (your form_name): 'standard', custom names, etc.
41 - * - owner_user_id for MultiUser ownership.
42 - * - engine, engine_version.
43 - * - structure_json (BFB structure, or legacy stub/simple_form).
44 - * - advanced_form + content_form (what front-end uses today).
36 + * What we do:
37 + * - Use booking_form_structures as canonical FormConfig storage.
38 + * Each row carries form_slug, owner_user_id, engine, structure_json,
39 + * settings_json, advanced_form and content_form.
45 40 *
46 41 * Main public API:
47 - * - wpbc_form_config_load():
48 - * Tries the booking_form_structures table first, falls back to legacy
49 - * wp_options-based configuration if no row exists.
42 + * - wpbc_form_config_load():
43 + * Loads only from booking_form_structures.
50 44 *
51 - * - wpbc_form_config_save():
52 - * Used by the new Builder save controller. Writes to
53 - * booking_form_structures via WPBC_BFB_Form_Storage::save_form().
54 - * Optionally syncs booking_form / booking_forms_extended so all old
55 - * runtime code keeps working.
45 + * - wpbc_form_config_save():
46 + * Writes only to booking_form_structures via
47 + * WPBC_BFB_Form_Storage::save_form().
56 48 *
57 49 * @package Booking Calendar.
58 50 * @author wpdevelop, oplugins
59 51 * @web-site https://wpbookingcalendar.com/
@@ -159,141 +151,15 @@
159 151 return ( $row && ! empty( $row->booking_form_id ) );
160 152 }
161 153
162 154
163 -// == 4. Legacy loader (fallback from old options) ==
155 +// == 4. Public loader: DB only ==
164 156
165 157 /**
166 - * Build FormConfig from legacy options when no row exists in booking_form_structures.
167 - *
168 - * Behaviour:
169 - * - Standard form uses:
170 - * - booking_form (advanced form).
171 - * - booking_form_show (content form).
172 - * - booking_form_visual (Simple form structure, if present).
173 - * - Custom forms use booking_forms_extended (serialized array of forms).
174 - *
175 - * Returned FormConfig uses:
176 - * - engine: 'legacy_advanced' or 'legacy_simple' depending on available data.
177 - * - structure_json: encoded visual/simple_form structure or legacy stub.
178 - *
179 - * @param string $form_key Form key. 'standard' or custom key used in legacy options.
180 - * @param int $user_id Owner user ID for bookkeeping. Default 0.
181 - *
182 - * @return array|null FormConfig array on success or null if no legacy form found.
183 - */
184 -function wpbc_form_config__load_from_legacy( $form_key, $user_id = 0 ) {
185 -
186 - $form_key = (string) $form_key;
187 - if ( '' === $form_key ) {
188 - $form_key = wpbc_bfb_get_default_form_key();
189 - }
190 -
191 - // 1) Standard form.
192 - if ( 'standard' === $form_key ) {
193 -
194 - $engine = 'legacy_advanced';
195 - $advanced_form = wpbc_bfb_get_legacy_option_value( 'booking_form', $user_id );
196 - $content_form = wpbc_bfb_get_legacy_option_value( 'booking_form_show', $user_id );
197 -
198 - $visual = wpbc_bfb_get_legacy_option_value( 'booking_form_visual', $user_id );
199 - $visual = maybe_unserialize( $visual );
200 -
201 - $structure_json = wpbc_form_config__encode_json( array() );
202 -
203 - // Free version only: use Simple Form structure as fallback Builder structure.
204 - if ( ! class_exists( 'wpdev_bk_personal' ) ) {
205 - if ( is_array( $visual ) && ! empty( $visual ) ) {
206 - $engine = 'legacy_simple';
207 - $structure_arr = wpbc_simple_form__export_to_bfb_structure( $visual );
208 - $structure_json = wpbc_form_config__encode_json( $structure_arr );
209 - }
210 - }
211 -
212 - return array(
213 - 'id' => 0,
214 - 'owner_user_id' => (int) $user_id,
215 - 'form_name' => 'standard',
216 - 'engine' => $engine,
217 - 'engine_version' => '1.0',
218 - 'title' => 'Standard',
219 - 'description' => '',
220 - 'scope' => 'global',
221 - 'status' => 'published',
222 - 'is_default' => 1,
223 - 'booking_resource_id' => null,
224 - 'structure_json' => $structure_json,
225 - 'settings' => array(),
226 - 'advanced_form' => (string) $advanced_form,
227 - 'content_form' => (string) $content_form,
228 - 'picture_url' => '',
229 - 'created_at' => '',
230 - 'updated_at' => '',
231 - );
232 - }
233 -
234 - // 2) Custom forms from booking_forms_extended.
235 - $extended = wpbc_bfb_get_legacy_option_value( 'booking_forms_extended', $user_id );
236 - $extended = maybe_unserialize( $extended );
237 -
238 - if ( is_array( $extended ) ) {
239 - foreach ( $extended as $one ) {
240 -
241 - if ( empty( $one['name'] ) || (string) $one['name'] !== $form_key ) {
242 - continue;
243 - }
244 -
245 - $adv = isset( $one['form'] ) ? $one['form'] : '';
246 - $cnt = isset( $one['content'] ) ? $one['content'] : '';
247 - $engine = 'legacy_advanced';
248 - $structure_json = wpbc_form_config__encode_json( array() );
249 -
250 - // Only if Advanced Form is absent, or plugin works in Free mode.
251 - if ( ( ! class_exists( 'wpdev_bk_personal' ) ) || empty( $adv ) ) {
252 - if ( ! empty( $one['simple_form'] ) && is_array( $one['simple_form'] ) ) {
253 - $engine = 'legacy_simple';
254 - $structure_arr = wpbc_simple_form__export_to_bfb_structure( $one['simple_form'] );
255 - $structure_json = wpbc_form_config__encode_json( $structure_arr );
256 - }
257 - }
258 -
259 - return array(
260 - 'id' => 0,
261 - 'owner_user_id' => (int) $user_id,
262 - 'form_name' => $form_key,
263 - 'engine' => $engine,
264 - 'engine_version' => '1.0',
265 - 'title' => isset( $one['title'] ) ? (string) $one['title'] : (string) $form_key,
266 - 'description' => isset( $one['description'] ) ? (string) $one['description'] : '',
267 - 'scope' => 'global',
268 - 'status' => 'published',
269 - 'is_default' => ! empty( $one['is_default'] ) ? 1 : 0,
270 - 'booking_resource_id' => isset( $one['booking_resource_id'] ) ? intval( $one['booking_resource_id'] ) : null,
271 - 'structure_json' => $structure_json,
272 - 'settings' => array(),
273 - 'advanced_form' => (string) $adv,
274 - 'content_form' => (string) $cnt,
275 - 'picture_url' => '',
276 - 'created_at' => '',
277 - 'updated_at' => '',
278 - );
279 - }
280 - }
281 -
282 - return null;
283 -}
284 -
285 -// == 5. Public loader: try DB first, then legacy ==
286 -
287 -/**
288 158 * Load unified FormConfig for a given form_key and optional owner.
289 159 *
290 160 * This is the main read API for booking form configuration:
291 - * - First tries the booking_form_structures table (new engine).
292 - * Currently we load status = 'published' row via
293 - * WPBC_BFB_Form_Storage::get_current_form_by_key().
294 - * - If nothing is found, falls back to legacy options via
295 - * wpbc_form_config__load_from_legacy().
161 + * Loads only from the booking_form_structures table.
296 162 *
297 163 * @param string $form_key Form key. 'standard' or custom key. Default 'standard'.
298 164 * @param int $user_id Owner user ID for MultiUser environment. Default 0.
299 165 *
@@ -298,9 +164,9 @@
298 164 * @param int $user_id Owner user ID for MultiUser environment. Default 0.
299 165 *
300 166 * @return array|null Normalized FormConfig array or null if nothing found.
301 167 */
302 -function wpbc_form_config_load( $form_key = 'standard', $user_id = 0, $status = 'published', $is_fallback_to_legacy = true ) {
168 +function wpbc_form_config_load( $form_key = 'standard', $user_id = 0, $status = 'published', $is_fallback_to_legacy = false ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
303 169
304 170 $form_key = (string) $form_key;
305 171 if ( '' === $form_key ) {
306 172 $form_key = 'standard';
@@ -306,106 +172,23 @@
306 172 $form_key = 'standard';
307 173
308 174 }
309 175
310 - // 1) Try storage table first (status = 'published').
311 - $row = WPBC_BFB_Form_Storage::get_current_form_by_key( $form_key, $user_id, $status );
312 - if ( $row ) {
313 - return wpbc_form_config__from_row( $row );
314 - }
176 + $row = WPBC_BFB_Form_Storage::get_current_form_by_key( $form_key, $user_id, $status );
177 + if ( $row ) {
178 + return wpbc_form_config__from_row( $row );
179 + }
180 +
181 + // Not found.
182 + return null;
183 +}
184 +
185 +// == 5. Public saver: BFB (and later other engines) -> DB ==
315 186
316 - // 2) Fallback to legacy options.
317 - if ( $is_fallback_to_legacy ) {
318 -
319 - return wpbc_form_config__load_from_legacy( $form_key, $user_id );
320 -
321 - }
322 -
323 - // Not found.
324 - return null;
325 -}
326 -
327 -// == 6. Sync back to legacy options (for runtime compatibility) ==
328 -
329 187 /**
330 - * Sync a normalized FormConfig back into legacy wp_options for runtime compatibility.
331 - *
332 - * This keeps all existing Booking Calendar runtime code working while the
333 - * new Form Builder engine is being rolled out.
334 - *
335 - * Behaviour:
336 - * - 'standard' form maps to:
337 - * - booking_form (advanced_form).
338 - * - booking_form_show (content_form).
339 - * - Custom forms are stored in booking_forms_extended (serialized array).
340 - *
341 - * @param array $cfg FormConfig array produced by the Form Manager.
342 - *
343 - * @return void
344 - */
345 -function wpbc_form_config__sync_legacy_options( array $cfg ) {
346 -
347 - if ( empty( $cfg['form_name'] ) ) {
348 - return;
349 - }
350 -
351 - $form_name = (string) $cfg['form_name'];
352 - $advanced_form = isset( $cfg['advanced_form'] ) ? (string) $cfg['advanced_form'] : '';
353 - $content_form = isset( $cfg['content_form'] ) ? (string) $cfg['content_form'] : '';
354 -
355 - // Standard form.
356 - if ( 'standard' === $form_name ) {
357 - if ( '' !== $advanced_form ) {
358 - update_bk_option( 'booking_form', $advanced_form );
359 - }
360 - if ( '' !== $content_form ) {
361 - update_bk_option( 'booking_form_show', $content_form );
362 - }
363 -
364 - // Optionally update booking_form_visual from structure_json for legacy_simple
365 - // (we can add this later when exact mapping is defined).
366 - return;
367 - }
368 -
369 - // Custom forms: booking_forms_extended.
370 - $extended = get_bk_option( 'booking_forms_extended' );
371 - $extended = maybe_unserialize( $extended );
372 -
373 - if ( ! is_array( $extended ) ) {
374 - $extended = array();
375 - }
376 -
377 - $found = false;
378 -
379 - foreach ( $extended as &$one ) {
380 - if ( empty( $one['name'] ) || (string) $one['name'] !== $form_name ) {
381 - continue;
382 - }
383 -
384 - $one['form'] = $advanced_form;
385 - $one['content'] = $content_form;
386 - $found = true;
387 - break;
388 - }
389 - unset( $one );
390 -
391 - if ( ! $found ) {
392 - $extended[] = array(
393 - 'name' => $form_name,
394 - 'form' => $advanced_form,
395 - 'content' => $content_form,
396 - );
397 - }
398 -
399 - update_bk_option( 'booking_forms_extended', serialize( $extended ) );
400 -}
401 -
402 -// == 7. Public saver: BFB (and later other engines) -> DB + legacy ==
403 -
404 -/**
405 188 * Save BFB Form into DB - Main Save Function!
406 189 *
407 - * Save unified FormConfig into booking_form_structures and sync legacy options.
190 + * Save unified FormConfig into booking_form_structures.
408 191 *
409 192 * Expected minimal keys in $form_config:
410 193 * - form_name
411 194 * - engine
@@ -416,28 +199,26 @@
416 199 * Behaviour:
417 200 * - Always writes to booking_form_structures via WPBC_BFB_Form_Storage::save_form().
418 201 * - Uses form_slug = form_name.
419 202 * - Uses status from $form_config['status'] or 'published' by default.
420 - * - Optionally calls wpbc_form_config__sync_legacy_options() to keep
421 - * existing legacy runtime code working.
422 203 *
423 204 * @param array $form_config Normalized FormConfig array.
424 205 * @param array $args {
425 206 * Optional. Additional saving arguments.
426 207 *
427 - * @type bool $sync_legacy Whether to sync legacy wp_options. Default true.
208 + * @type bool $sync_legacy Deprecated. Ignored. BFB does not sync legacy options.
428 209 * }
429 210 *
430 211 * @return int|false booking_form_id on success, or false on failure.
431 212 */
432 -function wpbc_form_config_save( array $form_config, array $args = array() ) {
213 +function wpbc_form_config_save( array $form_config, array $args = array() ) {
433 214
434 215 $args = wp_parse_args(
435 - $args,
436 - array(
437 - 'sync_legacy' => true,
438 - )
439 - );
216 + $args,
217 + array(
218 + 'sync_legacy' => false,
219 + )
220 + );
440 221
441 222 $form_name = isset( $form_config['form_name'] ) ? (string) $form_config['form_name'] : '';
442 223 if ( '' === $form_name ) {
443 224 $form_name = 'standard';
@@ -445,11 +226,14 @@
445 226
446 227 $engine = isset( $form_config['engine'] ) ? (string) $form_config['engine'] : 'bfb';
447 228 $engine_version = isset( $form_config['engine_version'] ) ? (string) $form_config['engine_version'] : '1.0';
448 229
449 - $structure_json = isset( $form_config['structure_json'] ) ? (string) $form_config['structure_json'] : '';
450 - $settings = isset( $form_config['settings'] ) ? $form_config['settings'] : array();
451 - $settings_json = wpbc_form_config__encode_json( $settings ); // Returns '' on error/empty.
230 + $structure_json = isset( $form_config['structure_json'] ) ? (string) $form_config['structure_json'] : '';
231 + $settings = isset( $form_config['settings'] ) ? $form_config['settings'] : array();
232 + if ( function_exists( 'wpbc_bfb_settings__strip_form_style_options_from_form_settings' ) ) {
233 + $settings = wpbc_bfb_settings__strip_form_style_options_from_form_settings( $settings );
234 + }
235 + $settings_json = wpbc_form_config__encode_json( $settings ); // Returns '' on error/empty.
452 236
453 237 $advanced_form = isset( $form_config['advanced_form'] ) ? (string) $form_config['advanced_form'] : '';
454 238 $content_form = isset( $form_config['content_form'] ) ? (string) $form_config['content_form'] : '';
455 239
@@ -485,17 +269,101 @@
485 269 );
486 270
487 271 $booking_form_id = WPBC_BFB_Form_Storage::save_form( $storage_data );
488 272
489 - if ( $booking_form_id && ! empty( $args['sync_legacy'] ) ) {
490 - wpbc_form_config__sync_legacy_options( $form_config );
491 - }
492 -
493 - return $booking_form_id;
494 -}
495 -
496 -
497 -// == Default Load Form !) ==
273 + return $booking_form_id;
274 +}
275 +
276 +/**
277 + * Save the Standard booking form as a BFB canonical form record.
278 + *
279 + * This is used by activation/setup paths that previously wrote directly into
280 + * legacy options such as booking_form and booking_form_show.
281 + *
282 + * @param string $advanced_form Advanced booking form shortcodes.
283 + * @param string $content_form Content of booking fields data shortcodes.
284 + * @param int $owner_user_id Optional MultiUser owner ID.
285 + * @param array $args Optional args: visual_form_structure, form_name, title.
286 + *
287 + * @return int|false booking_form_id on success, or false on failure.
288 + */
289 +function wpbc_bfb_save_standard_form_from_advanced_mode( $advanced_form, $content_form, $owner_user_id = 0, $args = array() ) {
290 +
291 + $args = wp_parse_args(
292 + $args,
293 + array(
294 + 'visual_form_structure' => false,
295 + 'form_name' => 'standard',
296 + 'title' => __( 'Standard', 'booking' ),
297 + )
298 + );
299 +
300 + $structure_arr = array();
301 + $engine = 'advanced_mode';
302 +
303 + if ( is_array( $args['visual_form_structure'] ) && function_exists( 'wpbc_simple_form__export_to_bfb_structure' ) ) {
304 + $structure_arr = wpbc_simple_form__export_to_bfb_structure( $args['visual_form_structure'] );
305 + if ( is_array( $structure_arr ) && ! empty( $structure_arr ) ) {
306 + $engine = 'bfb';
307 + }
308 + }
309 +
310 + $form_config = array(
311 + 'form_name' => (string) $args['form_name'],
312 + 'engine' => $engine,
313 + 'engine_version' => '1.0',
314 + 'structure_json' => wpbc_form_config__encode_json( $structure_arr ),
315 + 'settings' => array(),
316 + 'advanced_form' => (string) $advanced_form,
317 + 'content_form' => (string) $content_form,
318 + 'owner_user_id' => max( 0, (int) $owner_user_id ),
319 + 'title' => (string) $args['title'],
320 + 'description' => '',
321 + 'scope' => 'global',
322 + 'status' => 'published',
323 + 'is_default' => 1,
324 + 'booking_resource_id' => null,
325 + );
326 +
327 + return wpbc_form_config_save( $form_config, array( 'sync_legacy' => false ) );
328 +}
329 +
330 +
331 +/**
332 + * Delete all BFB forms owned by one regular MultiUser account.
333 + *
334 + * This belongs to the full owner-settings deletion lifecycle. Merely switching
335 + * an owner Off must not call it, so the user's Builder forms remain available
336 + * after reactivation.
337 + *
338 + * @param int $owner_user_id Owner user ID.
339 + *
340 + * @return bool
341 + */
342 +function wpbc_bfb_delete_forms_for_owner( $owner_user_id ) {
343 +
344 + $owner_user_id = absint( $owner_user_id );
345 + if ( $owner_user_id <= 0 ) {
346 + return false;
347 + }
348 + if ( function_exists( 'wpbc_is_table_exists' ) && ! wpbc_is_table_exists( 'booking_form_structures' ) ) {
349 + return true;
350 + }
351 +
352 + global $wpdb;
353 +
354 + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
355 + $deleted = $wpdb->delete(
356 + $wpdb->prefix . 'booking_form_structures',
357 + array( 'owner_user_id' => $owner_user_id ),
358 + array( '%d' )
359 + );
360 +
361 + return ( false !== $deleted );
362 +}
363 +
364 +
365 +// == Default Load Form !) ==
498 366
499 367 /**
500 368 * Get default form key used by the Form Builder.
501 369 *