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-date-time-formats / class-wpbc-setup-wizard-date-time-formats-save-handler.php

class-wpbc-setup-wizard-date-time-formats-save-handler.php in Booking Calendar 11.9, at includes/page-setup-wizard/step-date-time-formats/class-wpbc-setup-wizard-date-time-formats-save-handler.php

173 lines 5.9 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 Dates and times.
4 *
5 * @package Booking Calendar
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Persist the three scalar date/time choices through canonical WPBC options.
14 *
15 * The handler reloads, validates, writes, and verifies canonical values at the
16 * operation boundary. When a later option cannot be verified, earlier writes
17 * are restored from exact before-images because WordPress options do not offer
18 * a transaction spanning these three independent records.
19 */
20 final class WPBC_Setup_Wizard_Date_Time_Formats_Save_Handler implements WPBC_Setup_Wizard_Step_Save_Handler {
21
22 /** @var WPBC_Setup_Wizard_Date_Time_Formats */
23 private $date_time_formats;
24
25 /**
26 * Build the handler around the reusable field contract.
27 *
28 * @param WPBC_Setup_Wizard_Date_Time_Formats|null $date_time_formats Optional domain validator.
29 */
30 public function __construct( $date_time_formats = null ) {
31 $this->date_time_formats = $date_time_formats instanceof WPBC_Setup_Wizard_Date_Time_Formats
32 ? $date_time_formats
33 : new WPBC_Setup_Wizard_Date_Time_Formats();
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 'date_time_formats';
43 }
44
45 /**
46 * Return the scalar-settings save 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 * Revalidate and save the date format, time format, and week start.
61 *
62 * @param array<string,mixed> $validated_fields Validated current-step fields.
63 * @param array<string,mixed> $checkpoint Current checkpoint.
64 * @param array<string,mixed> $operation_context Stable operation metadata.
65 *
66 * @return array<string,mixed>|WP_Error Verified result or bounded error.
67 */
68 public function save( array $validated_fields, array $checkpoint, array $operation_context ) {
69 unset( $checkpoint, $operation_context );
70
71 if ( ! WPBC_Setup_Wizard_Access::current_user_can_access() ) {
72 return new WP_Error( 'wpbc_setup_wizard_date_time_forbidden', __( 'You are not allowed to change Booking Calendar date and time settings.', 'booking' ) );
73 }
74
75 $field_option_map = array(
76 'date_format' => 'booking_date_format',
77 'time_format' => 'booking_time_format',
78 'start_day_of_week' => 'booking_start_day_weeek',
79 );
80 $canonical_values = array();
81 foreach ( $field_option_map as $field_id => $option_name ) {
82 $field_value = $this->date_time_formats->validate_field(
83 $field_id,
84 isset( $validated_fields[ $field_id ] ) ? $validated_fields[ $field_id ] : null,
85 true
86 );
87 if ( is_wp_error( $field_value ) ) {
88 return $field_value;
89 }
90
91 $canonical_values[ $option_name ] = (string) $field_value;
92 }
93
94 $missing_marker = 'wpbc_setup_wizard_missing_' . wp_generate_uuid4();
95 $before_images = array();
96 $attempted = array();
97 $updated_ids = array();
98
99 foreach ( $canonical_values as $option_name => $canonical_value ) {
100 $before_value = get_bk_option( $option_name, $missing_marker );
101 $before_images[ $option_name ] = array(
102 'exists' => $missing_marker !== $before_value,
103 'value' => $before_value,
104 );
105
106 if ( $before_images[ $option_name ]['exists'] && (string) $before_value === $canonical_value ) {
107 continue;
108 }
109
110 $attempted[] = $option_name;
111 update_bk_option( $option_name, $canonical_value );
112 if ( $canonical_value !== (string) get_bk_option( $option_name, $missing_marker ) ) {
113 $compensated = $this->restore_before_images( $attempted, $before_images, $missing_marker );
114
115 return new WP_Error(
116 'wpbc_setup_wizard_date_time_not_saved',
117 $compensated
118 ? __( 'Booking Calendar could not save the date and time settings. Previous values were restored.', 'booking' )
119 : __( 'Booking Calendar could not save the date and time settings, and some previous values could not be restored. Review Date and time settings before continuing.', 'booking' )
120 );
121 }
122
123 $updated_ids[] = $option_name;
124 }
125
126 return array(
127 'status' => 'saved',
128 'summary' => empty( $updated_ids )
129 ? __( 'Date and time settings already matched this setup.', 'booking' )
130 : __( 'Date and time settings saved.', 'booking' ),
131 'canonical_fingerprint' => hash( 'sha256', wp_json_encode( $canonical_values ) ),
132 'created_ids' => array(),
133 'updated_ids' => $updated_ids,
134 'warnings' => array(),
135 'writes_canonical_settings' => true,
136 );
137 }
138
139 /**
140 * Restore attempted option writes from exact before-images.
141 *
142 * @param string[] $attempted Attempted option names in write order.
143 * @param array<string,array<string,mixed>> $before_images Before-images keyed by option name.
144 * @param string $missing_marker Unique missing-value marker.
145 *
146 * @return bool True when every attempted option matches its before-image.
147 */
148 private function restore_before_images( array $attempted, array $before_images, $missing_marker ) {
149 $restored = true;
150 foreach ( array_reverse( $attempted ) as $option_name ) {
151 $before_image = $before_images[ $option_name ];
152 if ( $before_image['exists'] ) {
153 update_bk_option( $option_name, $before_image['value'] );
154 $restored = $restored && (string) $before_image['value'] === (string) get_bk_option( $option_name, $missing_marker );
155 } else {
156 delete_bk_option( $option_name );
157 $restored = $restored && $missing_marker === get_bk_option( $option_name, $missing_marker );
158 }
159 }
160
161 return $restored;
162 }
163
164 /**
165 * Dates and times does not complete the route.
166 *
167 * @return bool False.
168 */
169 public function is_terminal() {
170 return false;
171 }
172 }
173