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-appearance / class-wpbc-setup-wizard-appearance-module.php

class-wpbc-setup-wizard-appearance-module.php in Booking Calendar 11.9, at includes/page-setup-wizard/step-appearance/class-wpbc-setup-wizard-appearance-module.php

273 lines 10.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Reusable module adapter for the Setup Wizard Appearance editor.
4 *
5 * @package Booking Calendar
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Expose canonical appearance choices through the shared setup-module contract.
14 */
15 final class WPBC_Setup_Wizard_Appearance_Module implements WPBC_Setup_Wizard_Step_Module, WPBC_Setup_Wizard_Current_Values_Module {
16
17 /** @var WPBC_Setup_Wizard_Appearance */
18 private $appearance;
19
20 /** @var WPBC_Setup_Wizard_Booking_Form_Templates */
21 private $templates;
22
23 /**
24 * Build the module around the read-only Appearance registry adapter.
25 *
26 * @param WPBC_Setup_Wizard_Appearance|null $appearance Optional Appearance service for testing.
27 * @param WPBC_Setup_Wizard_Booking_Form_Templates|null $templates Optional Form Builder template service for testing.
28 */
29 public function __construct( $appearance = null, $templates = null ) {
30 $this->appearance = $appearance instanceof WPBC_Setup_Wizard_Appearance
31 ? $appearance
32 : new WPBC_Setup_Wizard_Appearance();
33 $this->templates = $templates instanceof WPBC_Setup_Wizard_Booking_Form_Templates
34 ? $templates
35 : new WPBC_Setup_Wizard_Booking_Form_Templates();
36 }
37
38 /**
39 * Return the stable module and step identifier.
40 *
41 * @return string Stable identifier.
42 */
43 public function get_step_id() {
44 return 'appearance';
45 }
46
47 /**
48 * Return the rail and template metadata contributed by this module.
49 *
50 * @return array{id:string,label:string,template:string,footer_note:string} Step definition.
51 */
52 public function get_step_definition() {
53 return array(
54 'id' => $this->get_step_id(),
55 'label' => __( 'Appearance', 'booking' ),
56 'template' => 'step-appearance',
57 'footer_note' => __( 'Save & continue applies these Booking Form, calendar, and time-slot appearance settings immediately.', 'booking' ),
58 );
59 }
60
61 /**
62 * Return the absolute server-owned template path.
63 *
64 * @return string Absolute template path.
65 */
66 public function get_template_path() {
67 return __DIR__ . '/template.php';
68 }
69
70 /**
71 * Return the appearance fields accepted by this step.
72 *
73 * @return string[] Field allow-list.
74 */
75 public function get_field_names() {
76 return array( 'booking_form_style', 'booking_form_accent_color', 'booking_skin', 'booking_timeslot_picker' );
77 }
78
79 /**
80 * Require every appearance dimension before forward navigation.
81 *
82 * @return string[] Required field identifiers.
83 */
84 public function get_required_fields() {
85 return $this->get_field_names();
86 }
87
88 /**
89 * Return current canonical values as read-only draft suggestions.
90 *
91 * @return array<string,string> Initial appearance values.
92 */
93 public function get_initial_values() {
94 return $this->appearance->get_initial_values();
95 }
96
97 /**
98 * Refresh all appearance choices from their canonical plugin options.
99 *
100 * @return string[] Current-value field identifiers.
101 */
102 public function get_current_value_field_names() {
103 return $this->get_field_names();
104 }
105
106 /**
107 * Return the journey and saved Booking Form template used by the preview.
108 *
109 * @return string[] Dependency step identifiers.
110 */
111 public function get_context_dependencies() {
112 return array( 'customer_journey', 'booking_form_template' );
113 }
114
115 /**
116 * Build the authorized Appearance editor context and request-local preview.
117 *
118 * @param array<string,mixed> $field_values Validated appearance values.
119 * @param array<string,mixed> $consumer_context Read-only dependency values.
120 *
121 * @return array<string,mixed> Authorized presentation context.
122 */
123 public function get_context( array $field_values, array $consumer_context = array() ) {
124 $customer_journey = isset( $consumer_context['customer_journey']['customer_journey'] )
125 && is_scalar( $consumer_context['customer_journey']['customer_journey'] )
126 ? sanitize_key( (string) $consumer_context['customer_journey']['customer_journey'] )
127 : '';
128 $template_values = isset( $consumer_context['booking_form_template'] ) && is_array( $consumer_context['booking_form_template'] )
129 ? $consumer_context['booking_form_template']
130 : array();
131 $template_context = $this->templates->get_context( $template_values, $customer_journey );
132 $selected_template = isset( $template_context['selected_template'] ) && is_array( $template_context['selected_template'] )
133 ? $template_context['selected_template']
134 : array();
135 $template_slug = isset( $selected_template['slug'] ) ? (string) $selected_template['slug'] : '';
136 $preview_result = $this->render_inline_preview( $template_slug, $field_values );
137
138 return array(
139 'values' => $field_values,
140 'starting_styles' => $this->appearance->get_starting_styles(),
141 'accent_colors' => $this->appearance->get_accent_colors(),
142 'calendar_skins' => $this->appearance->get_calendar_skin_groups(),
143 'template_slug' => $template_slug,
144 'booking_form_usage' => WPBC_Setup_Wizard_Appearance::PREVIEW_BOOKING_FORM_USAGE,
145 'preview_html' => $preview_result['html'],
146 'preview_error' => $preview_result['error'],
147 );
148 }
149
150 /**
151 * Render the selected unsaved template directly for the Appearance step.
152 *
153 * Template definitions are resolved through the current server registry and
154 * appearance values are validated through their canonical allow-lists before
155 * the shared Form Builder preview service renders the snapshot. The operation
156 * is request-local and does not create a preview transient or save a form.
157 *
158 * @param string $template_slug Selected server-owned template slug.
159 * @param array<string,mixed> $field_values Validated Appearance draft values.
160 *
161 * @return array{html:string,error:string} Rendered preview result.
162 */
163 private function render_inline_preview( $template_slug, array $field_values ) {
164 $preview_payload = $this->templates->get_inline_preview_payload( $template_slug );
165 $preview_config = $this->appearance->get_preview_configuration( $field_values );
166 $render_mode = $this->templates->get_preview_render_mode( WPBC_Setup_Wizard_Appearance::PREVIEW_BOOKING_FORM_USAGE );
167
168 foreach ( array( $preview_payload, $preview_config, $render_mode ) as $validated_value ) {
169 if ( is_wp_error( $validated_value ) ) {
170 return array(
171 'html' => '',
172 'error' => $validated_value->get_error_message(),
173 );
174 }
175 }
176
177 if ( ! class_exists( 'WPBC_BFB_Preview_Service' ) || ! class_exists( 'WPBC_FE_Attr_Postprocessor' ) ) {
178 return array(
179 'html' => '',
180 'error' => __( 'The booking appearance preview is unavailable.', 'booking' ),
181 );
182 }
183
184 $resource_id = absint( WPBC_FE_Attr_Postprocessor::get_default_booking_resource_id() );
185 $resource_id = $resource_id > 0 ? $resource_id : 1;
186
187 $preview_html = WPBC_BFB_Preview_Service::get_instance()->render_inline_preview(
188 $resource_id,
189 $preview_payload['structure'],
190 $preview_payload['form_name'],
191 $preview_payload['advanced_form'],
192 $preview_payload['content_form'],
193 $preview_config['form_style'],
194 array(
195 'render_mode' => $render_mode,
196 'option_overrides' => $preview_config['option_overrides'],
197 )
198 );
199
200 if ( ! is_string( $preview_html ) || '' === trim( $preview_html ) ) {
201 return array(
202 'html' => '',
203 'error' => __( 'The selected booking form could not be rendered.', 'booking' ),
204 );
205 }
206
207 return array(
208 'html' => $preview_html,
209 'error' => '',
210 );
211 }
212
213 /**
214 * Validate one appearance field through its canonical server allow-list.
215 *
216 * @param string $field_id Stable field identifier.
217 * @param mixed $raw_value Untrusted field value.
218 * @param bool $is_required Whether an empty value is invalid.
219 *
220 * @return string|WP_Error Normalized value or an error.
221 */
222 public function validate_field( $field_id, $raw_value, $is_required ) {
223 switch ( $field_id ) {
224 case 'booking_form_style':
225 return $this->appearance->validate_style( $raw_value, $is_required );
226
227 case 'booking_form_accent_color':
228 return $this->appearance->validate_accent_color( $raw_value, $is_required );
229
230 case 'booking_skin':
231 return $this->appearance->validate_calendar_skin( $raw_value, $is_required );
232
233 case 'booking_timeslot_picker':
234 return $this->appearance->validate_timeslot_picker( $raw_value, $is_required );
235 }
236
237 return new WP_Error( 'wpbc_setup_wizard_appearance_field_unknown', __( 'The Appearance editor received an unsupported field.', 'booking' ) );
238 }
239
240 /**
241 * Enqueue compiled Appearance assets and instant preview configuration.
242 *
243 * @param string $module_url Absolute URL to the Setup Wizard root.
244 * @param string|false $asset_version Plugin version used for cache busting.
245 * @param string $shared_style_handle Consumer shell style handle.
246 * @param string $shared_script_handle Consumer shell script handle.
247 *
248 * @return void
249 */
250 public function enqueue_assets( $module_url, $asset_version, $shared_style_handle, $shared_script_handle ) {
251 $module_url = trailingslashit( $module_url );
252
253 wp_enqueue_style( 'coloris', wpbc_plugin_url( '/vendors/coloris/dist/coloris.min.css' ), array(), $asset_version );
254 wp_enqueue_script( 'coloris', wpbc_plugin_url( '/vendors/coloris/dist/coloris.min.js' ), array(), $asset_version, true );
255 wp_enqueue_style( 'wpbc-setup-wizard-appearance', $module_url . 'step-appearance/_out/step-appearance.css', array( $shared_style_handle, 'coloris' ), $asset_version );
256 wp_enqueue_script( 'wpbc-setup-wizard-appearance', $module_url . 'step-appearance/_out/step-appearance.js', array( $shared_script_handle, 'coloris' ), $asset_version, true );
257 wp_localize_script(
258 'wpbc-setup-wizard-appearance',
259 'wpbc_setup_wizard_appearance',
260 array(
261 'form_style_presets' => function_exists( 'wpbc_bfb_settings__get_form_style_presets' ) ? wpbc_bfb_settings__get_form_style_presets() : array(),
262 'form_style_css_var_names' => function_exists( 'wpbc_bfb_settings__get_form_style_css_var_names' ) ? wpbc_bfb_settings__get_form_style_css_var_names() : array(),
263 'i18n' => array(
264 'style_required' => __( 'Choose a starting style.', 'booking' ),
265 'accent_required' => __( 'Choose a valid accent color.', 'booking' ),
266 'skin_required' => __( 'Choose a calendar skin.', 'booking' ),
267 'time_required' => __( 'Choose how time slots are displayed.', 'booking' ),
268 ),
269 )
270 );
271 }
272 }
273