| @@ -10,8 +10,10 @@ | ||
| 10 | 10 | use Timetics\Core\Appointments\Appointment; |
| 11 | 11 | use Timetics\Core\Customers\Customer; |
| 12 | 12 | use Timetics\Core\Integrations\Google\Service\Calendar; |
| 13 | 13 | use Timetics\Core\Staffs\Staff; |
| 14 | +use TimeticsEvent\Core\Event_Bookings\Event_Booking; | |
| 15 | +use TimeticsEvent\Core\Events\Event; | |
| 14 | 16 | use WP_Query; |
| 15 | 17 | |
| 16 | 18 | /** |
| 17 | 19 | * Class Booking |
| @@ -45,8 +47,15 @@ | ||
| 45 | 47 | */ |
| 46 | 48 | protected $appointment; |
| 47 | 49 | |
| 48 | 50 | /** |
| 51 | + * Store appointment object | |
| 52 | + * | |
| 53 | + * @var Object | |
| 54 | + */ | |
| 55 | + protected $event; | |
| 56 | + | |
| 57 | + /** | |
| 49 | 58 | * Store booking data |
| 50 | 59 | * |
| 51 | 60 | * @var array |
| 52 | 61 | */ |
| @@ -51,33 +60,38 @@ | ||
| 51 | 60 | * @var array |
| 52 | 61 | */ |
| 53 | 62 | protected $data = [ |
| 54 | 63 | |
| 55 | - 'post_status' => '', | |
| 56 | - 'customer' => '', | |
| 57 | - 'appointment' => '', | |
| 58 | - 'appointment_name' => '', | |
| 59 | - 'staff' => '', | |
| 60 | - 'location' => '', | |
| 61 | - 'description' => '', | |
| 62 | - 'location_type' => '', | |
| 63 | - 'payment_method' => '', | |
| 64 | - 'payment_status' => '', | |
| 65 | - 'payment_details' => '', | |
| 66 | - 'order_total' => '', | |
| 67 | - 'start_date' => '', | |
| 68 | - 'end_date' => '', | |
| 69 | - 'start_time' => '', | |
| 70 | - 'end_time' => '', | |
| 71 | - 'calendar_event' => '', | |
| 72 | - 'random_id' => '', | |
| 73 | - 'seats' => '', | |
| 74 | - 'guests' => '', | |
| 75 | - 'zoom' => '', | |
| 76 | - 'custom_form_data' => '', | |
| 77 | - 'timezone' => '', | |
| 78 | - 'recurrence' => [], | |
| 79 | - 'parent' => 0, | |
| 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 | + 'security_token' => '' | |
| 80 | 94 | ]; |
| 81 | 95 | |
| 82 | 96 | /** |
| 83 | 97 | * Booking Constructor |
| @@ -112,8 +126,28 @@ | ||
| 112 | 126 | return $this->get_prop( 'customer' ); |
| 113 | 127 | } |
| 114 | 128 | |
| 115 | 129 | /** |
| 130 | + * Get attendee id | |
| 131 | + * | |
| 132 | + * @return integer | |
| 133 | + */ | |
| 134 | + public function get_attendees() { | |
| 135 | + $attendees = $this->get_prop( 'attendees' ); | |
| 136 | + return $attendees ? $attendees : []; | |
| 137 | + } | |
| 138 | + | |
| 139 | + /** | |
| 140 | + * Get custom url | |
| 141 | + * | |
| 142 | + * @return string | |
| 143 | + */ | |
| 144 | + public function get_custom_location_url() { | |
| 145 | + $custom_url = $this->get_prop( 'custom_location_url' ); | |
| 146 | + return $custom_url ? $custom_url : ''; | |
| 147 | + } | |
| 148 | + | |
| 149 | + /** | |
| 116 | 150 | * Get staff for the current booking |
| 117 | 151 | * |
| 118 | 152 | * @return integer |
| 119 | 153 | */ |
| @@ -121,8 +155,35 @@ | ||
| 121 | 155 | return $this->get_prop( 'staff' ); |
| 122 | 156 | } |
| 123 | 157 | |
| 124 | 158 | /** |
| 159 | + * Get speaker id | |
| 160 | + * | |
| 161 | + * @return integer | |
| 162 | + */ | |
| 163 | + public function get_speaker_id() { | |
| 164 | + return $this->get_prop( 'speaker' ); | |
| 165 | + } | |
| 166 | + | |
| 167 | + /** | |
| 168 | + * Get booking type | |
| 169 | + * | |
| 170 | + * @return string | |
| 171 | + */ | |
| 172 | + public function get_type() { | |
| 173 | + return $this->get_prop( 'type' ); | |
| 174 | + } | |
| 175 | + | |
| 176 | + /** | |
| 177 | + * Get event id | |
| 178 | + * | |
| 179 | + * @return integer | |
| 180 | + */ | |
| 181 | + public function get_event_id() { | |
| 182 | + return $this->get_prop( 'event' ); | |
| 183 | + } | |
| 184 | + | |
| 185 | + /** | |
| 125 | 186 | * Get customer |
| 126 | 187 | * |
| 127 | 188 | * @return User Object |
| 128 | 189 | */ |
| @@ -184,8 +245,17 @@ | ||
| 184 | 245 | return $this->get_prop( 'location_type' ); |
| 185 | 246 | } |
| 186 | 247 | |
| 187 | 248 | /** |
| 249 | + * Get booking time | |
| 250 | + * | |
| 251 | + * @return string | |
| 252 | + */ | |
| 253 | + public function get_booking_time() { | |
| 254 | + return $this->get_prop( 'booking_time' ); | |
| 255 | + } | |
| 256 | + | |
| 257 | + /** | |
| 188 | 258 | * Get last name |
| 189 | 259 | * |
| 190 | 260 | * @return string |
| 191 | 261 | */ |
| @@ -419,8 +489,17 @@ | ||
| 419 | 489 | return $this->get_prop( 'parent' ); |
| 420 | 490 | } |
| 421 | 491 | |
| 422 | 492 | /** |
| 493 | + * Get booking cancel reason | |
| 494 | + * | |
| 495 | + * @return integer | |
| 496 | + */ | |
| 497 | + public function get_cancel_reason() { | |
| 498 | + return $this->get_prop( 'cancel_reason' ); | |
| 499 | + } | |
| 500 | + | |
| 501 | + /** | |
| 423 | 502 | * Get booking data |
| 424 | 503 | * |
| 425 | 504 | * @param string $prop |
| 426 | 505 | * |
| @@ -474,8 +553,12 @@ | ||
| 474 | 553 | */ |
| 475 | 554 | public function set_props( $args = [] ) { |
| 476 | 555 | $this->data = wp_parse_args( $args, $this->data ); |
| 477 | 556 | $this->appointment = new Appointment( $this->data['appointment'] ); |
| 557 | + if ( isset( $this->data['type'] ) && 'timetics-event' == $this->data['type'] ) { | |
| 558 | + $this->event = new Event( $this->data['event'] ); | |
| 559 | + } | |
| 560 | + | |
| 478 | 561 | } |
| 479 | 562 | |
| 480 | 563 | /** |
| 481 | 564 | * Save metada for booking |
| @@ -506,9 +589,9 @@ | ||
| 506 | 589 | * Save appointment |
| 507 | 590 | * |
| 508 | 591 | * @return void |
| 509 | 592 | */ |
| 510 | - public function save() { | |
| 593 | + public function save( $type = '' ) { | |
| 511 | 594 | $args = [ |
| 512 | 595 | 'post_title' => $this->appointment->get_name(), |
| 513 | 596 | 'post_type' => $this->pos_type, |
| 514 | 597 | 'post_status' => $this->data['post_status'], |
| @@ -514,8 +597,17 @@ | ||
| 514 | 597 | 'post_status' => $this->data['post_status'], |
| 515 | 598 | 'post_author' => get_current_user_id(), |
| 516 | 599 | ]; |
| 517 | 600 | |
| 601 | + if ( 'timetics-event' == $type ) { | |
| 602 | + $args = [ | |
| 603 | + 'post_title' => $this->event->get_name(), | |
| 604 | + 'post_type' => $this->pos_type, | |
| 605 | + 'post_status' => $this->data['post_status'], | |
| 606 | + 'post_author' => get_current_user_id(), | |
| 607 | + ]; | |
| 608 | + } | |
| 609 | + | |
| 518 | 610 | $updated = false; |
| 519 | 611 | |
| 520 | 612 | if ( ! empty( $this->id ) ) { |
| 521 | 613 | $this->send_notification( 'update' ); |
| @@ -525,8 +617,9 @@ | ||
| 525 | 617 | |
| 526 | 618 | // Insert or Update appointment. |
| 527 | 619 | $booking_id = wp_insert_post( $args ); |
| 528 | 620 | $this->data['random_id'] = $this->generate_randon_id(); |
| 621 | + $this->data = apply_filters( 'timetics/event/booking/all_data', $this->data); | |
| 529 | 622 | |
| 530 | 623 | if ( ! is_wp_error( $booking_id ) ) { |
| 531 | 624 | $this->set_id( $booking_id ); |
| 532 | 625 | $this->save_metadata( $this->data ); |
| @@ -607,8 +700,10 @@ | ||
| 607 | 700 | ]; |
| 608 | 701 | |
| 609 | 702 | $args = wp_parse_args( $args, $defaults ); |
| 610 | 703 | |
| 704 | + $args = apply_filters( 'timetics/admin/bookings/all', $defaults, $args); | |
| 705 | + | |
| 611 | 706 | if ( ! empty( $args['start_date'] ) ) { |
| 612 | 707 | //_tt_booking_start_date |
| 613 | 708 | $args['meta_query'] = [ |
| 614 | 709 | [ |
| @@ -662,8 +757,17 @@ | ||
| 662 | 757 | if ( ! timetics_google_setup() ) { |
| 663 | 758 | return; |
| 664 | 759 | } |
| 665 | 760 | |
| 761 | + if ('timetics-event' == $this->get_type()) { | |
| 762 | + Event_Booking::instance()->create_online_event($this->get_id()); | |
| 763 | + }else { | |
| 764 | + $this->create_appointment_event(); | |
| 765 | + } | |
| 766 | + | |
| 767 | + } | |
| 768 | + | |
| 769 | + public function create_appointment_event() { | |
| 666 | 770 | $data = [ |
| 667 | 771 | 'summary' => timetics_get_option( 'booking_created_customer_email_title' ), |
| 668 | 772 | 'description' => timetics_get_option( 'booking_created_customer_email_body' ), |
| 669 | 773 | ]; |
| @@ -795,13 +899,13 @@ | ||
| 795 | 899 | $date = gmdate( 'd F Y', strtotime( $this->get_start_date() ) ); |
| 796 | 900 | $location = $this->get_location(); |
| 797 | 901 | |
| 798 | 902 | $placeholders = [ |
| 799 | - '{%meeting_title%}' => $meeting->name, | |
| 903 | + '{%meeting_title%}' => $meeting->get_name(), | |
| 800 | 904 | '{%meeting_date%}' => $date, |
| 801 | 905 | '{%meeting_time%}' => $time, |
| 802 | 906 | '{%meeting_location%}' => $location, |
| 803 | - '{%meeting_duration%}' => $meeting->duration, | |
| 907 | + '{%meeting_duration%}' => $meeting->get_duration(), | |
| 804 | 908 | '{%host_name%}' => $staff->get_display_name(), |
| 805 | 909 | '{%host_email%}' => $staff->get_email(), |
| 806 | 910 | '{%customer_name%}' => $customer->get_display_name(), |
| 807 | 911 | '{%customer_email%}' => $customer->get_email(), |
| @@ -826,8 +930,9 @@ | ||
| 826 | 930 | 'attendees' => [ |
| 827 | 931 | ['email' => $staff->get_email()], |
| 828 | 932 | ['email' => $customer->get_email()], |
| 829 | 933 | ], |
| 934 | + 'timezone' => $this->get_timezone(), | |
| 830 | 935 | 'google_meet' => 'google-meet' === $location_type, |
| 831 | 936 | 'access_token' => $access_token, |
| 832 | 937 | ]; |
| 833 | 938 | |
| @@ -857,6 +962,123 @@ | ||
| 857 | 962 | */ |
| 858 | 963 | private function send_notification( $action ) { |
| 859 | 964 | |
| 860 | 965 | do_action( 'timetics_booking_notification', $this, $action ); |
| 966 | + } | |
| 967 | + | |
| 968 | + /** | |
| 969 | + * Get booking ids by appointment id | |
| 970 | + * | |
| 971 | + * @param array Collection of appointment ids | |
| 972 | + * | |
| 973 | + * @return array Collection of booking ids | |
| 974 | + */ | |
| 975 | + public static function get_booking_ids_by_appointment( $appointment_ids, $per_page = -1 ) { | |
| 976 | + if ( empty( $appointment_ids ) ) { | |
| 977 | + return []; | |
| 978 | + } | |
| 979 | + | |
| 980 | + $query = new WP_Query([ | |
| 981 | + 'post_type' => 'timetics-booking', | |
| 982 | + 'post_status' => 'any', | |
| 983 | + 'posts_per_page' => $per_page, | |
| 984 | + 'meta_query' => [ | |
| 985 | + [ | |
| 986 | + 'key' => '_tt_booking_appointment', | |
| 987 | + 'value' => $appointment_ids, | |
| 988 | + 'compare' => 'IN', | |
| 989 | + ], | |
| 990 | + ], | |
| 991 | + ]); | |
| 992 | + | |
| 993 | + return [ | |
| 994 | + 'total' => $query->found_posts, | |
| 995 | + 'items' => $query->posts, | |
| 996 | + ]; | |
| 997 | + } | |
| 998 | + | |
| 999 | + /** | |
| 1000 | + * Get Google Calendar Event ID for this booking | |
| 1001 | + * | |
| 1002 | + * @return string | |
| 1003 | + */ | |
| 1004 | + public function get_google_event_id() { | |
| 1005 | + return $this->get_metadata( 'google_event_id' ); | |
| 1006 | + } | |
| 1007 | + | |
| 1008 | + /** | |
| 1009 | + * Set Google Calendar Event ID for this booking | |
| 1010 | + * | |
| 1011 | + * @param string $event_id | |
| 1012 | + * @return bool | |
| 1013 | + */ | |
| 1014 | + public function set_google_event_id( $event_id ) { | |
| 1015 | + return $this->save_metadata( 'google_event_id', $event_id ); | |
| 1016 | + } | |
| 1017 | + | |
| 1018 | + public function set_sync_status( $status ) { | |
| 1019 | + return $this->save_metadata( 'google_calendar_sync_status', $status ); | |
| 1020 | + } | |
| 1021 | + | |
| 1022 | + public function get_sync_status() { | |
| 1023 | + return $this->get_metadata( 'google_calendar_sync_status' ); | |
| 1024 | + } | |
| 1025 | + /** | |
| 1026 | + * Get all Google Event IDs for all bookings | |
| 1027 | + * | |
| 1028 | + * @return array | |
| 1029 | + */ | |
| 1030 | + public function get_all_google_event_ids() { | |
| 1031 | + $meta_key = $this->meta_prefix . 'google_event_id'; | |
| 1032 | + | |
| 1033 | + $posts = get_posts( | |
| 1034 | + array( | |
| 1035 | + 'post_type' => 'any', | |
| 1036 | + 'posts_per_page' => -1, | |
| 1037 | + 'meta_query' => array( | |
| 1038 | + array( | |
| 1039 | + 'key' => $meta_key, | |
| 1040 | + 'value' => '', | |
| 1041 | + 'compare' => '!=', | |
| 1042 | + ), | |
| 1043 | + ), | |
| 1044 | + 'fields' => 'ids', | |
| 1045 | + ) | |
| 1046 | + ); | |
| 1047 | + | |
| 1048 | + if ( empty( $posts ) ) { | |
| 1049 | + return array(); | |
| 1050 | + } | |
| 1051 | + | |
| 1052 | + $event_ids = array(); | |
| 1053 | + foreach ( $posts as $post_id ) { | |
| 1054 | + $event_id = get_post_meta( $post_id, $meta_key, true ); | |
| 1055 | + if ( ! empty( $event_id ) ) { | |
| 1056 | + $event_ids[] = $event_id; | |
| 1057 | + } | |
| 1058 | + } | |
| 1059 | + | |
| 1060 | + return $event_ids; | |
| 1061 | + } | |
| 1062 | + | |
| 1063 | + /** | |
| 1064 | + * Get name. | |
| 1065 | + * | |
| 1066 | + * @since 1.0.0 | |
| 1067 | + * | |
| 1068 | + * @return string | |
| 1069 | + */ | |
| 1070 | + public function get_security_token() { | |
| 1071 | + return $this->get_prop( 'security_token' ); | |
| 1072 | + } | |
| 1073 | + | |
| 1074 | + /** | |
| 1075 | + * Generate and store a secure reschedule token for a booking | |
| 1076 | + * | |
| 1077 | + * @param int $booking_id | |
| 1078 | + * @return string The generated token | |
| 1079 | + */ | |
| 1080 | + public function generate_security_token() { | |
| 1081 | + $token = bin2hex(random_bytes(4)); // 8 hex chars | |
| 1082 | + return $token; | |
| 861 | 1083 | } |
| 862 | 1084 | } |