PluginProbe
Timetics – Appointment Booking Calendar & Scheduling / 1.0.56
Timetics – Appointment Booking Calendar & Scheduling v1.0.56
1.0.64 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 All 65 releases
timetics / core / bookings / booking.php

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

1,141 lines 27.6 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 'security_token' => ''
94 ];
95
96 /**
97 * Booking Constructor
98 *
99 * @return void
100 */
101 public function __construct( $booking = 0 ) {
102 if ( $booking instanceof self ) {
103 $this->set_id( $booking->get_id() );
104 } elseif ( ! empty( $booking->ID ) ) {
105 $this->set_id( $booking->ID );
106 } elseif ( is_numeric( $booking ) && $booking > 0 ) {
107 $this->set_id( $booking );
108 }
109 }
110
111 /**
112 * Get id
113 *
114 * @return integer
115 */
116 public function get_id() {
117 return $this->id;
118 }
119
120 /**
121 * Get customer id
122 *
123 * @return integer
124 */
125 public function get_customer_id() {
126 return $this->get_prop( 'customer' );
127 }
128
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 /**
150 * Get staff for the current booking
151 *
152 * @return integer
153 */
154 public function get_staff_id() {
155 return $this->get_prop( 'staff' );
156 }
157
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 /**
186 * Get customer
187 *
188 * @return User Object
189 */
190 public function get_customer() {
191 return get_userdata( $this->get_customer_id() );
192 }
193
194 /**
195 * Get seats of a booking
196 *
197 * @return array
198 */
199 public function get_seat() {
200 return $this->get_prop( 'seats' );
201 }
202
203 /**
204 * Get guests
205 *
206 * @return array
207 */
208 public function get_guests() {
209 return $this->get_prop( 'guests' );
210 }
211
212 /**
213 * Get custom fields
214 *
215 * @return array
216 */
217 public function get_custom_fields() {
218 return $this->get_prop( 'custom_form_data' );
219 }
220
221 /**
222 * Get billing first name
223 *
224 * @return string
225 */
226 public function get_billing_first_name() {
227 return $this->get_prop( 'first_name' );
228 }
229
230 /**
231 * Get location
232 *
233 * @return string
234 */
235 public function get_location() {
236 return $this->get_prop( 'location' );
237 }
238
239 /**
240 * Get location type
241 *
242 * @return string
243 */
244 public function get_location_type() {
245 return $this->get_prop( 'location_type' );
246 }
247
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 /**
258 * Get last name
259 *
260 * @return string
261 */
262 public function get_billing_last_name() {
263 return $this->get_prop( 'last_name' );
264 }
265
266 /**
267 * Get email
268 *
269 * @return string
270 */
271 public function get_billing_email() {
272 return $this->get_prop( 'email' );
273 }
274
275 /**
276 * Get billing phone
277 *
278 * @return string
279 */
280 public function get_billing_phone() {
281 return $this->get_prop( 'phone' );
282 }
283
284 /**
285 * Get timezone
286 *
287 * @return string
288 */
289 public function get_timezone() {
290 return $this->get_prop( 'timezone' );
291 }
292
293 /**
294 * Get description
295 *
296 * @return string
297 */
298 public function get_description() {
299 return $this->get_prop( 'description' );
300 }
301
302 /**
303 * Get billing address
304 *
305 * @param string $adress_type Booking billing address
306 *
307 * @return string
308 */
309 public function get_billing_address( $adress_type = 'address_1' ) {
310 return $this->get_prop( $adress_type );
311 }
312
313 /**
314 * Get billing city
315 *
316 * @return string
317 */
318 public function get_billing_city() {
319 return $this->get_prop( 'city' );
320 }
321
322 /**
323 * Get billing state
324 *
325 * @return string
326 */
327 public function get_billing_state() {
328 return $this->get_prop( 'state' );
329 }
330
331 /**
332 * Get billing post code
333 *
334 * @return string
335 */
336 public function get_billing_post_code() {
337 return $this->get_prop( 'post_code' );
338 }
339
340 /**
341 * Get billing
342 *
343 * @return string
344 */
345 public function get_billing_country() {
346 return $this->get_prop( 'country' );
347 }
348
349 /**
350 * Get payment method
351 *
352 * @return string
353 */
354 public function get_payment_method() {
355 return $this->get_prop( 'payment_method' );
356 }
357
358 /**
359 * Get appointment
360 *
361 * @return Appointment
362 */
363 public function get_appointment() {
364 return $this->get_prop( 'appointment' );
365 }
366
367 /**
368 * Get appointment name
369 *
370 * @return string
371 */
372 public function get_appointment_name() {
373 return $this->get_prop( 'appointment_name' );
374 }
375
376 /**
377 * Get calendar event
378 *
379 * @return array
380 */
381 public function get_event() {
382 return $this->get_prop( 'calendar_event' );
383 }
384
385 /**
386 * Get post status
387 *
388 * @return string
389 */
390 public function get_status() {
391 return get_post( $this->id )->post_status;
392 }
393
394 /**
395 * Get total
396 *
397 * @return integer
398 */
399 public function get_total() {
400 return $this->get_prop( 'order_total' );
401 }
402
403 /**
404 * Get start date
405 *
406 * @return string
407 */
408 public function get_start_date() {
409 return $this->get_prop( 'start_date' );
410 }
411 /**
412 * Get start date
413 *
414 * @return string
415 */
416 public function get_date() {
417 return $this->get_prop( 'date' );
418 }
419
420 /**
421 * Get end date
422 *
423 * @return string
424 */
425 public function get_end_date() {
426 return $this->get_prop( 'end_date' );
427 }
428
429 /**
430 * Get start time
431 *
432 * @return string
433 */
434 public function get_start_time() {
435 return $this->get_prop( 'start_time' );
436 }
437
438 /**
439 * Get end time
440 *
441 * @return string
442 */
443 public function get_end_time() {
444 return $this->get_prop( 'end_time' );
445 }
446
447 /**
448 * Get random id for the current booking
449 *
450 * @return string
451 */
452 public function get_random_id() {
453 return $this->get_prop( 'random_id' );
454 }
455
456 /**
457 * Get payment details
458 *
459 * @return array
460 */
461 public function get_payment_details() {
462 return $this->get_prop( 'payment_details' );
463 }
464
465 /**
466 * Get zoom meeting details
467 *
468 * @return array
469 */
470 public function get_zoom() {
471 return $this->get_prop( 'zoom' );
472 }
473
474 /**
475 * Get recurrences
476 *
477 * @return array
478 */
479 public function get_recurrence() {
480 return $this->get_prop( 'recurrence' );
481 }
482
483 /**
484 * Get parent
485 *
486 * @return integer
487 */
488 public function get_parent() {
489 return $this->get_prop( 'parent' );
490 }
491
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 /**
502 * Get booking data
503 *
504 * @param string $prop
505 *
506 * @return mixed
507 */
508 private function get_prop( $prop = '' ) {
509 return $this->get_metadata( $prop );
510 }
511
512 /**
513 * Get metadata
514 *
515 * @param string $prop
516 *
517 * @return mixed
518 */
519 private function get_metadata( $prop = '' ) {
520 $meta_key = $this->meta_prefix . $prop;
521
522 return get_post_meta( $this->id, $meta_key, true );
523 }
524
525 /**
526 * Generate random id
527 *
528 * @return string
529 */
530 private function generate_randon_id() {
531 return chr( wp_rand( ord( 'A' ), ord( 'Z' ) ) ) . wp_rand( 575639, 575639 + 400 );
532 }
533
534 // Setter.
535
536 /**
537 * Set booking id
538 *
539 * @param integer $id
540 *
541 * @return void
542 */
543 public function set_id( $id ) {
544 $this->id = $id;
545 }
546
547 /**
548 * Set data
549 *
550 * @param array $args Booking Args
551 *
552 * @return void
553 */
554 public function set_props( $args = [] ) {
555 $this->data = wp_parse_args( $args, $this->data );
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
561 }
562
563 /**
564 * Save metada for booking
565 *
566 * @return void
567 */
568 public function save_metadata( $args = [] ) {
569 foreach ( $args as $key => $value ) {
570
571 // If a key not exists on data it will skip to save the data.
572 if ( ! array_key_exists( $key, $this->data ) ) {
573 continue;
574 }
575
576 // Prepare meta key.
577 $meta_key = $this->meta_prefix . $key;
578
579 if ( ! $value ) {
580 $value = $this->get_prop( $key );
581 }
582
583 // Update appointment meta data.
584 update_post_meta( $this->id, $meta_key, $value );
585 }
586 }
587
588 /**
589 * Save appointment
590 *
591 * @return void
592 */
593 public function save( $type = '' ) {
594 $args = [
595 'post_title' => $this->appointment->get_name(),
596 'post_type' => $this->pos_type,
597 'post_status' => $this->data['post_status'],
598 'post_author' => get_current_user_id(),
599 ];
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
610 $updated = false;
611
612 if ( ! empty( $this->id ) ) {
613 $this->send_notification( 'update' );
614 $args['ID'] = $this->id;
615 $updated = true;
616 }
617
618 // Insert or Update appointment.
619 $booking_id = wp_insert_post( $args );
620 $this->data['random_id'] = $this->generate_randon_id();
621 $this->data = apply_filters( 'timetics/event/booking/all_data', $this->data);
622
623 if ( ! is_wp_error( $booking_id ) ) {
624 $this->set_id( $booking_id );
625 $this->save_metadata( $this->data );
626 }
627
628 if ( ! $updated ) {
629 $this->send_notification( 'create' );
630 }
631 }
632
633 /**
634 * Update booking
635 *
636 * @param array $args
637 *
638 * @return bool
639 */
640 public function update( $args = [] ) {
641 $post = get_post( $this->id )->to_array();
642 $args = wp_parse_args( $args, $post );
643
644 $updated = wp_update_post( $args );
645
646 if ( ! is_wp_error( $updated ) ) {
647 $this->save_metadata( $args );
648 }
649
650 return $updated;
651 }
652
653 /**
654 * Delete booking
655 *
656 * @return bool | WP_Error
657 */
658 public function delete() {
659 // Set action for sending notification.
660 $this->send_notification( 'delete' );
661
662 return wp_delete_post( $this->id, true );
663 }
664
665 /**
666 * Check is a booking or not
667 *
668 * @return bool
669 */
670 public function is_booking() {
671 $post = get_post( $this->id );
672
673 if ( $post && $this->pos_type === $post->post_type ) {
674 return true;
675 }
676
677 return false;
678 }
679
680 /**
681 * Get all bookings
682 *
683 * @param array $args Bookings args
684 *
685 * @return array
686 */
687 public static function all( $args = [] ) {
688
689 $status = [
690 'approved',
691 'pending',
692 'cancel',
693 'completed',
694 ];
695 $defaults = [
696 'post_type' => 'timetics-booking',
697 'posts_per_page' => 20,
698 'post_status' => 'any',
699 'paged' => 1,
700 ];
701
702 $args = wp_parse_args( $args, $defaults );
703
704 $args = apply_filters( 'timetics/admin/bookings/all', $args, $defaults );
705
706 $meta_query = ! empty( $args['meta_query'] ) && is_array( $args['meta_query'] ) ? $args['meta_query'] : [];
707
708 if ( ! empty( $args['start_date'] ) ) {
709 $meta_query[] = [
710 'key' => '_tt_booking_start_date',
711 'value' => $args['start_date'],
712 'compare' => '>=',
713 'type' => 'DATE',
714 ];
715 }
716
717 if ( ! empty( $args['meeting'] ) ) {
718 $meta_query[] = [
719 'key' => '_tt_booking_appointment',
720 'value' => $args['meeting'],
721 'compare' => '=',
722 ];
723 }
724
725 if ( ! empty( $args['staff'] ) ) {
726 $meta_query[] = [
727 'key' => '_tt_booking_staff',
728 'value' => $args['staff'],
729 'compare' => '=',
730 ];
731 }
732
733 if ( ! empty( $meta_query ) ) {
734 if ( count( $meta_query ) > 1 && empty( $meta_query['relation'] ) ) {
735 $meta_query['relation'] = 'AND';
736 }
737 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Meta query is necessary for filtering bookings
738 $args['meta_query'] = $meta_query;
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 /**
968 * Get booking ids by appointment id
969 *
970 * @param array Collection of appointment ids
971 *
972 * @return array Collection of booking ids
973 */
974 public static function get_booking_ids_by_appointment( $appointment_ids, $per_page = -1 ) {
975 if ( empty( $appointment_ids ) ) {
976 return [];
977 }
978
979 $query = new WP_Query([
980 'post_type' => 'timetics-booking',
981 'post_status' => 'any',
982 'posts_per_page' => $per_page,
983 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Meta query is necessary for filtering bookings by appointment
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 booking ids visible to a given user.
1001 *
1002 * Union of:
1003 * - bookings where the user is the assigned staff (`_tt_booking_staff`)
1004 * - bookings whose appointment is authored by the user
1005 *
1006 * @param integer $user_id WP user id.
1007 *
1008 * @return int[] Deduped list of booking post ids.
1009 */
1010 public static function get_visible_ids_for_user( $user_id ) {
1011 $user_id = (int) $user_id;
1012
1013 if ( ! $user_id ) {
1014 return [];
1015 }
1016
1017 $staff_ids = get_posts( [
1018 'post_type' => 'timetics-booking',
1019 'post_status' => 'any',
1020 'posts_per_page' => -1,
1021 'fields' => 'ids',
1022 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- needed to scope bookings to current staff user
1023 'meta_query' => [
1024 [
1025 'key' => '_tt_booking_staff',
1026 'value' => $user_id,
1027 ],
1028 ],
1029 ] );
1030
1031 $appointment_ids = Appointment::get_appointment_ids_by_author( $user_id );
1032
1033 $appointment_booking_ids = [];
1034 if ( ! empty( $appointment_ids ) ) {
1035 $appointment_booking_ids = get_posts( [
1036 'post_type' => 'timetics-booking',
1037 'post_status' => 'any',
1038 'posts_per_page' => -1,
1039 'fields' => 'ids',
1040 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- needed to scope bookings to appointments owned by current user
1041 'meta_query' => [
1042 [
1043 'key' => '_tt_booking_appointment',
1044 'value' => $appointment_ids,
1045 'compare' => 'IN',
1046 ],
1047 ],
1048 ] );
1049 }
1050
1051 return array_values( array_unique( array_map( 'intval', array_merge( $staff_ids, $appointment_booking_ids ) ) ) );
1052 }
1053
1054 /**
1055 * Get Google Calendar Event ID for this booking
1056 *
1057 * @return string
1058 */
1059 public function get_google_event_id() {
1060 return $this->get_metadata( 'google_event_id' );
1061 }
1062
1063 /**
1064 * Set Google Calendar Event ID for this booking
1065 *
1066 * @param string $event_id
1067 * @return bool
1068 */
1069 public function set_google_event_id( $event_id ) {
1070 return $this->save_metadata( 'google_event_id', $event_id );
1071 }
1072
1073 public function set_sync_status( $status ) {
1074 return $this->save_metadata( 'google_calendar_sync_status', $status );
1075 }
1076
1077 public function get_sync_status() {
1078 return $this->get_metadata( 'google_calendar_sync_status' );
1079 }
1080 /**
1081 * Get all Google Event IDs for all bookings
1082 *
1083 * @return array
1084 */
1085 public function get_all_google_event_ids() {
1086 $meta_key = $this->meta_prefix . 'google_event_id';
1087
1088 $posts = get_posts(
1089 array(
1090 'post_type' => 'any',
1091 'posts_per_page' => -1,
1092 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Meta query is necessary for filtering posts by meta key
1093 'meta_query' => array(
1094 array(
1095 'key' => $meta_key,
1096 'value' => '',
1097 'compare' => '!=',
1098 ),
1099 ),
1100 'fields' => 'ids',
1101 )
1102 );
1103
1104 if ( empty( $posts ) ) {
1105 return array();
1106 }
1107
1108 $event_ids = array();
1109 foreach ( $posts as $post_id ) {
1110 $event_id = get_post_meta( $post_id, $meta_key, true );
1111 if ( ! empty( $event_id ) ) {
1112 $event_ids[] = $event_id;
1113 }
1114 }
1115
1116 return $event_ids;
1117 }
1118
1119 /**
1120 * Get name.
1121 *
1122 * @since 1.0.0
1123 *
1124 * @return string
1125 */
1126 public function get_security_token() {
1127 return $this->get_prop( 'security_token' );
1128 }
1129
1130 /**
1131 * Generate and store a secure reschedule token for a booking
1132 *
1133 * @param int $booking_id
1134 * @return string The generated token
1135 */
1136 public function generate_security_token() {
1137 $token = bin2hex(random_bytes(4)); // 8 hex chars
1138 return $token;
1139 }
1140 }
1141