PluginProbe
Booking Calendar / 11.9
Booking Calendar v11.9
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-setup-wizard / step-booking-form-template / template.php

template.php in Booking Calendar 11.9, at includes/page-setup-wizard/step-booking-form-template/template.php

248 lines 15.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Modular Page 9 Booking Form template selector.
4 *
5 * @package Booking Calendar
6 * @var array<string,mixed> $template_context Authorized step context.
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 $step_data = $template_context['step_data'];
14 $templates = isset( $step_data['templates'] ) && is_array( $step_data['templates'] ) ? $step_data['templates'] : array();
15 $filters = isset( $step_data['filters'] ) && is_array( $step_data['filters'] ) ? $step_data['filters'] : array();
16 $usage_options = isset( $step_data['usage_options'] ) && is_array( $step_data['usage_options'] ) ? $step_data['usage_options'] : array();
17 $selected_template = isset( $step_data['selected_template'] ) && is_array( $step_data['selected_template'] ) ? $step_data['selected_template'] : array();
18 $selected_slug = isset( $step_data['values']['booking_form_template'] ) ? (string) $step_data['values']['booking_form_template'] : '';
19 $selected_usage = isset( $step_data['values']['booking_form_usage'] ) ? sanitize_key( (string) $step_data['values']['booking_form_usage'] ) : 'direct_booking_form';
20 $selected_category = isset( $selected_template['category'] ) ? sanitize_key( (string) $selected_template['category'] ) : '';
21 $initial_filter = ! empty( $selected_template['is_recommended'] )
22 ? 'recommended'
23 : ( in_array( $selected_category, array( 'appointments', 'time_slots', 'full_days' ), true ) ? $selected_category : 'all' );
24 $preview_title = isset( $selected_template['title'] ) ? (string) $selected_template['title'] : '';
25 $preview_kind = isset( $step_data['preview_kind'] ) ? sanitize_key( (string) $step_data['preview_kind'] ) : '';
26 $preview_html = isset( $step_data['preview_html'] ) ? (string) $step_data['preview_html'] : '';
27 $preview_bootstrap = isset( $step_data['preview_bootstrap'] ) && is_array( $step_data['preview_bootstrap'] ) ? $step_data['preview_bootstrap'] : array();
28 $preview_error = isset( $step_data['preview_error'] ) ? (string) $step_data['preview_error'] : '';
29 $has_inline_preview = 'inline' === $preview_kind && '' !== trim( $preview_html ) && ! empty( $preview_bootstrap );
30 $applied_form_slug = 'standard';
31 $preview_shortcode = 'appointment_flow' === $selected_usage
32 ? sprintf( '[booking_appointment form_type="%s"]', $applied_form_slug )
33 : sprintf( '[booking form_type="%s"]', $applied_form_slug );
34 ?>
35 <section class="wpbc_setup_wizard__step-content wpbc_setup_wizard__booking-form-step" aria-labelledby="wpbc-setup-wizard-step-title">
36 <header class="wpbc_setup_wizard__step-heading">
37 <h1 id="wpbc-setup-wizard-step-title"><?php esc_html_e( 'Choose a booking form template', 'booking' ); ?></h1>
38 <p class="wpbc_setup_wizard__lead"><?php esc_html_e( 'Select a template and try the real booking form before continuing.', 'booking' ); ?></p>
39 </header>
40 <?php
41 $template_context['templates']->render(
42 'settings-hint',
43 array( 'settings_hint' => $template_context['settings_hint'] )
44 );
45 ?>
46
47 <form id="wpbc-setup-wizard-step-form" novalidate>
48 <div class="wpbc_setup_wizard__booking-form-layout" data-wpbc-booking-form-template-editor data-initial-filter="<?php echo esc_attr( $initial_filter ); ?>">
49 <section class="wpbc_setup_wizard__template-library" aria-labelledby="wpbc-setup-wizard-template-library-title">
50 <div class="wpbc_setup_wizard__template-controls">
51 <h2 id="wpbc-setup-wizard-template-library-title"><?php esc_html_e( 'Templates', 'booking' ); ?></h2>
52
53 <label class="wpbc_setup_wizard__template-search">
54 <span class="screen-reader-text"><?php esc_html_e( 'Search booking form templates', 'booking' ); ?></span>
55 <input type="search" placeholder="<?php esc_attr_e( 'Search templates', 'booking' ); ?>" autocomplete="off" data-wpbc-template-search>
56 </label>
57
58 <div class="wpbc_setup_wizard__template-filters" role="tablist" aria-label="<?php esc_attr_e( 'Filter booking form templates', 'booking' ); ?>">
59 <?php foreach ( $filters as $filter_index => $filter ) : ?>
60 <?php
61 $filter_id = isset( $filter['id'] ) ? sanitize_key( (string) $filter['id'] ) : '';
62 $filter_label = isset( $filter['label'] ) ? (string) $filter['label'] : '';
63 $filter_count = isset( $filter['count'] ) ? absint( $filter['count'] ) : 0;
64 $is_active = $initial_filter === $filter_id;
65 ?>
66 <button
67 type="button"
68 role="tab"
69 id="wpbc-setup-wizard-template-filter-<?php echo esc_attr( $filter_id ); ?>"
70 aria-selected="<?php echo $is_active ? 'true' : 'false'; ?>"
71 tabindex="<?php echo $is_active ? '0' : '-1'; ?>"
72 class="wpbc_setup_wizard__template-filter<?php echo $is_active ? ' is-active' : ''; ?>"
73 data-wpbc-template-filter="<?php echo esc_attr( $filter_id ); ?>"
74 data-template-count="<?php echo esc_attr( (string) $filter_count ); ?>"
75 >
76 <?php echo esc_html( $filter_label ); ?><?php if ( 'all' === $filter_id ) : ?> <span>(<?php echo esc_html( (string) $filter_count ); ?>)</span><?php endif; ?>
77 </button>
78 <?php endforeach; ?>
79 </div>
80 </div>
81
82 <div
83 class="wpbc_setup_wizard__template-grid"
84 role="tabpanel"
85 tabindex="0"
86 aria-live="polite"
87 aria-labelledby="wpbc-setup-wizard-template-filter-<?php echo esc_attr( $initial_filter ); ?>"
88 data-wpbc-template-grid
89 >
90 <?php foreach ( $templates as $template ) : ?>
91 <?php
92 $template_slug = isset( $template['slug'] ) ? (string) $template['slug'] : '';
93 $template_title = isset( $template['title'] ) ? (string) $template['title'] : '';
94 $template_description = isset( $template['description'] ) ? (string) $template['description'] : '';
95 $template_picture_url = isset( $template['picture_url'] ) ? (string) $template['picture_url'] : '';
96 $template_category = isset( $template['category'] ) ? sanitize_key( (string) $template['category'] ) : 'other';
97 $is_recommended = ! empty( $template['is_recommended'] );
98 $is_selected = $selected_slug === $template_slug;
99 ?>
100 <article
101 class="wpbc_setup_wizard__template-card<?php echo $is_selected ? ' is-selected' : ''; ?>"
102 data-wpbc-template-card
103 data-template-slug="<?php echo esc_attr( $template_slug ); ?>"
104 data-template-category="<?php echo esc_attr( $template_category ); ?>"
105 data-template-recommended="<?php echo $is_recommended ? 'true' : 'false'; ?>"
106 data-template-picture-url="<?php echo esc_url( $template_picture_url ); ?>"
107 >
108 <label>
109 <span class="wpbc_setup_wizard__template-card-preview" data-wpbc-template-card-preview>
110 <?php if ( '' !== $template_picture_url ) : ?>
111 <img src="<?php echo esc_url( $template_picture_url ); ?>" alt="" loading="lazy" data-wpbc-template-card-image>
112 <?php endif; ?>
113 <span class="wpbc_setup_wizard__template-image-placeholder"<?php if ( '' !== $template_picture_url ) : ?> hidden<?php endif; ?> data-wpbc-template-image-placeholder>
114 <i class="menu_icon icon-2x wpbc-bi-image-fill" aria-hidden="true"></i>
115 <span><?php esc_html_e( 'Preview unavailable', 'booking' ); ?></span>
116 </span>
117 </span>
118 <span class="wpbc_setup_wizard__template-card-heading">
119 <input
120 type="radio"
121 name="booking_form_template"
122 value="<?php echo esc_attr( $template_slug ); ?>"
123 required
124 data-wpbc-setup-wizard-field
125 data-wpbc-template-radio
126 <?php checked( $is_selected ); ?>
127 >
128 <span class="wpbc_setup_wizard__radio-mark" aria-hidden="true"></span>
129 <strong data-wpbc-template-title><?php echo esc_html( $template_title ); ?></strong>
130 </span>
131 <span class="screen-reader-text" data-wpbc-template-description><?php echo esc_html( $template_description ); ?></span>
132 </label>
133 </article>
134 <?php endforeach; ?>
135 </div>
136 <p class="wpbc_setup_wizard__template-empty" data-wpbc-template-empty hidden><?php esc_html_e( 'No templates match this search and filter.', 'booking' ); ?></p>
137 <?php if ( empty( $templates ) ) : ?>
138 <p class="wpbc_setup_wizard__template-catalog-unavailable wpbc_setup_wizard__message wpbc_setup_wizard__message--warning"><?php esc_html_e( 'Booking form templates are temporarily unavailable. You can go back without changing any live form.', 'booking' ); ?></p>
139 <?php endif; ?>
140 <span class="wpbc_setup_wizard__field-error wpbc_setup_wizard__field-error--group" id="wpbc-setup-wizard-booking-form-template-error" data-wpbc-setup-wizard-error-for="booking_form_template"></span>
141 </section>
142
143 <section class="wpbc_setup_wizard__booking-form-usage-panel" aria-labelledby="wpbc-setup-wizard-booking-form-usage-title">
144 <fieldset class="wpbc_setup_wizard__booking-form-usage" data-wpbc-booking-form-usage>
145 <legend id="wpbc-setup-wizard-booking-form-usage-title"><?php esc_html_e( 'Use template with', 'booking' ); ?></legend>
146 <div class="wpbc_setup_wizard__booking-form-usage-options">
147 <?php foreach ( $usage_options as $usage_option ) : ?>
148 <?php
149 $usage_id = isset( $usage_option['id'] ) ? sanitize_key( (string) $usage_option['id'] ) : '';
150 $usage_label = isset( $usage_option['label'] ) ? (string) $usage_option['label'] : '';
151 $usage_description = isset( $usage_option['description'] ) ? (string) $usage_option['description'] : '';
152 ?>
153 <label class="wpbc_setup_wizard__booking-form-usage-option<?php echo $selected_usage === $usage_id ? ' is-selected' : ''; ?>">
154 <input
155 type="radio"
156 name="booking_form_usage"
157 value="<?php echo esc_attr( $usage_id ); ?>"
158 required
159 data-wpbc-setup-wizard-field
160 data-wpbc-booking-form-usage-radio
161 <?php checked( $selected_usage, $usage_id ); ?>
162 >
163 <span>
164 <strong><?php echo esc_html( $usage_label ); ?></strong>
165 <small><?php echo esc_html( $usage_description ); ?></small>
166 </span>
167 </label>
168 <?php endforeach; ?>
169 </div>
170 <span class="wpbc_setup_wizard__field-error wpbc_setup_wizard__field-error--group" data-wpbc-setup-wizard-error-for="booking_form_usage"></span>
171 </fieldset>
172 </section>
173
174 <section class="wpbc_setup_wizard__template-preview-panel" aria-labelledby="wpbc-setup-wizard-template-preview-title">
175 <header class="wpbc_setup_wizard__template-preview-toolbar">
176 <div class="wpbc_setup_wizard__template-preview-heading">
177 <h2 id="wpbc-setup-wizard-template-preview-title"><?php esc_html_e( 'Live preview', 'booking' ); ?></h2>
178 <span><i aria-hidden="true"></i><?php esc_html_e( 'Real booking form preview', 'booking' ); ?></span>
179 </div>
180 <div class="wpbc_setup_wizard__template-preview-actions">
181 <button type="button" class="button button-secondary" data-wpbc-template-refresh>
182 <i class="menu_icon icon-1x wpbc_icn_refresh" aria-hidden="true"></i>
183 <span><?php esc_html_e( 'Refresh', 'booking' ); ?></span>
184 </button>
185 <button
186 type="button"
187 class="button button-secondary"
188 data-wpbc-template-open-preview
189 >
190 <i class="menu_icon icon-1x wpbc_icn_open_in_new" aria-hidden="true"></i>
191 <span><?php esc_html_e( 'Open in new window', 'booking' ); ?></span>
192 </button>
193 </div>
194 </header>
195
196 <div
197 class="wpbc_setup_wizard__template-preview-stage"
198 data-wpbc-template-preview-stage
199 data-initial-preview-kind="<?php echo esc_attr( $has_inline_preview ? 'inline' : '' ); ?>"
200 data-initial-preview-template-slug="<?php echo esc_attr( $has_inline_preview ? $selected_slug : '' ); ?>"
201 data-initial-preview-booking-form-usage="<?php echo esc_attr( $has_inline_preview ? $selected_usage : '' ); ?>"
202 >
203 <div class="wpbc_setup_wizard__template-preview-loader" role="status" aria-live="polite" <?php echo $has_inline_preview || '' !== $preview_error ? 'hidden' : ''; ?> data-wpbc-template-preview-loader>
204 <span class="spinner is-active" aria-hidden="true"></span>
205 <span><?php esc_html_e( 'Loading the interactive booking form preview.', 'booking' ); ?></span>
206 </div>
207 <div class="wpbc_setup_wizard__template-inline-preview" <?php echo $has_inline_preview ? '' : 'hidden'; ?> data-wpbc-template-inline-preview data-wpbc-inline-booking-preview="1">
208 <div class="wpbc_theme_preview wpbc_theme_preview_mode_form" data-wpbc-theme-preview="1">
209 <div class="wpbc_theme_real_preview" data-wpbc-template-inline-preview-content>
210 <?php echo $preview_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- generated by the shared Form Builder renderer after server registry resolution and preview sanitization. ?>
211 </div>
212 </div>
213 </div>
214 <?php if ( $has_inline_preview ) : ?>
215 <script type="application/json" data-wpbc-template-initial-preview-bootstrap><?php echo wp_json_encode( $preview_bootstrap, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JSON is hex encoded and parsed only as data by the allow-listed preview renderer. ?></script>
216 <?php endif; ?>
217 <iframe
218 title="<?php esc_attr_e( 'Interactive booking form template preview', 'booking' ); ?>"
219 src="about:blank"
220 hidden
221 data-wpbc-template-preview-frame
222 ></iframe>
223 <div class="wpbc_setup_wizard__template-preview-error" role="alert" <?php echo '' === $preview_error ? 'hidden' : ''; ?> data-wpbc-template-preview-error>
224 <i class="menu_icon icon-1x wpbc_icn_error_outline" aria-hidden="true"></i>
225 <span><?php echo '' !== $preview_error ? esc_html( $preview_error ) : esc_html__( 'The interactive preview could not be loaded. Try refreshing it.', 'booking' ); ?></span>
226 </div>
227 </div>
228
229 <footer class="wpbc_setup_wizard__template-preview-details">
230 <div>
231 <strong data-wpbc-template-preview-title><?php echo esc_html( $preview_title ); ?></strong>
232 <code data-wpbc-template-preview-slug><?php echo esc_html( $selected_slug ); ?></code>
233 <span class="wpbc_setup_wizard__template-preview-shortcode">
234 <span><?php esc_html_e( 'Shortcode:', 'booking' ); ?></span>
235 <code data-wpbc-template-preview-shortcode><?php echo esc_html( $preview_shortcode ); ?></code>
236 </span>
237 </div>
238 <p data-wpbc-template-preview-description><?php echo isset( $selected_template['description'] ) ? esc_html( (string) $selected_template['description'] ) : ''; ?></p>
239 </footer>
240 <p class="wpbc_setup_wizard__template-preview-note wpbc_setup_wizard__message wpbc_setup_wizard__message--info">
241 <i class="menu_icon icon-1x wpbc_icn_info_outline" aria-hidden="true"></i>
242 <span><?php esc_html_e( 'The embedded preview uses the real booking form and Booking Calendar styles. In this request-local preview, calculated date, time, capacity, and cost summaries are marked Preview only and final booking submission is disabled. Open it in a new window to use the complete preview behavior and check the active site theme. Selecting or trying a template does not replace a saved form. Update booking form & continue applies the selected template to the Standard Booking Form used on the front end.', 'booking' ); ?></span>
243 </p>
244 </section>
245 </div>
246 </form>
247 </section>
248