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

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

201 lines 7.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 Fixed Time Slots setup editor.
4 *
5 * @package Booking Calendar
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Expose Fixed Time Slots through the common setup-module contract.
14 */
15 final class WPBC_Setup_Wizard_Fixed_Time_Slots_Module implements WPBC_Setup_Wizard_Step_Module, WPBC_Setup_Wizard_Contextual_Values_Validator {
16
17 /** @var WPBC_Setup_Wizard_Fixed_Time_Slots */
18 private $fixed_time_slots;
19
20 /**
21 * Build the module around its reusable fixed-slot service.
22 *
23 * @param WPBC_Setup_Wizard_Fixed_Time_Slots|null $fixed_time_slots Optional service for tests or composition.
24 */
25 public function __construct( $fixed_time_slots = null ) {
26 $this->fixed_time_slots = $fixed_time_slots instanceof WPBC_Setup_Wizard_Fixed_Time_Slots
27 ? $fixed_time_slots
28 : new WPBC_Setup_Wizard_Fixed_Time_Slots();
29 }
30
31 /**
32 * Return the stable step identifier.
33 *
34 * @return string Stable step ID.
35 */
36 public function get_step_id() {
37 return 'fixed_time_slots';
38 }
39
40 /**
41 * Return rail, template, and footer metadata.
42 *
43 * @return array{id:string,label:string,template:string,footer_note:string} Step definition.
44 */
45 public function get_step_definition() {
46 return array(
47 'id' => $this->get_step_id(),
48 'label' => __( 'Fixed time slots', 'booking' ),
49 'template' => 'step-fixed-time-slots',
50 'footer_note' => __( 'Save your fixed time slots and continue to the next step.', 'booking' ),
51 );
52 }
53
54 /**
55 * Return the domain-owned fixed-slot template.
56 *
57 * @return string Absolute template path.
58 */
59 public function get_template_path() {
60 return __DIR__ . '/template.php';
61 }
62
63 /**
64 * Return the owned draft field.
65 *
66 * @return string[] Field allow-list.
67 */
68 public function get_field_names() {
69 return array( 'fixed_time_slots' );
70 }
71
72 /**
73 * Require at least one valid fixed slot for forward navigation.
74 *
75 * @return string[] Required field list.
76 */
77 public function get_required_fields() {
78 return $this->get_field_names();
79 }
80
81 /**
82 * Return safe wizard-owned starter slots.
83 *
84 * @return array<string,mixed> Initial values.
85 */
86 public function get_initial_values() {
87 return array(
88 'fixed_time_slots' => $this->fixed_time_slots->get_initial_fixed_time_slots(),
89 );
90 }
91
92 /**
93 * Return dependencies used for display formatting and route validation.
94 *
95 * @return string[] Dependency step IDs.
96 */
97 public function get_context_dependencies() {
98 return array( 'date_time_formats', 'customer_journey' );
99 }
100
101 /**
102 * Build the fixed-slot editor context.
103 *
104 * @param array<string,mixed> $field_values Validated module values.
105 * @param array<string,mixed> $consumer_context Read-only dependency values.
106 *
107 * @return array<string,mixed> Authorized presentation context.
108 */
109 public function get_context( array $field_values, array $consumer_context = array() ) {
110 $time_format = isset( $consumer_context['date_time_formats']['time_format'] ) && is_scalar( $consumer_context['date_time_formats']['time_format'] )
111 ? (string) $consumer_context['date_time_formats']['time_format']
112 : 'H:i';
113
114 return $this->fixed_time_slots->get_context( $field_values, $time_format );
115 }
116
117 /**
118 * Validate the complete JSON transport field.
119 *
120 * @param string $field_id Stable field identifier.
121 * @param mixed $raw_value Untrusted JSON or array value.
122 * @param bool $is_required Whether at least one slot is required.
123 *
124 * @return array<string,mixed>|WP_Error Normalized value or an error.
125 */
126 public function validate_field( $field_id, $raw_value, $is_required ) {
127 if ( 'fixed_time_slots' !== $field_id ) {
128 return new WP_Error( 'wpbc_setup_wizard_fixed_time_slots_field_unknown', __( 'The Fixed Time Slots editor received an unsupported field.', 'booking' ) );
129 }
130
131 return $this->fixed_time_slots->validate_fixed_time_slots( $raw_value, $is_required );
132 }
133
134 /**
135 * Restrict this editor to the Fixed Time Slots journey.
136 *
137 * @param array<string,mixed> $validated_values Validated module values.
138 * @param array<string,mixed> $consumer_context Read-only dependency values.
139 *
140 * @return array<string,mixed>|WP_Error Validated values or a route error.
141 */
142 public function validate_values_with_context( array $validated_values, array $consumer_context ) {
143 $journey_id = isset( $consumer_context['customer_journey']['customer_journey'] )
144 ? sanitize_key( (string) $consumer_context['customer_journey']['customer_journey'] )
145 : '';
146
147 if ( '' === $journey_id || WPBC_Setup_Wizard_Customer_Journey_Policy::uses_fixed_time_slots_configuration( $journey_id ) ) {
148 return $validated_values;
149 }
150
151 $message = __( 'Fixed time slots are not available for the selected customer journey.', 'booking' );
152
153 return new WP_Error(
154 'wpbc_setup_wizard_fixed_time_slots_journey_invalid',
155 $message,
156 array( 'field_errors' => array( 'fixed_time_slots' => $message ) )
157 );
158 }
159
160 /**
161 * Enqueue compiled domain assets and the shared Sortable library.
162 *
163 * @param string $module_url Setup Wizard module URL.
164 * @param string|false $asset_version Plugin version for cache busting.
165 * @param string $shared_style_handle Shared shell style handle.
166 * @param string $shared_script_handle Shared shell script handle.
167 *
168 * @return void
169 */
170 public function enqueue_assets( $module_url, $asset_version, $shared_style_handle, $shared_script_handle ) {
171 $module_url = trailingslashit( $module_url );
172
173 wp_enqueue_style( 'wpbc-setup-wizard-fixed-time-slots', $module_url . 'step-fixed-time-slots/_out/step-fixed-time-slots.css', array( $shared_style_handle ), $asset_version );
174 wp_enqueue_script( 'wpbc-sortable', wpbc_plugin_url( '/vendors/sortablejs/Sortable.min.js' ), array(), $asset_version, true );
175 wp_enqueue_script( 'wpbc-setup-wizard-fixed-time-slots', $module_url . 'step-fixed-time-slots/_out/step-fixed-time-slots.js', array( $shared_script_handle, 'wpbc-sortable' ), $asset_version, true );
176 wp_localize_script(
177 'wpbc-setup-wizard-fixed-time-slots',
178 'wpbc_setup_wizard_fixed_time_slots',
179 array(
180 'module_id' => $this->get_step_id(),
181 'field_id' => 'fixed_time_slots',
182 'max_time_slots' => WPBC_Setup_Wizard_Fixed_Time_Slots::MAX_TIME_SLOTS,
183 'time_increment' => WPBC_Setup_Wizard_Fixed_Time_Slots::TIME_INCREMENT,
184 'i18n' => array(
185 'slots_required' => __( 'Add at least one fixed time slot.', 'booking' ),
186 'slot_invalid' => __( 'Every fixed time slot must end after it starts.', 'booking' ),
187 'slot_duplicate' => __( 'The same fixed time slot cannot appear twice.', 'booking' ),
188 'generator_invalid' => __( 'Choose a valid first start, last start, spacing, and duration.', 'booking' ),
189 'generator_day_overflow' => __( 'The generated slot duration must finish by the end of the day.', 'booking' ),
190 'slot_limit' => __( 'No additional fixed time slot can be added.', 'booking' ),
191 'slots_cleared' => __( 'Fixed time slots cleared.', 'booking' ),
192 /* translators: %s: Displayed fixed time slot. */
193 'move_slot' => __( 'Move fixed time slot %s', 'booking' ),
194 /* translators: %s: Displayed fixed time slot. */
195 'remove_slot' => __( 'Remove fixed time slot %s', 'booking' ),
196 ),
197 )
198 );
199 }
200 }
201