PluginProbe
Timetics – Appointment Booking Calendar & Scheduling / 1.0.1
Timetics – Appointment Booking Calendar & Scheduling v1.0.1
1.0.62 1.0.63 1.0.61 1.0.60 1.0.59 1.0.58 1.0.57 1.0.56 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.19 1.0.2 1.0.20 1.0.21 1.0.22 All 64 releases
timetics / core / bookings / api-booking.php

api-booking.php in Timetics – Appointment Booking Calendar & Scheduling 1.0.1, at core/bookings/api-booking.php

697 lines 24.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Booking api
4 *
5 * @package Timetics
6 */
7 namespace Timetics\Core\Bookings;
8
9 use Timetics\Base\Api;
10 use Timetics\Core\Appointments\Appointment;
11 use Timetics\Core\Customers\Customer;
12 use Timetics\Core\Emails\New_Event_Email;
13 use Timetics\Core\Staffs\Staff;
14 use Timetics\Utils\Singleton;
15 use WP_HTTP_Response;
16 use WP_Query;
17
18 class Api_Booking extends Api {
19 use Singleton;
20
21 /**
22 * Store api namespace
23 *
24 * @var string
25 */
26 protected $namespace = 'timetics/v1';
27
28 /**
29 * Store rest base
30 *
31 * @var string
32 */
33 protected $rest_base = 'bookings';
34
35 /**
36 * Register rest routes
37 *
38 * @return void
39 */
40 public function register_routes() {
41 /**
42 * Register route
43 *
44 * @var void
45 */
46 register_rest_route(
47 $this->namespace, $this->rest_base, [
48 [
49 'methods' => \WP_REST_Server::READABLE,
50 'callback' => [$this, 'get_items'],
51 'permission_callback' => function () {
52 return current_user_can( 'manage_timetics' );
53 },
54 ],
55 [
56 'methods' => \WP_REST_Server::CREATABLE,
57 'callback' => [$this, 'create_item'],
58 'permission_callback' => function () {
59 return true;
60 },
61 ],
62 [
63 'methods' => \WP_REST_Server::DELETABLE,
64 'callback' => [$this, 'bulk_delete'],
65 'permission_callback' => function () {
66 return current_user_can( 'edit_booking' );
67 },
68 ],
69 ]
70 );
71
72 /**
73 * Register route
74 *
75 * @var void
76 */
77 register_rest_route(
78 $this->namespace, '/' . $this->rest_base . '/(?P<booking_id>[\d]+)', [
79 [
80 'methods' => \WP_REST_Server::READABLE,
81 'callback' => [$this, 'get_item'],
82 'permission_callback' => function () {
83 return current_user_can( 'manage_timetics' );
84 },
85 ],
86 [
87 'methods' => \WP_REST_Server::EDITABLE,
88 'callback' => [$this, 'update_item'],
89 'permission_callback' => function () {
90 return true;
91 },
92 ],
93 [
94 'methods' => \WP_REST_Server::DELETABLE,
95 'callback' => [$this, 'delete_item'],
96 'permission_callback' => function () {
97 return current_user_can( 'edit_booking' );
98 },
99 ],
100 ]
101 );
102
103 register_rest_route(
104 $this->namespace, '/' . $this->rest_base . '/(?P<booking_id>[\d]+)/payment', [
105 [
106 'methods' => \WP_REST_Server::EDITABLE,
107 'callback' => [$this, 'make_payment'],
108 'permission_callback' => function () {
109 return true;
110 },
111 ],
112 ]
113 );
114
115 register_rest_route(
116 $this->namespace, $this->rest_base . '/search', [
117 [
118 'methods' => \WP_REST_Server::READABLE,
119 'callback' => [$this, 'search_items'],
120 'permission_callback' => function () {
121 return current_user_can( 'edit_posts' );
122 },
123 ],
124 ]
125 );
126
127 register_rest_route(
128 $this->namespace, $this->rest_base . '/entries', [
129 [
130 'methods' => \WP_REST_Server::READABLE,
131 'callback' => [$this, 'get_entries'],
132 'permission_callback' => function () {
133 return true;
134 },
135 ],
136 ]
137 );
138 }
139
140 /**
141 * Get all bookings
142 *
143 * @param WP_Rest_Request $request
144 *
145 * @return JSON
146 */
147 public function get_items( $request ) {
148 $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
149 $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
150 $meeting_id = ! empty( $request['meeting_id'] ) ? intval( $request['meeting_id'] ) : 0;
151 $staff_id = ! current_user_can( 'edit_booking' ) ? get_current_user_id() : 0;
152
153 $args = [
154 'posts_per_page' => $per_page,
155 'paged' => $paged,
156 'meeting' => $meeting_id,
157 'staff' => $staff_id,
158 ];
159 $appoint = Booking::all( $args );
160
161 $items = [];
162
163 foreach ( $appoint['items'] as $item ) {
164 $items[] = $this->prepare_item( $item->ID );
165 }
166
167 $data = [
168 'success' => 1,
169 'status_code' => 200,
170 'data' => [
171 'total' => $appoint['total'],
172 'items' => $items,
173 ],
174 ];
175
176 return rest_ensure_response( $data );
177 }
178
179 /**
180 * Get single booking
181 *
182 * @param WP_Rest_Request $request
183 *
184 * @return JSON
185 */
186 public function get_item( $request ) {
187 $booking_id = (int) $request['booking_id'];
188 $booking = new Booking( $booking_id );
189
190 if ( ! $booking->is_booking() ) {
191 return [
192 'success' => 0,
193 'status_code' => 404,
194 'message' => __( 'Invalid booking id.', 'timetics' ),
195 'data' => [],
196 ];
197 }
198
199 $data = [
200 'success' => 1,
201 'status_code' => 200,
202 'data' => $this->prepare_item( $booking ),
203 ];
204
205 return rest_ensure_response( $data );
206 }
207
208 /**
209 * Create booking
210 *
211 * @param WP_Rest_Request $request
212 *
213 * @return JSON
214 */
215 public function create_item( $request ) {
216 return $this->save_bookings( $request );
217 }
218
219 /**
220 * Update booking
221 *
222 * @param WP_Rest_Request $request
223 *
224 * @return JSON
225 */
226 public function update_item( $request ) {
227 $booking_id = (int) $request['booking_id'];
228 $booking = new Booking( $booking_id );
229
230 if ( ! $booking->is_booking() ) {
231 return [
232 'status_code' => 404,
233 'message' => __( 'Invalid booking id.', 'timetics' ),
234 'data' => [],
235 ];
236 }
237
238 return $this->save_bookings( $request, $booking_id );
239 }
240
241 /**
242 * Delete booking
243 *
244 * @param WP_Rest_Request $request
245 *
246 * @return JSON
247 */
248 public function delete_item( $request ) {
249 $booking_id = (int) $request['booking_id'];
250 $booking = new Booking( $booking_id );
251
252 if ( ! $booking->is_booking() ) {
253 return [
254 'status_code' => 404,
255 'message' => __( 'Invalid booking id.', 'timetics' ),
256 'data' => [],
257 ];
258 }
259
260 $booking->delete_event();
261 $booking->delete();
262
263 $data = [
264 'success' => 1,
265 'status_code' => 200,
266 'message' => __( 'Successfully deleted booking', 'timetics' ),
267 'data' => [],
268 ];
269
270 return rest_ensure_response( $data );
271 }
272
273 /**
274 * Delete multiples
275 *
276 * @param WP_Rest_Request $request
277 *
278 * @return JSON
279 */
280 public function bulk_delete( $request ) {
281 $bookings = json_decode( $request->get_body(), true );
282
283 foreach ( $bookings as $booking ) {
284 $booking = new Booking( $booking );
285
286 if ( ! $booking->is_booking() ) {
287 return [
288 'success' => 0,
289 'status_code' => 404,
290 'message' => __( 'Invalid booking id.', 'timetics' ),
291 'data' => [],
292 ];
293 }
294
295 $booking->delete();
296 }
297
298 return [
299 'success' => 1,
300 'status_code' => 200,
301 'message' => __( 'Successfully deleted booking', 'timetics' ),
302 ];
303 }
304
305 /**
306 * Search bookings
307 *
308 * @param WP_Rest_Request $request
309 *
310 * @return JSON
311 */
312 public function search_items( $request ) {
313 // Prepare search args.
314 $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
315 $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
316 $search = ! empty( $request['search'] ) ? sanitize_text_field( $request['search'] ) : '';
317
318 // Get search.
319 $booking = new WP_Query(
320 array(
321 'post_type' => 'timetics-booking',
322 'posts_per_page' => $per_page,
323 'paged' => $paged,
324 'post_status' => 'any',
325
326 // @codingStandardsIgnoreStart
327 'meta_query' => array(
328 'relation' => 'OR',
329 array(
330 'key' => '_tt_booking_customer_fname',
331 'value' => $search,
332 'compare' => 'LIKE',
333 ),
334 array(
335 'key' => '_tt_booking_customer_lname',
336 'value' => $search,
337 'compare' => 'LIKE',
338 ),
339 array(
340 'key' => '_tt_booking_customer_email',
341 'value' => $search,
342 'compare' => 'LIKE',
343 ),
344 array(
345 'key' => '_tt_booking_customer_phone',
346 'value' => $search,
347 'compare' => 'LIKE',
348 ),
349 array(
350 'key' => '_tt_booking_staff_fname',
351 'value' => $search,
352 'compare' => 'LIKE',
353 ),
354 array(
355 'key' => '_tt_booking_staff_lname',
356 'value' => $search,
357 'compare' => 'LIKE',
358 ),
359 array(
360 'key' => '_tt_booking_staff_email',
361 'value' => $search,
362 'compare' => 'LIKE',
363 ),
364 array(
365 'key' => '_tt_booking_meeting_name',
366 'value' => $search,
367 'compare' => 'LIKE',
368 ),
369 array(
370 'key' => '_tt_booking_meeting_description',
371 'value' => $search,
372 'compare' => 'LIKE',
373 ),
374 array(
375 'key' => '_tt_booking_meeting_type',
376 'value' => $search,
377 'compare' => 'LIKE',
378 ),
379 ),
380 // @codingStandardsIgnoreEnd
381 )
382 );
383
384 // Prepare items for response.
385 $items = [];
386
387 foreach ( $booking->posts as $item ) {
388 $items[] = $this->prepare_item( $item->ID );
389 }
390
391 $data = [
392 'success' => 1,
393 'status' => 200,
394 'data' => [
395 'total' => $booking->found_posts,
396 'items' => $items,
397 ],
398 ];
399
400 return rest_ensure_response( $data );
401 }
402
403 /**
404 * Get all booking entries
405 *
406 * @param WP_Rest_Request $request
407 *
408 * @return JSON
409 */
410 public function get_entries( $request ) {
411 $staff_id = ! empty( $request['staff_id'] ) ? intval( $request['staff_id'] ) : 0;
412 $meeting_id = ! empty( $request['meeting_id'] ) ? intval( $request['meeting_id'] ) : 0;
413 $start_date = ! empty( $request['start_date'] ) ? sanitize_text_field( $request['start_date'] ) : 0;
414 $end_date = ! empty( $request['end_date'] ) ? sanitize_text_field( $request['end_date'] ) : 0;
415
416 $meeting = new Appointment( $meeting_id );
417
418 $days = $meeting->prepare_schedule( $start_date, $end_date, $staff_id );
419
420 $data = [
421 'today' => gmdate( 'Y-m-d' ),
422 'availability_timezone' => $meeting->get_timezone(),
423 'days' => $days,
424 ];
425
426 return [
427 'success' => true,
428 'status_code' => 200,
429 'message' => __( 'Get all entries', 'timetics' ),
430 'data' => $data,
431 ];
432 }
433
434 /**
435 * Make payment transaction for the current booking
436 *
437 * @param WP_Rest_Request $request
438 *
439 * @return JSON
440 */
441 public function make_payment( $request ) {
442 $booking_id = intval( $request['booking_id'] );
443 $booking = new Booking( $booking_id );
444 $data = json_decode( $request->get_body(), true );
445 $status = ! empty( $data['status'] ) ? sanitize_text_field( $data['status'] ) : '';
446 $post_status = 'succeeded' === $status ? 'completed' : 'pending';
447 $payment_method = ! empty( $data['payment_method'] ) ? sanitize_text_field( $data['payment_method'] ) : '';
448 $payment_details = ! empty( $data['payment_details'] ) ? $data['payment_details'] : '';
449
450 if ( ! $booking->is_booking() ) {
451 return [
452 'status_code' => 404,
453 'message' => __( 'Invalid booking id.', 'timetics' ),
454 'data' => [],
455 ];
456 }
457
458 $update = $booking->update(
459 [
460 'post_status' => $post_status,
461 'payment_status' => $status,
462 'payment_details' => $payment_details,
463 'payment_method' => $payment_method,
464 ]
465 );
466
467 if ( is_wp_error( $update ) ) {
468 $data = [
469 'success' => 0,
470 'status_code' => 409,
471 /* translators: Action */
472 'message' => $update->get_error_message(),
473 ];
474
475 return new WP_HTTP_Response( $data, 409 );
476 }
477
478 $data = [
479 'success' => 1,
480 'status_code' => 200,
481 /* translators: Action */
482 'message' => sprintf( __( 'Payment %s', 'timetics' ), $post_status ),
483 ];
484
485 return new WP_HTTP_Response( $data, 200 );
486 }
487
488 /**
489 * Save booking
490 *
491 * @param WP_Rest_Request $request
492 * @param integer $id Booking id
493 *
494 * @return JSON
495 */
496 public function save_bookings( $request, $id = 0 ) {
497 $data = json_decode( $request->get_body(), true );
498
499 $first_name = ! empty( $data['first_name'] ) ? sanitize_text_field( $data['first_name'] ) : '';
500 $last_name = ! empty( $data['last_name'] ) ? sanitize_text_field( $data['last_name'] ) : '';
501 $email = ! empty( $data['email'] ) ? sanitize_text_field( $data['email'] ) : '';
502 $phone = ! empty( $data['phone'] ) ? sanitize_text_field( $data['phone'] ) : '';
503 $city = ! empty( $data['city'] ) ? sanitize_text_field( $data['city'] ) : '';
504 $state = ! empty( $data['state'] ) ? sanitize_text_field( $data['state'] ) : '';
505 $post_code = ! empty( $data['post_code'] ) ? sanitize_text_field( $data['post_code'] ) : '';
506 $country = ! empty( $data['country'] ) ? sanitize_text_field( $data['country'] ) : '';
507 $payment_method = ! empty( $data['payment_method'] ) ? sanitize_text_field( $data['payment_method'] ) : '';
508 $address_1 = ! empty( $data['address_1'] ) ? sanitize_text_field( $data['address_1'] ) : '';
509 $address_2 = ! empty( $data['address_2'] ) ? sanitize_text_field( $data['address_2'] ) : '';
510 $appointment = ! empty( $data['appointment'] ) ? intval( $data['appointment'] ) : 0;
511 $staff = ! empty( $data['staff'] ) ? intval( $data['staff'] ) : 0;
512 $start_date = ! empty( $data['start_date'] ) ? sanitize_text_field( $data['start_date'] ) : '';
513 $date = ! empty( $data['date'] ) ? sanitize_text_field( $data['date'] ) : '';
514 $end_date = ! empty( $data['end_date'] ) ? sanitize_text_field( $data['end_date'] ) : $start_date;
515 $start_time = ! empty( $data['start_time'] ) ? sanitize_text_field( $data['start_time'] ) : '';
516 $end_time = ! empty( $data['end_time'] ) ? sanitize_text_field( $data['end_time'] ) : '';
517 $order_total = ! empty( $data['order_total'] ) ? intval( $data['order_total'] ) : 0;
518 $status = ! empty( $data['status'] ) ? sanitize_text_field( $data['status'] ) : timetics_get_option( 'default_booking_status' );
519 $location = ! empty( $data['location'] ) ? sanitize_text_field( $data['location'] ) : '';
520 $location_type = ! empty( $data['location_type'] ) ? sanitize_text_field( $data['location_type'] ) : '';
521 $description = ! empty( $data['description'] ) ? sanitize_text_field( $data['description'] ) : '';
522 $action = $id ? 'updated' : 'created';
523
524 $validate = $this->validate(
525 $data, [
526 'first_name',
527 'email',
528 'payment_method',
529 'appointment',
530 'start_date',
531 'start_time',
532 'end_time',
533 ]
534 );
535
536 if ( is_wp_error( $validate ) ) {
537 $data = [
538 'status_code' => 403,
539 'success' => 0,
540 'message' => $validate->get_error_messages(),
541 ];
542 return new WP_HTTP_Response( $data, 403 );
543 }
544
545 $customer = new Customer();
546 $meeting = new Appointment( $appointment );
547 $staff = new Staff( $staff );
548 $customer->make(
549 [
550 'first_name' => $first_name,
551 'last_name' => $last_name,
552 'email' => $email,
553 'phone' => $phone,
554 ]
555 );
556
557 $booking = new Booking( $id );
558 $booking_entry = new Booking_Entry();
559
560 $booking->set_props(
561 [
562 'customer' => $customer->get_id(),
563 'appointment' => $meeting->get_id(),
564 'staff' => $staff->get_id(),
565 'customer_fname' => $customer->get_first_name(),
566 'customer_lname' => $customer->get_last_name(),
567 'customer_email' => $customer->get_email(),
568 'customer_phone' => $customer->get_phone(),
569 'staff_fname' => $staff->get_first_name(),
570 'staff_lname' => $staff->get_last_name(),
571 'staff_email' => $staff->get_email(),
572 'meeting_name' => $meeting->get_name(),
573 'meeting_description' => $meeting->get_description(),
574 'meeting_type' => $meeting->get_type(),
575 'description' => $description,
576 'start_date' => $start_date,
577 'date' => $date,
578 'end_date' => $end_date,
579 'start_time' => $start_time,
580 'end_time' => $end_time,
581 'order_total' => $order_total,
582 'post_status' => $status,
583 'location' => $location,
584 'location_type' => $location_type,
585 ]
586 );
587
588 $booking->save();
589
590 // Create or update calendar event.
591 if ( $id ) {
592 $booking->update_event();
593 } else {
594 $booking->create_event();
595 $new_event_email = new New_Event_Email( $booking );
596 $new_event_email->send();
597 }
598
599 // Create booking schedule.
600 $entries = $booking_entry->find(
601 [
602 'staff_id' => $staff->get_id(),
603 'meeting_id' => $meeting->get_id(),
604 'date' => $start_date,
605 'start' => $start_time,
606 ]
607 );
608
609 if ( $entries ) {
610 $entry = $booking_entry->first();
611 $booked = intval( $entry->get_booked() ) + 1;
612 $entry->update( ['booked' => $booked] );
613 } else {
614 $booking_entry->create(
615 [
616 'meeting_id' => $meeting->get_id(),
617 'staff_id' => $staff->get_id(),
618 'customer_id' => $customer->get_id(),
619 'booking_id' => $booking->get_id(),
620 'booked' => 1,
621 'date' => $start_date,
622 'start' => $start_time,
623 'end' => $end_time,
624 ]
625 );
626 }
627
628 $data = [
629 'success' => 1,
630 'status_code' => 200,
631 /* translators: Action */
632 'message' => sprintf( __( 'Successfully %s booking', 'timetics' ), $action ),
633 'data' => $this->prepare_item( $booking ),
634 ];
635
636 return new WP_HTTP_Response( $data, 200 );
637 }
638
639 /**
640 * Prepare item for response
641 *
642 * @param integer $booking_id
643 *
644 * @return array
645 */
646 public function prepare_item( $booking_id ) {
647 $booking = new Booking( $booking_id );
648 $appointment = new Appointment( $booking->get_appointment() );
649 $staff = new Staff( $booking->get_staff_id() );
650 $customer = new Customer( $booking->get_customer_id() );
651
652 $start_date = gmdate( 'd F, Y', strtotime( $booking->get_start_date() ) );
653 $end_date = gmdate( 'd F, Y', strtotime( $booking->get_end_date() ) );
654 $date = gmdate( 'd F, Y', strtotime( $booking->get_date() ) );
655
656 return [
657 'id' => $booking->get_id(),
658 'random_id' => $booking->get_random_id(),
659 'status' => $booking->get_status(),
660 'order_total' => $booking->get_total(),
661 'start_date' => $start_date,
662 'end_date' => $end_date,
663 'date' => $date,
664 'start_time' => $booking->get_start_time(),
665 'end_time' => $booking->get_end_time(),
666 'location' => $booking->get_location(),
667 'location_type' => $booking->get_location_type(),
668 'description' => $booking->get_description(),
669 'customer' => [
670 'id' => $customer->get_id(),
671 'full_name' => $customer->get_display_name(),
672 'first_name' => $customer->get_first_name(),
673 'last_name' => $customer->get_last_name(),
674 'email' => $customer->get_email(),
675 ],
676 'appointment' => [
677 'id' => $appointment->get_id(),
678 'name' => $appointment->get_name(),
679 'duration' => $appointment->get_duration(),
680 'type' => $appointment->get_type(),
681 'price' => $appointment->get_price(),
682 'locations' => $appointment->get_locations(),
683 'timezone' => $appointment->get_timezone(),
684 ],
685 'staff' => [
686 'id' => $staff->get_id(),
687 'full_name' => $staff->get_display_name(),
688 'first_name' => $staff->get_first_name(),
689 'last_name' => $staff->get_last_name(),
690 'email_name' => $staff->get_email(),
691 'phone' => $staff->get_phone(),
692 'image' => $staff->get_image(),
693 ],
694 ];
695 }
696 }
697