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 / class-wpbc-setup-wizard-customer-journey-save-handler.php

class-wpbc-setup-wizard-customer-journey-save-handler.php in Booking Calendar 11.9, at includes/page-setup-wizard/class-wpbc-setup-wizard-customer-journey-save-handler.php

212 lines 7.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Progressive save handler for Setup Wizard Customer Journey.
4 *
5 * @package Booking Calendar
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Save Customer Journey metadata and enforce journey-owned canonical defaults.
14 *
15 * Most journeys remain wizard-only metadata. First-date start and last-date end
16 * is different: its explicit boundary times must not be filtered by the global
17 * weekly Working Hours restriction. That restriction is disabled atomically at
18 * the journey-save boundary before the route skips the Working Hours page.
19 */
20 final class WPBC_Setup_Wizard_Customer_Journey_Save_Handler implements WPBC_Setup_Wizard_Step_Save_Handler {
21
22 /** @var WPBC_Setup_Wizard_Working_Hours */
23 private $working_hours;
24
25 /**
26 * Build the handler around the Working Hours authorization boundary.
27 *
28 * @param WPBC_Setup_Wizard_Working_Hours|null $working_hours Optional domain service for tests.
29 */
30 public function __construct( $working_hours = null ) {
31 $this->working_hours = $working_hours instanceof WPBC_Setup_Wizard_Working_Hours
32 ? $working_hours
33 : new WPBC_Setup_Wizard_Working_Hours();
34 }
35
36 /**
37 * Return the owned step identifier.
38 *
39 * @return string Stable step identifier.
40 */
41 public function get_step_id() {
42 return 'customer_journey';
43 }
44
45 /**
46 * Return the ordinary progressive-save action label.
47 *
48 * @param array<string,mixed> $checkpoint Current checkpoint.
49 * @param array<string,mixed> $step_context Authorized presentation context.
50 *
51 * @return string Translated action label.
52 */
53 public function get_primary_action_label( array $checkpoint, array $step_context = array() ) {
54 unset( $checkpoint, $step_context );
55
56 return __( 'Save & continue', 'booking' );
57 }
58
59 /**
60 * Save the journey and disable Working Hours for the boundary-time flow.
61 *
62 * Existing default weekdays and Resource-specific overrides are preserved.
63 * A failed readback is compensated with the complete before-image so a
64 * partially written pair of canonical options is never accepted as saved.
65 *
66 * @param array<string,mixed> $validated_fields Validated current-step fields.
67 * @param array<string,mixed> $checkpoint Current checkpoint.
68 * @param array<string,mixed> $operation_context Stable operation metadata.
69 *
70 * @return array<string,mixed>|WP_Error Verified result or bounded error.
71 */
72 public function save( array $validated_fields, array $checkpoint, array $operation_context ) {
73 unset( $checkpoint, $operation_context );
74
75 if ( ! WPBC_Setup_Wizard_Access::current_user_can_access() ) {
76 return new WP_Error(
77 'wpbc_setup_wizard_customer_journey_forbidden',
78 __( 'You are not allowed to save this Customer Journey.', 'booking' )
79 );
80 }
81
82 $journey_id = isset( $validated_fields['customer_journey'] ) && is_scalar( $validated_fields['customer_journey'] )
83 ? sanitize_key( (string) $validated_fields['customer_journey'] )
84 : '';
85 if (
86 ! WPBC_Setup_Wizard_Customer_Journey_Policy::is_registered_journey( $journey_id )
87 || ! WPBC_Setup_Wizard_Customer_Journey_Policy::is_journey_available( $journey_id )
88 ) {
89 return new WP_Error( 'wpbc_setup_wizard_customer_journey_invalid', __( 'The selected Customer Journey is not available.', 'booking' ) );
90 }
91
92 if ( 'first_start_last_end' !== $journey_id ) {
93 return $this->create_result( $journey_id, array(), false, __( 'Customer Journey saved for Setup Wizard recommendations.', 'booking' ) );
94 }
95
96 if ( ! $this->working_hours->current_user_can_manage() ) {
97 return new WP_Error(
98 'wpbc_setup_wizard_customer_journey_working_hours_forbidden',
99 __( 'You are not allowed to disable global Working Hours for this Customer Journey.', 'booking' )
100 );
101 }
102 if ( ! function_exists( 'wpbc_working_time__get_settings' ) || ! function_exists( 'wpbc_working_time__update_settings' ) ) {
103 return new WP_Error(
104 'wpbc_setup_wizard_customer_journey_working_hours_unavailable',
105 __( 'Working Hours storage is not available.', 'booking' )
106 );
107 }
108
109 $before_settings = wpbc_working_time__get_settings();
110 if ( ! is_array( $before_settings ) ) {
111 return new WP_Error(
112 'wpbc_setup_wizard_customer_journey_working_hours_read_failed',
113 __( 'Current Working Hours could not be read safely.', 'booking' )
114 );
115 }
116
117 if ( 'Off' === ( isset( $before_settings['enabled'] ) ? $before_settings['enabled'] : '' ) ) {
118 return $this->create_result(
119 $journey_id,
120 array(),
121 false,
122 __( 'Customer Journey saved. Working Hours were already disabled.', 'booking' )
123 );
124 }
125
126 $next_settings = $before_settings;
127 $next_settings['enabled'] = 'Off';
128 $expected_settings = $this->normalize_settings( $next_settings );
129
130 wpbc_working_time__update_settings( $next_settings );
131 if ( ! $this->settings_match( $expected_settings, wpbc_working_time__get_settings() ) ) {
132 wpbc_working_time__update_settings( $before_settings );
133 $was_restored = $this->settings_match( $this->normalize_settings( $before_settings ), wpbc_working_time__get_settings() );
134
135 return new WP_Error(
136 'wpbc_setup_wizard_customer_journey_working_hours_not_saved',
137 $was_restored
138 ? __( 'Working Hours could not be disabled. The previous settings were restored.', 'booking' )
139 : __( 'Working Hours could not be disabled or restored completely. Review General Availability before continuing.', 'booking' )
140 );
141 }
142
143 return $this->create_result(
144 $journey_id,
145 array( 'booking_working_time_enabled', 'booking_working_time_rules' ),
146 true,
147 __( 'Customer Journey saved and Working Hours disabled.', 'booking' )
148 );
149 }
150
151 /**
152 * Normalize complete Working Time settings through the canonical helper.
153 *
154 * @param array<string,mixed> $settings Complete Working Time settings.
155 *
156 * @return array<string,mixed> Normalized settings.
157 */
158 private function normalize_settings( array $settings ) {
159 return function_exists( 'wpbc_working_time__normalize_settings' )
160 ? wpbc_working_time__normalize_settings( $settings )
161 : $settings;
162 }
163
164 /**
165 * Compare complete expected settings with a canonical readback.
166 *
167 * @param array<string,mixed> $expected_settings Expected normalized settings.
168 * @param mixed $canonical_settings Canonical readback candidate.
169 *
170 * @return bool True when every preserved and changed setting matches.
171 */
172 private function settings_match( array $expected_settings, $canonical_settings ) {
173 return is_array( $canonical_settings ) && $expected_settings === $this->normalize_settings( $canonical_settings );
174 }
175
176 /**
177 * Build the normalized progressive-save result.
178 *
179 * @param string $journey_id Validated journey identifier.
180 * @param string[] $updated_ids Canonical option identifiers changed by this request.
181 * @param bool $writes_canonical_settings Whether canonical settings were written.
182 * @param string $summary Translated result summary.
183 *
184 * @return array<string,mixed> Progressive-save result proposal.
185 */
186 private function create_result( $journey_id, array $updated_ids, $writes_canonical_settings, $summary ) {
187 $fingerprint_values = array(
188 'customer_journey' => $journey_id,
189 'working_hours_enabled' => 'first_start_last_end' === $journey_id ? 'Off' : null,
190 );
191
192 return array(
193 'status' => 'saved',
194 'summary' => sanitize_text_field( $summary ),
195 'canonical_fingerprint' => hash( 'sha256', wp_json_encode( $fingerprint_values ) ),
196 'created_ids' => array(),
197 'updated_ids' => array_values( $updated_ids ),
198 'warnings' => array(),
199 'writes_canonical_settings' => (bool) $writes_canonical_settings,
200 );
201 }
202
203 /**
204 * Customer Journey never completes the route.
205 *
206 * @return bool False.
207 */
208 public function is_terminal() {
209 return false;
210 }
211 }
212