PluginProbe
Timetics – Appointment Booking Calendar & Scheduling / 1.0.2
Timetics – Appointment Booking Calendar & Scheduling v1.0.2
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 1.0.22 All 64 releases
timetics / core / appointments / appointment.php

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

681 lines 15.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 Timetics\Base\PostModel;
12 use Timetics\Core\Bookings\Booking_Entry;
13 use Timetics\Core\Staffs\Staff;
14 use WP_Query;
15
16 /**
17 * Class Appointments.
18 *
19 * @since 1.0.0
20 */
21 class Appointment extends PostModel {
22 /**
23 * Store post type
24 *
25 * @since 1.0.0
26 *
27 * @var string $post_type
28 */
29 public $post_type = 'timetics-appointment';
30
31 /**
32 * Store timetics custom taxonomy
33 *
34 * @since 1.0.0
35 *
36 * @var string $taxonomy
37 */
38 protected $taxonomy = 'tt_category';
39
40 /**
41 * Store id
42 *
43 * @since 1.0.0
44 *
45 * @var int $id
46 */
47 protected $id;
48
49 /**
50 * Store post metadata
51 *
52 * @since 1.0.0
53 *
54 * @var array $data
55 */
56 public $data = [
57 'name' => '',
58 'type' => '',
59 'description' => '',
60 'staff' => '',
61 'locations' => '',
62 'duration' => '',
63 'schedule' => '',
64 'price' => '',
65 'buffer_time' => '',
66 'timezone' => '',
67 'availability' => '',
68 'visibility' => '',
69 'capacity' => '',
70 'seat_plan' => '',
71 'duplicate' => 0,
72 'seat_plan_settings' => '',
73 'notifications' => [
74 'booking_created_email_form' => '',
75 'booking_created_email_title' => '',
76 'booking_created_email_body' => '',
77 'booking_canceled_email_form' => '',
78 'booking_canceled_email_title' => '',
79 'booking_canceled_email_body' => '',
80 'booking_reschedule_email_form' => '',
81 'booking_reschedule_email_title' => '',
82 'booking_reschedule_email_body' => '',
83 'booking_reminder_email_form' => '',
84 'booking_reminder_email_title' => '',
85 'booking_reminder_email_body' => '',
86 'booking_reminder_time' => 30,
87 ],
88 ];
89
90 /**
91 * Store meta key prefix
92 *
93 * @since 1.0.0
94 *
95 * @var string $prefix
96 */
97 public $prefix = '_tt_apointment_';
98
99 /**
100 * Appointments Constructor
101 *
102 * @since 1.0.0
103 *
104 * @param int $appointment Optional. Default 0.
105 * @return void
106 */
107 public function __construct( $appointment = 0 ) {
108 if ( $appointment instanceof self ) {
109 $this->set_id( $appointment->get_id() );
110 } elseif ( ! empty( $appointment->ID ) ) {
111 $this->set_id( $appointment->ID );
112 } elseif ( is_numeric( $appointment ) && $appointment > 0 ) {
113 $this->set_id( $appointment );
114 }
115 }
116
117 /**
118 * Get appoint id.
119 *
120 * @since 1.0.0
121 *
122 * @return int
123 */
124 public function get_id() {
125 return $this->id;
126 }
127
128 /**
129 * Get name.
130 *
131 * @since 1.0.0
132 *
133 * @return string
134 */
135 public function get_name() {
136 return $this->get_prop( 'name' );
137 }
138
139 /**
140 * Get coach
141 *
142 * @since 1.0.0
143 *
144 * @return int
145 */
146 public function get_staff() {
147 $staff_ids = $this->get_prop( 'staff' );
148 $staffs = [];
149
150 if ( $staff_ids ) {
151 foreach ( $staff_ids as $staff_id ) {
152 $staff = new Staff( $staff_id );
153
154 if ( ! $staff->is_staff() ) {
155 continue;
156 }
157
158 $staffs[] = $staff->get_data();
159 }
160 }
161 return $staffs;
162 }
163
164 /**
165 * Get staff ids
166 *
167 * @return array
168 */
169 public function get_staff_ids() {
170 return $this->get_prop( 'staff' );
171 }
172
173 /**
174 * Get duplicate number
175 *
176 * @return integer
177 */
178 public function get_duplicate_nuber() {
179 return $this->get_prop('duplicate');
180 }
181
182 /**
183 * Get capacity
184 *
185 * @return integer
186 */
187 public function get_capacity() {
188 return $this->get_prop( 'capacity' );
189 }
190
191 /**
192 * Get location
193 *
194 * @since 1.0.0
195 *
196 * @return string
197 */
198 public function get_locations() {
199 return $this->get_prop( 'locations' );
200 }
201
202 /**
203 * Get duration
204 *
205 * @since 1.0.0
206 *
207 * @return string
208 */
209 public function get_duration() {
210 return $this->get_prop( 'duration' );
211 }
212
213 /**
214 * Get interval for the duration
215 *
216 * @return integer
217 */
218 public function get_interval() {
219 $duration = $this->get_duration();
220 if ( $duration ) {
221 $duration = explode(' ', $duration);
222 $duration = 'hr' === $duration[1] ? intval($duration[0]) * 60 * 60 : intval($duration[0]) * 60;
223 }
224
225 return $duration;
226 }
227
228 /**
229 * Get schedule
230 *
231 * @since 1.0.0
232 *
233 * @return array
234 */
235 public function get_schedule() {
236 return $this->get_prop( 'schedule' );
237 }
238
239 /**
240 * Get price
241 *
242 * @since 1.0.0
243 *
244 * @return string
245 */
246 public function get_price() {
247 return $this->get_prop( 'price' );
248 }
249
250 /**
251 * Get type
252 *
253 * @since 1.0.0
254 *
255 * @return string
256 */
257 public function get_type() {
258 return $this->get_prop( 'type' );
259 }
260
261 /**
262 * Get description
263 *
264 * @since 1.0.0
265 *
266 * @return string
267 */
268 public function get_description() {
269 return $this->get_prop( 'description' );
270 }
271
272 public function get_buffer_time() {
273 return $this->get_prop( 'buffer_time' );
274 }
275
276 public function get_timezone() {
277 return $this->get_prop( 'timezone' );
278 }
279
280 public function get_availability() {
281 return $this->get_prop( 'availability' );
282 }
283
284 public function get_visibility() {
285 return $this->get_prop( 'visibility' );
286 }
287
288 /**
289 * Get notifications
290 *
291 * @return array
292 */
293 public function get_notifications() {
294 return $this->get_prop( 'notifications' );
295 }
296
297 /**
298 * Get appointment categories
299 *
300 * @since 1.0.0
301 *
302 * @return array
303 */
304 public function get_categories() {
305 $categories = wp_get_post_terms( $this->id, $this->taxonomy );
306
307 if ( is_wp_error( $categories ) ) {
308 return [];
309 }
310
311 return $categories;
312 }
313
314 /**
315 * Get post thumbnail.
316 *
317 * @param string $size Image size
318 *
319 * @return string
320 */
321 public function get_image( $size = 'post-thumbnail' ) {
322 return get_the_post_thumbnail_url( $size );
323 }
324
325 /**
326 * Get permalink
327 *
328 * @return string
329 */
330 public function get_link() {
331 return get_post_permalink( $this->id );
332 }
333
334 /**
335 * Get Seat plan for a meeting
336 *
337 * @return array
338 */
339 public function get_seats() {
340 return $this->get_prop( 'seat_plan' );
341 }
342
343 /**
344 * Get seat plan settings
345 *
346 * @return array
347 */
348 public function get_seat_settings() {
349 return $this->get_prop( 'seat_plan_settings' );
350 }
351
352 /**
353 * Get appointment data
354 *
355 * @param string $prop
356 *
357 * @return mixed
358 */
359 public function get_prop( $prop = '' ) {
360 return $this->get_metadata( $prop );
361 }
362
363 /**
364 * Get metadata
365 *
366 * @since 1.0.0
367 *
368 * @param string $prop Optional. Default empty string.
369 *
370 * @return mixed
371 */
372 private function get_metadata( $prop = '' ) {
373 $meta_key = $this->prefix . $prop;
374 return get_post_meta( $this->id, $meta_key, true );
375 }
376
377 /**
378 * Set appointment id
379 *
380 * @since 1.0.0
381 *
382 * @param int $id
383 *
384 * @return void
385 */
386 public function set_id( $id ) {
387 $this->id = $id;
388 }
389
390 /**
391 * Set props
392 *
393 * @param array $data Metadata array. Default empty array.
394 *
395 * @return void
396 */
397 public function set_props( $data = [] ) {
398 $this->data = wp_parse_args( $data, $this->data );
399 }
400
401 /**
402 * Save appointment
403 *
404 * @since 1.0.0
405 *
406 * @return void
407 */
408 public function save() {
409
410 $args = [
411 'post_title' => $this->data['name'],
412 'post_type' => $this->post_type,
413 'post_status' => 'publish',
414 'post_author' => 1,
415 ];
416
417 if ( ! empty( $this->id ) ) {
418 $args['ID'] = $this->id;
419 }
420
421 // Insert or Update appointment.
422 $appoint_id = wp_insert_post( $args );
423
424 if ( ! is_wp_error( $appoint_id ) ) {
425 $this->set_id( $appoint_id );
426 $this->save_metadata();
427 }
428 }
429
430 /**
431 * Update appointment meta data.
432 *
433 * @since 1.0.0
434 *
435 * @return void
436 */
437 private function save_metadata() {
438 foreach ( $this->data as $key => $value ) {
439 // Prepare meta key.
440 $meta_key = $this->prefix . $key;
441
442 // Update appointment meta data.
443 update_post_meta( $this->id, $meta_key, $value );
444 }
445 }
446
447 /**
448 * Update meeting data
449 *
450 * @param array $args meeting data
451 *
452 * @return bool
453 */
454 public function update( $args = [] ) {
455
456 foreach ( $args as $key => $value ) {
457 if ( ! array_key_exists( $key, $this->data ) ) {
458 continue;
459 }
460
461 // Prepare meta key.
462 $meta_key = $this->prefix . $key;
463
464 // Update appointment meta data.
465 update_post_meta( $this->id, $meta_key, $value );
466 }
467 }
468
469 /**
470 * Delete appointment
471 *
472 * @return bool | WP_Error
473 */
474 public function delete() {
475 return wp_delete_post( $this->id, true );
476 }
477
478 /**
479 * Check the appoint is valid or not
480 *
481 * @return bool
482 */
483 public function is_appointment() {
484 $post = get_post( $this->id );
485
486 if ( $post && $this->post_type === $post->post_type ) {
487 return true;
488 }
489
490 return false;
491 }
492
493 /**
494 * Get all appointments
495 *
496 * @param array $args Appointments args. Default empty array.
497 *
498 * @return array
499 */
500 public static function all( $args = [] ) {
501 $defaults = [
502 'post_type' => (new self)->post_type,
503 'post_status' => 'publish',
504 'posts_per_page' => 20,
505 'paged' => 1,
506 'orderby' => 'ID',
507 'order' => 'DESC',
508 ];
509
510 $args = wp_parse_args( $args, $defaults );
511
512 if ( ! empty( $args['staff'] ) ) {
513 $args['meta_query'][] = [
514 'key' => '_tt_apointment_staff',
515 'value' => $args['staff'],
516 'compare' => 'LIKE',
517 ];
518 }
519
520 if ( ! empty( $args['visibility'] ) ) {
521 $args['meta_query'][] = [
522 'key' => '_tt_apointment_visibility',
523 'value' => $args['visibility'],
524 'compare' => 'LIKE',
525 ];
526 }
527
528 if ( ! empty( $args['type'] ) ) {
529 $args['meta_query'][] = [
530 'key' => '_tt_apointment_type',
531 'value' => $args['type'],
532 'compare' => 'LIKE',
533 ];
534 }
535
536 $post = new WP_Query( $args );
537
538 return [
539 'total' => $post->found_posts,
540 'items' => $post->posts,
541 ];
542 }
543
544 /**
545 * Duplicate appointment
546 *
547 * @since 1.0.0
548 *
549 * @return void
550 */
551 public function duplicate() {
552 $this->set_props( [
553 'name' => $this->get_name(),
554 'description' => $this->get_description(),
555 'type' => $this->get_type(),
556 'locations' => $this->get_locations(),
557 'staff' => $this->get_staff_ids(),
558 'duplicate' => intval( $this->get_duplicate_nuber() ) + 1,
559 'duration' => $this->get_duration(),
560 'price' => $this->get_price(),
561 'capacity' => $this->get_capacity(),
562 'schedule' => $this->get_schedule(),
563 'categories' => $this->get_categories(),
564 'timezone' => $this->get_timezone(),
565 'availability' => $this->get_availability(),
566 'visibility' => $this->get_visibility(),
567 'buffer_time' => $this->get_buffer_time(),
568 'notifications' => $this->get_notifications(),
569 ] );
570
571 $this->set_id( 0 );
572 $this->save();
573 }
574
575 /**
576 * Prepare meeting schedule
577 *
578 * @param string $start
579 * @param string $end
580 * @param integer $staff_id
581 *
582 * @return array
583 */
584 public function prepare_schedule( $start, $end, $staff_id ) {
585 $start = new \DateTime( $start );
586 $end = new \DateTime( $end );
587 $schedule = [];
588
589 // Prepare schedule for the current meeting
590 for ( $date = $start; $date <= $end; $date->modify( '+1 day' ) ) {
591 $schedule[] = $this->get_schedule_by_date( $date->format( 'Y-m-d' ), $staff_id );
592 }
593
594 return $schedule;
595 }
596
597 /**
598 * Get meeting schedule by date
599 *
600 * @param string $date [$date description]
601 * @param integer $staff_id [$staff_id description]
602 *
603 * @return array
604 */
605 private function get_schedule_by_date( $date, $staff_id ) {
606 $day_name = ucfirst( date( 'D', strtotime( $date ) ) );
607 $schedule = $this->get_schedule();
608 $interval = $this->get_interval();
609 $tartget_schedule = [];
610
611 $slots = [];
612
613 if ( ! empty( $schedule[$staff_id] ) ) {
614 $tartget_schedule = $schedule[$staff_id][$day_name];
615 }
616
617 foreach ( $tartget_schedule as $day ) {
618 $start = strtotime( $day['start'] );
619 $end = strtotime( $day['end'] );
620
621 for ( $time = $start; $time <= $end; $time += $interval ) {
622 $booked_entry = $this->get_booking_entries( $date, $time, $staff_id );
623 $status = 'available';
624 $capacity = $this->get_capacity();
625 $booked = 0;
626
627 if ( $booked_entry ) {
628 if ( $booked_entry->get_booked() >= $capacity ) {
629 $status = 'unavailable';
630 }
631
632 $booked = $booked_entry->get_booked();
633 }
634
635 $slot = [
636 'status' => $status,
637 'start_time' => gmdate( 'g:ia', $time ),
638 'booked' => $booked,
639 ];
640
641 $slot = apply_filters( 'timetics_booking_slot', $slot, $this, $booked_entry );
642
643 $slots[] = $slot;
644 }
645 }
646
647 return [
648 'date' => $date,
649 'status' => empty( $slots ) ? 'unavailable' : 'available',
650 'slots' => $slots,
651 ];
652 }
653
654 /**
655 * Get booked entry status
656 *
657 * @param string $date
658 * @param string $time
659 * @param interger $staff_id
660 *
661 * @return bool
662 */
663 private function get_booking_entries( $date, $time, $staff_id ) {
664 $time = gmdate( 'H:i', $time );
665 $booking_entries = new Booking_Entry();
666 $entries = $booking_entries->find( [
667 'meeting_id' => $this->id,
668 'staff_id' => $staff_id,
669 'date' => $date,
670 ] );
671
672 foreach ( $entries as $entry ) {
673 if ( gmdate( 'H:i', strtotime( $entry->get_start() ) ) == $time ) {
674 return $entry;
675 }
676 }
677
678 return false;
679 }
680 }
681