PluginProbe
Booking Calendar / 11.8
Booking Calendar v11.8
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 10.11.3 All 202 releases
booking / includes / page-form-builder / bfb-bootstrap.php

bfb-bootstrap.php in Booking Calendar 11.8, at includes/page-form-builder/bfb-bootstrap.php

363 lines 18.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Hybrid++ Bootstrap: collect packs, localize schemas, print pack templates.
4 *
5 * @package Booking Calendar.
6 * @author wpdevelop, oplugins
7 * @web-site https://wpbookingcalendar.com/
8 * @email info@wpbookingcalendar.com
9 *
10 * @since 11.0.0
11 * @modified 2025-08-29
12 * @version 1.0
13 */
14
15 // ---------------------------------------------------------------------------------------------------------------------
16 // == File bfb-bootstrap.php == Time point: 2025-08-29 12:25
17 // ---------------------------------------------------------------------------------------------------------------------
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit;
20 }
21
22
23 class WPBC_BFB_Bootstrap {
24
25 /**
26 * Guard flag.
27 *
28 * @var bool
29 */
30 protected static $packs_collected = false;
31
32 /**
33 * Guard flag.
34 *
35 * @var bool
36 */
37 protected static $templates_printed = false;
38
39 /**
40 * Packs keyed by type.
41 *
42 * @var array
43 */
44 protected static $packs_by_type = array();
45
46
47 /**
48 * Init all hooks for the current request.
49 *
50 * @return void
51 */
52 public static function init() {
53
54 // 1) Enqueue BFB scripts, after enqueued basic WPBC scripts (EXTERNAL HOOK). Localize schemas, etc...
55 add_action( 'wpbc_enqueue_js_files', array( __CLASS__, 'on_admin_enqueue__js_files' ), 50 );
56
57 // 2) Enqueue BFB CSS, after basic WPBC scripts are enqueued (EXTERNAL HOOK).
58 add_action( 'wpbc_enqueue_css_files', array( __CLASS__, 'on_admin_enqueue__css_files' ), 50 );
59
60 // 3) Primary: print templates at the end of the page using custom footer hook. The hook passes the slug; we only print when it equals our builder slug.
61 add_action( 'wpbc_hook_settings_page_footer', array( __CLASS__, 'on_settings_page_footer' ), 10, 1 );
62
63 // 4) Fallback printer (for the URL path) so templates still print if the custom footer hook isn’t fired.
64 add_action( 'admin_print_footer_scripts', array( __CLASS__, 'fallback_print_on_admin_footer' ), 20 );
65 }
66
67
68 /**
69 * Enqueue JS files and Localize them.
70 *
71 * @param sring $where_to_load - parameter from root JS loader script. Value can be: 'both', 'client', 'admin'. In this method can be ignore, because we check via self::is_builder_by_request().
72 *
73 * @return void
74 */
75 public static function on_admin_enqueue__js_files( $where_to_load ) {
76
77 if ( ! self::is_builder_by_request() ) {
78 // Might still reach the page via the custom footer hook path; in that case we'll only print templates there.
79 return;
80 }
81 $in_footer = true;
82 $core_handle = apply_filters( 'wpbc_bfb_inspector_script_handle', 'wpbc-bfb' );
83
84 // --- Vendor ---
85 wp_enqueue_script( 'wpbc-sortable', wpbc_plugin_url( '/vendors/sortablejs/Sortable.min.js' ), array( 'wpbc_all' ), WP_BK_VERSION_NUM, $in_footer );
86
87 // --- Color picker (Coloris) --- Load BEFORE core BFB scripts so the Inspector can detect window.Coloris during first render.
88 wp_enqueue_style( 'coloris', wpbc_plugin_url( '/vendors/coloris/dist/coloris.min.css' ), array(), WP_BK_VERSION_NUM );
89 wp_enqueue_script( 'coloris', wpbc_plugin_url( '/vendors/coloris/dist/coloris.min.js' ), array(), WP_BK_VERSION_NUM, $in_footer );
90
91
92 // -- Admin WP Templates Helper (for modals etc..).
93 wp_enqueue_script( 'wpbc-bfb-templates', wpbc_plugin_url( '/includes/page-form-builder/admin-page-tpl/_out/bfb-templates.js' ), array( 'wp-util' ), WP_BK_VERSION_NUM, $in_footer );
94
95 // --- Support Functions ---
96 wp_enqueue_script( 'wpbc-bfb_support_functions', wpbc_plugin_url( '/includes/page-form-builder/_src/support_functions.js' ), array(), WP_BK_VERSION_NUM, $in_footer );
97
98 // --- All Core BFB Scripts ---
99 wp_enqueue_script( $core_handle, wpbc_plugin_url( '/_dist/bfb/_out/wpbc_bfb.js' ), array( 'wpbc-bfb_support_functions', 'wpbc-sortable', 'wp-util', 'wpbc-bfb-templates', 'coloris' ), WP_BK_VERSION_NUM, $in_footer );
100
101 // 2) --- Time Utils ---
102 wp_enqueue_script( 'wpbc-bfb-time-utils', wpbc_plugin_url( '/includes/page-form-builder/_out/bfb-time-utils.js' ), array( $core_handle ), WP_BK_VERSION_NUM, $in_footer );
103
104 // 3) --- Field packs (they can now safely reference wpbc_bfb_inspector_factory_slots/value_from)
105 do_action( 'wpbc_enqueue_js_field_pack', WPBC_BFB_BUILDER_PAGE_SLUG );
106
107 // 5) --- Builder ---
108 wp_enqueue_script( 'wpbc-bfb_builder', wpbc_plugin_url( '/includes/page-form-builder/_out/bfb-builder.js' ), array( $core_handle ), WP_BK_VERSION_NUM, $in_footer );
109
110 // -------------------------------------------------------------------------------------------------------------
111 // == Self attached modules here == - (AFTER builder, because it auto-attaches via wpbc_bfb_api.ready) ---
112 // -------------------------------------------------------------------------------------------------------------
113 // --- Modals, such as page deleteing etc..
114 wp_enqueue_script( 'wpbc-bfb_modal__form_templates', wpbc_plugin_url( '/includes/page-form-builder/admin-page-tpl/_out/modal__form_templates.js' ), array( 'wpbc-bfb_builder' ), WP_BK_VERSION_NUM, $in_footer );
115 wp_enqueue_script( 'wpbc-bfb_modal_page_delete', wpbc_plugin_url( '/includes/page-form-builder/admin-page-tpl/_out/modal_page_delete.js' ), array( 'wpbc-bfb_builder' ), WP_BK_VERSION_NUM, $in_footer );
116 wp_enqueue_script( 'wpbc-bfb_modal_item_delete', wpbc_plugin_url( '/includes/page-form-builder/admin-page-tpl/_out/modal_item_delete.js' ), array( 'wpbc-bfb_builder' ), WP_BK_VERSION_NUM, $in_footer );
117 wp_enqueue_script( 'wpbc-bfb_modal__form_add_new', wpbc_plugin_url( '/includes/page-form-builder/admin-page-tpl/_out/modal__form_add_new.js' ), array( 'wpbc-bfb_builder', 'wpbc-bfb_modal__form_templates' ), WP_BK_VERSION_NUM, $in_footer );
118 wp_enqueue_script( 'wpbc-bfb_modal__form_save_as', wpbc_plugin_url( '/includes/page-form-builder/admin-page-tpl/_out/modal__form_save_as.js' ), array( 'wpbc-bfb_builder' ), WP_BK_VERSION_NUM, $in_footer );
119 wp_enqueue_script( 'wpbc-bfb_modal__form_open', wpbc_plugin_url( '/includes/page-form-builder/admin-page-tpl/_out/modal__form_open.js' ), array( 'wpbc-bfb_builder' ), WP_BK_VERSION_NUM, $in_footer );
120 wp_enqueue_script( 'wpbc-bfb_modal__apply_template', wpbc_plugin_url( '/includes/page-form-builder/admin-page-tpl/_out/modal__form_apply_template.js' ), array( 'wpbc-bfb_builder', 'wpbc-bfb_modal__form_templates' ), WP_BK_VERSION_NUM, $in_footer );
121
122 // Form Settings.
123 // // FixIn: 2026-01-24 wp_enqueue_script( 'wpbc-bfb-so', wpbc_plugin_url( '/includes/page-form-builder/settings-options/_out/bfb-so.js' ), array( 'jquery', 'wp-util', 'wpbc-save-load-option' ), WP_BK_VERSION_NUM, $in_footer );
124 wp_enqueue_script( 'wpbc-bfb-form_settings', wpbc_plugin_url( '/includes/page-form-builder/form-settings/_out/settings.js' ), array( 'jquery', 'wp-util', 'wpbc-save-load-option', 'coloris' ), WP_BK_VERSION_NUM, $in_footer );
125 wp_enqueue_script( 'wpbc-bfb-global_save_behavior', wpbc_plugin_url( '/includes/page-form-builder/form-settings/_out/global_save_behavior.js' ), array( 'wpbc-bfb-form_settings' ), WP_BK_VERSION_NUM, $in_footer );
126 wp_enqueue_script( 'wpbc-bfb-form_settings_effects', wpbc_plugin_url( '/includes/page-form-builder/form-settings/_out/settings_effects.js' ), array( 'wpbc-bfb-form_settings' ), WP_BK_VERSION_NUM, $in_footer );
127 $wpbc_bfb_form_style = wpbc_bfb_settings__get_current_form_style();
128 $wpbc_bfb_form_style_preset = wpbc_bfb_settings__get_form_style_preset( $wpbc_bfb_form_style );
129 $wpbc_bfb_custom_form_style = wpbc_bfb_settings__get_custom_form_style_options();
130 $wpbc_bfb_form_accent = wpbc_bfb_settings__get_form_accent_options();
131 $wpbc_bfb_style_options = array_merge( $wpbc_bfb_custom_form_style, $wpbc_bfb_form_accent );
132 $wpbc_bfb_form_style_vars = wpbc_bfb_settings__get_form_style_css_vars( $wpbc_bfb_form_style, $wpbc_bfb_style_options );
133 $wpbc_bfb_container_style = isset( $wpbc_bfb_form_style_preset['container_style'] ) ? (string) $wpbc_bfb_form_style_preset['container_style'] : 'bordered';
134 $wpbc_bfb_theme_class = isset( $wpbc_bfb_form_style_preset['theme_class'] ) ? (string) $wpbc_bfb_form_style_preset['theme_class'] : '';
135 $wpbc_bfb_legacy_appearance = array(
136 'booking_form_theme' => $wpbc_bfb_theme_class,
137 'booking_form_container_style' => $wpbc_bfb_container_style,
138 'booking_form_background_color' => isset( $wpbc_bfb_form_style_vars['--wpbc-bfb-form-background'] ) ? $wpbc_bfb_form_style_vars['--wpbc-bfb-form-background'] : '#ffffff',
139 'booking_form_border_color' => isset( $wpbc_bfb_form_style_vars['--wpbc-bfb-form-border-color'] ) ? $wpbc_bfb_form_style_vars['--wpbc-bfb-form-border-color'] : '#cccccc',
140 'booking_form_border_width' => isset( $wpbc_bfb_form_style_vars['--wpbc-bfb-form-border-width'] ) ? $wpbc_bfb_form_style_vars['--wpbc-bfb-form-border-width'] : '1px',
141 'booking_form_border_radius' => isset( $wpbc_bfb_form_style_vars['--wpbc-bfb-form-border-radius'] ) ? $wpbc_bfb_form_style_vars['--wpbc-bfb-form-border-radius'] : '2px',
142 'booking_form_padding' => isset( $wpbc_bfb_form_style_vars['--wpbc-bfb-form-padding'] ) ? $wpbc_bfb_form_style_vars['--wpbc-bfb-form-padding'] : '10px 30px',
143 'booking_form_text_color' => isset( $wpbc_bfb_form_style_vars['--wpbc_form-label-color'] ) ? $wpbc_bfb_form_style_vars['--wpbc_form-label-color'] : '',
144 'booking_form_field_background_color' => isset( $wpbc_bfb_form_style_vars['--wpbc_form-field-background-color'] ) ? $wpbc_bfb_form_style_vars['--wpbc_form-field-background-color'] : '',
145 'booking_form_field_text_color' => isset( $wpbc_bfb_form_style_vars['--wpbc_form-field-text-color'] ) ? $wpbc_bfb_form_style_vars['--wpbc_form-field-text-color'] : '',
146 'booking_form_field_border_color' => isset( $wpbc_bfb_form_style_vars['--wpbc_form-field-border-color'] ) ? $wpbc_bfb_form_style_vars['--wpbc_form-field-border-color'] : '',
147 );
148 wp_localize_script(
149 'wpbc-bfb-form_settings',
150 'wpbc_bfb_settings_vars',
151 array(
152 'global_form_style' => array_merge(
153 array(
154 'booking_form_style' => $wpbc_bfb_form_style,
155 'theme_class' => $wpbc_bfb_theme_class,
156 'container_style' => $wpbc_bfb_container_style,
157 'css_vars' => $wpbc_bfb_form_style_vars,
158 ),
159 $wpbc_bfb_style_options
160 ),
161 'form_style_options' => wpbc_bfb_settings__get_form_style_options(),
162 'form_style_presets' => wpbc_bfb_settings__get_form_style_presets(),
163 'form_style_css_var_names' => wpbc_bfb_settings__get_form_style_css_var_names(),
164 'form_style_option_keys' => wpbc_bfb_settings__get_form_json_style_option_keys(),
165 'custom_form_style_defaults' => wpbc_bfb_settings__get_default_custom_form_style_options(),
166 'form_accent_defaults' => wpbc_bfb_settings__get_default_form_accent_options(),
167 'global_appearance' => $wpbc_bfb_legacy_appearance,
168 'i18n' => array(
169 'accent_enable_first' => __( 'Enable Custom accent color first.', 'booking' ),
170 'accent_applied_one' => __( 'Accent applied to one form element. Save Form to keep the change.', 'booking' ),
171 'accent_applied_many' => __( 'Accent applied to %d form elements. Save Form to keep the changes.', 'booking' ),
172 'accent_already_applied' => __( 'All supported form elements already have the current accent color.', 'booking' ),
173 'accent_no_elements' => __( 'No accent-capable form elements were found.', 'booking' ),
174 'accent_applied_announcement' => __( 'Form accent applied.', 'booking' ),
175 'accent_time_picker_automatic' => __( 'Time slots now use Automatic — Match Booking Form.', 'booking' ),
176 ),
177 )
178 );
179
180 // Form Details.
181 wp_enqueue_script( 'wpbc-bfb-form_details_ui', wpbc_plugin_url( '/includes/page-form-builder/form-details/_out/current-form-details-ui.js' ), array( 'wpbc-bfb-form_settings' ), WP_BK_VERSION_NUM, $in_footer );
182 wp_enqueue_script( 'wpbc-bfb-form_details_save_delete', wpbc_plugin_url( '/includes/page-form-builder/form-details/_out/current-form-details-save_delete.js' ), array( 'wpbc-bfb-form_settings' ), WP_BK_VERSION_NUM, $in_footer );
183
184
185
186 wp_enqueue_script( 'wpbc-bfb-top-tabs', wpbc_plugin_url( '/includes/page-form-builder/ui-parts/_out/bfb-top-tabs.js' ), array(), WP_BK_VERSION_NUM, true );
187
188 // --- Ajax for Save / Load ---
189 wp_enqueue_script( 'wpbc-bfb_save_load_ajax', wpbc_plugin_url( '/includes/page-form-builder/ajax/_out/bfb-ajax.js' ), array( 'wpbc-bfb_builder' ), WP_BK_VERSION_NUM, $in_footer );
190
191 // --- Exporter ---
192 wp_enqueue_script( 'wpbc-bfb_exporter', wpbc_plugin_url( '/includes/page-form-builder/_out/export/builder-exporter.js' ), array( 'wpbc-bfb_builder' ), WP_BK_VERSION_NUM, $in_footer );
193 wp_enqueue_script( 'wpbc-bfb_debug_ui', wpbc_plugin_url( '/includes/page-form-builder/_out/export/debug-ui.js' ), array( 'wpbc-bfb_exporter' ), WP_BK_VERSION_NUM, $in_footer );
194
195
196
197 // -- Templates (optional tools) --
198 wp_enqueue_script( 'wpbc-bfb_form_templates', wpbc_plugin_url( '/includes/page-form-builder/_out/form_templates.js' ), array( 'wpbc-bfb_builder' ), WP_BK_VERSION_NUM, $in_footer );
199
200 // --- Right Tabs ---
201 wp_enqueue_script( 'wpbc-bfb_rightbar_tabs', wpbc_plugin_url( '/includes/page-form-builder/_out/bfb-rightbar-tabs.js' ), array( $core_handle ), WP_BK_VERSION_NUM, $in_footer );
202
203 // Enqueue phase: collect & localize schemas if we're on the Builder screen (by URL fallback).
204 self::collect_packs_once();
205 self::localize_schemas_to_inspector();
206
207 //wpbc_load_js__required_for_modals();
208 wpbc_load_js__required_for_media_upload();
209
210
211 // Loaded JavaScript files for this settings page.
212 do_action( 'wpbc_enqueue_js_files_on_page_done', WPBC_BFB_BUILDER_PAGE_SLUG );
213 }
214
215
216 /**
217 * Enqueue CSS files.
218 *
219 * @param sring $where_to_load - parameter from root JS loader script. Value can be: 'both', 'client', 'admin'. In this method can be ignore, because we check via self::is_builder_by_request().
220 *
221 * @return void
222 */
223 public static function on_admin_enqueue__css_files() {
224
225 if ( ! self::is_builder_by_request() ) {
226 // Might still reach the page via the custom footer hook path; in that case we'll only print templates there.
227 return;
228 }
229
230 wp_enqueue_style( 'wpbc-ajx__builder_booking_form_page', wpbc_plugin_url( '/includes/page-form-builder/_out/builder-form-page.css' ), array(), WP_BK_VERSION_NUM );
231
232 // CSS.
233 wpbc_enqueue_styles__front_end();
234 wpbc_enqueue_styles__calendar();
235 }
236
237
238 /**
239 * Custom footer hook — primary place to print pack templates.
240 *
241 * @param string $page Page slug passed by the hook (expected: 'wpbc-ajx_booking_builder_booking_form', e.g. - WPBC_BFB_BUILDER_PAGE_SLUG ).
242 * @return void
243 */
244 public static function on_settings_page_footer( $page ) {
245
246 if ( WPBC_BFB_BUILDER_PAGE_SLUG !== $page ) {
247 return;
248 }
249
250 // Optional. Doucle ensure packs & schemas ready even if enqueue path didn’t run.
251 self::collect_packs_once();
252 self::localize_schemas_to_inspector();
253
254 self::print_pack_templates_once( $page );
255 }
256
257
258 /**
259 * Fallback printer (for the URL path) so templates still print if the custom footer hook isn’t fired.
260 *
261 * @return void
262 */
263 public static function fallback_print_on_admin_footer() {
264
265 if ( self::$templates_printed ) {
266 return;
267 }
268 if ( ! self::is_builder_by_request() ) {
269 return;
270 }
271 // Ensure packs & localization are ready.
272 self::collect_packs_once();
273 self::localize_schemas_to_inspector();
274
275 // Print pack templates once.
276 self::print_pack_templates_once( WPBC_BFB_BUILDER_PAGE_SLUG );
277 }
278
279
280 // -- PROTECTED --
281
282 /**
283 * Collect packs via filter (only once).
284 *
285 * @return void
286 */
287 protected static function collect_packs_once() {
288 if ( self::$packs_collected ) {
289 return;
290 }
291 $packs_raw = apply_filters( 'wpbc_bfb_register_field_packs', array() );
292 $packs_raw = is_array( $packs_raw ) ? $packs_raw : array();
293 self::$packs_by_type = WPBC_BFB_Schemas_Util::merge_packs( $packs_raw );
294 self::$packs_collected = true;
295 }
296
297 /**
298 * Localize schemas to the inspector script handle.
299 *
300 * @return void
301 */
302 protected static function localize_schemas_to_inspector() {
303
304 $handle = apply_filters( 'wpbc_bfb_inspector_script_handle', 'wpbc-bfb' );
305
306 // If the handle isn't registered yet, try again later in the same request (once).
307 if ( ! wp_script_is( $handle, 'registered' ) && ! wp_script_is( $handle, 'enqueued' ) ) {
308 // As a last resort, hook wp_print_scripts for this page load so we don't miss it.
309 add_action( 'admin_print_scripts', function () use ( $handle ) {
310 if ( wp_script_is( $handle, 'registered' ) || wp_script_is( $handle, 'enqueued' ) ) {
311 WPBC_BFB_Bootstrap::do_localize( $handle );
312 }
313 }, 100 );
314 return;
315 }
316
317 self::do_localize( $handle );
318 }
319
320 /**
321 * Perform the actual localization.
322 *
323 * @param string $handle
324 * @return void
325 */
326 protected static function do_localize( $handle ) {
327 $js_payload = WPBC_BFB_Schemas_Util::extract_schemas_for_js( self::$packs_by_type );
328 wp_localize_script( $handle, 'WPBC_BFB_Schemas', $js_payload );
329 }
330
331 /**
332 * Print templates for all collected packs (only once).
333 *
334 * @param string $page
335 * @return void
336 */
337 protected static function print_pack_templates_once( $page ) {
338
339 if ( self::$templates_printed ) {
340 return;
341 }
342 foreach ( self::$packs_by_type as $pack ) {
343 if ( isset( $pack['templates_printer'] ) && is_callable( $pack['templates_printer'] ) ) {
344 call_user_func( $pack['templates_printer'], $page );
345 }
346 }
347 self::$templates_printed = true;
348 }
349
350 /**
351 * Request-based detection of the Builder settings tab: page=wpbc-settings&tab=builder_booking_form
352 *
353 * @return bool
354 */
355 protected static function is_builder_by_request() {
356
357 $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
358 $tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
359
360 return ( 'wpbc-settings' === $page && 'builder_booking_form' === $tab );
361 }
362 }
363