PluginProbe
Timetics – Appointment Booking Calendar & Scheduling / 1.0.49
Timetics – Appointment Booking Calendar & Scheduling v1.0.49
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 / api-appointment.php

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

939 lines 34.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Apointment api
4 *
5 * @since 1.0.0
6 *
7 * @package Timetics
8 */
9 namespace Timetics\Core\Appointments;
10
11 use Timetics\Base\Api;
12 use Timetics\Core\Appointments\Appointment;
13 use Timetics\Core\Staffs\Staff;
14 use Timetics\Utils\Singleton;
15 use WP_Error;
16 use WP_HTTP_Response;
17 use WP_REST_Request;
18
19 /**
20 * Api_Appointment class
21 *
22 * @since 1.0.0
23 */
24 class Api_Appointment extends Api {
25
26 use Singleton;
27
28 /**
29 * Store api namespace
30 *
31 * @since 1.0.0
32 *
33 * @var string $namespace
34 */
35 protected $namespace = 'timetics/v1';
36
37 /**
38 * Store rest base
39 *
40 * @since 1.0.0
41 *
42 * @var string $rest_base
43 */
44 protected $rest_base = 'appointments';
45
46 /**
47 * Register rest routes.
48 *
49 * @since 1.0.0
50 *
51 * @return void
52 */
53 public function register_routes() {
54 /*
55 * Register route
56 */
57 register_rest_route( $this->namespace, $this->rest_base, [
58 [
59 'methods' => \WP_REST_Server::READABLE,
60 'callback' => [$this, 'get_items'],
61 'permission_callback' => function () {
62 return true;
63 },
64 ],
65 [
66 'methods' => \WP_REST_Server::CREATABLE,
67 'callback' => [$this, 'create_item'],
68 'permission_callback' => function () {
69 return current_user_can( 'read_meeting' );
70 },
71 ],
72 [
73 'methods' => \WP_REST_Server::DELETABLE,
74 'callback' => [$this, 'bulk_delete'],
75 'permission_callback' => function () {
76 return current_user_can( 'read_meeting' );
77 },
78 ],
79 ] );
80
81 /**
82 * Register route
83 *
84 * @var void
85 */
86 register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<appointment_id>[\d]+)', [
87 [
88 'methods' => \WP_REST_Server::READABLE,
89 'callback' => [$this, 'get_item'],
90 'permission_callback' => function () {
91 return true;
92 },
93 ],
94 [
95 'methods' => \WP_REST_Server::EDITABLE,
96 'callback' => [$this, 'update_item'],
97 'permission_callback' => [ $this, 'update_item_permissions_check' ],
98 ],
99 [
100 'methods' => \WP_REST_Server::DELETABLE,
101 'callback' => [$this, 'delete_item'],
102 'permission_callback' => [$this, 'delete_item_permissions_check' ],
103 ],
104 ] );
105
106 register_rest_route( $this->namespace, $this->rest_base . '/search', [
107 [
108 'methods' => \WP_REST_Server::READABLE,
109 'callback' => [$this, 'search_items'],
110 'permission_callback' => function () {
111 return current_user_can( 'edit_posts' );
112 },
113 ],
114 ] );
115
116 register_rest_route( $this->namespace, $this->rest_base . '/filter', [
117 [
118 'methods' => \WP_REST_Server::READABLE,
119 'callback' => [$this, 'filter_items'],
120 'permission_callback' => function () {
121 return true;
122 },
123 ],
124 ] );
125
126 register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<appointment_id>[\d]+)' . '/duplicate', [
127 [
128 'methods' => \WP_REST_Server::CREATABLE,
129 'callback' => [$this, 'duplicate_item'],
130 'permission_callback' => function () {
131 return current_user_can( 'edit_meeting' );
132 },
133 ],
134 ] );
135 }
136
137 /**
138 * Get all appointments
139 *
140 * @param WP_Rest_Request $request
141 *
142 * @return JSON
143 */
144 public function get_items( $request ) {
145
146 $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
147 $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
148 $type = ! empty( $request['type'] ) ? sanitize_text_field( $request['type'] ) : '';
149
150 $args = [
151 'posts_per_page' => $per_page,
152 'paged' => $paged,
153 'type' => $type,
154 ];
155
156 if ( ! current_user_can( 'edit_meeting' ) ) {
157 $args['staff'] = get_current_user_id();
158 }
159
160 $appoint = Appointment::all( $args );
161
162 $items = [];
163
164 foreach ( $appoint['items'] as $item ) {
165 $items[] = $this->prepare_item( $item->ID );
166 }
167
168 $data = [
169 'success' => 1,
170 'status_code' => 200,
171 'data' => [
172 'total' => $appoint['total'],
173 'items' => $items,
174 ],
175 ];
176
177 return rest_ensure_response( $data );
178 }
179
180 /**
181 * Search appointment
182 *
183 * @param Object $request
184 *
185 * @return JSON
186 */
187 public function search_items( $request ) {
188
189 // Prepare search args.
190 $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
191 $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
192 $search = ! empty( $request['search'] ) ? sanitize_text_field( $request['search'] ) : '';
193
194 // Get search.
195 $appointments = new \WP_Query(
196 array(
197 'post_type' => 'timetics-appointment',
198 'posts_per_page' => $per_page,
199 'paged' => $paged,
200 'orderby' => 'ID',
201 'order' => 'DESC',
202
203 // @codingStandardsIgnoreStart
204 'meta_query' => array(
205 'relation' => 'OR',
206 array(
207 'key' => '_tt_apointment_name',
208 'value' => $search,
209 'compare' => 'LIKE',
210 ),
211 array(
212 'key' => '_tt_apointment_type',
213 'value' => $search,
214 'compare' => 'LIKE',
215 ),
216 array(
217 'key' => '_tt_apointment_description',
218 'value' => $search,
219 'compare' => 'LIKE',
220 ),
221 array(
222 'key' => '_tt_apointment_location',
223 'value' => $search,
224 'compare' => 'LIKE',
225 ),
226 array(
227 'key' => '_tt_apointment_duration',
228 'value' => $search,
229 'compare' => 'LIKE',
230 ),
231 array(
232 'key' => '_tt_apointment_schedule',
233 'value' => $search,
234 'compare' => 'LIKE',
235 ),
236 ),
237 // @codingStandardsIgnoreEnd
238 )
239 );
240
241 // Prepare items for response.
242 $items = [];
243
244 foreach ( $appointments->posts as $item ) {
245 $items[] = $this->prepare_item( $item->ID );
246 }
247
248 $data = [
249 'success' => 1,
250 'status' => 200,
251 'data' => [
252 'total' => $appointments->found_posts,
253 'items' => $items,
254 ],
255 ];
256
257 return rest_ensure_response( $data );
258 }
259
260 public function filter_items( $request ) {
261
262 $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
263 $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
264 $staff = ! empty( $request['staff_id'] ) ? intval( $request['staff_id'] ) : 0;
265 $category = ! empty( $request['category'] ) ? intval( $request['category'] ) : 0;
266 $visibility = ! empty( $request['visibility'] ) ? sanitize_text_field( $request['visibility'] ) : '';
267
268 $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
269 $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
270
271 $appoint = Appointment::all( [
272 'posts_per_page' => $per_page,
273 'paged' => $paged,
274 'visibility' => $visibility,
275 'staff' => $staff,
276 'category' => $category,
277 ] );
278
279 $items = [];
280
281 foreach ( $appoint['items'] as $item ) {
282 $items[] = $this->prepare_item( $item->ID );
283 }
284
285 $data = [
286 'success' => 1,
287 'status' => 200,
288 'data' => [
289 'total' => $appoint['total'],
290 'items' => $items,
291 ],
292 ];
293
294 return rest_ensure_response( $data );
295 }
296
297 /**
298 * Create appointment
299 *
300 * @param WP_Rest_Request $request
301 *
302 * @return JSON Newly created appointment data
303 */
304 public function create_item( $request ) {
305
306 /**
307 * Added temporary for leagacy sass. It will remove in future.
308 */
309
310 $meetings_count = Appointment::all();
311 $data = json_decode( $request->get_body(), true );
312
313 $response = [
314 'success' => 0,
315 'status_code' => 403,
316 'message' => esc_html__( 'Something went wrong', 'timetics' ),
317 'data' => [],
318 ];
319
320 if ( ! empty( $data['price'] ) && apply_filters( 'timetics/staff/appointment/price_check', false, $data['price'] ) == true ) {
321 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'price_check' ), 403 );
322 }
323
324 if ( apply_filters( 'timetics/staff/appointment/count_check', false, $meetings_count ) == true ) {
325 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'count_check' ), 403 );
326 }
327
328 $type = ! empty( $data['type'] ) ? sanitize_text_field( $data['type'] ) : '';
329
330 if ( apply_filters( 'timetics/staff/appointment/type_check', false, $type ) == true ) {
331 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'type_check' ), 403 );
332 }
333
334 $categories = ! empty( $data['categories'] ) ? $data['categories'] : '';
335
336 if ( apply_filters( 'timetics/staff/appointment/category_check', false, $categories ) == true ) {
337 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'category_check' ), 403 );
338 }
339
340 $staff = ! empty( $data['staff'] ) ? array_map( 'intval', $data['staff'] ) : [];
341
342 if ( apply_filters( 'timetics/staff/appointment/staff_check', false, $staff ) == true ) {
343 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'staff_check' ), 403 );
344 }
345
346 $custom_fields = ! empty( $data['custom_fields'] ) ? $data['custom_fields'] : [];
347
348 if ( apply_filters( 'timetics/staff/appointment/custom_field_check', false, $custom_fields ) == true ) {
349 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'custom_field_check' ), 403 );
350 }
351
352 $recurring_limit = ! empty( $data['recurring_limit'] ) ? $data['recurring_limit'] : [];
353
354 if ( apply_filters( 'timetics/staff/appointment/recurring_limit_check', false, $recurring_limit ) == true ) {
355
356 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'recurring_limit_check' ), 403 );
357 }
358
359 // End
360
361 return $this->save_appointment( $request );
362 }
363
364 /**
365 * Update appointment
366 *
367 * @param WP_Rest_Request $request
368 *
369 * @return JSON Updated appointment data
370 */
371 public function update_item( $request ) {
372
373 $appointment_id = (int) $request['appointment_id'];
374 $appoint = new Appointment( $appointment_id );
375
376 $data = json_decode( $request->get_body(), true );
377
378 /**
379 * Added temporary for leagacy sass. It will remove in future.
380 */
381 $response = [
382 'success' => 0,
383 'status_code' => 502,
384 'message' => esc_html__( 'Something went wrong', 'timetics' ),
385 'data' => [],
386 ];
387
388 if ( !empty($data['availability']) && $data['availability'] && apply_filters('timetics/staff/meeting/availability', false)) {
389 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'availability_update' ), 403 );
390 }
391
392 if ( ! empty( $data['price'] ) && apply_filters( 'timetics/staff/appointment/price_check', false, $data['price'] ) == true ) {
393 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'price_check' ), 403 );
394 }
395
396 $categories = ! empty( $data['categories'] ) ? $data['categories'] : '';
397
398 if ( apply_filters( 'timetics/staff/appointment/category_check', false, $categories ) == true ) {
399 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'category_check' ), 403 );
400 }
401
402 $staff = ! empty( $data['staff'] ) ? array_map( 'intval', $data['staff'] ) : [];
403
404 if ( apply_filters( 'timetics/staff/appointment/staff_check', false, $staff ) == true ) {
405 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'staff_check' ), 403 );
406 }
407
408 $custom_fields = ! empty( $data['custom_fields'] ) ? $data['custom_fields'] : [];
409
410 if ( apply_filters( 'timetics/staff/appointment/custom_field_check', false, $custom_fields ) == true ) {
411 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'custom_field_check' ), 403 );
412 }
413
414 $recurring_limit = ! empty( $data['recurring_limit'] ) ? $data['recurring_limit'] : [];
415
416 if ( apply_filters( 'timetics/staff/appointment/recurring_limit_check', false, $recurring_limit ) == true ) {
417
418 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'recurring_limit_check' ), 403 );
419 }
420
421 // End.
422
423 if ( ! $appoint->is_appointment() ) {
424
425 $response = [
426 'success' => 0,
427 'status_code' => 404,
428 'message' => esc_html__( 'Invalid appointment id.', 'timetics' ),
429 'data' => [],
430 ];
431
432 return new WP_HTTP_Response( $response, 404 );
433 }
434
435 return $this->save_appointment( $request, $appointment_id );
436 }
437
438 /**
439 * Update permission check
440 *
441 * @param WP_Rest_Request $request
442 *
443 * @return bool
444 */
445 public function update_item_permissions_check( $request ) {
446 $appoinment_id = (int) $request['appointment_id'];
447 $appointment = new Appointment( $appoinment_id );
448
449 $staff_ids = $appointment->get_staff_ids();
450 $author = $appointment->get_author();
451 $current_user_id = get_current_user_id();
452
453 if (
454 current_user_can( 'manage_options' )
455 || current_user_can( 'read_meeting' )
456 || in_array( $current_user_id, $staff_ids )
457 || $author == $current_user_id
458 ) {
459 return true;
460 }
461
462 return false;
463 }
464
465 /**
466 * Get single appointment
467 *
468 * @param WP_Rest_Requesr $request
469 *
470 * @return JSON Single appointment data
471 */
472 public function get_item( $request ) {
473 $appoinment_id = (int) $request['appointment_id'];
474 $appoint = new Appointment( $appoinment_id );
475
476 if ( ! $appoint->is_appointment() ) {
477
478 $data = [
479 'status_code' => 404,
480 'message' => esc_html__( 'Invalid appointment id.', 'timetics' ),
481 'data' => [],
482 ];
483
484 return new WP_HTTP_Response( $data, 404 );
485 }
486
487 $response = [
488 'status_code' => 200,
489 'message' => esc_html__( 'Successfully retrieved appointments', 'timetics' ),
490 'data' => $this->prepare_item( $appoint ),
491 ];
492
493 return rest_ensure_response( $response );
494 }
495
496 /**
497 * Delete single appointment
498 *
499 * @param WP_Rest_Request $request
500 *
501 * @return
502 */
503 public function delete_item( $request ) {
504
505 $appoinment_id = (int) $request['appointment_id'];
506 $appoint = new Appointment( $appoinment_id );
507
508 $current_user_id = get_current_user_id();
509
510 if ( $appoint->get_author() != $current_user_id ) {
511 $data = [
512 'success' => 0,
513 'message' => __( 'You are not allowed to delete this meeting.', 'timetics' ),
514 ];
515
516 return new WP_HTTP_Response( $data, 403 );
517 }
518
519 if ( ! $appoint->is_appointment() ) {
520 return [
521 'status_code' => 404,
522 'message' => esc_html__( 'Invalid appointment id.', 'timetics' ),
523 'data' => [],
524 ];
525 }
526
527 $appoint->delete();
528
529 $response = [
530 'status_code' => 201,
531 'message' => esc_html__( 'Successfully deleted appointment', 'timetics' ),
532 'data' => [
533 'item' => $appoinment_id,
534 ],
535 ];
536
537 return rest_ensure_response( $response );
538 }
539
540 /**
541 * Delete item permission check
542 *
543 * @param WP_Rest_Request $request
544 *
545 * @return bool
546 */
547 public function delete_item_permissions_check( $request ) {
548 $appoinment_id = (int) $request['appointment_id'];
549 $appointment = new Appointment( $appoinment_id );
550
551 $staff_ids = $appointment->get_staff_ids();
552 $author = $appointment->get_author();
553 $current_user_id = get_current_user_id();
554
555 if (
556 current_user_can( 'manage_options' )
557 || $author == $current_user_id
558 ) {
559 return true;
560 }
561
562 return false;
563 }
564
565 /**
566 * Delete multiples
567 *
568 * @param WP_Rest_Request $request
569 *
570 * @return JSON
571 */
572 public function bulk_delete( $request ) {
573
574 $appointments = json_decode( $request->get_body(), true );
575
576 foreach ( $appointments as $appoint ) {
577 $appoint = new Appointment( $appoint );
578
579 if ( ! $appoint->is_appointment() ) {
580 $data = [
581 'success' => 0,
582 'status' => 404,
583 'message' => esc_html__( 'Invalid appointment id.', 'timetics' ),
584 'data' => [],
585 ];
586
587 return new WP_HTTP_Response( $data, 404 );
588 }
589
590 $appoint->delete();
591 }
592
593 return rest_ensure_response( [
594 'success' => 1,
595 'status' => 201,
596 'message' => esc_html__( 'Successfully deleted all appointments', 'timetics' ),
597 'data' => [
598 'items' => $appointments,
599 ],
600 ] );
601 }
602
603 /**
604 * Duplicate appointment
605 *
606 * @since 1.0.0
607 *
608 * @param object $request
609 *
610 * @return JSON
611 */
612 public function duplicate_item( $request ) {
613
614 /**
615 * Added temporary for leagacy sass. It will remove in future.
616 */
617
618 $meetings_count = Appointment::all();
619
620 $response = [
621 'success' => 0,
622 'status_code' => 502,
623 'message' => esc_html__( 'Something went wrong', 'timetics' ),
624 'data' => [],
625 ];
626
627 if ( apply_filters( 'timetics/staff/appointment/count_check', false, $meetings_count ) == true ) {
628 return rest_ensure_response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'count_check' ) );
629 }
630
631 $custom_fields = ! empty( $data['custom_fields'] ) ? $data['custom_fields'] : [];
632
633 if ( apply_filters( 'timetics/staff/appointment/custom_field_check', false, $custom_fields ) == true ) {
634 return rest_ensure_response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'custom_field_check' ) );
635 }
636
637 $appoinment_id = (int) $request['appointment_id'];
638 $appoint = new Appointment( $appoinment_id );
639
640 if ( ! $appoint->is_appointment() ) {
641 return new WP_HTTP_Response(
642 [
643 'success' => 0,
644 'status_code' => 404,
645 'message' => esc_html__( 'Invalid appointment id.', 'timetics' ),
646 'data' => [],
647 ],
648 404
649 );
650 }
651
652 $appoint->duplicate();
653
654 $item = $this->prepare_item( $appoint );
655
656 $response = [
657 'success' => 1,
658 'status_code' => 201,
659 'message' => esc_html__( 'Successfully duplicated appointment', 'timetics' ),
660 'data' => $item,
661 ];
662
663 return rest_ensure_response( $response );
664 }
665
666 /**
667 * Save appointment
668 *
669 * @param WP_Rest_Request $request
670 * @param integer $id Appointment id
671 *
672 * @return JSON Updated appoitment data
673 */
674 public function save_appointment( $request, $id = 0 ) {
675 $appoint = new Appointment( $id );
676
677 $data = json_decode( $request->get_body(), true );
678
679 $data = apply_filters( 'timetics_meeting_data', $data );
680
681 $name = ! empty( $data['name'] ) ? sanitize_text_field( $data['name'] ) : $appoint->get_name();
682 $type = ! empty( $data['type'] ) ? sanitize_text_field( $data['type'] ) : $appoint->get_type();
683 $description = ! empty( $data['description'] ) ? sanitize_text_field( $data['description'] ) : '';
684 $staff = ! empty( $data['staff'] ) ? array_map( 'intval', $data['staff'] ) : $appoint->get_staff();
685 $locations = ! empty( $data['locations'] ) ? $data['locations'] : $appoint->get_locations();
686 $duration = ! empty( $data['duration'] ) ? sanitize_text_field( $data['duration'] ) : '';
687 $schedule = ! empty( $data['schedule'] ) ? $data['schedule'] : $appoint->get_schedule();
688 $blocked_schedule = ! empty( $data['blocked_schedule'] ) ? $data['blocked_schedule'] : $appoint->get_blocked_schedule();
689 $price = ! empty( $data['price'] ) ? $data['price'] : '';
690 $categories = ! empty( $data['categories'] ) ? $data['categories'] : '';
691 $buffer_time = ! empty( $data['buffer_time'] ) ? $data['buffer_time'] : '';
692 $timezone = ! empty( $data['timezone'] ) ? $data['timezone'] : '';
693 $availability = ! empty( $data['availability'] ) ? $data['availability'] : '';
694 $visibility = ! empty( $data['visibility'] ) ? strtolower( $data['visibility'] ) : 'enabled';
695 $notifications = ! empty( $data['notifications'] ) ? $data['notifications'] : '';
696 $fleunt_crm_webhook = ! empty( $data['fleunt_crm_webhook'] ) ? $data['fleunt_crm_webhook'] : '';
697 $fluent_hook_overwrite = ! empty( $data['fluent_hook_overwrite'] ) ? (bool) $data['fluent_hook_overwrite'] : false;
698 $pabbly_hook_overwrite = ! empty( $data['pabbly_hook_overwrite'] ) ? (bool) $data['pabbly_hook_overwrite'] : false;
699 $zapier_hook_overwrite = ! empty( $data['zapier_hook_overwrite'] ) ? (bool) $data['zapier_hook_overwrite'] : false;
700 $pabbly_webook = ! empty( $data['pabbly_webook'] ) ? $data['pabbly_webook'] : '';
701 $zapier_webook = ! empty( $data['zapier_webook'] ) ? $data['zapier_webook'] : '';
702 $min_notice_time = ! empty( $data['min_notice_time'] ) ? $data['min_notice_time'] : '';
703 $custom_fields = ! empty( $data['custom_fields'] ) ? $data['custom_fields'] : [];
704 $guest_enabled = ! empty( $data['guest_enabled'] ) ? intval( $data['guest_enabled'] ) : false;
705 $guest_limit = ! empty( $data['guest_limit'] ) ? intval( $data['guest_limit'] ) : 1;
706 $capacity = ! empty( $data['capacity'] ) ? intval( $data['capacity'] ) : 1;
707 $appointment_id = ! empty( $data['appointment'] ) ? intval( $data['appointment'] ) : 1;
708 $action = $id ? 'updated' : 'created';
709 $buffer_time_before_value = ! empty( $data['buffer_time_before_value'] ) ? $data['buffer_time_before_value'] : 0;
710 $buffer_time_before_unit = ! empty( $data['buffer_time_before_unit'] ) ? $data['buffer_time_before_unit'] : 'min';
711 $buffer_time_after_value = ! empty( $data['buffer_time_after_value'] ) ? $data['buffer_time_after_value'] : 0;
712 $buffer_time_after_unit = ! empty( $data['buffer_time_after_unit'] ) ? $data['buffer_time_after_unit'] : 'min';
713
714 if ( $id ) {
715 $dulicate = $appoint->get_duplicate_nuber();
716 if ( $dulicate && strpos( $name, '-Duplicate' ) == 0 ) {
717 $appoint->update([
718 'duplicate' => 0
719 ]);
720 }
721 }
722
723 if ( is_array( $price ) ) {
724 $ticket_quantity = 0;
725 foreach ( $price as &$ticket ) {
726 if ( empty( $ticket['ticket_price'] ) ) {
727 $ticket['ticket_price'] = 0;
728 }
729 if ( ! empty( $ticket['ticket_quantity'] ) ) {
730 $ticket_quantity += intval( $ticket['ticket_quantity'] );
731 }
732 }
733
734 $capacity = $ticket_quantity;
735 }
736
737 $validate_data = [
738 'name' => $name,
739 'type' => $type,
740 'locations' => $locations,
741 'schedule' => $schedule,
742 'blocked_schedule' => $blocked_schedule,
743 'staff' => $staff,
744
745 ];
746 // Validate input data.
747 $validate = $this->validate( $validate_data, [
748 'name',
749 'type',
750 'locations',
751 'schedule',
752 'staff',
753 ] );
754
755 if ( ! timetics_is_valid_timezone( $timezone ) ) {
756 return new WP_Error( 'timezone_error', __( 'Your timezone is invaid.', 'timetics' ) );
757 }
758
759 $lolcation_errors = $this->get_location_errors( $locations, $staff );
760
761 if ( $lolcation_errors ) {
762 $data = [
763 'status_code' => 409,
764 'success' => 0,
765 'message' => $lolcation_errors,
766 'data' => [],
767 ];
768
769 return new WP_HTTP_Response( $data, 409 );
770 }
771
772 if ( is_wp_error( $validate ) ) {
773 $data = [
774 'status_code' => 409,
775 'success' => 0,
776 'message' => $validate->get_error_messages(),
777 'data' => [],
778 ];
779
780 return new WP_HTTP_Response( $data, 409 );
781 }
782
783 // Save appointment.
784 $appointment_data = [
785 'name' => str_replace( '-Duplicate', '', $name ),
786 'description' => $description,
787 'type' => $type,
788 'locations' => $locations,
789 'staff' => $staff,
790 'duration' => $duration,
791 'price' => $price,
792 'capacity' => $capacity,
793 'schedule' => $schedule,
794 'blocked_schedule' => $blocked_schedule,
795 'categories' => $categories,
796 'timezone' => $timezone,
797 'availability' => $availability,
798 'visibility' => $visibility,
799 'buffer_time' => $buffer_time,
800 'notifications' => $notifications,
801 'fleunt_crm_webhook' => $fleunt_crm_webhook,
802 'fluent_hook_overwrite' => $fluent_hook_overwrite,
803 'pabbly_hook_overwrite' => $pabbly_hook_overwrite,
804 'zapier_hook_overwrite' => $zapier_hook_overwrite,
805 'pabbly_webook' => $pabbly_webook,
806 'zapier_webook' => $zapier_webook,
807 'min_notice_time' => $min_notice_time,
808 'custom_fields' => $custom_fields,
809 'guest_enabled' => $guest_enabled,
810 'guest_limit' => $guest_limit,
811 'buffer_time_before_value' => $buffer_time_before_value,
812 'buffer_time_before_unit' => $buffer_time_before_unit,
813 'buffer_time_after_value' => $buffer_time_after_value,
814 'buffer_time_after_unit' => $buffer_time_after_unit,
815
816 ];
817
818 $appointment_data = apply_filters( 'timetics_meeting_insert_data', $data, $appointment_data );
819
820 $appoint->set_props( $appointment_data );
821 $appoint->save();
822
823 // Assign meeting category.
824 wp_set_post_terms( $appoint->get_id(), $categories, 'timetics-meeting-category' );
825
826 do_action( 'timetics_meeting_after_insert', $appoint, $data );
827
828 // Prepare response data.
829 $item = $this->prepare_item( $appoint );
830
831 $response = [
832 'status_code' => 201,
833 'success' => 1,
834 'message' => sprintf( esc_html__( 'Successfully %s meeting', 'timetics' ), $action ),
835 'data' => $item,
836 ];
837
838 return rest_ensure_response( $response );
839 }
840
841 /**
842 * Prepare item for response
843 *
844 * @param integer $appoinment_id
845 *
846 * @return array
847 */
848 public function prepare_item( $appoint_id, $timezone = '' ) {
849 $appointment = new Appointment( $appoint_id );
850 $dulicate = $appointment->get_duplicate_nuber();
851
852 $dulicate_text = $dulicate ? ' -Duplicate' : '';
853 $custom_fields = $appointment->get_custom_fields();
854 $data = [
855 'id' => $appointment->get_id(),
856 'name' => $appointment->get_name() . $dulicate_text,
857 'image' => $appointment->get_image(),
858 // 'link' => $appointment->get_link(),
859 'description' => $appointment->get_description(),
860 'type' => $appointment->get_type(),
861 'locations' => $appointment->get_locations(),
862 'schedule' => $appointment->get_schedule(),
863 'blocked_schedule' => $appointment->get_blocked_schedule(),
864 'price' => $appointment->get_price(),
865 'categories' => $appointment->get_category_ids(),
866 'staff' => $appointment->get_staff(),
867 'buffer_time' => $appointment->get_buffer_time(),
868 'timezone' => $appointment->get_timezone(),
869 'availability' => $appointment->get_availability(),
870 'visibility' => $appointment->get_visibility(),
871 'duration' => $appointment->get_duration(),
872 'notifications' => $appointment->get_notifications(),
873 'capacity' => $appointment->get_capacity(),
874 'fluent_hook_overwrite' => $appointment->get_fluent_hook_overwrite(),
875 'fleunt_crm_webhook' => $appointment->get_fleunt_crm_webhook(),
876 'pabbly_hook_overwrite' => $appointment->get_pabbly_hook_overwrite(),
877 'pabbly_webook' => $appointment->get_pabbly_webook(),
878 'zapier_hook_overwrite' => $appointment->get_zapier_hook_overwrite(),
879 'zapier_webook' => $appointment->get_zapier_webook(),
880 'min_notice_time' => $appointment->get_min_notice_time(),
881 'custom_fields' => $custom_fields ?: [],
882 'permalink' => get_permalink( $appointment->get_id() ),
883 'guest_enabled' => $appointment->get_guest_enabled(),
884 'guest_limit' => $appointment->get_guest_limit(),
885 'author' => $appointment->get_author(),
886 'buffer_time_before_value' => $appointment->get_buffer_time_before_value(),
887 'buffer_time_before_unit' => $appointment->get_buffer_time_before_unit(),
888 'buffer_time_after_value' => $appointment->get_buffer_time_after_value(),
889 'buffer_time_after_unit' => $appointment->get_buffer_time_after_unit(),
890 ];
891
892 return apply_filters( 'timetics_meeting_json_data', $data, $appointment );
893 }
894
895 /**
896 * Validate location with zoom and google connection
897 *
898 * @param array $locations
899 * @param array $staffs
900 *
901 * @return array
902 */
903 public function get_location_errors( $locations, $staffs ) {
904
905 $errors = [];
906
907 foreach ( $staffs as $staff_id ) {
908 $staff = new Staff( $staff_id );
909 foreach ( $locations as $location ) {
910 switch ( $location['location_type'] ) {
911 case 'google-meet':
912 if ( ! timetics_is_google_meet_connected( $staff_id ) ) {
913 $errors[] = sprintf( '%s %s', $staff->get_display_name(), esc_html__( 'is not connected to google meet. Please connect to google meet then try again', 'timetics' ) );
914 }
915 break;
916 case 'zoom':
917 // Check if zoom addon plugin is active
918 if ( ! is_plugin_active( 'timetics-zoom-addon/timetics-zoom-addon.php' ) ) {
919 $errors[] = sprintf( '%s %s', $staff->get_display_name(), esc_html__( 'Zoom addon plugin is not active. Please activate the plugin then try again', 'timetics' ) );
920 break;
921 }
922
923 // if zoom_connection_type is server_to_server then no need to check for zoom connection
924 if ( timetics_get_option( 'zoom_connection_type' ) == 'server_to_server' ) {
925 break;
926 }
927
928 if ( ! timetics_is_zoom_connected( $staff_id ) ) {
929 $errors[] = sprintf( '%s %s', $staff->get_display_name(), esc_html__( 'is not connected to zoom. Please connect to zoom then try again', 'timetics' ) );
930 }
931 break;
932 }
933 }
934 }
935
936 return $errors;
937 }
938 }
939