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

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