PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.19
Booktics – Appointment Booking Calendar for Service Businesses v1.0.19
1.0.25 1.0.24 1.0.23 1.0.22 1.0.21 1.0.20 1.0.19 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 All 27 releases
booktics / base / installer.php

installer.php in Booktics – Appointment Booking Calendar for Service Businesses 1.0.19, at base/installer.php

308 lines 13.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Booktics;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit;
7 }
8
9 use Booktics\Dummy_Data\Dummy_Data_Manager;
10
11 class Installer {
12 /**
13 * Initializes the Booktics plugin by performing necessary setup tasks.
14 *
15 * This method performs the following setup operations:
16 * - Creates or updates required database tables
17 * - Initializes user roles and capabilities
18 * - Generates initial onboarding data using dummy data manager
19 */
20 public static function run(): void {
21 self::create_tables();
22 ( new Role() )->init();
23 ( new Dummy_Data_Manager() )->generate_onboarding_data();
24 }
25
26 /**
27 * Creates and updates database tables required for the Booktics plugin.
28 *
29 * Creates the following tables if they don't exist:
30 * - booktics_schedules: Stores scheduling information for team members and services
31 * - booktics_carts: Stores shopping cart information
32 * - booktics_cart_items: Stores individual items in shopping carts
33 * - booktics_orders: Stores order information and payment details
34 * - booktics_payments: Stores payment transaction records
35 *
36 * Also handles table structure updates by adding missing columns to existing tables
37 * and performing necessary column modifications.
38 */
39 public static function create_tables(): void {
40 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
41
42 global $wpdb;
43 $charset_collate = $wpdb->get_charset_collate();
44
45 $table_prefix = $wpdb->prefix;
46 $table_schema = array(
47 "CREATE TABLE IF NOT EXISTS {$table_prefix}booktics_schedules (
48 id mediumint(9) NOT NULL AUTO_INCREMENT,
49 team_member_id int(11) NOT NULL,
50 service_id int(11) NOT NULL,
51 location_id int(11) NOT NULL,
52 start_time varchar(100) NOT NULL,
53 end_time varchar(100) NOT NULL,
54 week_day varchar(100) NOT NULL,
55 custom_date varchar(100) NOT NULL,
56 created_at datetime DEFAULT NULL,
57 updated_at datetime DEFAULT NULL,
58 PRIMARY KEY (id)
59 ) $charset_collate;",
60
61 "CREATE TABLE IF NOT EXISTS {$table_prefix}booktics_carts (
62 id mediumint(9) NOT NULL AUTO_INCREMENT,
63 uuid varchar(36) NOT NULL,
64 user_id int(11) NOT NULL,
65 coupon_code varchar(100) DEFAULT NULL,
66 total decimal(10,2) DEFAULT NULL,
67 created_at datetime DEFAULT NULL,
68 updated_at datetime DEFAULT NULL,
69 PRIMARY KEY (id)
70 ) $charset_collate;",
71
72 "CREATE TABLE IF NOT EXISTS {$table_prefix}booktics_cart_items (
73 id mediumint(9) NOT NULL AUTO_INCREMENT,
74 uuid varchar(36) NOT NULL,
75 cart_id mediumint(9) NOT NULL,
76 team_member_id int(11) DEFAULT NULL,
77 service_id int(11) DEFAULT NULL,
78 location_id int(11) DEFAULT NULL,
79 date date DEFAULT NULL,
80 start_time varchar(100) DEFAULT NULL,
81 end_time varchar(100) DEFAULT NULL,
82 price VARCHAR(100) DEFAULT NULL,
83 created_at datetime DEFAULT NULL,
84 updated_at datetime DEFAULT NULL,
85 PRIMARY KEY (id)
86 ) $charset_collate;",
87
88 "CREATE TABLE IF NOT EXISTS {$table_prefix}booktics_orders (
89 id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
90 order_no VARCHAR(100) NOT NULL,
91 customer_id BIGINT UNSIGNED NOT NULL,
92 customer_note VARCHAR(100) DEFAULT NULL,
93 status VARCHAR(50) DEFAULT 'pending',
94 payment_status VARCHAR(50) DEFAULT NULL,
95 timezone VARCHAR(50) DEFAULT 'UTC',
96 currency VARCHAR(10) DEFAULT NULL,
97 price_breakdown JSON DEFAULT NULL,
98 tax_total VARCHAR(100) DEFAULT NULL,
99 coupon_code VARCHAR(100) DEFAULT NULL,
100 coupon_discount VARCHAR(100) DEFAULT NULL,
101 subtotal VARCHAR(100) DEFAULT 0,
102 total VARCHAR(100) DEFAULT 0,
103 payment_method VARCHAR(50) DEFAULT NULL,
104 payment_intent_id VARCHAR(250) DEFAULT NULL,
105 payment_transaction_id VARCHAR(250) DEFAULT NULL,
106 directorist_id BIGINT UNSIGNED DEFAULT NULL,
107 created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
108 updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
109 PRIMARY KEY (id),
110 INDEX (order_no),
111 INDEX (directorist_id)
112 ) $charset_collate;",
113
114 "CREATE TABLE IF NOT EXISTS {$table_prefix}booktics_payments (
115 id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
116 order_id BIGINT UNSIGNED NOT NULL,
117 customer_id BIGINT UNSIGNED NOT NULL,
118 amount VARCHAR(20) NOT NULL,
119 currency VARCHAR(10) DEFAULT 'usd',
120 intent_id VARCHAR(255),
121 transaction_id VARCHAR(255),
122 status varchar(100) NOT NULL DEFAULT 'pending',
123 payment_method VARCHAR(50) NOT NULL,
124 refunded_amount VARCHAR(20) DEFAULT '0.00',
125 failure_reason TEXT,
126 date DATE NOT NULL,
127 date_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
128 INDEX (order_id),
129 INDEX (customer_id),
130 INDEX (intent_id),
131 INDEX (transaction_id)
132 ) $charset_collate;",
133
134 "CREATE TABLE IF NOT EXISTS {$table_prefix}booktics_guests (
135 id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
136 wp_user_id BIGINT UNSIGNED DEFAULT NULL,
137 first_name VARCHAR(100) DEFAULT NULL,
138 last_name VARCHAR(100) DEFAULT NULL,
139 user_login VARCHAR(100) DEFAULT NULL,
140 email VARCHAR(100) DEFAULT NULL,
141 phone VARCHAR(10) DEFAULT NULL,
142 description VARCHAR(250) DEFAULT NULL,
143 image VARCHAR(250) DEFAULT NULL,
144 status INT DEFAULT 0,
145 created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
146 updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
147 INDEX (wp_user_id),
148 INDEX (email),
149 INDEX (first_name)
150 ) $charset_collate;",
151 );
152 foreach ( $table_schema as $table_sql ) {
153 dbDelta( $table_sql );
154 }
155
156 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.NotPrepared -- Schema migration; direct DB access required, caching inappropriate for DDL, identifiers sanitized via esc_sql().
157
158 // Add currency column to existing orders table if it doesn't exist
159 $orders_table = "{$table_prefix}booktics_orders";
160 $column_exists = $wpdb->get_results(
161 "SHOW COLUMNS FROM `" . \esc_sql( $orders_table ) . "` LIKE 'currency'"
162 );
163 if ( empty( $column_exists ) ) {
164 $wpdb->query(
165 "ALTER TABLE `" . \esc_sql( $orders_table ) . "` ADD COLUMN currency VARCHAR(10) DEFAULT NULL AFTER timezone"
166 );
167 }
168
169 // Handle booktics_guests table
170 $guests_table = "{$table_prefix}booktics_guests";
171 $guests_columns = $wpdb->get_col( 'DESC `' . \esc_sql( $guests_table ) . '`', 0 );
172
173 // Drop index on first_name if it exists
174 $indexes = $wpdb->get_results( "SHOW INDEX FROM `" . \esc_sql( $guests_table ) . "` WHERE Key_name = 'first_name'", ARRAY_A );
175 if ( ! empty( $indexes ) ) {
176 $wpdb->query(
177 sprintf(
178 'ALTER TABLE `%s` DROP INDEX `first_name`',
179 \esc_sql( $guests_table )
180 )
181 );
182 }
183
184 // Rename first_name to name if first_name exists and name does not
185 if ( in_array( 'first_name', $guests_columns, true ) && ! in_array( 'name', $guests_columns, true ) ) {
186 $wpdb->query(
187 sprintf(
188 'ALTER TABLE `%s` CHANGE COLUMN `first_name` `name` VARCHAR(100) DEFAULT NULL',
189 \esc_sql( $guests_table )
190 )
191 );
192 }
193
194 // Remove last_name column if it exists
195 if ( in_array( 'last_name', $guests_columns, true ) ) {
196 $wpdb->query(
197 sprintf(
198 'ALTER TABLE `%s` DROP COLUMN `last_name`',
199 \esc_sql( $guests_table )
200 )
201 );
202 }
203
204 // Add index on name if it does not exist
205 $indexes_name = $wpdb->get_results( "SHOW INDEX FROM `" . \esc_sql( $guests_table ) . "` WHERE Key_name = 'name'", ARRAY_A );
206 if ( empty( $indexes_name ) && in_array( 'name', $guests_columns, true ) ) {
207 $wpdb->query(
208 sprintf(
209 'ALTER TABLE `%s` ADD INDEX (`name`)',
210 \esc_sql( $guests_table )
211 )
212 );
213 }
214
215 // Alter first_name column if it exists
216 if ( in_array( 'first_name', $guests_columns, true ) ) {
217 $wpdb->query(
218 sprintf(
219 'ALTER TABLE `%s` MODIFY COLUMN `first_name` VARCHAR(100) DEFAULT NULL',
220 \esc_sql( $guests_table )
221 )
222 );
223 }
224
225 // Add missing columns to booktics_orders table
226 $orders_table = "{$table_prefix}booktics_orders";
227 $orders_columns = $wpdb->get_col( 'DESC `' . esc_sql( $orders_table ) . '`', 0 );
228
229 $orders_columns_to_add = array(
230 'payment_method' => 'VARCHAR(50) DEFAULT NULL',
231 'payment_intent_id' => 'VARCHAR(250) DEFAULT NULL',
232 'payment_transaction_id' => 'VARCHAR(250) DEFAULT NULL',
233 'custom_fields' => 'TEXT DEFAULT NULL',
234 'directorist_id' => 'BIGINT UNSIGNED DEFAULT NULL',
235 );
236
237 foreach ( $orders_columns_to_add as $column => $definition ) {
238 if ( ! in_array( $column, $orders_columns, true ) ) {
239 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.NotPrepared -- Schema migration; identifiers sanitized via esc_sql().
240 $wpdb->query(
241 sprintf(
242 'ALTER TABLE `%s` ADD COLUMN `%s` %s',
243 esc_sql( $orders_table ),
244 esc_sql( $column ),
245 $definition
246 )
247 );
248 }
249 }
250
251 // Add index for directorist_id if it doesn't exist
252 $indexes = $wpdb->get_results( "SHOW INDEX FROM `" . esc_sql( $orders_table ) . "` WHERE Key_name = 'directorist_id'", ARRAY_A );
253 if ( empty( $indexes ) && in_array( 'directorist_id', $orders_columns, true ) ) {
254 $wpdb->query(
255 sprintf(
256 'ALTER TABLE `%s` ADD INDEX (`directorist_id`)',
257 esc_sql( $orders_table )
258 )
259 );
260 }
261
262 // Handle booktics_cart_items table
263 $cart_items_table = "{$table_prefix}booktics_cart_items";
264 $cart_items_columns = $wpdb->get_col( 'DESC `' . esc_sql( $cart_items_table ) . '`', 0 );
265
266 // Rename sub_total to subtotal if exists
267 if ( in_array( 'sub_total', $cart_items_columns, true ) ) {
268 $wpdb->query(
269 sprintf(
270 'ALTER TABLE `%s` CHANGE COLUMN `sub_total` `subtotal` VARCHAR(20) NOT NULL',
271 esc_sql( $cart_items_table )
272 )
273 );
274 } elseif ( ! in_array( 'subtotal', $cart_items_columns, true ) ) {
275 $wpdb->query(
276 sprintf(
277 'ALTER TABLE `%s` ADD COLUMN `subtotal` VARCHAR(20) NOT NULL',
278 esc_sql( $cart_items_table )
279 )
280 );
281 }
282
283 $cart_items_columns_to_add = array(
284 'extra_services' => 'TEXT DEFAULT NULL',
285 'total' => 'VARCHAR(20) NOT NULL',
286 'additional_duration_id' => 'VARCHAR(100) NOT NULL',
287 'group_booking' => 'TEXT DEFAULT NULL',
288 'time_format' => 'VARCHAR(10) DEFAULT NULL',
289 );
290
291 foreach ( $cart_items_columns_to_add as $column => $definition ) {
292 if ( ! in_array( $column, $cart_items_columns, true ) ) {
293 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.NotPrepared -- Schema migration; identifiers sanitized via esc_sql().
294 $wpdb->query(
295 sprintf(
296 'ALTER TABLE `%s` ADD COLUMN `%s` %s',
297 esc_sql( $cart_items_table ),
298 esc_sql( $column ),
299 $definition
300 )
301 );
302 }
303 }
304
305 // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.NotPrepared
306 }
307 }
308