PluginProbe
Timetics – Appointment Booking Calendar & Scheduling / 1.0.0
Timetics – Appointment Booking Calendar & Scheduling v1.0.0
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 1.0.23 1.0.24 All 62 releases
timetics / core / bookings / api-booking.php

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

692 lines 23.7 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'] ) : 'publish';
519 $location = ! empty( $data['location'] ) ? sanitize_text_field( $data['location'] ) : '';
520 $location_type = ! empty( $data['location_type'] ) ? sanitize_text_field( $data['location_type'] ) : '';
521 $action = $id ? 'updated' : 'created';
522
523 $validate = $this->validate(
524 $data, [
525 'first_name',
526 'email',
527 'payment_method',
528 'appointment',
529 'start_date',
530 'start_time',
531 'end_time',
532 ]
533 );
534
535 if ( is_wp_error( $validate ) ) {
536 $data = [
537 'status_code' => 403,
538 'success' => 0,
539 'message' => $validate->get_error_messages(),
540 ];
541 return new WP_HTTP_Response( $data, 403 );
542 }
543
544 $customer = new Customer();
545 $meeting = new Appointment( $appointment );
546 $staff = new Staff( $staff );
547 $customer->make(
548 [
549 'first_name' => $first_name,
550 'last_name' => $last_name,
551 'email' => $email,
552 'phone' => $phone,
553 ]
554 );
555
556 $booking = new Booking( $id );
557 $booking_entry = new Booking_Entry();
558
559 $booking->set_props(
560 [
561 'customer' => $customer->get_id(),
562 'appointment' => $meeting->get_id(),
563 'staff' => $staff->get_id(),
564 'customer_fname' => $customer->get_first_name(),
565 'customer_lname' => $customer->get_last_name(),
566 'customer_email' => $customer->get_email(),
567 'customer_phone' => $customer->get_phone(),
568 'staff_fname' => $staff->get_first_name(),
569 'staff_lname' => $staff->get_last_name(),
570 'staff_email' => $staff->get_email(),
571 'meeting_name' => $meeting->get_name(),
572 'meeting_description' => $meeting->get_description(),
573 'meeting_type' => $meeting->get_type(),
574 'start_date' => $start_date,
575 'date' => $date,
576 'end_date' => $end_date,
577 'start_time' => $start_time,
578 'end_time' => $end_time,
579 'order_total' => $order_total,
580 'post_status' => $status,
581 'location' => $location,
582 'location_type' => $location_type
583 ]
584 );
585
586 $booking->save();
587
588 // Create or update calendar event.
589 if ( $id ) {
590 $booking->update_event();
591 } else {
592 $booking->create_event();
593 $new_event_email = new New_Event_Email( $booking );
594 $new_event_email->send();
595 }
596
597 // Create booking schedule.
598 $entries = $booking_entry->find(
599 [
600 'staff_id' => $staff->get_id(),
601 'meeting_id' => $meeting->get_id(),
602 'date' => $start_date,
603 'start' => $start_time,
604 ]
605 );
606
607 if ( $entries ) {
608 $entry = $booking_entry->first();
609 $booked = intval( $entry->get_booked() ) + 1;
610 $entry->update( [ 'booked' => $booked ] );
611 } else {
612 $booking_entry->create(
613 [
614 'meeting_id' => $meeting->get_id(),
615 'staff_id' => $staff->get_id(),
616 'customer_id' => $customer->get_id(),
617 'booking_id' => $booking->get_id(),
618 'booked' => 1,
619 'date' => $start_date,
620 'start' => $start_time,
621 'end' => $end_time,
622 ]
623 );
624 }
625
626 $data = [
627 'success' => 1,
628 'status_code' => 200,
629 /* translators: Action */
630 'message' => sprintf( __( 'Successfully %s booking', 'timetics' ), $action ),
631 'data' => $this->prepare_item( $booking ),
632 ];
633
634 return new WP_HTTP_Response( $data, 200 );
635 }
636
637 /**
638 * Prepare item for response
639 *
640 * @param integer $booking_id
641 *
642 * @return array
643 */
644 public function prepare_item( $booking_id ) {
645 $booking = new Booking( $booking_id );
646 $appointment = new Appointment( $booking->get_appointment() );
647 $staff = new Staff( $booking->get_staff_id() );
648 $customer = new Customer( $booking->get_customer_id() );
649
650 $start_date = gmdate( 'd F, Y', strtotime( $booking->get_start_date() ) );
651 $end_date = gmdate( 'd F, Y', strtotime( $booking->get_end_date() ) );
652 $date = gmdate( 'd F, Y', strtotime( $booking->get_date() ) );
653
654 return [
655 'id' => $booking->get_id(),
656 'random_id' => $booking->get_random_id(),
657 'status' => $booking->get_status(),
658 'order_total' => $booking->get_total(),
659 'start_date' => $start_date,
660 'end_date' => $end_date,
661 'date' => $date,
662 'start_time' => $booking->get_start_time(),
663 'end_time' => $booking->get_end_time(),
664 'customer' => [
665 'id' => $customer->get_id(),
666 'full_name' => $customer->get_display_name(),
667 'first_name' => $customer->get_first_name(),
668 'last_name' => $customer->get_last_name(),
669 'email' => $customer->get_email(),
670 ],
671 'appointment' => [
672 'id' => $appointment->get_id(),
673 'name' => $appointment->get_name(),
674 'duration' => $appointment->get_duration(),
675 'type' => $appointment->get_type(),
676 'price' => $appointment->get_price(),
677 'locations' => $appointment->get_locations(),
678 'timezone' => $appointment->get_timezone(),
679 ],
680 'staff' => [
681 'id' => $staff->get_id(),
682 'full_name' => $staff->get_display_name(),
683 'first_name' => $staff->get_first_name(),
684 'last_name' => $staff->get_last_name(),
685 'email_name' => $staff->get_email(),
686 'phone' => $staff->get_phone(),
687 'image' => $staff->get_image(),
688 ],
689 ];
690 }
691 }
692