PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.24
Booktics – Appointment Booking Calendar for Service Businesses v1.0.24
1.0.29 1.0.28 1.0.27 1.0.26 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 All 31 releases
booktics / core / cart / cart-manager.php

cart-manager.php in Booktics – Appointment Booking Calendar for Service Businesses 1.0.24, at core/cart/cart-manager.php

365 lines 10.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Booktics\Cart;
4
5 use Booktics\Abstracts\Booktics_Database;
6
7 /**
8 * Class Cart_Manager
9 * Manages shopping cart operations including adding items, updating quantities, and calculating totals
10 *
11 * @package Booktics\Cart
12 */
13 class Cart_Manager {
14 /**
15 * @var Booktics_Database The database instance
16 */
17 protected $db;
18
19 /**
20 * @var string The carts table name
21 */
22 protected $carts_table;
23
24 /**
25 * @var string The cart items table name
26 */
27 protected $cart_items_table;
28
29 /**
30 * Initialize CartManager with database connection
31 */
32 public function __construct() {
33 $this->db = new Booktics_Database();
34 $this->carts_table = booktics_get_table_name( 'booktics_carts' );
35 $this->cart_items_table = booktics_get_table_name( 'booktics_cart_items' );
36 }
37
38 /**
39 * Add item to the cart for guest users
40 *
41 * @param array $item
42 *
43 * @return array
44 */
45 public function add_to_cart_guest( array $item ): array {
46 return Cart_Session::add_item( $item );
47 }
48
49 /**
50 * Add item to the cart for both guest and registered users
51 *
52 * @param array $params Cart item parameters
53 *
54 * @return array Added cart item
55 */
56 public function add_to_cart( array $params ): array {
57 $user_id = get_current_user_id();
58 $params['uuid'] = wp_generate_uuid4();
59 if ( $user_id ) {
60 return $this->add_to_cart_user( $user_id, $params );
61 }
62
63 return $this->add_to_cart_guest( $params );
64 }
65
66 /**
67 * Add item to the cart for registered users
68 *
69 * @param int $user_id
70 * @param array $item
71 *
72 * @return array
73 */
74 public function add_to_cart_user( int $user_id, array $item ): array {
75 $carts = $this->db->select(
76 $this->carts_table, array(
77 'user_id' => $user_id,
78 )
79 );
80
81 if ( ! count( $carts ) ) {
82 $uuid = wp_generate_uuid4();
83 $this->db->insert_batch(
84 $this->carts_table, array(
85 array(
86 'uuid' => $uuid,
87 'user_id' => $user_id,
88 'total' => 0,
89 'created_at' => current_time( 'mysql' ),
90 'updated_at' => current_time( 'mysql' ),
91 ),
92 )
93 );
94
95 $carts = $this->db->select(
96 $this->carts_table, array(
97 'user_id' => $user_id,
98 )
99 );
100 }
101
102 // Check if the service_id already exists in the cart items for this cart
103 if ( count( $carts ) ) {
104 $cart = $carts[0];
105 $existing_items = $this->db->select(
106 $this->cart_items_table,
107 array(
108 'cart_id' => $cart->id,
109 'service_id' => $item['service_id'],
110 )
111 );
112 if ( ! empty( $existing_items ) ) {
113 // Delete existing items with the same service_id for this cart
114 foreach ( $existing_items as $existing_item ) {
115 $this->db->delete(
116 $this->cart_items_table,
117 array(
118 'id' => $existing_item->id,
119 )
120 );
121 }
122 }
123 }
124 $cart = count( $carts ) ? $carts[0] : array();
125 $cart_item_data = array(
126 'uuid' => $item['uuid'],
127 'cart_id' => $cart->id,
128 'team_member_id' => $item['team_member_id'],
129 'service_id' => $item['service_id'],
130 'date' => $item['date'],
131 'start_time' => $item['start_time'],
132 'end_time' => $item['end_time'],
133 'price' => $item['price'] ?? 0,
134 'subtotal' => $item['subtotal'] ?? $item['price'],
135 'total' => $item['total'] ?? $item['subtotal'],
136 'additional_duration_id' => booktics_sanitize_id_string( $item['additional_duration_id'] ?? '' ),
137 'created_at' => current_time( 'mysql' ),
138 'updated_at' => current_time( 'mysql' ),
139 );
140
141 $cart_item_data = apply_filters( 'booktics_pro_cart_db', $cart_item_data, $item );
142 $this->db->insert_batch( $this->cart_items_table, array( $cart_item_data ) );
143 if ( isset( $cart->id ) ) {
144 $this->update_cart_total( $cart->id );
145 }
146
147 if ( isset( $cart_item_data['extra_services'] ) ) {
148 $cart_item_data['extra_services'] = json_decode( $cart_item_data['extra_services'], true );
149 }
150
151 return $cart_item_data;
152 }
153
154 /**
155 * Synchronize session cart items to a database
156 *
157 * @param int $user_id
158 */
159 public function sync_session_to_db( int $user_id ): void {
160 $session_cart = Cart_Session::get();
161 if ( empty( $session_cart['items'] ) ) {
162 return;
163 }
164
165 foreach ( $session_cart['items'] as $item ) {
166 $this->add_to_cart_user( $user_id, $item );
167 }
168
169 Cart_Session::clear();
170 }
171
172 /**
173 * Update cart total based on items
174 *
175 * @param int $cart_id
176 */
177 protected function update_cart_total( int $cart_id ): void {
178 $items = $this->db->select(
179 $this->cart_items_table, array(
180 'cart_id' => $cart_id,
181 )
182 );
183
184 if ( empty( $items ) ) {
185 $this->db->delete( $this->carts_table, array( 'id' => $cart_id ) );
186
187 return;
188 }
189
190 $total = 0;
191 foreach ( $items as $item ) {
192 $total += (float) ( $item->total ?? $item->subtotal ?? 0 );
193 }
194
195 $this->db->update(
196 $this->carts_table,
197 array(
198 'total' => $total,
199 'updated_at' => current_time( 'mysql' ),
200 ),
201 array( 'id' => $cart_id )
202 );
203 }
204
205 /**
206 * Get a cart and its items for a user
207 *
208 * @return array
209 */
210 public function get_cart(): array {
211 $user_id = get_current_user_id();
212
213 if ( ! $user_id ) {
214 return Cart_Session::get();
215 }
216
217 $carts = $this->db->select(
218 $this->carts_table, array(
219 'user_id' => $user_id,
220 )
221 );
222 $cart = count( $carts ) ? $carts[0] : null;
223
224 if ( ! $cart ) {
225 return array( 'items' => array() );
226 }
227
228 $items = $this->db->select(
229 $this->cart_items_table, array(
230 'cart_id' => $cart->id,
231 )
232 );
233 foreach ( $items as $i => $item ) {
234 if ( isset( $item->extra_services ) ) {
235 $item->extra_services = json_decode( $item->extra_services, true );
236 }
237 }
238
239 return array_merge( (array) $cart, array( 'items' => $items ) );
240 }
241
242 /**
243 * Remove item from the cart
244 *
245 * @param string|null $id
246 */
247 public function remove_cart_item( $id = null ): void {
248 $user_id = get_current_user_id();
249 if ( ! $user_id ) {
250 if ( ! $id ) {
251 Cart_Session::clear();
252 } else {
253 Cart_Session::delete_item( $id );
254 }
255 }
256
257 $carts = $this->db->select(
258 $this->carts_table, array(
259 'user_id' => $user_id,
260 )
261 );
262
263 $cart = count( $carts ) ? $carts[0] : null;
264
265 if ( ! $cart ) {
266 return;
267 }
268
269 $conditions = array( 'cart_id' => $cart->id );
270 if ( ! empty( $id ) ) {
271 $conditions['uuid'] = $id;
272 }
273
274 $this->db->delete( $this->cart_items_table, $conditions );
275
276 $this->update_cart_total( $cart->id );
277 }
278
279 /**
280 * Edit item in the cart
281 *
282 * @param string $uuid
283 * @param array $new_data
284 *
285 * @return array Updated item data or empty array if item not found
286 */
287 public function edit_cart_item( string $uuid, array $new_data ): array {
288 if ( ! is_user_logged_in() ) {
289 Cart_Session::edit_item( $uuid, $new_data );
290 $cart = Cart_Session::get();
291 foreach ( $cart['items'] as $item ) {
292 if ( $item['uuid'] === $uuid ) {
293 return $item;
294 }
295 }
296
297 return array();
298 }
299
300 $user_id = get_current_user_id();
301 $carts = $this->db->select(
302 $this->carts_table, array(
303 'user_id' => $user_id,
304 )
305 );
306
307 $cart = count( $carts ) ? $carts[0] : null;
308
309 if ( ! $cart ) {
310 return array();
311 }
312
313 // Only allow known, editable columns from client input. This prevents
314 // arbitrary request-body keys from reaching the SQL UPDATE clause
315 // the list via the filter below.
316 $allowed_columns = apply_filters(
317 'booktics_cart_item_editable_columns',
318 array(
319 'date',
320 'start_time',
321 'end_time',
322 'service_id',
323 'team_member_id',
324 'price',
325 'subtotal',
326 'total',
327 'additional_duration_id',
328 'extra_services',
329 'group_booking',
330 'time_format',
331 'location_id',
332 )
333 );
334
335 $cart_item_data = array_intersect_key( $new_data, array_flip( $allowed_columns ) );
336 $cart_item_data['uuid'] = $uuid;
337 $cart_item_data['updated_at'] = current_time( 'mysql' );
338 $cart_item_data = apply_filters( 'booktics_pro_cart_db', $cart_item_data, $new_data );
339 $this->db->update(
340 $this->cart_items_table, $cart_item_data,
341 array(
342 'cart_id' => $cart->id,
343 'uuid' => $uuid,
344 )
345 );
346
347 $this->update_cart_total( $cart->id );
348
349 $updated_item = $this->db->select(
350 $this->cart_items_table, array(
351 'cart_id' => $cart->id,
352 'uuid' => $uuid,
353 )
354 );
355
356 foreach ( $updated_item as $i => $item ) {
357 if ( isset( $item->extra_services ) ) {
358 $item->extra_services = json_decode( $item->extra_services, true );
359 }
360 }
361
362 return count( $updated_item ) ? (array) $updated_item[0] : array();
363 }
364 }
365