PluginProbe
Timetics – Appointment Booking Calendar & Scheduling / 1.0.49
Timetics – Appointment Booking Calendar & Scheduling v1.0.49
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 / appointments / appointment.php

appointment.php in Timetics – Appointment Booking Calendar & Scheduling 1.0.49, at core/appointments/appointment.php

1,046 lines 26.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class Apointment
4 *
5 * @since 1.0.0
6 *
7 * @package Timetics
8 */
9 namespace Timetics\Core\Appointments;
10
11 use DateTime;
12 use Timetics\Base\PostModel;
13 use Timetics\Core\Bookings\Booking;
14 use Timetics\Core\Bookings\Booking_Entry;
15 use Timetics\Core\Staffs\Staff;
16 use WP_Query;
17
18 /**
19 * Class Appointments.
20 *
21 * @since 1.0.0
22 */
23 class Appointment extends PostModel {
24 /**
25 * Store post type
26 *
27 * @since 1.0.0
28 *
29 * @var string $post_type
30 */
31 public $post_type = 'timetics-appointment';
32
33 /**
34 * Store timetics custom taxonomy
35 *
36 * @since 1.0.0
37 *
38 * @var string $taxonomy
39 */
40 protected $taxonomy = 'timetics-meeting-category';
41
42 /**
43 * Store id
44 *
45 * @since 1.0.0
46 *
47 * @var int $id
48 */
49 protected $id;
50
51 /**
52 * Store post metadata
53 *
54 * @since 1.0.0
55 *
56 * @var array $data
57 */
58 public $data = [
59 'name' => '',
60 'type' => '',
61 'description' => '',
62 'staff' => '',
63 'locations' => '',
64 'duration' => '',
65 'schedule' => '',
66 'blocked_schedule' => '',
67 'price' => '',
68 'buffer_time' => '',
69 'buffer_time_before_value'=> '',
70 'buffer_time_before_unit' => '',
71 'buffer_time_after_value' => '',
72 'buffer_time_after_unit' => '',
73 'timezone' => '',
74 'availability' => '',
75 'visibility' => '',
76 'capacity' => '',
77 'seat_plan' => '',
78 'duplicate' => 0,
79 'custom_fields' => [],
80 'wc_product_id' => 0,
81 'seat_plan_settings' => '',
82 'fleunt_crm_webhook' => '',
83 'fluent_hook_overwrite' => '',
84 'pabbly_hook_overwrite' => '',
85 'zapier_hook_overwrite' => '',
86 'pabbly_webook' => '',
87 'zapier_webook' => '',
88 'min_notice_time' => '',
89 'notifications' => [
90 'booking_created_email_form' => '',
91 'booking_created_email_title' => '',
92 'booking_created_email_body' => '',
93 'booking_canceled_email_form' => '',
94 'booking_canceled_email_title' => '',
95 'booking_canceled_email_body' => '',
96 'booking_reschedule_email_form' => '',
97 'booking_reschedule_email_title' => '',
98 'booking_reschedule_email_body' => '',
99 'booking_reminder_email_form' => '',
100 'booking_reminder_email_title' => '',
101 'booking_reminder_email_body' => '',
102 'booking_reminder_time' => 30,
103 ],
104 'permalink' => '',
105 'recurring' => false,
106 'recurring_limit' => 0,
107 'recurring_interval' => 1,
108 'recurring_interval_name' => 'day',
109 'guest_enabled' => false,
110 'guest_limit' => 1,
111 ];
112
113 /**
114 * Store meta key prefix
115 *
116 * @since 1.0.0
117 *
118 * @var string $prefix
119 */
120 public $prefix = '_tt_apointment_';
121
122 /**
123 * Appointments Constructor
124 *
125 * @since 1.0.0
126 *
127 * @param int $appointment Optional. Default 0.
128 * @return void
129 */
130 public function __construct( $appointment = 0 ) {
131 if ( $appointment instanceof self ) {
132 $this->set_id( $appointment->get_id() );
133 } elseif ( ! empty( $appointment->ID ) ) {
134 $this->set_id( $appointment->ID );
135 } elseif ( is_numeric( $appointment ) && $appointment > 0 ) {
136 $this->set_id( $appointment );
137 }
138 }
139
140 /**
141 * Get appoint id.
142 *
143 * @since 1.0.0
144 *
145 * @return int
146 */
147 public function get_id() {
148 return $this->id;
149 }
150
151 /**
152 * Get appointment slug
153 *
154 * @return mixed
155 */
156 public function get_slug() {
157 $post = get_post( $this->get_id() );
158
159 if ( $post ) {
160 return $post->post_name;
161 }
162
163 return false;
164 }
165
166 /**
167 * Get woocommerce product id
168 *
169 * @return integer
170 */
171 public function get_wc_product_id() {
172 return $this->get_prop( 'wc_product_id' );
173 }
174
175 /**
176 * Get name.
177 *
178 * @since 1.0.0
179 *
180 * @return string
181 */
182 public function get_name() {
183 return $this->get_prop( 'name' );
184 }
185
186 /**
187 * Get coach
188 *
189 * @since 1.0.0
190 *
191 * @return int
192 */
193 public function get_staff() {
194 $staff_ids = $this->get_prop( 'staff' );
195 $staffs = [];
196
197 if ( $staff_ids ) {
198 foreach ( $staff_ids as $staff_id ) {
199 $staff = new Staff( $staff_id );
200
201 if ( ! $staff->is_staff() ) {
202 continue;
203 }
204
205 $staffs[] = $staff->get_data();
206 }
207 }
208 return $staffs;
209 }
210
211 /**
212 * Get staff ids
213 *
214 * @return array
215 */
216 public function get_staff_ids() {
217 $ids = $this->get_prop( 'staff' );
218
219 return is_array( $ids ) ? array_values( $ids ) : [];
220 }
221
222 /**
223 * Get duplicate number
224 *
225 * @return integer
226 */
227 public function get_duplicate_nuber() {
228 return $this->get_prop( 'duplicate' );
229 }
230
231 /**
232 * Get capacity
233 *
234 * @return integer
235 */
236 public function get_capacity() {
237 return $this->get_prop( 'capacity' );
238 }
239
240 /**
241 * Get location
242 *
243 * @since 1.0.0
244 *
245 * @return string
246 */
247 public function get_locations() {
248 return $this->get_prop( 'locations' );
249 }
250
251 /**
252 * Get Permalink
253 *
254 * @since 1.0.0
255 *
256 * @return string
257 */
258 public function get_appointment_permalink() {
259 return get_post_permalink( $this->id );
260 }
261
262 /**
263 * Get duration
264 *
265 * @since 1.0.0
266 *
267 * @return string
268 */
269 public function get_duration() {
270 return $this->get_prop( 'duration' );
271 }
272
273 /**
274 * Get interval for the duration
275 *
276 * @return integer
277 */
278 public function get_interval() {
279 $duration = $this->get_duration();
280 if ( $duration ) {
281 $duration = explode( ' ', $duration );
282 $duration = 'hr' === $duration[1] ? intval( $duration[0] ) * 60 * 60 : intval( $duration[0] ) * 60;
283 }
284
285 return $duration;
286 }
287
288 /**
289 * Get schedule
290 *
291 * @since 1.0.0
292 *
293 * @return array
294 */
295 public function get_schedule() {
296 return $this->get_prop( 'schedule' );
297 }
298
299 /**
300 * Get blocked schedule
301 *
302 * @since 1.0.0
303 *
304 * @return array
305 */
306 public function get_blocked_schedule() {
307 return $this->get_prop( 'blocked_schedule' );
308 }
309
310 /**
311 * Get price
312 *
313 * @since 1.0.0
314 *
315 * @return string
316 */
317 public function get_price() {
318 return $this->get_prop( 'price' );
319 }
320
321 /**
322 * Get type
323 *
324 * @since 1.0.0
325 *
326 * @return string
327 */
328 public function get_type() {
329 return $this->get_prop( 'type' );
330 }
331
332 /**
333 * Get description
334 *
335 * @since 1.0.0
336 *
337 * @return string
338 */
339 public function get_description() {
340 return $this->get_prop( 'description' );
341 }
342
343 public function get_buffer_time() {
344 return $this->get_prop( 'buffer_time' );
345 }
346
347 /**
348 * Returns the amount of buffer time before the appointment (without unit like minute or hour)
349 *
350 * @return integer
351 */
352 public function get_buffer_time_before_value() {
353 return $this->get_prop( 'buffer_time_before_value' );
354 }
355
356 /**
357 * Returns the unit of buffer time before the appointment (like minute or hour)
358 *
359 * @return string
360 */
361 public function get_buffer_time_before_unit() {
362 return $this->get_prop( 'buffer_time_before_unit' );
363 }
364
365 /**
366 * Returns the amount of buffer time after the appointment (without unit like minute or hour)
367 *
368 * @return integer
369 */
370 public function get_buffer_time_after_value() {
371 return $this->get_prop( 'buffer_time_after_value' );
372 }
373
374 /**
375 * Returns the unit of buffer time after the appointment (like minute or hour)
376 *
377 * @return string
378 */
379 public function get_buffer_time_after_unit() {
380 return $this->get_prop( 'buffer_time_after_unit' );
381 }
382
383 public function get_timezone() {
384 return $this->get_prop( 'timezone' );
385 }
386
387 public function get_availability() {
388 return $this->get_prop( 'availability' );
389 }
390
391 public function get_visibility() {
392 return $this->get_prop( 'visibility' );
393 }
394 public function get_fleunt_crm_webhook() {
395 return $this->get_prop( 'fleunt_crm_webhook' );
396 }
397 public function get_fluent_hook_overwrite() {
398 return $this->get_prop( 'fluent_hook_overwrite' );
399 }
400 public function get_pabbly_webook() {
401 return $this->get_prop( 'pabbly_webook' );
402 }
403 public function get_pabbly_hook_overwrite() {
404 return $this->get_prop( 'pabbly_hook_overwrite' );
405 }
406 public function get_zapier_webook() {
407 return $this->get_prop( 'zapier_webook' );
408 }
409 public function get_zapier_hook_overwrite() {
410 return $this->get_prop( 'zapier_hook_overwrite' );
411 }
412 public function get_min_notice_time() {
413 return $this->get_prop( 'min_notice_time' );
414 }
415 public function get_guest_enabled() {
416 return $this->get_prop( 'guest_enabled' );
417 }
418 public function get_guest_limit() {
419 return $this->get_prop( 'guest_limit' );
420 }
421
422 /**
423 * Get Custom fields
424 *
425 * @return array
426 */
427 public function get_custom_fields() {
428 return $this->get_prop( 'custom_fields' );
429 }
430
431 /**
432 * Get notifications
433 *
434 * @return array
435 */
436 public function get_notifications() {
437 return $this->get_prop( 'notifications' );
438 }
439
440 /**
441 * Returns the buffer time before the appointment in seconds
442 *
443 * @return integer seconds
444 */
445 public function get_buffer_time_before_in_seconds() {
446 $buffer_time_value = (int) $this->get_buffer_time_before_value() ?? 0;
447
448 if ( 'hr' === $this->get_buffer_time_before_unit() ) {
449 return $buffer_time_value * 60 * 60;
450 }
451
452 return $buffer_time_value * 60;
453 }
454
455 /**
456 * Returns the buffer time after the appointment in seconds
457 *
458 * @return integer seconds
459 */
460 public function get_buffer_time_after_in_seconds() {
461 $buffer_time_value = (int) $this->get_buffer_time_after_value() ?? 0;
462
463 if ( 'hr' === $this->get_buffer_time_after_unit() ) {
464 return $buffer_time_value * 60 * 60;
465 }
466
467 return $buffer_time_value * 60;
468 }
469
470 /**
471 * Get appointment categories
472 *
473 * @since 1.0.0
474 *
475 * @return array
476 */
477 public function get_categories() {
478 $categories = wp_get_post_terms( $this->id, $this->taxonomy );
479
480 if ( is_wp_error( $categories ) ) {
481 return [];
482 }
483
484 return $categories;
485 }
486
487 /**
488 * Get category ids
489 *
490 * @return array
491 */
492 public function get_category_ids() {
493 $categories = $this->get_categories();
494
495 $ids = [];
496
497 foreach ( $categories as $category ) {
498 $ids[] = $category->term_id;
499 }
500
501 return $ids;
502 }
503
504 /**
505 * Get post thumbnail.
506 *
507 * @param string $size Image size
508 *
509 * @return string
510 */
511 public function get_image( $size = 'post-thumbnail' ) {
512 return get_the_post_thumbnail_url( $size );
513 }
514
515 /**
516 * Get permalink
517 *
518 * @return string
519 */
520 public function get_link() {
521 return get_post_permalink( $this->id );
522 }
523
524 /**
525 * Get Seat plan for a meeting
526 *
527 * @return array
528 */
529 public function get_seats() {
530 return $this->get_prop( 'seat_plan' );
531 }
532
533 /**
534 * Get appointment author
535 *
536 * @return integer
537 */
538 public function get_author() {
539 $post = get_post( $this->id );
540
541 return $post->post_author;
542 }
543
544 /**
545 * Get seat plan settings
546 *
547 * @return array
548 */
549 public function get_seat_settings() {
550 return $this->get_prop( 'seat_plan_settings' );
551 }
552
553 // Recurring options.
554
555 /**
556 * Check it is recurring or not
557 *
558 * @return bool
559 */
560 public function is_recurring() {
561 return boolval( $this->get_prop( 'recurring' ) );
562 }
563
564 /**
565 * Get recurring limit
566 *
567 * @return integer
568 */
569 public function get_recurring_limit() {
570 return intval( $this->get_prop( 'recurring_limit' ) );
571 }
572
573 /**
574 * Get recurring interval
575 *
576 * @return integer
577 */
578 public function get_recurring_interval() {
579 return intval( $this->get_prop( 'recurring_interval' ) );
580 }
581
582 /**
583 * Get recurring interval name
584 *
585 * @return string
586 */
587 public function get_recurring_interval_name() {
588 return $this->get_prop( 'recurring_interval_name' );
589 }
590
591 /**
592 * Get appointment data
593 *
594 * @param string $prop
595 *
596 * @return mixed
597 */
598 public function get_prop( $prop = '' ) {
599 return $this->get_metadata( $prop );
600 }
601
602 /**
603 * Get metadata
604 *
605 * @since 1.0.0
606 *
607 * @param string $prop Optional. Default empty string.
608 *
609 * @return mixed
610 */
611 private function get_metadata( $prop = '' ) {
612 $meta_key = $this->prefix . $prop;
613 return get_post_meta( $this->id, $meta_key, true );
614 }
615
616 /**
617 * Set appointment id
618 *
619 * @since 1.0.0
620 *
621 * @param int $id
622 *
623 * @return void
624 */
625 public function set_id( $id ) {
626 $this->id = $id;
627 }
628
629 /**
630 * Set props
631 *
632 * @param array $data Metadata array. Default empty array.
633 *
634 * @return void
635 */
636 public function set_props( $data = [] ) {
637 $this->data = $data;
638 }
639
640 /**
641 * Save appointment
642 *
643 * @since 1.0.0
644 *
645 * @return void
646 */
647 public function save() {
648
649 $args = [
650 'post_title' => $this->data['name'],
651 'post_type' => $this->post_type,
652 'post_status' => 'publish',
653 'post_author' => get_current_user_id(),
654 ];
655
656 if ( ! empty( $this->id ) ) {
657 $args['ID'] = $this->id;
658 }
659
660 // Insert or Update appointment.
661 $appoint_id = wp_insert_post( $args );
662
663 if ( ! is_wp_error( $appoint_id ) ) {
664 $this->set_id( $appoint_id );
665 $this->save_metadata();
666 }
667 }
668
669 /**
670 * Update appointment meta data.
671 *
672 * @since 1.0.0
673 *
674 * @return void
675 */
676 private function save_metadata() {
677 foreach ( $this->data as $key => $value ) {
678 // Prepare meta key.
679 $meta_key = $this->prefix . $key;
680
681 // Update appointment meta data.
682 update_post_meta( $this->id, $meta_key, $value );
683 }
684 }
685
686 /**
687 * Update meeting data
688 *
689 * @param array $args meeting data
690 *
691 * @return bool
692 */
693 public function update( $args = [] ) {
694
695 foreach ( $args as $key => $value ) {
696 if ( ! array_key_exists( $key, $this->data ) ) {
697 continue;
698 }
699
700 // Prepare meta key.
701 $meta_key = $this->prefix . $key;
702
703 // Update appointment meta data.
704 update_post_meta( $this->id, $meta_key, $value );
705 }
706 }
707
708 /**
709 * Delete appointment
710 *
711 * @return bool | WP_Error
712 */
713 public function delete() {
714 return wp_delete_post( $this->id, true );
715 }
716
717 /**
718 * Check the appoint is valid or not
719 *
720 * @return bool
721 */
722 public function is_appointment() {
723 $post = get_post( $this->id );
724
725 if ( $post && $this->post_type === $post->post_type ) {
726 return true;
727 }
728
729 return false;
730 }
731
732 /**
733 * Get all appointments
734 *
735 * @param array $args Appointments args. Default empty array.
736 *
737 * @return array
738 */
739 public static function all( $args = [] ) {
740 $defaults = [
741 'post_type' => ( new self )->post_type,
742 'post_status' => 'publish',
743 'posts_per_page' => 20,
744 'paged' => 1,
745 'orderby' => 'ID',
746 'order' => 'DESC',
747 ];
748
749 $args = wp_parse_args( $args, $defaults );
750
751 if ( ! empty( $args['staff'] ) ) {
752 $args['meta_query'][] = [
753 'key' => '_tt_apointment_staff',
754 'value' => $args['staff'],
755 'compare' => 'LIKE',
756 ];
757 }
758
759 if ( ! empty( $args['visibility'] ) ) {
760 $args['meta_query'][] = [
761 'key' => '_tt_apointment_visibility',
762 'value' => $args['visibility'],
763 'compare' => 'LIKE',
764 ];
765 }
766
767 if ( ! empty( $args['type'] ) ) {
768 $args['meta_query'][] = [
769 'key' => '_tt_apointment_type',
770 'value' => $args['type'],
771 'compare' => 'LIKE',
772 ];
773 }
774
775 if ( ! empty( $args['category'] ) ) {
776 $args['tax_query'][] = [
777 'taxonomy' => 'timetics-meeting-category',
778 'terms' => $args['category'],
779 'include_children' => false,
780 ];
781 }
782
783 $post = new WP_Query( $args );
784
785 return [
786 'total' => $post->found_posts,
787 'items' => $post->posts,
788 ];
789 }
790
791 /**
792 * Duplicate appointment
793 *
794 * @since 1.0.0
795 *
796 * @return void
797 */
798 public function duplicate() {
799 $this->set_props( [
800 'name' => $this->get_name(),
801 'description' => $this->get_description(),
802 'type' => $this->get_type(),
803 'locations' => $this->get_locations(),
804 'staff' => $this->get_staff_ids(),
805 'duplicate' => intval( $this->get_duplicate_nuber() ) + 1,
806 'duration' => $this->get_duration(),
807 'price' => $this->get_price(),
808 'capacity' => $this->get_capacity(),
809 'schedule' => $this->get_schedule(),
810 'categories' => $this->get_categories(),
811 'timezone' => $this->get_timezone(),
812 'availability' => $this->get_availability(),
813 'visibility' => $this->get_visibility(),
814 'buffer_time' => $this->get_buffer_time(),
815 'notifications' => $this->get_notifications(),
816 'fluent_hook_overwrite' => $this->get_fluent_hook_overwrite(),
817 'fleunt_crm_webhook' => $this->get_fleunt_crm_webhook(),
818 'pabbly_hook_overwrite' => $this->get_pabbly_hook_overwrite(),
819 'pabbly_webook' => $this->get_pabbly_webook(),
820 'zapier_webook' => $this->get_zapier_webook(),
821 'min_notice_time' => $this->get_min_notice_time(),
822 'zapier_hook_overwrite' => $this->get_zapier_hook_overwrite(),
823 'guest_enabled' => $this->get_guest_enabled(),
824 'guest_limit' => $this->get_guest_limit(),
825 ] );
826
827 $this->set_id( 0 );
828 $this->save();
829 }
830
831 /**
832 * Prepare meeting schedule
833 *
834 * @param string $start
835 * @param string $end
836 * @param integer $staff_id
837 *
838 * @return array
839 */
840 public function prepare_schedule( $start, $end, $staff_id, $timze_zone = '' ) {
841 $start = new \DateTime( $start );
842 $end = new \DateTime( $end );
843 $schedule = [];
844
845 // Prepare schedule for the current meeting
846 for ( $date = $start; $date <= $end; $date->modify( '+1 day' ) ) {
847 $schedule[] = $this->get_schedule_by_date( $date->format( 'Y-m-d' ), $staff_id, $timze_zone );
848 }
849
850 return $schedule;
851 }
852
853 /**
854 * Get meeting schedule by date
855 *
856 * @param string $date [$date description]
857 * @param integer $staff_id [$staff_id description]
858 * @param string $timze_zone [$timze_zone description]
859 *
860 * @return array
861 */
862 private function get_schedule_by_date( $date, $staff_id, $time_zone = '' ) {
863 $day_name = ucfirst( date( 'D', strtotime( $date ) ) );
864 $schedule = $this->get_schedule();
865 $interval = $this->get_interval();
866 $target_schedule = [];
867
868 $slots = [];
869
870 if ( ! empty( $schedule[$staff_id] ) ) {
871 $target_schedule = $schedule[$staff_id][$day_name];
872 }
873
874 foreach ( $target_schedule as $day ) {
875 $start = strtotime( $day['start'] );
876 $end = strtotime( $day['end'] );
877
878 // Get buffer times in seconds
879 $buffer_before = $this->get_buffer_time_before_in_seconds();
880 $buffer_after = $this->get_buffer_time_after_in_seconds();
881
882 // Adjust the start time to include buffer before
883 $adjusted_start = $start + $buffer_before;
884
885 // Adjust the end time to ensure we have enough time for the slot + buffer after
886 $min_slot_duration = $interval + $buffer_after;
887
888 for ( $time = $adjusted_start; $time + $min_slot_duration <= $end; $time += $interval + $buffer_after + $buffer_before ) {
889 $booked_entry = $this->get_booking_entries( $date, $time, $staff_id );
890 $status = 'available';
891 $capacity = $this->get_capacity();
892 $booked = 0;
893
894 if ( $booked_entry ) {
895 if ( $booked_entry->get_booked() >= $capacity ) {
896 $status = 'unavailable';
897 }
898
899 $booked = $booked_entry->get_booked();
900 }
901
902 $datetime = $this->convert_timezone( $time, $time_zone );
903
904 $slot = [
905 'status' => $status,
906 'start_time' => $datetime->format( 'g:ia' ),
907 'booked' => $booked,
908 ];
909
910 $slot = apply_filters( 'timetics_booking_slot', $slot, $this, $booked_entry );
911
912 $slots[] = $slot;
913 }
914 }
915
916 return [
917 'date' => $date,
918 'status' => empty( $slots ) ? 'unavailable' : 'available',
919 'slots' => $slots,
920 ];
921 }
922
923 /**
924 * Get booked entry status
925 *
926 * @param string $date
927 * @param string $time
928 * @param interger $staff_id
929 *
930 * @return bool
931 */
932 private function get_booking_entries( $date, $time, $staff_id ) {
933 $time = gmdate( 'h:i a', $time );
934 $booking_entries = new Booking_Entry();
935 $entries = $booking_entries->find( [
936 'staff_id' => $staff_id,
937 'date' => $this->convert_timezone( $date, $this->get_timezone())->format('Y-m-d'),
938 ] );
939
940 foreach ( $entries as $entry ) {
941 $booking = new Booking( $entry->get_booking_id() );
942 $start_time = $entry->get_start();
943 $end_time = $entry->get_end();
944
945 // Check if current time slot falls within the booking duration
946 if ( $this->is_time_in_range( $time, $start_time, $end_time ) ) {
947 return $entry;
948 }
949 }
950
951 return false;
952 }
953
954 /**
955 * Check if a time falls within a given time range
956 *
957 * @param string $current_time Current time in h:i a format
958 * @param string $start_time Start time in h:i a format
959 * @param string $end_time End time in h:i a format
960 *
961 * @return bool
962 */
963 private function is_time_in_range( $current_time, $start_time, $end_time ) {
964 $current = strtotime( $current_time );
965 $start = strtotime( $start_time );
966 $end = strtotime( $end_time );
967
968 return $current >= $start && $current < $end;
969 }
970
971 /**
972 * Convert timestamp in target timezone
973 *
974 * @param integer $timestamp
975 * @param string $timze_zone
976 *
977 * @return DateTime
978 */
979 public function convert_timezone( $date, $timze_zone ) {
980 $date = is_int( $date ) ? gmdate( 'Y-m-d g:ia', $date ) : $date;
981
982 // Create a DateTime object with the provided timestamp and time zone
983 $datetime = new \DateTime( $date, new \DateTimeZone( $this->get_timezone() ) );
984
985 // Convert the time zone
986 $datetime->setTimezone( new \DateTimeZone( $timze_zone ) );
987
988 // Get the converted timestamp
989 return $datetime;
990 }
991
992 /**
993 * Get appointmentt ids by author id
994 *
995 * @param integer $author_id Appointment author id
996 *
997 * @return array Appointment ids
998 */
999 public static function get_appointment_ids_by_author( $author_id ) {
1000 $query = new WP_Query([
1001 'post_type' => 'timetics-appointment',
1002 'post_status' => 'any',
1003 'author' => $author_id,
1004 'posts_per_page' => -1,
1005 'fields' => 'ids'
1006 ]);
1007
1008 return $query->posts;
1009 }
1010
1011 /**
1012 * Get meeting available time slot
1013 *
1014 * @param string $date Start date
1015 * @param integer $staff_id Meeting assigned staff id
1016 * @param string $timze_zone Booking timezone
1017 *
1018 * @return array Available timeslots
1019 */
1020 public function get_avilable_timeslots( $date, $staff_id, $time_zone = '' ) {
1021 $day_name = ucfirst( date( 'D', strtotime( $date ) ) );
1022 $schedule = $this->get_schedule();
1023 $interval = $this->get_interval();
1024 $tartget_schedule = [];
1025
1026 $slots = [];
1027
1028 if ( isset($schedule[$staff_id]) && ! empty(array_filter($schedule[$staff_id])) ) {
1029 $tartget_schedule = $schedule[$staff_id][$day_name];
1030 }
1031
1032 foreach ( $tartget_schedule as $day ) {
1033 $start = strtotime( $day['start'] );
1034 $end = strtotime( $day['end'] );
1035
1036 for ( $time = $start; $time <= $end; $time += $interval ) {
1037 $datetime = $this->convert_timezone( $time, $time_zone );
1038 $slot = $datetime->format( 'g:ia' );
1039 $slots[] = $slot;
1040 }
1041 }
1042
1043 return $slots;
1044 }
1045 }
1046