PluginProbe
Timetics – Appointment Booking Calendar & Scheduling / 1.0.0
Timetics – Appointment Booking Calendar & Scheduling v1.0.0
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.0, at core/appointments/appointment.php

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