PluginProbe
Booking Calendar / 11.8.3
Booking Calendar v11.8.3
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 10.11 10.11.2 All 203 releases
booking / includes / booking_modes_v3 / quickstart / appointment.php

appointment.php in Booking Calendar 11.8.3, at includes/booking_modes_v3/quickstart/appointment.php

282 lines 11.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Appointment mode QuickStart operation.
4 *
5 * @package Booking Calendar
6 * @since 11.5.0
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Reuse or create the bundled Appointment-ready Booking Form.
15 *
16 * Only the one required owner-scoped form is created. Existing forms,
17 * including the Standard form, are never modified or replaced.
18 *
19 * @return int|WP_Error Published Booking Form ID, or a setup error.
20 */
21 function wpbc_booking_modes_quickstart_ensure_appointment_form() {
22
23 if (
24 ! class_exists( 'WPBC_BFB_Form_Storage' )
25 || ! function_exists( 'wpbc_get_bfb_template_record_by_key' )
26 || ( function_exists( 'wpbc_is_table_exists' ) && ! wpbc_is_table_exists( 'booking_form_structures' ) )
27 ) {
28 return new WP_Error( 'wpbc_booking_modes_quickstart_form_storage_missing', __( 'The Booking Form storage is not ready.', 'booking' ) );
29 }
30
31 $form_slug = 'time_appointments_booking';
32 $owner_user_id = function_exists( 'wpbc_appointment_services_get_owner_user_id' ) ? absint( wpbc_appointment_services_get_owner_user_id() ) : 0;
33
34 if ( $owner_user_id && 'On' !== get_bk_option( 'booking_is_custom_forms_for_regular_users' ) ) {
35 return new WP_Error( 'wpbc_booking_modes_quickstart_owner_forms_disabled', __( 'Enable custom Booking Forms for regular users, or add Start Time to the owner Standard form, before running Appointment QuickStart.', 'booking' ) );
36 }
37
38 $existing_form = WPBC_BFB_Form_Storage::get_current_form_by_key( $form_slug, $owner_user_id, 'published' );
39
40 if ( ! empty( $existing_form->booking_form_id ) ) {
41 return absint( $existing_form->booking_form_id );
42 }
43
44 $template_record = wpbc_get_bfb_template_record_by_key( 'appointments_services_flow' );
45
46 if ( empty( $template_record ) || ! is_array( $template_record ) ) {
47 return new WP_Error( 'wpbc_booking_modes_quickstart_form_template_missing', __( 'The bundled Appointment Booking Form template is not available.', 'booking' ) );
48 }
49
50 $template_record['form_slug'] = $form_slug;
51 $template_record['status'] = 'published';
52 $template_record['scope'] = $owner_user_id ? 'user' : 'global';
53 $template_record['owner_user_id'] = $owner_user_id;
54 $template_record['booking_resource_id'] = null;
55 $template_record['is_default'] = 0;
56 $template_record['title'] = __( 'Time Appointments Booking Form', 'booking' );
57 $template_record['picture_url'] = isset( $template_record['picture_url'] ) ? (string) $template_record['picture_url'] : '';
58
59 if ( function_exists( 'wpbc_bfb_resolve_picture_url' ) ) {
60 $template_record['picture_url'] = wpbc_bfb_resolve_picture_url( $template_record['picture_url'] );
61 }
62
63 $booking_form_id = WPBC_BFB_Form_Storage::save_form( $template_record );
64
65 return $booking_form_id
66 ? absint( $booking_form_id )
67 : new WP_Error( 'wpbc_booking_modes_quickstart_form_not_created', __( 'The Appointment Booking Form could not be created.', 'booking' ) );
68 }
69
70 /**
71 * Find a repeat-safe starter Service for the active owner.
72 *
73 * A QuickStart-marked Service is preferred. An existing active Service is
74 * reused only when it already has a Provider and a start-time-capable form;
75 * otherwise a dedicated starter is created without changing customer data.
76 *
77 * @param int $booking_form_id Optional Appointment-ready Booking Form ID. Zero
78 * performs a read-only reusable-Service pass first.
79 * @param int $default_provider_id Fallback existing Provider resource ID.
80 *
81 * @return array<string,mixed>|WP_Error Service row, or a repository error.
82 */
83 function wpbc_booking_modes_quickstart_ensure_appointment_service( $booking_form_id, $default_provider_id ) {
84
85 if (
86 ! function_exists( 'wpbc_appointment_services_repository' )
87 || ! function_exists( 'wpbc_appointment_services_get_starter_service_values' )
88 ) {
89 return new WP_Error( 'wpbc_booking_modes_quickstart_service_api_missing', __( 'The Appointment Services API is not available.', 'booking' ) );
90 }
91
92 $repository = wpbc_appointment_services_repository();
93 $service_rows = array();
94 $owner_user_id = function_exists( 'wpbc_appointment_services_get_owner_user_id' ) ? absint( wpbc_appointment_services_get_owner_user_id() ) : 0;
95
96 foreach ( array( 'active', 'inactive', 'archived' ) as $service_status ) {
97 $status_rows = $repository->list_items(
98 array(
99 'status' => $service_status,
100 'sort_by' => 'service_id',
101 'sort_order' => 'asc',
102 'limit' => 500,
103 )
104 );
105
106 if ( is_wp_error( $status_rows ) ) {
107 return $status_rows;
108 }
109
110 $service_rows = array_merge( $service_rows, $status_rows );
111 }
112
113 $marked_service = array();
114
115 foreach ( $service_rows as $service_row ) {
116 if ( absint( $service_row['owner_user_id'] ) !== $owner_user_id ) {
117 continue;
118 }
119
120 $metadata = function_exists( 'wpbc_appointment_services_decode_metadata' )
121 ? wpbc_appointment_services_decode_metadata( $service_row['metadata'] )
122 : json_decode( (string) $service_row['metadata'], true );
123
124 if ( is_array( $metadata ) && 'appointment_starter' === ( isset( $metadata['quickstart_key'] ) ? $metadata['quickstart_key'] : '' ) ) {
125 $marked_service = $service_row;
126 break;
127 }
128 }
129
130 if ( ! empty( $marked_service ) ) {
131 if ( 'active' !== $marked_service['status'] ) {
132 return new WP_Error( 'wpbc_booking_modes_quickstart_service_not_active', __( 'A previous QuickStart Service exists but is not active. Activate or remove that Service before trying again.', 'booking' ) );
133 }
134
135 $service_needs_repair = false;
136 if ( empty( $marked_service['resource_ids'] ) ) {
137 $marked_service['resource_ids'] = array( absint( $default_provider_id ) );
138 $service_needs_repair = true;
139 }
140
141 $marked_provider_id = absint( reset( $marked_service['resource_ids'] ) );
142 $marked_form_slug = function_exists( 'wpbc_booking_appointment_resolve_form_slug' )
143 ? wpbc_booking_appointment_resolve_form_slug( $marked_service, $marked_provider_id, array() )
144 : '';
145 $marked_form_is_suitable = '' !== $marked_form_slug
146 && function_exists( 'wpbc_booking_appointment_form_has_start_time' )
147 && wpbc_booking_appointment_form_has_start_time( $marked_form_slug, $marked_provider_id );
148
149 if ( $marked_form_is_suitable && ! $booking_form_id ) {
150 return $service_needs_repair ? $repository->save( $marked_service ) : $marked_service;
151 }
152
153 if ( ! $booking_form_id ) {
154 return new WP_Error( 'wpbc_booking_modes_quickstart_appointment_form_required', __( 'An Appointment-ready Booking Form is required for the starter Service.', 'booking' ) );
155 }
156
157 if ( absint( $marked_service['booking_form_id'] ) !== absint( $booking_form_id ) ) {
158 $marked_service['booking_form_id'] = absint( $booking_form_id );
159 $service_needs_repair = true;
160 }
161 if ( $service_needs_repair ) {
162 $marked_service = $repository->save( $marked_service );
163 }
164
165 return $marked_service;
166 }
167
168 foreach ( $service_rows as $service_row ) {
169 if (
170 'active' !== $service_row['status']
171 || absint( $service_row['owner_user_id'] ) !== $owner_user_id
172 || empty( $service_row['resource_ids'] )
173 ) {
174 continue;
175 }
176
177 $provider_id = absint( reset( $service_row['resource_ids'] ) );
178 $form_slug = function_exists( 'wpbc_booking_appointment_resolve_form_slug' )
179 ? wpbc_booking_appointment_resolve_form_slug( $service_row, $provider_id, array() )
180 : '';
181
182 if (
183 '' !== $form_slug
184 && function_exists( 'wpbc_booking_appointment_form_has_start_time' )
185 && wpbc_booking_appointment_form_has_start_time( $form_slug, $provider_id )
186 ) {
187 return $service_row;
188 }
189 }
190
191 if ( ! $booking_form_id ) {
192 return new WP_Error( 'wpbc_booking_modes_quickstart_appointment_form_required', __( 'An Appointment-ready Booking Form is required for the starter Service.', 'booking' ) );
193 }
194
195 $starter_service = wpbc_appointment_services_get_starter_service_values( $default_provider_id );
196 $starter_service['booking_form_id'] = absint( $booking_form_id );
197
198 return $repository->save( $starter_service );
199 }
200
201 /**
202 * Run Appointment QuickStart without modifying existing resources or settings.
203 *
204 * The operation provisions the minimum missing Service, assignment, suitable
205 * form, and public page. Existing availability remains authoritative and is
206 * exposed through Working Hours and Days Off follow-up URLs.
207 *
208 * @return array<string,mixed>|WP_Error QuickStart result, or an error.
209 */
210 function wpbc_booking_modes_run_appointment_quickstart() {
211
212 $state = wpbc_booking_modes_get_quickstart_state( 'appointment' );
213 $default_provider_id = wpbc_booking_modes_quickstart_get_first_resource_id();
214
215 if ( is_wp_error( $default_provider_id ) ) {
216 return $default_provider_id;
217 }
218
219 $service = wpbc_booking_modes_quickstart_ensure_appointment_service( 0, $default_provider_id );
220
221 if ( is_wp_error( $service ) && 'wpbc_booking_modes_quickstart_appointment_form_required' === $service->get_error_code() ) {
222 $booking_form_id = wpbc_booking_modes_quickstart_ensure_appointment_form();
223
224 if ( is_wp_error( $booking_form_id ) ) {
225 return $booking_form_id;
226 }
227
228 $service = wpbc_booking_modes_quickstart_ensure_appointment_service( $booking_form_id, $default_provider_id );
229 }
230
231 if ( is_wp_error( $service ) ) {
232 return $service;
233 }
234
235 $booking_form_id = ! empty( $service['booking_form_id'] ) ? absint( $service['booking_form_id'] ) : 0;
236 $provider_id = ! empty( $service['resource_ids'] ) ? absint( reset( $service['resource_ids'] ) ) : absint( $default_provider_id );
237 $activation_page_configs = function_exists( 'wpbc_get_activation_booking_page_configs' )
238 ? wpbc_get_activation_booking_page_configs()
239 : array();
240 $appointment_page_config = isset( $activation_page_configs['appointment_booking'] )
241 ? $activation_page_configs['appointment_booking']
242 : array();
243 $appointment_page_slug = isset( $appointment_page_config['page_slug'] )
244 ? (string) $appointment_page_config['page_slug']
245 : 'booking-calendar-appointment';
246 $page_result = wpbc_booking_modes_quickstart_ensure_page(
247 'appointment_booking',
248 $appointment_page_slug,
249 __( 'Book an Appointment', 'booking' ),
250 '[booking_appointment]',
251 '[booking_appointment'
252 );
253
254 if ( is_wp_error( $page_result ) ) {
255 return $page_result;
256 }
257
258 $state['completed'] = true;
259 $state['completed_at'] = ! empty( $state['completed_at'] ) ? $state['completed_at'] : current_time( 'mysql' );
260 $state['resource_id'] = $provider_id;
261 $state['service_id'] = absint( $service['service_id'] );
262 $state['booking_form_id'] = absint( $booking_form_id );
263 $state['page_id'] = absint( $page_result['page_id'] );
264 $state_result = wpbc_booking_modes_set_quickstart_state( 'appointment', $state );
265
266 if ( is_wp_error( $state_result ) ) {
267 return $state_result;
268 }
269
270 return array(
271 'mode_id' => 'appointment',
272 'message' => __( 'Appointment QuickStart is ready. Review Schedule & Rules and Block Dates, then test the booking page.', 'booking' ),
273 'test_url' => $page_result['test_url'],
274 'page_id' => absint( $page_result['page_id'] ),
275 'resource_id' => $provider_id,
276 'service_id' => absint( $service['service_id'] ),
277 'booking_form_id' => absint( $booking_form_id ),
278 'working_hours_url' => function_exists( 'wpbc_appointment_services_get_provider_availability_url' ) ? wpbc_appointment_services_get_provider_availability_url( $provider_id ) : '',
279 'days_off_url' => add_query_arg( 'resource_id', $provider_id, wpbc_booking_modes_get_canonical_page_url( 'wpbc-availability__availability' ) ),
280 );
281 }
282