PluginProbe
Timetics – Appointment Booking Calendar & Scheduling / 1.0.20
Timetics – Appointment Booking Calendar & Scheduling v1.0.20
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.20, at core/bookings/booking.php

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