PluginProbe
Booking Calendar / 11.2
Booking Calendar v11.2
11.9 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 All 205 releases
booking / includes / page-form-builder / assets / template-records / bfb-activate-templates.php

bfb-activate-templates.php in Booking Calendar 11.2, at includes/page-form-builder/assets/template-records/bfb-activate-templates.php

479 lines 14.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Booking Form Builder - Bundled templates activation/update helpers.
4 *
5 * Responsibilities:
6 * - Register bundled BFB templates.
7 * - Seed missing template records into wp_booking_form_structures.
8 * - Track per-template seed versions.
9 * - Optionally update bundled template rows in future releases.
10 *
11 * @package Booking Calendar
12 * @author wpdevelop, oplugins
13 * @web-site https://wpbookingcalendar.com/
14 * @email [email protected]
15 *
16 * @since 11.0.x
17 * @file ../includes/page-form-builder/assets/template-records/bfb-activate-templates.php
18 * @modified 2026-03-09
19 */
20
21 if ( ! defined( 'ABSPATH' ) ) {
22 exit; // Exit if accessed directly.
23 }
24
25 /**
26 * Return option key storing bundled templates seed state.
27 *
28 * Stored value example:
29 * array(
30 * 'service_appointments' => '11.0.0',
31 * 'contact_inquiry' => '11.1.0',
32 * )
33 *
34 * @return string
35 */
36 function wpbc_bfb_activation__get_templates_seed_state_option_key() {
37 return 'wpbc_bfb_templates_seed_state';
38 }
39
40 /**
41 * Get stored bundled templates seed state.
42 *
43 * @return array
44 */
45 function wpbc_bfb_activation__get_templates_seed_state() {
46
47 $state = get_option( wpbc_bfb_activation__get_templates_seed_state_option_key(), array() );
48
49 return ( is_array( $state ) ) ? $state : array();
50 }
51
52 /**
53 * Save bundled templates seed state.
54 *
55 * @param array $state Seed state.
56 *
57 * @return void
58 */
59 function wpbc_bfb_activation__save_templates_seed_state( $state ) {
60
61 if ( ! is_array( $state ) ) {
62 $state = array();
63 }
64
65 update_option( wpbc_bfb_activation__get_templates_seed_state_option_key(), $state );
66 }
67
68 /**
69 * Delete bundled templates seed state.
70 *
71 * @return void
72 */
73 function wpbc_bfb_activation__delete_templates_seed_state() {
74 delete_bk_option( wpbc_bfb_activation__get_templates_seed_state_option_key() );
75 }
76
77 /**
78 * Return absolute path to bundled template records directory.
79 *
80 * @return string
81 */
82 function wpbc_bfb_activation__get_templates_dir_path() {
83
84 // return dirname( __FILE__ ); // . '/../assets/template-records'; //.
85
86 return WPBC_PLUGIN_DIR . '/includes/page-form-builder/assets/template-records';
87 }
88
89 /**
90 * Return bundled template registry.
91 *
92 * Each item must return:
93 * array(
94 * 'template_key' => 'service_appointments',
95 * 'seed_version' => '11.0.0',
96 * 'sync_mode' => 'insert_only', // or 'upsert'
97 * 'record' => array( ... DB columns ... ),
98 * )
99 *
100 * Notes:
101 * - template_key must stay stable across releases.
102 * - seed_version is compared against stored seed state for this template.
103 * - sync_mode:
104 * - insert_only = insert once if missing, never overwrite existing row.
105 * - upsert = insert if missing, update existing row when seed_version increases.
106 *
107 * @return array
108 */
109 function wpbc_bfb_activation__get_templates_registry() {
110
111 $templates = array();
112 $template_files = array(
113
114 // Contact Forms.
115 wpbc_bfb_activation__get_templates_dir_path() . '/contact_form_simple.php',
116 wpbc_bfb_activation__get_templates_dir_path() . '/technical_support_form.php',
117 wpbc_bfb_activation__get_templates_dir_path() . '/inquiry_form_simple.php',
118
119 // Advanced Not Synced Forms.
120 wpbc_bfb_activation__get_templates_dir_path() . '/dates_advanced_2_steps_wizard_with_hints.php',
121 wpbc_bfb_activation__get_templates_dir_path() . '/dates_advanced_form_with_hints.php',
122
123 // Time Slots.
124 wpbc_bfb_activation__get_templates_dir_path() . '/time_slots_start_end_times_1_hour_selection.php',
125 wpbc_bfb_activation__get_templates_dir_path() . '/time_slots_start_duration_times_selection.php',
126 wpbc_bfb_activation__get_templates_dir_path() . '/time_slots_30_min_2_steps_wizard.php',
127 wpbc_bfb_activation__get_templates_dir_path() . '/time_slots_20_min_2_steps_wizard.php',
128
129 // Time - Service Appointments.
130 wpbc_bfb_activation__get_templates_dir_path() . '/time_appointments_3_steps_wizard.php',
131 wpbc_bfb_activation__get_templates_dir_path() . '/time_appointments_2_steps_vertical_layout.php',
132 wpbc_bfb_activation__get_templates_dir_path() . '/time_appointments_2_steps_wizard.php',
133
134 // Full Day - Booking Forms.
135 wpbc_bfb_activation__get_templates_dir_path() . '/dates_form_with_3_columns_layout.php',
136 wpbc_bfb_activation__get_templates_dir_path() . '/dates_form_with_calendar_next_to_form.php',
137 wpbc_bfb_activation__get_templates_dir_path() . '/dates_form_with_vertical_layout.php',
138 wpbc_bfb_activation__get_templates_dir_path() . '/dates_form_wizard_2_steps.php',
139
140 // Hints
141 wpbc_bfb_activation__get_templates_dir_path() . '/time_slots_20_min_3_steps_review_with_hints.php',
142 wpbc_bfb_activation__get_templates_dir_path() . '/time_appointments_3_steps_review_with_hints.php',
143 wpbc_bfb_activation__get_templates_dir_path() . '/dates_advanced_3_steps_review_with_hints.php',
144 wpbc_bfb_activation__get_templates_dir_path() . '/dates_2_columns_sidebar_hints.php',
145
146 // Example future records:
147 // wpbc_bfb_activation__get_templates_dir_path() . '/template-contact-inquiry.php',
148 // wpbc_bfb_activation__get_templates_dir_path() . '/template-event-registration.php',
149 );
150
151 foreach ( $template_files as $template_file ) {
152 if ( file_exists( $template_file ) ) {
153 $template_config = require $template_file;
154
155 if ( is_array( $template_config ) ) {
156 $templates[] = $template_config;
157 }
158 }
159 }
160
161 /**
162 * Allow third-party code or future modules to register bundled templates.
163 */
164 $templates = apply_filters( 'wpbc_bfb_activation__templates_registry', $templates );
165
166 return $templates;
167 }
168
169 /**
170 * Normalize bundled template config.
171 *
172 * @param array $template_config Raw template config.
173 *
174 * @return array
175 */
176 function wpbc_bfb_activation__normalize_template_config( $template_config ) {
177
178 $template_config = wp_parse_args(
179 $template_config,
180 array(
181 'template_key' => '',
182 'seed_version' => '1.0.0',
183 'sync_mode' => 'insert_only',
184 'record' => array(),
185 )
186 );
187
188 $template_config['template_key'] = sanitize_key( $template_config['template_key'] );
189 $template_config['seed_version'] = (string) $template_config['seed_version'];
190 $template_config['sync_mode'] = ( 'upsert' === $template_config['sync_mode'] ) ? 'upsert' : 'insert_only';
191
192 $template_config['record'] = wp_parse_args(
193 $template_config['record'],
194 array(
195 'form_slug' => '',
196 'status' => 'template',
197 'scope' => 'global',
198 'version' => 1,
199 'booking_resource_id' => null,
200 'owner_user_id' => 0,
201 'engine' => 'bfb',
202 'engine_version' => '1.0',
203 'structure_json' => '',
204 'settings_json' => '',
205 'advanced_form' => '',
206 'content_form' => '',
207 'is_default' => 0,
208 'title' => '',
209 'description' => '',
210 'picture_url' => '',
211 )
212 );
213
214 $template_config['record']['form_slug'] = sanitize_title( $template_config['record']['form_slug'] );
215 $template_config['record']['status'] = sanitize_key( $template_config['record']['status'] );
216 $template_config['record']['scope'] = sanitize_key( $template_config['record']['scope'] );
217 $template_config['record']['version'] = (int) $template_config['record']['version'];
218 $template_config['record']['owner_user_id'] = (int) $template_config['record']['owner_user_id'];
219 $template_config['record']['is_default'] = (int) $template_config['record']['is_default'];
220 $template_config['record']['engine'] = (string) $template_config['record']['engine'];
221 $template_config['record']['engine_version'] = (string) $template_config['record']['engine_version'];
222 $template_config['record']['title'] = (string) $template_config['record']['title'];
223 $template_config['record']['description'] = (string) $template_config['record']['description'];
224 $template_config['record']['picture_url'] = (string) $template_config['record']['picture_url'];
225
226 if ( null !== $template_config['record']['booking_resource_id'] ) {
227 $template_config['record']['booking_resource_id'] = (int) $template_config['record']['booking_resource_id'];
228 }
229
230 return $template_config;
231 }
232
233 /**
234 * Find existing bundled template row by unique fields.
235 *
236 * @param array $record Template DB record.
237 *
238 * @return int
239 */
240 function wpbc_bfb_activation__find_existing_template_id( $record ) {
241
242 global $wpdb;
243
244 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
245 $existing_id = (int) $wpdb->get_var( $wpdb->prepare(
246 "SELECT booking_form_id
247 FROM {$wpdb->prefix}booking_form_structures
248 WHERE form_slug = %s
249 AND status = %s
250 AND owner_user_id = %d
251 LIMIT 1",
252 $record['form_slug'],
253 $record['status'],
254 (int) $record['owner_user_id']
255 ) );
256
257 return $existing_id;
258 }
259
260 /**
261 * Build DB row for insert/update.
262 *
263 * @param array $record Template DB record.
264 *
265 * @return array
266 */
267 function wpbc_bfb_activation__build_template_db_row( $record ) {
268
269 $now = current_time( 'mysql' );
270
271 return array(
272 'form_slug' => $record['form_slug'],
273 'status' => $record['status'],
274 'scope' => $record['scope'],
275 'version' => (int) $record['version'],
276 'booking_resource_id' => $record['booking_resource_id'],
277 'owner_user_id' => (int) $record['owner_user_id'],
278 'engine' => $record['engine'],
279 'engine_version' => $record['engine_version'],
280 'structure_json' => $record['structure_json'],
281 'settings_json' => $record['settings_json'],
282 'advanced_form' => $record['advanced_form'],
283 'content_form' => $record['content_form'],
284 'is_default' => (int) $record['is_default'],
285 'title' => $record['title'],
286 'description' => $record['description'],
287 'picture_url' => $record['picture_url'],
288 'updated_at' => $now,
289 'updated_by' => 0,
290 );
291 }
292
293 /**
294 * Insert bundled template record.
295 *
296 * @param array $record Template DB record.
297 *
298 * @return bool
299 */
300 function wpbc_bfb_activation__insert_template_record( $record ) {
301
302 global $wpdb;
303
304 $table_name = $wpdb->prefix . 'booking_form_structures';
305 $data = wpbc_bfb_activation__build_template_db_row( $record );
306
307 $data['created_at'] = $data['updated_at'];
308 $data['created_by'] = 0;
309 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
310 $inserted = $wpdb->insert( $table_name, $data );
311
312 return ( false !== $inserted );
313 }
314
315 /**
316 * Update bundled template record by row ID.
317 *
318 * @param int $booking_form_id Existing row ID.
319 * @param array $record Template DB record.
320 *
321 * @return bool
322 */
323 function wpbc_bfb_activation__update_template_record( $booking_form_id, $record ) {
324
325 global $wpdb;
326
327 $table_name = $wpdb->prefix . 'booking_form_structures';
328 $booking_form_id = (int) $booking_form_id;
329 $data = wpbc_bfb_activation__build_template_db_row( $record );
330
331 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
332 $updated = $wpdb->update(
333 $table_name,
334 $data,
335 array(
336 'booking_form_id' => $booking_form_id,
337 )
338 );
339
340 return ( false !== $updated );
341 }
342
343 /**
344 * Sync one bundled template.
345 *
346 * @param array $template_config Template config.
347 * @param array $seed_state Current stored seed state.
348 *
349 * @return array
350 */
351 /**
352 * Sync one bundled template.
353 *
354 * @param array $template_config Template config.
355 * @param array $seed_state Current stored seed state.
356 *
357 * @return array
358 */
359 function wpbc_bfb_activation__sync_one_template( $template_config, $seed_state ) {
360
361 $result = array(
362 'ok' => false,
363 'seed_state' => $seed_state,
364 );
365
366 $template_config = wpbc_bfb_activation__normalize_template_config( $template_config );
367
368 if ( empty( $template_config['template_key'] ) ) {
369 return $result;
370 }
371
372 if ( empty( $template_config['record']['form_slug'] ) ) {
373 return $result;
374 }
375
376 $template_key = $template_config['template_key'];
377 $seed_version = $template_config['seed_version'];
378 $sync_mode = $template_config['sync_mode'];
379 $record = $template_config['record'];
380 $stored_version = isset( $seed_state[ $template_key ] ) ? (string) $seed_state[ $template_key ] : '';
381 $existing_row_id = wpbc_bfb_activation__find_existing_template_id( $record );
382
383 // Already synced for this template version and DB row still exists.
384 if (
385 ( $existing_row_id > 0 ) &&
386 ( ! empty( $stored_version ) ) &&
387 version_compare( $stored_version, $seed_version, '>=' )
388 ) {
389 $result['ok'] = true;
390 return $result;
391 }
392
393 // Insert if missing.
394 if ( $existing_row_id <= 0 ) {
395 $result['ok'] = wpbc_bfb_activation__insert_template_record( $record );
396
397 if ( $result['ok'] ) {
398 $result['seed_state'][ $template_key ] = $seed_version;
399 }
400
401 return $result;
402 }
403
404 // Existing row found.
405 if ( 'upsert' === $sync_mode ) {
406 $result['ok'] = wpbc_bfb_activation__update_template_record( $existing_row_id, $record );
407 } else {
408 // insert_only mode: mark as synced, do not overwrite existing row.
409 $result['ok'] = true;
410 }
411
412 if ( $result['ok'] ) {
413 $result['seed_state'][ $template_key ] = $seed_version;
414 }
415
416 return $result;
417 }
418
419 /**
420 * Seed bundled BFB templates.
421 *
422 * Runs both:
423 * - after table creation,
424 * - when table already exists.
425 *
426 * @return void
427 */
428 /**
429 * Seed bundled BFB templates.
430 *
431 * Runs both:
432 * - after table creation,
433 * - when table already exists.
434 *
435 * @return void
436 */
437 function wpbc_bfb_activation__seed_templates() {
438
439 if ( ! wpbc_is_table_exists( 'booking_form_structures' ) ) {
440 return;
441 }
442
443 $templates = wpbc_bfb_activation__get_templates_registry();
444 if ( empty( $templates ) || ! is_array( $templates ) ) {
445 return;
446 }
447
448 $seed_state = wpbc_bfb_activation__get_templates_seed_state();
449 $is_changed = false;
450
451 foreach ( $templates as $template_config ) {
452
453 $seed_state_before = $seed_state;
454
455 $sync_result = wpbc_bfb_activation__sync_one_template( $template_config, $seed_state );
456 $seed_state = $sync_result['seed_state'];
457
458 if ( $seed_state !== $seed_state_before ) {
459 $is_changed = true;
460 }
461 }
462
463 if ( $is_changed ) {
464 wpbc_bfb_activation__save_templates_seed_state( $seed_state );
465 }
466 }
467 add_action( 'wpbc_bfb_activation__form_structures_table__after_create', 'wpbc_bfb_activation__seed_templates' );
468 add_action( 'wpbc_bfb_activation__form_structures_table__table_already_exists', 'wpbc_bfb_activation__seed_templates' );
469
470 /**
471 * Cleanup bundled templates seed state on deactivation.
472 *
473 * @return void
474 */
475 function wpbc_bfb_activation__cleanup_templates_seed_state_on_deactivation() {
476 wpbc_bfb_activation__delete_templates_seed_state();
477 }
478 add_bk_action( 'wpbc_free_version_deactivation', 'wpbc_bfb_activation__cleanup_templates_seed_state_on_deactivation' );
479