PluginProbe
Timetics – Appointment Booking Calendar & Scheduling / 1.0.21
Timetics – Appointment Booking Calendar & Scheduling v1.0.21
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 / booking.php

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

967 lines 22.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Booking Class
4 *
5 * @package Timetics
6 */
7
8 namespace Timetics\Core\Bookings;
9
10 use Timetics\Core\Appointments\Appointment;
11 use Timetics\Core\Customers\Customer;
12 use Timetics\Core\Integrations\Google\Service\Calendar;
13 use Timetics\Core\Staffs\Staff;
14 use TimeticsEvent\Core\Event_Bookings\Event_Booking;
15 use TimeticsEvent\Core\Events\Event;
16 use WP_Query;
17
18 /**
19 * Class Booking
20 */
21 class Booking {
22 /**
23 * Store booking post type
24 *
25 * @var string
26 */
27 protected $pos_type = 'timetics-booking';
28
29 /**
30 * Store booking meta prefix
31 *
32 * @var string
33 */
34 protected $meta_prefix = '_tt_booking_';
35
36 /**
37 * Store booking id
38 *
39 * @var string
40 */
41 protected $id;
42
43 /**
44 * Store appointment object
45 *
46 * @var Object
47 */
48 protected $appointment;
49
50 /**
51 * Store appointment object
52 *
53 * @var Object
54 */
55 protected $event;
56
57 /**
58 * Store booking data
59 *
60 * @var array
61 */
62 protected $data = [
63
64 'post_status' => '',
65 'customer' => '',
66 'appointment' => '',
67 'appointment_name' => '',
68 'staff' => '',
69 'speaker' => '',
70 'event' => '',
71 'location' => '',
72 'description' => '',
73 'location_type' => '',
74 'payment_method' => '',
75 'payment_status' => '',
76 'payment_details' => '',
77 'order_total' => '',
78 'start_date' => '',
79 'end_date' => '',
80 'start_time' => '',
81 'end_time' => '',
82 'calendar_event' => '',
83 'random_id' => '',
84 'seats' => '',
85 'guests' => '',
86 'zoom' => '',
87 'custom_form_data' => '',
88 'timezone' => '',
89 'recurrence' => [],
90 'parent' => 0,
91 'cancel_reason' => '',
92 'custom_location_url' => '',
93 ];
94
95 /**
96 * Booking Constructor
97 *
98 * @return void
99 */
100 public function __construct( $booking = 0 ) {
101 if ( $booking instanceof self ) {
102 $this->set_id( $booking->get_id() );
103 } elseif ( ! empty( $booking->ID ) ) {
104 $this->set_id( $booking->ID );
105 } elseif ( is_numeric( $booking ) && $booking > 0 ) {
106 $this->set_id( $booking );
107 }
108 }
109
110 /**
111 * Get id
112 *
113 * @return integer
114 */
115 public function get_id() {
116 return $this->id;
117 }
118
119 /**
120 * Get customer id
121 *
122 * @return integer
123 */
124 public function get_customer_id() {
125 return $this->get_prop( 'customer' );
126 }
127
128 /**
129 * Get attendee id
130 *
131 * @return integer
132 */
133 public function get_attendees() {
134 $attendees = $this->get_prop( 'attendees' );
135 return $attendees ? $attendees : [];
136 }
137
138 /**
139 * Get custom url
140 *
141 * @return string
142 */
143 public function get_custom_location_url() {
144 $custom_url = $this->get_prop( 'custom_location_url' );
145 return $custom_url ? $custom_url : '';
146 }
147
148 /**
149 * Get staff for the current booking
150 *
151 * @return integer
152 */
153 public function get_staff_id() {
154 return $this->get_prop( 'staff' );
155 }
156
157 /**
158 * Get speaker id
159 *
160 * @return integer
161 */
162 public function get_speaker_id() {
163 return $this->get_prop( 'speaker' );
164 }
165
166 /**
167 * Get booking type
168 *
169 * @return string
170 */
171 public function get_type() {
172 return $this->get_prop( 'type' );
173 }
174
175 /**
176 * Get event id
177 *
178 * @return integer
179 */
180 public function get_event_id() {
181 return $this->get_prop( 'event' );
182 }
183
184 /**
185 * Get customer
186 *
187 * @return User Object
188 */
189 public function get_customer() {
190 return get_userdata( $this->get_customer_id() );
191 }
192
193 /**
194 * Get seats of a booking
195 *
196 * @return array
197 */
198 public function get_seat() {
199 return $this->get_prop( 'seats' );
200 }
201
202 /**
203 * Get guests
204 *
205 * @return array
206 */
207 public function get_guests() {
208 return $this->get_prop( 'guests' );
209 }
210
211 /**
212 * Get custom fields
213 *
214 * @return array
215 */
216 public function get_custom_fields() {
217 return $this->get_prop( 'custom_form_data' );
218 }
219
220 /**
221 * Get billing first name
222 *
223 * @return string
224 */
225 public function get_billing_first_name() {
226 return $this->get_prop( 'first_name' );
227 }
228
229 /**
230 * Get location
231 *
232 * @return string
233 */
234 public function get_location() {
235 return $this->get_prop( 'location' );
236 }
237
238 /**
239 * Get location type
240 *
241 * @return string
242 */
243 public function get_location_type() {
244 return $this->get_prop( 'location_type' );
245 }
246
247 /**
248 * Get booking time
249 *
250 * @return string
251 */
252 public function get_booking_time() {
253 return $this->get_prop( 'booking_time' );
254 }
255
256 /**
257 * Get last name
258 *
259 * @return string
260 */
261 public function get_billing_last_name() {
262 return $this->get_prop( 'last_name' );
263 }
264
265 /**
266 * Get email
267 *
268 * @return string
269 */
270 public function get_billing_email() {
271 return $this->get_prop( 'email' );
272 }
273
274 /**
275 * Get billing phone
276 *
277 * @return string
278 */
279 public function get_billing_phone() {
280 return $this->get_prop( 'phone' );
281 }
282
283 /**
284 * Get timezone
285 *
286 * @return string
287 */
288 public function get_timezone() {
289 return $this->get_prop( 'timezone' );
290 }
291
292 /**
293 * Get description
294 *
295 * @return string
296 */
297 public function get_description() {
298 return $this->get_prop( 'description' );
299 }
300
301 /**
302 * Get billing address
303 *
304 * @param string $adress_type Booking billing address
305 *
306 * @return string
307 */
308 public function get_billing_address( $adress_type = 'address_1' ) {
309 return $this->get_prop( $adress_type );
310 }
311
312 /**
313 * Get billing city
314 *
315 * @return string
316 */
317 public function get_billing_city() {
318 return $this->get_prop( 'city' );
319 }
320
321 /**
322 * Get billing state
323 *
324 * @return string
325 */
326 public function get_billing_state() {
327 return $this->get_prop( 'state' );
328 }
329
330 /**
331 * Get billing post code
332 *
333 * @return string
334 */
335 public function get_billing_post_code() {
336 return $this->get_prop( 'post_code' );
337 }
338
339 /**
340 * Get billing
341 *
342 * @return string
343 */
344 public function get_billing_country() {
345 return $this->get_prop( 'country' );
346 }
347
348 /**
349 * Get payment method
350 *
351 * @return string
352 */
353 public function get_payment_method() {
354 return $this->get_prop( 'payment_method' );
355 }
356
357 /**
358 * Get appointment
359 *
360 * @return Appointment
361 */
362 public function get_appointment() {
363 return $this->get_prop( 'appointment' );
364 }
365
366 /**
367 * Get appointment name
368 *
369 * @return string
370 */
371 public function get_appointment_name() {
372 return $this->get_prop( 'appointment_name' );
373 }
374
375 /**
376 * Get calendar event
377 *
378 * @return array
379 */
380 public function get_event() {
381 return $this->get_prop( 'calendar_event' );
382 }
383
384 /**
385 * Get post status
386 *
387 * @return string
388 */
389 public function get_status() {
390 return get_post( $this->id )->post_status;
391 }
392
393 /**
394 * Get total
395 *
396 * @return integer
397 */
398 public function get_total() {
399 return $this->get_prop( 'order_total' );
400 }
401
402 /**
403 * Get start date
404 *
405 * @return string
406 */
407 public function get_start_date() {
408 return $this->get_prop( 'start_date' );
409 }
410 /**
411 * Get start date
412 *
413 * @return string
414 */
415 public function get_date() {
416 return $this->get_prop( 'date' );
417 }
418
419 /**
420 * Get end date
421 *
422 * @return string
423 */
424 public function get_end_date() {
425 return $this->get_prop( 'end_date' );
426 }
427
428 /**
429 * Get start time
430 *
431 * @return string
432 */
433 public function get_start_time() {
434 return $this->get_prop( 'start_time' );
435 }
436
437 /**
438 * Get end time
439 *
440 * @return string
441 */
442 public function get_end_time() {
443 return $this->get_prop( 'end_time' );
444 }
445
446 /**
447 * Get random id for the current booking
448 *
449 * @return string
450 */
451 public function get_random_id() {
452 return $this->get_prop( 'random_id' );
453 }
454
455 /**
456 * Get payment details
457 *
458 * @return array
459 */
460 public function get_payment_details() {
461 return $this->get_prop( 'payment_details' );
462 }
463
464 /**
465 * Get zoom meeting details
466 *
467 * @return array
468 */
469 public function get_zoom() {
470 return $this->get_prop( 'zoom' );
471 }
472
473 /**
474 * Get recurrences
475 *
476 * @return array
477 */
478 public function get_recurrence() {
479 return $this->get_prop( 'recurrence' );
480 }
481
482 /**
483 * Get parent
484 *
485 * @return integer
486 */
487 public function get_parent() {
488 return $this->get_prop( 'parent' );
489 }
490
491 /**
492 * Get booking cancel reason
493 *
494 * @return integer
495 */
496 public function get_cancel_reason() {
497 return $this->get_prop( 'cancel_reason' );
498 }
499
500 /**
501 * Get booking data
502 *
503 * @param string $prop
504 *
505 * @return mixed
506 */
507 private function get_prop( $prop = '' ) {
508 return $this->get_metadata( $prop );
509 }
510
511 /**
512 * Get metadata
513 *
514 * @param string $prop
515 *
516 * @return mixed
517 */
518 private function get_metadata( $prop = '' ) {
519 $meta_key = $this->meta_prefix . $prop;
520
521 return get_post_meta( $this->id, $meta_key, true );
522 }
523
524 /**
525 * Generate random id
526 *
527 * @return string
528 */
529 private function generate_randon_id() {
530 return chr( rand( ord( 'A' ), ord( 'Z' ) ) ) . rand( 575639, 575639 + 400 );
531 }
532
533 // Setter.
534
535 /**
536 * Set booking id
537 *
538 * @param integer $id
539 *
540 * @return void
541 */
542 public function set_id( $id ) {
543 $this->id = $id;
544 }
545
546 /**
547 * Set data
548 *
549 * @param array $args Booking Args
550 *
551 * @return void
552 */
553 public function set_props( $args = [] ) {
554 $this->data = wp_parse_args( $args, $this->data );
555 $this->appointment = new Appointment( $this->data['appointment'] );
556 if ( isset( $this->data['type'] ) && 'timetics-event' == $this->data['type'] ) {
557 $this->event = new Event( $this->data['event'] );
558 }
559
560 }
561
562 /**
563 * Save metada for booking
564 *
565 * @return void
566 */
567 public function save_metadata( $args = [] ) {
568 foreach ( $args as $key => $value ) {
569
570 // If a key not exists on data it will skip to save the data.
571 if ( ! array_key_exists( $key, $this->data ) ) {
572 continue;
573 }
574
575 // Prepare meta key.
576 $meta_key = $this->meta_prefix . $key;
577
578 if ( ! $value ) {
579 $value = $this->get_prop( $key );
580 }
581
582 // Update appointment meta data.
583 update_post_meta( $this->id, $meta_key, $value );
584 }
585 }
586
587 /**
588 * Save appointment
589 *
590 * @return void
591 */
592 public function save( $type = '' ) {
593 $args = [
594 'post_title' => $this->appointment->get_name(),
595 'post_type' => $this->pos_type,
596 'post_status' => $this->data['post_status'],
597 'post_author' => get_current_user_id(),
598 ];
599
600 if ( 'timetics-event' == $type ) {
601 $args = [
602 'post_title' => $this->event->get_name(),
603 'post_type' => $this->pos_type,
604 'post_status' => $this->data['post_status'],
605 'post_author' => get_current_user_id(),
606 ];
607 }
608
609 $updated = false;
610
611 if ( ! empty( $this->id ) ) {
612 $this->send_notification( 'update' );
613 $args['ID'] = $this->id;
614 $updated = true;
615 }
616
617 // Insert or Update appointment.
618 $booking_id = wp_insert_post( $args );
619 $this->data['random_id'] = $this->generate_randon_id();
620 $this->data = apply_filters( 'timetics/event/booking/all_data', $this->data);
621
622 if ( ! is_wp_error( $booking_id ) ) {
623 $this->set_id( $booking_id );
624 $this->save_metadata( $this->data );
625 }
626
627 if ( ! $updated ) {
628 $this->send_notification( 'create' );
629 }
630 }
631
632 /**
633 * Update booking
634 *
635 * @param array $args
636 *
637 * @return bool
638 */
639 public function update( $args = [] ) {
640 $post = get_post( $this->id )->to_array();
641 $args = wp_parse_args( $args, $post );
642
643 $updated = wp_update_post( $args );
644
645 if ( ! is_wp_error( $updated ) ) {
646 $this->save_metadata( $args );
647 }
648
649 return $updated;
650 }
651
652 /**
653 * Delete booking
654 *
655 * @return bool | WP_Error
656 */
657 public function delete() {
658 // Set action for sending notification.
659 $this->send_notification( 'delete' );
660
661 return wp_delete_post( $this->id, true );
662 }
663
664 /**
665 * Check is a booking or not
666 *
667 * @return bool
668 */
669 public function is_booking() {
670 $post = get_post( $this->id );
671
672 if ( $post && $this->pos_type === $post->post_type ) {
673 return true;
674 }
675
676 return false;
677 }
678
679 /**
680 * Get all bookings
681 *
682 * @param array $args Bookings args
683 *
684 * @return array
685 */
686 public static function all( $args = [] ) {
687
688 $status = [
689 'approved',
690 'pending',
691 'cancel',
692 'completed',
693 ];
694 $defaults = [
695 'post_type' => 'timetics-booking',
696 'posts_per_page' => 20,
697 'post_status' => 'any',
698 'paged' => 1,
699 ];
700
701 $args = wp_parse_args( $args, $defaults );
702
703 $args = apply_filters( 'timetics/admin/bookings/all', $defaults, $args);
704
705 if ( ! empty( $args['start_date'] ) ) {
706 //_tt_booking_start_date
707 $args['meta_query'] = [
708 [
709 'key' => '_tt_booking_start_date',
710 'value' => $args['start_date'],
711 'compare' => '>=',
712 'type' => 'DATE',
713 ],
714 ];
715 }
716
717 if ( ! empty( $args['meeting'] ) ) {
718 // @codingStandardsIgnoreStart
719 $args['meta_query'] = [
720 [
721 'key' => '_tt_booking_appointment',
722 'value' => $args['meeting'],
723 'compare' => '=',
724 ],
725 ];
726 // @codingStandardsIgnoreEnd
727 }
728
729 if ( ! empty( $args['staff'] ) ) {
730 // @codingStandardsIgnoreStart
731 $args['meta_query'] = [
732 [
733 'key' => '_tt_booking_staff',
734 'value' => $args['staff'],
735 'compare' => '=',
736 ],
737 ];
738 // @codingStandardsIgnoreEnd
739 }
740
741 $post = new WP_Query( $args );
742
743 return [
744 'total' => $post->found_posts,
745 'items' => $post->posts,
746 ];
747 }
748
749 /**
750 * Create event after creating a booking
751 *
752 * @return bool
753 */
754 public function create_event() {
755
756 if ( ! timetics_google_setup() ) {
757 return;
758 }
759
760 if ('timetics-event' == $this->get_type()) {
761 Event_Booking::instance()->create_online_event($this->get_id());
762 }else {
763 $this->create_appointment_event();
764 }
765
766 }
767
768 public function create_appointment_event() {
769 $data = [
770 'summary' => timetics_get_option( 'booking_created_customer_email_title' ),
771 'description' => timetics_get_option( 'booking_created_customer_email_body' ),
772 ];
773
774 $calendar = new Calendar();
775 $event_data = $this->prepare_event( $data );
776
777 if ( ! $event_data ) {
778 return;
779 }
780
781 $booking_entry = new Booking_Entry();
782 $meeting = new Appointment( $this->get_appointment() );
783
784 $date_time = timetics_convert_timezone( $this->get_start_date() .' '. $this->get_start_time(), $this->get_timezone(), $meeting->get_timezone() );
785
786 $entries = $booking_entry->find(
787 [
788 'staff_id' => $this->get_staff_id(),
789 'meeting_id' => $this->get_appointment(),
790 'date' => $date_time->format('Y-m-d'),
791 'start' => $date_time->format('h:i a'),
792 ]
793 );
794
795 if ( $entries ) {
796 $entry = $booking_entry->first();
797
798 $event = $entry->get_google_event();
799
800 if ( ! $event ) {
801 $event = $calendar->create_event( $event_data );
802 $entry->update( [
803 'google_event' => $event,
804 ] );
805 }
806 }
807
808 if ( $event ) {
809 update_post_meta( $this->id, $this->meta_prefix . 'calendar_event', $event );
810 }
811 }
812
813 /**
814 * Update calendar event
815 *
816 * @return bool
817 */
818 public function update_event() {
819 if ( ! timetics_google_setup() ) {
820 return;
821 }
822
823 $data = [
824 'summary' => timetics_get_option( 'booking_rescheduled_customer_email_title' ),
825 'description' => timetics_get_option( 'booking_rescheduled_customer_email_body' ),
826 ];
827
828 $calendar = new Calendar();
829 $event_data = $this->prepare_event( $data );
830 $calendar_event = $this->get_event();
831
832 if ( ! is_array( $calendar_event ) ) {
833 return;
834 }
835
836 if ( ! empty( $calendar_event['id'] ) ) {
837 // Update calendar event.
838 $event = $calendar->update_event( $calendar_event['id'], $event_data );
839
840 // update calendar event data.
841 update_post_meta( $this->id, $this->meta_prefix . 'calendar_event', $event );
842 }
843 }
844
845 /**
846 * Delete calendar event
847 *
848 * @return
849 */
850 public function delete_event() {
851 if ( ! timetics_google_setup() ) {
852 return;
853 }
854
855 $calendar = new Calendar();
856 $calendar_event = $this->get_event();
857 $access_token = timetics_get_google_access_token( $this->get_staff_id() );
858
859 if ( ! is_array( $calendar_event ) ) {
860 return;
861 }
862
863 if ( ! $access_token ) {
864 return;
865 }
866
867 if ( ! empty( $calendar_event['id'] ) ) {
868 // Update calendar event.
869 $event = $calendar->delete_event( $calendar_event['id'], $access_token );
870
871 // update calendar event data.
872 update_post_meta( $this->id, $this->meta_prefix . 'calendar_event', $event );
873 }
874 }
875
876 /**
877 * Prepare event data
878 *
879 * @return array
880 */
881 private function prepare_event( $data = [] ) {
882
883 $meeting_id = $this->get_appointment();
884 $staff_id = $this->get_staff_id();
885 $customer_id = $this->get_customer_id();
886 $location_type = $this->get_location_type();
887 $access_token = timetics_get_google_access_token( $staff_id );
888
889 if ( ! $access_token ) {
890 return false;
891 }
892
893 $meeting = new Appointment( $meeting_id );
894 $staff = new Staff( $staff_id );
895 $customer = new Customer( $customer_id );
896
897 $time = gmdate( 'h:i a', strtotime( $this->get_start_time() ) );
898 $date = gmdate( 'd F Y', strtotime( $this->get_start_date() ) );
899 $location = $this->get_location();
900
901 $placeholders = [
902 '{%meeting_title%}' => $meeting->get_name(),
903 '{%meeting_date%}' => $date,
904 '{%meeting_time%}' => $time,
905 '{%meeting_location%}' => $location,
906 '{%meeting_duration%}' => $meeting->get_duration(),
907 '{%host_name%}' => $staff->get_display_name(),
908 '{%host_email%}' => $staff->get_email(),
909 '{%customer_name%}' => $customer->get_display_name(),
910 '{%customer_email%}' => $customer->get_email(),
911 ];
912
913 $summary = ! empty( $data['summary'] ) ? timetics_replace_placeholder( $data['summary'], $placeholders ) : $meeting->get_name();
914 $description = ! empty( $data['description'] ) ? timetics_replace_placeholder( $data['description'], $placeholders ) : $meeting->get_description();
915
916 $description = apply_filters( 'timetics_booking_event_data', $description, $summary, $this );
917
918 $event = [
919 'summary' => $summary,
920 'description' => $description,
921 'start' => [
922 'date' => $this->get_start_date(),
923 'time' => $this->get_start_time(),
924 ],
925 'end' => [
926 'date' => $this->get_end_date(),
927 'time' => $this->get_end_time(),
928 ],
929 'attendees' => [
930 ['email' => $staff->get_email()],
931 ['email' => $customer->get_email()],
932 ],
933 'timezone' => $this->get_timezone(),
934 'google_meet' => 'google-meet' === $location_type,
935 'access_token' => $access_token,
936 ];
937
938 return $event;
939 }
940
941 /**
942 * Get all data of an object
943 *
944 * @return array
945 */
946 public function to_array() {
947 $data = [];
948
949 foreach ( $this->data as $key => $value ) {
950
951 $data[$key] = $this->get_prop( $key );
952 }
953
954 return $data;
955 }
956
957 /**
958 * Send notification after booking
959 *
960 * @return void
961 */
962 private function send_notification( $action ) {
963
964 do_action( 'timetics_booking_notification', $this, $action );
965 }
966 }
967