PluginProbe
Booking Calendar / 11.0
Booking Calendar v11.0
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.0, at includes/page-form-builder/assets/template-records/bfb-activate-templates.php

477 lines 14.8 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
145 // Example future records:
146 // wpbc_bfb_activation__get_templates_dir_path() . '/template-contact-inquiry.php',
147 // wpbc_bfb_activation__get_templates_dir_path() . '/template-event-registration.php',
148 );
149
150 foreach ( $template_files as $template_file ) {
151 if ( file_exists( $template_file ) ) {
152 $template_config = require $template_file;
153
154 if ( is_array( $template_config ) ) {
155 $templates[] = $template_config;
156 }
157 }
158 }
159
160 /**
161 * Allow third-party code or future modules to register bundled templates.
162 */
163 $templates = apply_filters( 'wpbc_bfb_activation__templates_registry', $templates );
164
165 return $templates;
166 }
167
168 /**
169 * Normalize bundled template config.
170 *
171 * @param array $template_config Raw template config.
172 *
173 * @return array
174 */
175 function wpbc_bfb_activation__normalize_template_config( $template_config ) {
176
177 $template_config = wp_parse_args(
178 $template_config,
179 array(
180 'template_key' => '',
181 'seed_version' => '1.0.0',
182 'sync_mode' => 'insert_only',
183 'record' => array(),
184 )
185 );
186
187 $template_config['template_key'] = sanitize_key( $template_config['template_key'] );
188 $template_config['seed_version'] = (string) $template_config['seed_version'];
189 $template_config['sync_mode'] = ( 'upsert' === $template_config['sync_mode'] ) ? 'upsert' : 'insert_only';
190
191 $template_config['record'] = wp_parse_args(
192 $template_config['record'],
193 array(
194 'form_slug' => '',
195 'status' => 'template',
196 'scope' => 'global',
197 'version' => 1,
198 'booking_resource_id' => null,
199 'owner_user_id' => 0,
200 'engine' => 'bfb',
201 'engine_version' => '1.0',
202 'structure_json' => '',
203 'settings_json' => '',
204 'advanced_form' => '',
205 'content_form' => '',
206 'is_default' => 0,
207 'title' => '',
208 'description' => '',
209 'picture_url' => '',
210 )
211 );
212
213 $template_config['record']['form_slug'] = sanitize_title( $template_config['record']['form_slug'] );
214 $template_config['record']['status'] = sanitize_key( $template_config['record']['status'] );
215 $template_config['record']['scope'] = sanitize_key( $template_config['record']['scope'] );
216 $template_config['record']['version'] = (int) $template_config['record']['version'];
217 $template_config['record']['owner_user_id'] = (int) $template_config['record']['owner_user_id'];
218 $template_config['record']['is_default'] = (int) $template_config['record']['is_default'];
219 $template_config['record']['engine'] = (string) $template_config['record']['engine'];
220 $template_config['record']['engine_version'] = (string) $template_config['record']['engine_version'];
221 $template_config['record']['title'] = (string) $template_config['record']['title'];
222 $template_config['record']['description'] = (string) $template_config['record']['description'];
223 $template_config['record']['picture_url'] = (string) $template_config['record']['picture_url'];
224
225 if ( null !== $template_config['record']['booking_resource_id'] ) {
226 $template_config['record']['booking_resource_id'] = (int) $template_config['record']['booking_resource_id'];
227 }
228
229 return $template_config;
230 }
231
232 /**
233 * Find existing bundled template row by unique fields.
234 *
235 * @param array $record Template DB record.
236 *
237 * @return int
238 */
239 function wpbc_bfb_activation__find_existing_template_id( $record ) {
240
241 global $wpdb;
242
243 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
244 $existing_id = (int) $wpdb->get_var( $wpdb->prepare(
245 "SELECT booking_form_id
246 FROM {$wpdb->prefix}booking_form_structures
247 WHERE form_slug = %s
248 AND status = %s
249 AND owner_user_id = %d
250 LIMIT 1",
251 $record['form_slug'],
252 $record['status'],
253 (int) $record['owner_user_id']
254 ) );
255
256 return $existing_id;
257 }
258
259 /**
260 * Build DB row for insert/update.
261 *
262 * @param array $record Template DB record.
263 *
264 * @return array
265 */
266 function wpbc_bfb_activation__build_template_db_row( $record ) {
267
268 $now = current_time( 'mysql' );
269
270 return array(
271 'form_slug' => $record['form_slug'],
272 'status' => $record['status'],
273 'scope' => $record['scope'],
274 'version' => (int) $record['version'],
275 'booking_resource_id' => $record['booking_resource_id'],
276 'owner_user_id' => (int) $record['owner_user_id'],
277 'engine' => $record['engine'],
278 'engine_version' => $record['engine_version'],
279 'structure_json' => $record['structure_json'],
280 'settings_json' => $record['settings_json'],
281 'advanced_form' => $record['advanced_form'],
282 'content_form' => $record['content_form'],
283 'is_default' => (int) $record['is_default'],
284 'title' => $record['title'],
285 'description' => $record['description'],
286 'picture_url' => $record['picture_url'],
287 'updated_at' => $now,
288 'updated_by' => 0,
289 );
290 }
291
292 /**
293 * Insert bundled template record.
294 *
295 * @param array $record Template DB record.
296 *
297 * @return bool
298 */
299 function wpbc_bfb_activation__insert_template_record( $record ) {
300
301 global $wpdb;
302
303 $table_name = $wpdb->prefix . 'booking_form_structures';
304 $data = wpbc_bfb_activation__build_template_db_row( $record );
305
306 $data['created_at'] = $data['updated_at'];
307 $data['created_by'] = 0;
308 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
309 $inserted = $wpdb->insert( $table_name, $data );
310
311 return ( false !== $inserted );
312 }
313
314 /**
315 * Update bundled template record by row ID.
316 *
317 * @param int $booking_form_id Existing row ID.
318 * @param array $record Template DB record.
319 *
320 * @return bool
321 */
322 function wpbc_bfb_activation__update_template_record( $booking_form_id, $record ) {
323
324 global $wpdb;
325
326 $table_name = $wpdb->prefix . 'booking_form_structures';
327 $booking_form_id = (int) $booking_form_id;
328 $data = wpbc_bfb_activation__build_template_db_row( $record );
329
330 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
331 $updated = $wpdb->update(
332 $table_name,
333 $data,
334 array(
335 'booking_form_id' => $booking_form_id,
336 )
337 );
338
339 return ( false !== $updated );
340 }
341
342 /**
343 * Sync one bundled template.
344 *
345 * @param array $template_config Template config.
346 * @param array $seed_state Current stored seed state.
347 *
348 * @return array
349 */
350 /**
351 * Sync one bundled template.
352 *
353 * @param array $template_config Template config.
354 * @param array $seed_state Current stored seed state.
355 *
356 * @return array
357 */
358 function wpbc_bfb_activation__sync_one_template( $template_config, $seed_state ) {
359
360 $result = array(
361 'ok' => false,
362 'seed_state' => $seed_state,
363 );
364
365 $template_config = wpbc_bfb_activation__normalize_template_config( $template_config );
366
367 if ( empty( $template_config['template_key'] ) ) {
368 return $result;
369 }
370
371 if ( empty( $template_config['record']['form_slug'] ) ) {
372 return $result;
373 }
374
375 $template_key = $template_config['template_key'];
376 $seed_version = $template_config['seed_version'];
377 $sync_mode = $template_config['sync_mode'];
378 $record = $template_config['record'];
379 $stored_version = isset( $seed_state[ $template_key ] ) ? (string) $seed_state[ $template_key ] : '';
380 $existing_row_id = wpbc_bfb_activation__find_existing_template_id( $record );
381
382 // Already synced for this template version and DB row still exists.
383 if (
384 ( $existing_row_id > 0 ) &&
385 ( ! empty( $stored_version ) ) &&
386 version_compare( $stored_version, $seed_version, '>=' )
387 ) {
388 $result['ok'] = true;
389 return $result;
390 }
391
392 // Insert if missing.
393 if ( $existing_row_id <= 0 ) {
394 $result['ok'] = wpbc_bfb_activation__insert_template_record( $record );
395
396 if ( $result['ok'] ) {
397 $result['seed_state'][ $template_key ] = $seed_version;
398 }
399
400 return $result;
401 }
402
403 // Existing row found.
404 if ( 'upsert' === $sync_mode ) {
405 $result['ok'] = wpbc_bfb_activation__update_template_record( $existing_row_id, $record );
406 } else {
407 // insert_only mode: mark as synced, do not overwrite existing row.
408 $result['ok'] = true;
409 }
410
411 if ( $result['ok'] ) {
412 $result['seed_state'][ $template_key ] = $seed_version;
413 }
414
415 return $result;
416 }
417
418 /**
419 * Seed bundled BFB templates.
420 *
421 * Runs both:
422 * - after table creation,
423 * - when table already exists.
424 *
425 * @return void
426 */
427 /**
428 * Seed bundled BFB templates.
429 *
430 * Runs both:
431 * - after table creation,
432 * - when table already exists.
433 *
434 * @return void
435 */
436 function wpbc_bfb_activation__seed_templates() {
437
438 if ( ! wpbc_is_table_exists( 'booking_form_structures' ) ) {
439 return;
440 }
441
442 $templates = wpbc_bfb_activation__get_templates_registry();
443 if ( empty( $templates ) || ! is_array( $templates ) ) {
444 return;
445 }
446
447 $seed_state = wpbc_bfb_activation__get_templates_seed_state();
448 $is_changed = false;
449
450 foreach ( $templates as $template_config ) {
451
452 $seed_state_before = $seed_state;
453
454 $sync_result = wpbc_bfb_activation__sync_one_template( $template_config, $seed_state );
455 $seed_state = $sync_result['seed_state'];
456
457 if ( $seed_state !== $seed_state_before ) {
458 $is_changed = true;
459 }
460 }
461
462 if ( $is_changed ) {
463 wpbc_bfb_activation__save_templates_seed_state( $seed_state );
464 }
465 }
466 add_action( 'wpbc_bfb_activation__form_structures_table__after_create', 'wpbc_bfb_activation__seed_templates' );
467 add_action( 'wpbc_bfb_activation__form_structures_table__table_already_exists', 'wpbc_bfb_activation__seed_templates' );
468
469 /**
470 * Cleanup bundled templates seed state on deactivation.
471 *
472 * @return void
473 */
474 function wpbc_bfb_activation__cleanup_templates_seed_state_on_deactivation() {
475 wpbc_bfb_activation__delete_templates_seed_state();
476 }
477 add_bk_action( 'wpbc_free_version_deactivation', 'wpbc_bfb_activation__cleanup_templates_seed_state_on_deactivation' );