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

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