PluginProbe
Booking Calendar / 11.5
Booking Calendar v11.5
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-appointment-services / appointment_services__activate.php

appointment_services__activate.php in Booking Calendar 11.5, at includes/page-appointment-services/appointment_services__activate.php

332 lines 12.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /** Database schema for Appointment Services. @package Booking Calendar */
3 if ( ! defined( 'ABSPATH' ) ) { exit; }
4
5 if ( ! defined( 'WPBC_APPOINTMENT_SERVICES_DB_VERSION' ) ) {
6 define( 'WPBC_APPOINTMENT_SERVICES_DB_VERSION', '1.0.0' );
7 }
8
9 /**
10 * Return the canonical starter Service used during activation and upgrades.
11 *
12 * Keeping one definition prevents newly upgraded sites and Setup Wizard sites
13 * from receiving different starter data. The Provider remains an existing
14 * Booking Resource and is never created or renamed here.
15 *
16 * @param int $provider_id Existing Booking Resource used as the Provider.
17 * @param int $booking_form_id Optional published Booking Form assigned to the Service.
18 *
19 * @return array<string,mixed> Normalized values accepted by the Service repository.
20 */
21 function wpbc_appointment_services_get_starter_service_values( $provider_id, $booking_form_id = 0 ) {
22 return array(
23 'title' => __( 'Consultation', 'booking' ),
24 'description' => __( 'A 30-minute consultation.', 'booking' ),
25 'duration_minutes' => 30,
26 'buffer_before_minutes' => 0,
27 'buffer_after_minutes' => 0,
28 'base_cost' => '0.00',
29 'booking_form_id' => absint( $booking_form_id ),
30 'status' => 'active',
31 'resource_ids' => array( absint( $provider_id ) ),
32 'metadata' => array(
33 'quickstart_key' => 'appointment_starter',
34 'schema_version' => 1,
35 ),
36 );
37 }
38
39 /**
40 * Resolve the published starter form assigned to the default Appointment Service.
41 *
42 * The activation form registry owns the form identity. This resolver reads its
43 * assignment marker so the Service seed does not duplicate a form slug.
44 *
45 * @return int Published Booking Form ID, or zero while form storage is unavailable.
46 */
47 function wpbc_appointment_services_get_starter_booking_form_id() {
48 if (
49 ! function_exists( 'wpbc_get_activation_booking_form_page_configs' )
50 || ! function_exists( 'wpbc_is_table_exists' )
51 || ! wpbc_is_table_exists( 'booking_form_structures' )
52 || ! class_exists( 'WPBC_BFB_Form_Storage' )
53 ) {
54 return 0;
55 }
56
57 $form_configs = wpbc_get_activation_booking_form_page_configs();
58 if ( empty( $form_configs ) || ! is_array( $form_configs ) ) {
59 return 0;
60 }
61
62 foreach ( $form_configs as $form_config ) {
63 if ( empty( $form_config['assign_to_default_appointment_service'] ) ) {
64 continue;
65 }
66
67 $form_slug = isset( $form_config['form_slug'] )
68 ? sanitize_key( (string) $form_config['form_slug'] )
69 : '';
70 if ( '' === $form_slug ) {
71 return 0;
72 }
73
74 $booking_form = WPBC_BFB_Form_Storage::get_current_form_by_key( $form_slug, 0, 'published' );
75
76 return ! empty( $booking_form->booking_form_id )
77 ? absint( $booking_form->booking_form_id )
78 : 0;
79 }
80
81 return 0;
82 }
83
84 /**
85 * Resolve a logical Appointment Services table suffix to its full table name.
86 *
87 * @param string $suffix Logical suffix: services, service_resources, or appointment_details.
88 *
89 * @return string WordPress-prefixed database table name.
90 */
91 function wpbc_appointment_services_table_name( $suffix = 'services' ) {
92 global $wpdb;
93 $tables = array(
94 'services' => 'booking_services',
95 'service_resources' => 'booking_service_resources',
96 'appointment_details' => 'booking_appointment_details',
97 );
98 $suffix = isset( $tables[ $suffix ] ) ? $suffix : 'services';
99 return $wpdb->prefix . $tables[ $suffix ];
100 }
101
102 /**
103 * Determine whether every Appointment Services table is available.
104 *
105 * @return bool True when the Service, assignment, and snapshot tables exist.
106 */
107 function wpbc_appointment_services_tables_exist() {
108 return wpbc_is_table_exists( 'booking_services' )
109 && wpbc_is_table_exists( 'booking_service_resources' )
110 && wpbc_is_table_exists( 'booking_appointment_details' );
111 }
112
113 /**
114 * Create the starter Service after its database tables are installed.
115 *
116 * This runs only for a newly created Services table, or when an earlier seed
117 * attempt was marked for retry. It deliberately does not inspect an existing
118 * empty catalog because administrators may intentionally remove every Service.
119 *
120 * @return bool True when the starter Service was created successfully.
121 */
122 function wpbc_activation__appointment_services__seed_default_service() {
123 global $wpdb;
124
125 if ( ! wpbc_appointment_services_tables_exist() ) {
126 return false;
127 }
128
129 $provider_id = function_exists( 'wpbc_get_default_resource' ) ? absint( wpbc_get_default_resource() ) : 1;
130 if ( ! $provider_id ) {
131 $provider_id = 1;
132 }
133
134 $booking_form_id = wpbc_appointment_services_get_starter_booking_form_id();
135 if ( ! $booking_form_id ) {
136 return false;
137 }
138
139 $starter_service = wpbc_appointment_services_get_starter_service_values( $provider_id, $booking_form_id );
140 $metadata = wp_json_encode( $starter_service['metadata'] );
141 $now = current_time( 'mysql' );
142 $current_user_id = get_current_user_id();
143 $owner_user_id = function_exists( 'wpbc_appointment_services_get_owner_user_id' )
144 ? absint( wpbc_appointment_services_get_owner_user_id() )
145 : 0;
146
147 $service_inserted = $wpdb->insert(
148 wpbc_appointment_services_table_name( 'services' ),
149 array(
150 'owner_user_id' => $owner_user_id,
151 'title' => $starter_service['title'],
152 'description' => $starter_service['description'],
153 'duration_minutes' => $starter_service['duration_minutes'],
154 'buffer_before_minutes' => $starter_service['buffer_before_minutes'],
155 'buffer_after_minutes' => $starter_service['buffer_after_minutes'],
156 'base_cost' => $starter_service['base_cost'],
157 'booking_form_id' => $starter_service['booking_form_id'],
158 'status' => $starter_service['status'],
159 'metadata' => false === $metadata ? '{}' : $metadata,
160 'created_by' => $current_user_id,
161 'modified_by' => $current_user_id,
162 'creation_date' => $now,
163 'modification_date' => $now,
164 ),
165 array( '%d', '%s', '%s', '%d', '%d', '%d', '%s', '%d', '%s', '%s', '%d', '%d', '%s', '%s' )
166 ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
167 $service_id = absint( $wpdb->insert_id );
168 if ( false === $service_inserted || ! $service_id ) {
169 return false;
170 }
171
172 $assignment_inserted = $wpdb->insert(
173 wpbc_appointment_services_table_name( 'service_resources' ),
174 array(
175 'service_id' => $service_id,
176 'resource_id' => $provider_id,
177 'priority' => 0,
178 'status' => 'active',
179 ),
180 array( '%d', '%d', '%d', '%s' )
181 ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
182 if ( false === $assignment_inserted ) {
183 $wpdb->delete(
184 wpbc_appointment_services_table_name( 'services' ),
185 array( 'service_id' => $service_id ),
186 array( '%d' )
187 ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
188 return false;
189 }
190
191 return true;
192 }
193
194 /**
195 * Complete a pending starter Service seed after activation forms are available.
196 *
197 * @return bool True when the pending Service was created; otherwise false.
198 */
199 function wpbc_activation__appointment_services__maybe_seed_default_service() {
200 if ( 'On' !== get_bk_option( 'booking_appointment_services_default_seed_pending' ) ) {
201 return false;
202 }
203
204 if ( ! wpbc_activation__appointment_services__seed_default_service() ) {
205 return false;
206 }
207
208 delete_bk_option( 'booking_appointment_services_default_seed_pending' );
209
210 return true;
211 }
212 add_action(
213 'wpbc_activation_custom_booking_forms_created',
214 'wpbc_activation__appointment_services__maybe_seed_default_service'
215 );
216
217 /**
218 * Create or upgrade all Service, assignment, and Appointment snapshot tables.
219 *
220 * @return void
221 */
222 function wpbc_activation__appointment_services() {
223 global $wpdb;
224 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
225
226 $services_table_existed = wpbc_is_table_exists( 'booking_services' );
227 if ( ! $services_table_existed ) {
228 update_bk_option( 'booking_appointment_services_default_seed_pending', 'On' );
229 }
230
231 $charset_collate = $wpdb->get_charset_collate();
232 $services = wpbc_appointment_services_table_name( 'services' );
233 $assignments = wpbc_appointment_services_table_name( 'service_resources' );
234 $details = wpbc_appointment_services_table_name( 'appointment_details' );
235
236 $sql_services = "CREATE TABLE {$services} (
237 service_id bigint(20) unsigned NOT NULL auto_increment,
238 owner_user_id bigint(20) unsigned NOT NULL default 0,
239 title varchar(200) NOT NULL default '',
240 description text NULL,
241 duration_minutes smallint(5) unsigned NOT NULL default 30,
242 buffer_before_minutes smallint(5) unsigned NOT NULL default 0,
243 buffer_after_minutes smallint(5) unsigned NOT NULL default 0,
244 base_cost decimal(12,2) NOT NULL default 0.00,
245 booking_form_id bigint(20) unsigned NOT NULL default 0,
246 status varchar(20) NOT NULL default 'active',
247 metadata longtext NULL,
248 created_by bigint(20) unsigned NOT NULL default 0,
249 modified_by bigint(20) unsigned NOT NULL default 0,
250 creation_date datetime NOT NULL default '0000-00-00 00:00:00',
251 modification_date datetime NOT NULL default '0000-00-00 00:00:00',
252 PRIMARY KEY (service_id),
253 KEY owner_status (owner_user_id,status),
254 KEY status_title (status,title)
255 ) {$charset_collate};";
256
257 $sql_assignments = "CREATE TABLE {$assignments} (
258 assignment_id bigint(20) unsigned NOT NULL auto_increment,
259 service_id bigint(20) unsigned NOT NULL,
260 resource_id bigint(20) unsigned NOT NULL,
261 duration_override smallint(5) unsigned NULL,
262 cost_override decimal(12,2) NULL,
263 priority int(10) unsigned NOT NULL default 0,
264 status varchar(20) NOT NULL default 'active',
265 PRIMARY KEY (assignment_id),
266 UNIQUE KEY service_resource (service_id,resource_id),
267 KEY resource_status (resource_id,status),
268 KEY service_status (service_id,status)
269 ) {$charset_collate};";
270
271 $sql_details = "CREATE TABLE {$details} (
272 appointment_detail_id bigint(20) unsigned NOT NULL auto_increment,
273 booking_id bigint(20) unsigned NOT NULL,
274 service_id bigint(20) unsigned NOT NULL,
275 resource_id bigint(20) unsigned NOT NULL,
276 service_title varchar(200) NOT NULL default '',
277 duration_minutes smallint(5) unsigned NOT NULL default 0,
278 buffer_before_minutes smallint(5) unsigned NOT NULL default 0,
279 buffer_after_minutes smallint(5) unsigned NOT NULL default 0,
280 base_cost decimal(12,2) NOT NULL default 0.00,
281 booking_form_id bigint(20) unsigned NOT NULL default 0,
282 metadata longtext NULL,
283 creation_date datetime NOT NULL default '0000-00-00 00:00:00',
284 modification_date datetime NOT NULL default '0000-00-00 00:00:00',
285 PRIMARY KEY (appointment_detail_id),
286 UNIQUE KEY booking_id (booking_id),
287 KEY service_id (service_id),
288 KEY resource_id (resource_id)
289 ) {$charset_collate};";
290
291 dbDelta( $sql_services );
292 dbDelta( $sql_assignments );
293 dbDelta( $sql_details );
294 update_bk_option( 'booking_appointment_services_db_version', WPBC_APPOINTMENT_SERVICES_DB_VERSION );
295
296 wpbc_activation__appointment_services__maybe_seed_default_service();
297 }
298 add_bk_action( 'wpbc_free_version_activation', 'wpbc_activation__appointment_services' );
299 add_bk_action( 'wpbc_other_versions_activation', 'wpbc_activation__appointment_services' );
300
301 /**
302 * Upgrade the Appointment Services schema from an authorized admin request.
303 *
304 * @return void
305 */
306 function wpbc_activation__appointment_services__maybe_upgrade() {
307 if ( ! is_admin() || ! current_user_can( 'activate_plugins' ) ) { return; }
308 if (
309 WPBC_APPOINTMENT_SERVICES_DB_VERSION !== get_bk_option( 'booking_appointment_services_db_version' )
310 || ! wpbc_appointment_services_tables_exist()
311 || 'On' === get_bk_option( 'booking_appointment_services_default_seed_pending' )
312 ) {
313 wpbc_activation__appointment_services();
314 }
315 }
316 add_action( 'admin_init', 'wpbc_activation__appointment_services__maybe_upgrade' );
317
318 /**
319 * Remove Appointment Services tables during Booking Calendar's full data removal.
320 *
321 * @return void
322 */
323 function wpbc_deactivation__appointment_services() {
324 global $wpdb;
325 $wpdb->query( 'DROP TABLE IF EXISTS ' . wpbc_appointment_services_table_name( 'appointment_details' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
326 $wpdb->query( 'DROP TABLE IF EXISTS ' . wpbc_appointment_services_table_name( 'service_resources' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
327 $wpdb->query( 'DROP TABLE IF EXISTS ' . wpbc_appointment_services_table_name( 'services' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
328 delete_bk_option( 'booking_appointment_services_default_seed_pending' );
329 }
330 add_bk_action( 'wpbc_free_version_deactivation', 'wpbc_deactivation__appointment_services' );
331 add_bk_action( 'wpbc_other_versions_deactivation', 'wpbc_deactivation__appointment_services' );
332