PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.28
Booktics – Appointment Booking Calendar for Service Businesses v1.0.28
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
← All changes | core/customer/controllers/customer-controller.php +333 -155 1.0.3 → 1.0.28 View file →
@@ -7,8 +7,9 @@
7 7 use Booktics\Abstracts\User_Model;
8 8 use Booktics\Customer\Handlers\Customer_Event_Handler;
9 9 use Booktics\Models\Appointment_Model;
10 10 use Booktics\Models\Customer_Model;
11 +use Booktics\Models\Guest_Model;
11 12 use Booktics\Models\Order_Model;
12 13 use Booktics\Models\Payment_Model;
13 14 use WP_Error;
14 15 use WP_HTTP_Response;
@@ -43,64 +44,103 @@
43 44 */
44 45 public function register_routes(): void {
45 46 register_rest_route(
46 47 $this->namespace, $this->base, array(
47 - array(
48 - 'methods' => WP_REST_Server::CREATABLE,
49 - 'callback' => array( $this, 'create_item' ),
50 - 'permission_callback' => array(
51 - $this,
52 - 'create_customer_permission',
53 - ),
54 - ),
55 - array(
56 - 'methods' => WP_REST_Server::READABLE,
57 - 'callback' => array( $this, 'get_items' ),
58 - 'permission_callback' => array(
59 - $this,
60 - 'get_customer_permission',
61 - ),
62 - ),
63 - array(
64 - 'methods' => WP_REST_Server::DELETABLE,
65 - 'callback' => array( $this, 'delete_items' ),
66 - 'permission_callback' => array(
67 - $this,
68 - 'delete_customer_permission',
69 - ),
70 - ),
48 + array(
49 + 'methods' => WP_REST_Server::CREATABLE,
50 + 'callback' => array( $this, 'create_item' ),
51 + 'permission_callback' => array(
52 + $this,
53 + 'create_customer_permission',
54 + ),
55 + ),
56 + array(
57 + 'methods' => WP_REST_Server::READABLE,
58 + 'callback' => array( $this, 'get_items' ),
59 + 'permission_callback' => array(
60 + $this,
61 + 'get_customer_permission',
62 + ),
63 + ),
64 + array(
65 + 'methods' => WP_REST_Server::DELETABLE,
66 + 'callback' => array( $this, 'delete_items' ),
67 + 'permission_callback' => array(
68 + $this,
69 + 'delete_customer_permission',
70 + ),
71 + ),
71 72 )
72 73 );
73 74
74 75 register_rest_route(
76 + $this->namespace, $this->base . '/profile', array(
77 + array(
78 + 'methods' => WP_REST_Server::READABLE,
79 + 'callback' => array( $this, 'get_profile' ),
80 + 'permission_callback' => array(
81 + $this,
82 + 'customer_profile_permission',
83 + ),
84 + ),
85 + )
86 + );
87 +
88 + register_rest_route(
75 89 $this->namespace, '/' . $this->base . '/(?P<id>[\d]+)', array(
76 - array(
77 - 'methods' => WP_REST_Server::EDITABLE,
78 - 'callback' => array( $this, 'update_item' ),
79 - 'permission_callback' => array(
80 - $this,
81 - 'update_customer_permission',
82 - ),
83 - 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
84 - ),
85 - array(
86 - 'methods' => WP_REST_Server::DELETABLE,
87 - 'callback' => array( $this, 'delete_item' ),
88 - 'permission_callback' => array(
89 - $this,
90 - 'delete_customer_permission',
91 - ),
92 - ),
93 - array(
94 - 'method' => WP_REST_Server::READABLE,
95 - 'callback' => array( $this, 'get_item' ),
96 - 'permission_callback' => array(
97 - $this,
98 - 'get_customer_permission',
99 - ),
100 - ),
90 + array(
91 + 'methods' => WP_REST_Server::EDITABLE,
92 + 'callback' => array( $this, 'update_item' ),
93 + 'permission_callback' => array(
94 + $this,
95 + 'update_customer_permission',
96 + ),
97 + 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
98 + ),
99 + array(
100 + 'methods' => WP_REST_Server::DELETABLE,
101 + 'callback' => array( $this, 'delete_item' ),
102 + 'permission_callback' => array(
103 + $this,
104 + 'delete_customer_permission',
105 + ),
106 + ),
107 + array(
108 + 'method' => WP_REST_Server::READABLE,
109 + 'callback' => array( $this, 'get_item' ),
110 + 'permission_callback' => array(
111 + $this,
112 + 'get_customer_permission',
113 + ),
114 + ),
101 115 )
102 116 );
117 +
118 + register_rest_route(
119 + $this->namespace, '/' . $this->base . '/(?P<id>[\d]+)/connect', array(
120 + array(
121 + 'methods' => WP_REST_Server::EDITABLE,
122 + 'callback' => array( $this, 'connect_customer' ),
123 + 'permission_callback' => array(
124 + $this,
125 + 'update_customer_permission',
126 + ),
127 + ),
128 + )
129 + );
130 +
131 + register_rest_route(
132 + $this->namespace, '/' . $this->base . '/(?P<id>[\d]+)/disconnect', array(
133 + array(
134 + 'methods' => WP_REST_Server::EDITABLE,
135 + 'callback' => array( $this, 'disconnect_customer' ),
136 + 'permission_callback' => array(
137 + $this,
138 + 'update_customer_permission',
139 + ),
140 + ),
141 + )
142 + );
103 143 }
104 144
105 145 /**
106 146 * Check if a given request has access to create items.
@@ -107,9 +147,9 @@
107 147 *
108 148 * @param $request Full data about the request.
109 149 */
110 150 public function create_customer_permission( $request ) {
111 - return true;
151 + return current_user_can( 'manage_options' );
112 152 }
113 153
114 154 /**
115 155 * Prepare and validate customer data
@@ -122,15 +162,15 @@
122 162 $input_data = json_decode( $request->get_body(), true );
123 163
124 164 $validate = booktics_validate(
125 165 $input_data, array(
126 - 'first_name' => array(
127 - 'required',
128 - ),
129 - 'email' => array(
130 - 'required',
131 - 'unique:wp_users,email',
132 - ),
166 + 'name' => array(
167 + 'required',
168 + ),
169 + 'email' => array(
170 + 'required',
171 + 'unique:' . booktics_get_table_name( 'booktics_guests' ) . ',email',
172 + ),
133 173 )
134 174 );
135 175
136 176 if ( is_wp_error( $validate ) ) {
@@ -137,15 +177,12 @@
137 177 return $validate;
138 178 }
139 179
140 180 return array(
141 - 'first_name' => $input_data['first_name'],
142 - 'last_name' => $input_data['last_name'],
143 - 'user_email' => $input_data['email'],
181 + 'name' => $input_data['name'],
182 + 'email' => $input_data['email'],
144 183 'user_login' => User_Model::generate_username( $input_data['email'] ),
145 184 'phone' => $input_data['phone'],
146 - 'email' => $input_data['email'],
147 - 'status' => 'pending',
148 185 );
149 186 }
150 187
151 188 /**
@@ -165,25 +202,21 @@
165 202 $prepared_data->errors
166 203 );
167 204 }
168 205
169 - $customer = new Customer_Model();
170 - $created = $customer->save( $prepared_data );
171 -
206 + $db = new Booktics_Database();
207 + $customer = ( new Guest_Model( $db ) )->create( $prepared_data );
172 208 $image_url = $request->get_param( 'image' );
173 209 if ( $image_url ) {
174 210 $customer->update( array( 'image' => esc_url_raw( $image_url ) ) );
175 211 }
176 212
177 - if ( ! $created ) {
213 + if ( ! $customer ) {
178 214 return $this->error( __( 'Customer create error', 'booktics' ), 500 );
179 215 }
180 216
181 217 do_action( 'booktics_customer_created', $customer, $request );
182 218
183 - ( new Customer_Event_Handler() )->on_customer_create( $created );
184 - $customer = $customer->find( $created );
185 -
186 219 return $this->response( $customer, __( 'Successfully created customer', 'booktics' ), 201 );
187 220 }
188 221
189 222 /**
@@ -193,9 +226,36 @@
193 226 *
194 227 * @return bool
195 228 */
196 229 public function get_customer_permission( $request ) {
197 - return true;
230 + if ( current_user_can( 'manage_options' ) ) {
231 + return true;
232 + }
233 +
234 + if ( is_user_logged_in() ) {
235 + $current_user = wp_get_current_user();
236 +
237 + if ( in_array( 'booktics_team_member', (array) $current_user->roles, true ) ) {
238 + return true;
239 + }
240 +
241 + $requested_customer_id = isset( $request['id'] ) ? intval( $request['id'] ) : 0;
242 +
243 + if ( $requested_customer_id > 0 ) {
244 + $db = new Booktics_Database();
245 + $requested_customer = ( new Guest_Model( $db ) )->find( array( 'id' => $requested_customer_id ) );
246 +
247 + if ( $requested_customer && intval( $requested_customer->wp_user_id ) === get_current_user_id() ) {
248 + return true;
249 + }
250 + }
251 + }
252 +
253 + return new WP_Error(
254 + 'booktics_forbidden',
255 + __( 'You are not allowed to view this customer data.', 'booktics' ),
256 + array( 'status' => 403 )
257 + );
198 258 }
199 259
200 260 /**
201 261 * Get paginated list items for customer
@@ -206,54 +266,47 @@
206 266 */
207 267 public function get_items( $request ) {
208 268 $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
209 269 $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
210 - $first_name = ! empty( $request['first_name'] ) ? trim( $request['first_name'] ) : '';
211 - $last_name = ! empty( $request['last_name'] ) ? trim( $request['last_name'] ) : '';
212 - $email = ! empty( $request['email'] ) ? trim( $request['email'] ) : '';
213 - $phone = ! empty( $request['phone'] ) ? trim( $request['phone'] ) : '';
214 - $user_name = ! empty( $request['user_name'] ) ? trim( $request['user_name'] ) : '';
215 - $search = ! empty( $request['search'] ) ? trim( $request['search'] ) : '';
270 + $name = ! empty( $request['name'] ) ? sanitize_text_field( $request['name'] ) : '';
271 + $email = ! empty( $request['email'] ) ? sanitize_email( $request['email'] ) : '';
272 + $phone = ! empty( $request['phone'] ) ? sanitize_text_field( $request['phone'] ) : '';
273 + $user_name = ! empty( $request['user_name'] ) ? sanitize_text_field( $request['user_name'] ) : '';
274 + $search = ! empty( $request['search'] ) ? sanitize_text_field( $request['search'] ) : '';
216 275
217 - $customers = ( new Customer_Model() )
218 - ->when(
219 - $first_name, function ( $q, $v ) {
220 - $q->where( 'first_name', $v, 'LIKE' );
221 - }
222 - )
223 - ->when(
224 - $last_name, function ( $q, $v ) {
225 - $q->where( 'last_name', $v, 'LIKE' );
226 - }
227 - )
228 - ->when(
229 - $email, function ( $q, $v ) {
230 - $q->where( 'user_email', $v, 'LIKE' );
231 - }
232 - )
233 - ->when(
234 - $phone, function ( $q, $v ) {
235 - $q->where( 'phone', $v, 'LIKE' );
236 - }
237 - )
238 - ->when(
239 - $user_name, function ( $q, $v ) {
240 - $q->where( 'user_login', 'LIKE', $v, 'LIKE' );
241 - }
242 - )
243 - ->when(
244 - $search, function ( $q, $v ) {
245 - $q->where( 'first_name', $v, 'LIKE' )
246 - ->or_where( 'last_name', $v, 'LIKE' )
247 - ->or_where( 'phone', $v, 'LIKE' );
248 - }
249 - )->all(
250 - array(
251 - 'paged' => $paged,
252 - 'number' => $per_page,
253 - )
254 - );
276 + $db = new Booktics_Database();
277 + $customers = ( new Guest_Model( $db ) )->query();
255 278
279 + $args = array(
280 + 'name' => array( 'LIKE', $name ),
281 + 'email' => array( 'LIKE', $email ),
282 + 'phone' => array( 'LIKE', $phone ),
283 + 'user_login' => array( 'LIKE', $user_name ),
284 + );
285 +
286 + foreach ( $args as $key => $value ) {
287 + if ( $value[1] ) {
288 + $customers->where( $key, $value[0], $value[1] );
289 + }
290 + }
291 +
292 + if ( $search ) {
293 + $customers->where( 'name', 'LIKE', $search )
294 + ->or_where( 'email', 'LIKE', $search )
295 + ->or_where( 'phone', 'LIKE', $search );
296 + }
297 +
298 + $customers = $customers->paginate( $paged, $per_page );
299 + foreach ( $customers['items'] as &$customer ) {
300 + $customer = ( new Guest_Model( $db ) )->with_virtual_attributes( $customer );
301 +
302 + // Mask wp_user_id and user_login from non-admins (use empty string instead of unset for API consistency)
303 + if ( ! current_user_can( 'manage_options' ) ) {
304 + $customer->wp_user_id = '';
305 + $customer->user_login = '';
306 + }
307 + }
308 +
256 309 return $this->response( $customers, __( 'Successfully fetched customer', 'booktics' ) );
257 310 }
258 311
259 312 /**
@@ -263,9 +316,9 @@
263 316 *
264 317 * @return bool
265 318 */
266 319 public function delete_customer_permission( $request ) {
267 - return true;
320 + return current_user_can( 'manage_options' );
268 321 }
269 322
270 323 /**
271 324 * Delete a customer
@@ -276,19 +329,19 @@
276 329 */
277 330 public function delete_item( $request ) {
278 331 $id = intval( $request['id'] );
279 332
280 - $db = new Booktics_Database();
333 + $db = new Booktics_Database();
281 334 $order_model = new Order_Model( $db );
282 - $orders = $order_model->get( array( 'customer_id' => $id ) );
335 + $orders = $order_model->get( array( 'customer_id' => $id ) );
283 336 foreach ( $orders['items'] as $order ) {
284 337 $appointment_model = new Appointment_Model();
285 - $appointments = $appointment_model->where( 'order_id', $order->id );
338 + $appointments = $appointment_model->where( 'order_id', $order->id );
286 339 foreach ( $appointments as $appointment ) {
287 340 $appointment->delete();
288 341 }
289 342 $payment_model = new Payment_Model( $db );
290 - $payments = $payment_model->get( array( 'order_id' => $order->id ) );
343 + $payments = $payment_model->get( array( 'order_id' => $order->id ) );
291 344 foreach ( $payments['items'] as $payment ) {
292 345 ( new Payment_Model( $db ) )->delete( $payment->id );
293 346 }
294 347 $order_model->delete( $order->id );
@@ -293,12 +346,17 @@
293 346 }
294 347 $order_model->delete( $order->id );
295 348 }
296 349
297 - $customer = new Customer_Model( $id );
298 - $previous = $customer->find( $id );
299 - $deleted = $customer->delete();
350 + $guest_model = ( new Guest_Model( $db ) );
351 + $guest = $guest_model->find( array( 'id' => $id ) );
300 352
353 + if ( $guest->wp_user_id ) {
354 + $customer = new Customer_Model( $guest->wp_user_id );
355 + $customer->delete();
356 + }
357 +
358 + $deleted = $guest_model->delete( $id );
301 359 if ( ! $deleted ) {
302 360 return $this->error( __( 'Customer delete error', 'booktics' ), 500 );
303 361 }
304 362
@@ -303,9 +361,9 @@
303 361 }
304 362
305 363 do_action( 'booktics_customers_deleted', $request );
306 364
307 - return $this->response( $previous, __( 'Successfully deleted customer', 'booktics' ) );
365 + return $this->response( array(), __( 'Successfully deleted customer', 'booktics' ) );
308 366 }
309 367
310 368 /**
311 369 * Delete multiple customer
@@ -324,19 +382,19 @@
324 382 $db = new Booktics_Database();
325 383 foreach ( $ids as $id ) {
326 384 // Delete all orders (and their related appointments and payments) for this customer
327 385 $order_model = new Order_Model( $db );
328 - $orders = $order_model->get( array( 'customer_id' => $id ) );
386 + $orders = $order_model->get( array( 'customer_id' => $id ) );
329 387 foreach ( $orders['items'] as $order ) {
330 388 // Delete related appointments
331 389 $appointment_model = new Appointment_Model();
332 - $appointments = $appointment_model->where( 'order_id', $order->id );
390 + $appointments = $appointment_model->where( 'order_id', $order->id );
333 391 foreach ( $appointments as $appointment ) {
334 392 $appointment->delete();
335 393 }
336 394 // Delete related payments
337 395 $payment_model = new Payment_Model( $db );
338 - $payments = $payment_model->get( array( 'order_id' => $order->id ) );
396 + $payments = $payment_model->get( array( 'order_id' => $order->id ) );
339 397 foreach ( $payments['items'] as $payment ) {
340 398 ( new Payment_Model( $db ) )->delete( $payment->id );
341 399 }
342 400 // Delete the order
@@ -341,14 +399,19 @@
341 399 }
342 400 // Delete the order
343 401 $order_model->delete( $order->id );
344 402 }
345 - $customer = new Customer_Model( $id );
346 - if ( $customer->delete() ) {
403 + $guest_model = ( new Guest_Model( $db ) );
404 + $guest = $guest_model->find( array( 'id' => $id ) );
405 + if ( $guest->wp_user_id ) {
406 + $customer = new Customer_Model( $guest->wp_user_id );
407 + $customer->delete();
408 + }
409 + if ( $guest_model->delete( $id ) ) {
347 410 ++$count;
348 411 }
349 412 }
350 - if ( $count == 0 ) {
413 + if ( 0 == $count ) {
351 414 return $this->error( __( 'Customer delete error', 'booktics' ), 500 );
352 415 }
353 416
354 417 do_action( 'booktics_customers_deleted', $request );
@@ -364,31 +427,35 @@
364 427 * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response
365 428 */
366 429 public function get_item( $request ) {
367 430 $id = intval( $request['id'] );
368 - $customer = new Customer_Model( $id );
369 - $customer = $customer->find( $id );
431 + $db = new Booktics_Database();
432 + $customer = ( new Guest_Model( $db ) )->find( array( 'id' => $id ) );
370 433 if ( ! $customer ) {
371 434 return $this->error( __( 'Customer not found', 'booktics' ), 404 );
372 435 }
373 436
374 - $db = new Booktics_Database();
375 - $orders = ( new Order_Model( $db ) )->get( array( 'customer_id' => $id ) );
376 - $customer_data = $customer->to_array();
377 - $customer_data['orders'] = array_map(
437 + $orders = ( new Order_Model( $db ) )->get( array( 'customer_id' => $id ) );
438 + $customer->orders = array_map(
378 439 function ( $order ) {
379 440 $booking_count = ( new Appointment_Model() )
380 - ->get_appointments_count_by_order_id( $order->id );
441 + ->get_appointments_count_by_order_id( $order->id );
381 442
382 443 return array(
383 - 'date' => $order->created_at ? gmdate( 'j F, Y', strtotime( $order->created_at ) ) : '',
384 - 'total_booking' => $booking_count,
385 - 'total_amount' => $order->total,
444 + 'date' => $order->created_at ? gmdate( 'j F, Y', strtotime( $order->created_at ) ) : '',
445 + 'total_booking' => $booking_count,
446 + 'total_amount' => $order->total,
386 447 );
387 448 }, $orders['items']
388 449 );
389 450
390 - return $this->response( $customer_data, __( 'Customer found successfully', 'booktics' ) );
451 + // Mask wp_user_id and user_login from non-admins (use empty string instead of unset for API consistency)
452 + if ( ! current_user_can( 'manage_options' ) ) {
453 + $customer->wp_user_id = '';
454 + $customer->user_login = '';
455 + }
456 +
457 + return $this->response( $customer, __( 'Customer found successfully', 'booktics' ) );
391 458 }
392 459
393 460 /**
394 461 * Checks if a given request has access to update a customer.
@@ -397,9 +464,9 @@
397 464 *
398 465 * @return bool True if the request has access to update the item, WP_Error object otherwise.
399 466 */
400 467 public function update_customer_permission( $request ) {
401 - return true;
468 + return current_user_can( 'manage_options' );
402 469 }
403 470
404 471 /**
405 472 * Prepare data for customer update
@@ -408,9 +475,10 @@
408 475 *
409 476 * @return array|bool|WP_Error
410 477 */
411 478 public function prepare_customer_update( $request ) {
412 - $input_data = json_decode( $request->get_body(), true );
479 + $input_data = json_decode( $request->get_body(), true );
480 +
413 481 $validation_rules = array(
414 482 'first_name' => array(
415 483 'required',
416 484 ),
@@ -415,9 +483,9 @@
415 483 'required',
416 484 ),
417 485 'email' => array(
418 486 'required',
419 - 'unique:wp_users,email,' . $request['id'],
487 + 'unique:' . booktics_get_table_name( 'booktics_guests' ) . ',email,' . $request['id'],
420 488 ),
421 489 );
422 490 $update_validation_rules = array();
423 491 $validated_data = array();
@@ -429,13 +497,8 @@
429 497 );
430 498 }
431 499
432 500 foreach ( $input_data as $key => $value ) {
433 - if ( $key == 'email' ) {
434 - $update_validation_rules[ $key ] = $validation_rules[ $key ];
435 - $validated_data['user_email'] = sanitize_email( $value );
436 - continue;
437 - }
438 501 $validated_data[ $key ] = $value;
439 502 }
440 503
441 504 $validate = booktics_validate( $input_data, $update_validation_rules );
@@ -442,9 +505,8 @@
442 505
443 506 if ( is_wp_error( $validate ) ) {
444 507 return $validate;
445 508 }
446 - $validated_data['status'] = 'active';
447 509
448 510 return $validated_data;
449 511 }
450 512
@@ -454,9 +516,9 @@
454 516 * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response
455 517 */
456 518 public function update_item( $request ) {
457 519 if ( ! isset( $request['id'] ) ) {
458 - return $this->error( 'Invalid team member id', 400 );
520 + return $this->error( 'Invalid customer id', 400 );
459 521 }
460 522 $prepared_data = $this->prepare_customer_update( $request );
461 523
462 524 if ( is_wp_error( $prepared_data ) ) {
@@ -462,21 +524,137 @@
462 524 if ( is_wp_error( $prepared_data ) ) {
463 525 return $this->error( __( 'Customer validation error', 'booktics' ), 422, 'Validation', $prepared_data->errors );
464 526 }
465 527
466 - $customer = new Customer_Model( $request['id'] );
467 - $updated = $customer->update( $prepared_data );
528 + $db = new Booktics_Database();
529 + $customer = ( new Guest_Model( $db ) )->update( $request['id'], $prepared_data );
468 530 $image_url = $request->get_param( 'image' );
469 531 if ( $image_url ) {
470 - $customer->update( array( 'image' => esc_url_raw( $image_url ) ) );
532 + ( new Guest_Model( $db ) )->update( $request['id'], array( 'image' => esc_url_raw( $image_url ) ) );
533 + ( new Guest_Model( $db ) )->update( absint( $request['id'] ), array( 'image' => esc_url_raw( $image_url ) ) );
471 534 }
472 535
473 - if ( ! $updated ) {
536 + if ( ! $customer ) {
474 537 return $this->error( __( 'Customer update error', 'booktics' ), 500 );
475 538 }
476 539
477 540 do_action( 'booktics_customer_updated', $customer, $request );
478 - $customer = $customer->find( $request['id'] );
541 + $customer = ( new Guest_Model( $db ) )->find( array( 'id' => $request['id'] ) );
479 542
480 543 return $this->response( $customer, __( 'Successfully updated customer', 'booktics' ) );
544 + }
545 +
546 + /**
547 + * Check if a given request has access to get customer profile.
548 + *
549 + * @param $request
550 + *
551 + * @return bool
552 + */
553 + public function customer_profile_permission( $request ) {
554 + if ( is_user_logged_in() ) {
555 + return true;
556 + }
557 +
558 + return new WP_Error(
559 + 'booktics_unauthorized',
560 + __( 'You must be logged in to view your profile.', 'booktics' ),
561 + array( 'status' => 401 )
562 + );
563 + }
564 +
565 + /**
566 + * Get customer profile
567 + *
568 + * @param $request
569 + *
570 + * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response
571 + */
572 + public function get_profile( $request ) {
573 + $user_id = get_current_user_id();
574 + $db = new Booktics_Database();
575 + $customer = ( new Guest_Model( $db ) )->find( array( 'wp_user_id' => $user_id ) );
576 + $args = array(
577 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Meta query is necessary for filtering customers by meta fields
578 + 'meta_query' => array(
579 + array(
580 + 'key' => 'customer_id',
581 + 'value' => $customer->id,
582 + 'compare' => '=',
583 + ),
584 + ),
585 + );
586 +
587 + $appointments = ( new Appointment_Model() )->all( $args );
588 + $customer->appointments = $appointments;
589 +
590 + return $this->response( $customer, __( 'Successfully fetched customer profile', 'booktics' ) );
591 + }
592 +
593 + /**
594 + * Connect a guest to a customer
595 + *
596 + * @param $request
597 + *
598 + * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response
599 + */
600 + public function connect_customer( $request ) {
601 + $id = intval( $request['id'] );
602 + $db = new Booktics_Database();
603 + $guest = ( new Guest_Model( $db ) )->find( array( 'id' => $id ) );
604 +
605 + if ( ! $guest ) {
606 + return $this->error( __( 'Customer not found', 'booktics' ), 404 );
607 + }
608 +
609 + if ( $guest->wp_user_id ) {
610 + return $this->error( __( 'Customer already connected', 'booktics' ), 400 );
611 + }
612 +
613 + $customer_model = ( new Customer_Model() );
614 + $customer_id = $customer_model->save(
615 + array(
616 + 'user_login' => $guest->user_login,
617 + 'user_email' => $guest->email,
618 + 'first_name' => $guest->first_name ?? '',
619 + 'last_name' => $guest->last_name ?? '',
620 + 'display_name' => $guest->display_name ?? '',
621 + 'phone' => $guest->phone ?? '',
622 + )
623 + );
624 +
625 + if ( is_wp_error( $customer_id ) ) {
626 + return $this->error( __( 'Customer create error', 'booktics' ), 500 );
627 + }
628 + ( new Customer_Event_Handler() )->on_customer_create( $customer_id );
629 +
630 + ( new Guest_Model( $db ) )->update( $id, array( 'wp_user_id' => $customer_id ) );
631 + $guest = ( new Guest_Model( $db ) )->find( array( 'id' => $id ) );
632 + return $this->response( $guest, __( 'Successfully connected customer', 'booktics' ) );
633 + }
634 +
635 +
636 + /**
637 + * Disconnect a guest from a customer
638 + *
639 + * @param $request
640 + *
641 + * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response
642 + */
643 + public function disconnect_customer( $request ) {
644 + $id = intval( $request['id'] );
645 + $db = new Booktics_Database();
646 + $guest = ( new Guest_Model( $db ) )->find( array( 'id' => $id ) );
647 +
648 + if ( ! $guest ) {
649 + return $this->error( __( 'Customer not found', 'booktics' ), 404 );
650 + }
651 + if ( $guest->wp_user_id ) {
652 + $customer = new Customer_Model( $guest->wp_user_id );
653 + $customer->delete();
654 + }
655 +
656 + ( new Guest_Model( $db ) )->update( $id, array( 'wp_user_id' => null ) );
657 + $guest = ( new Guest_Model( $db ) )->find( array( 'id' => $id ) );
658 + return $this->response( $guest, __( 'Successfully disconnected customer', 'booktics' ) );
481 659 }
482 660 }