PluginProbe
Timetics – Appointment Booking Calendar & Scheduling / 1.0.21
Timetics – Appointment Booking Calendar & Scheduling v1.0.21
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.21, at core/appointments/api-appointment.php

872 lines 31.8 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' => function () {
98 return current_user_can( 'read_meeting' );
99 },
100 ],
101 [
102 'methods' => \WP_REST_Server::DELETABLE,
103 'callback' => [$this, 'delete_item'],
104 'permission_callback' => function () {
105 return current_user_can( 'read_meeting' );
106 },
107 ],
108 ] );
109
110 register_rest_route( $this->namespace, $this->rest_base . '/search', [
111 [
112 'methods' => \WP_REST_Server::READABLE,
113 'callback' => [$this, 'search_items'],
114 'permission_callback' => function () {
115 return current_user_can( 'edit_posts' );
116 },
117 ],
118 ] );
119
120 register_rest_route( $this->namespace, $this->rest_base . '/filter', [
121 [
122 'methods' => \WP_REST_Server::READABLE,
123 'callback' => [$this, 'filter_items'],
124 'permission_callback' => function () {
125 return true;
126 },
127 ],
128 ] );
129
130 register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<appointment_id>[\d]+)' . '/duplicate', [
131 [
132 'methods' => \WP_REST_Server::CREATABLE,
133 'callback' => [$this, 'duplicate_item'],
134 'permission_callback' => function () {
135 return current_user_can( 'edit_meeting' );
136 },
137 ],
138 ] );
139 }
140
141 /**
142 * Get all appointments
143 *
144 * @param WP_Rest_Request $request
145 *
146 * @return JSON
147 */
148 public function get_items( $request ) {
149
150 $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
151 $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
152 $type = ! empty( $request['type'] ) ? sanitize_text_field( $request['type'] ) : '';
153
154 $args = [
155 'posts_per_page' => $per_page,
156 'paged' => $paged,
157 'type' => $type,
158 ];
159
160 if ( ! current_user_can( 'edit_meeting' ) ) {
161 $args['staff'] = get_current_user_id();
162 }
163
164 $appoint = Appointment::all( $args );
165
166 $items = [];
167
168 foreach ( $appoint['items'] as $item ) {
169 $items[] = $this->prepare_item( $item->ID );
170 }
171
172 $data = [
173 'success' => 1,
174 'status_code' => 200,
175 'data' => [
176 'total' => $appoint['total'],
177 'items' => $items,
178 ],
179 ];
180
181 return rest_ensure_response( $data );
182 }
183
184 /**
185 * Search appointment
186 *
187 * @param Object $request
188 *
189 * @return JSON
190 */
191 public function search_items( $request ) {
192 // Prepare search args.
193 $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
194 $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
195 $search = ! empty( $request['search'] ) ? sanitize_text_field( $request['search'] ) : '';
196
197 // Get search.
198 $appointments = new \WP_Query(
199 array(
200 'post_type' => 'timetics-appointment',
201 'posts_per_page' => $per_page,
202 'paged' => $paged,
203 'orderby' => 'ID',
204 'order' => 'DESC',
205
206 // @codingStandardsIgnoreStart
207 'meta_query' => array(
208 'relation' => 'OR',
209 array(
210 'key' => '_tt_apointment_name',
211 'value' => $search,
212 'compare' => 'LIKE',
213 ),
214 array(
215 'key' => '_tt_apointment_type',
216 'value' => $search,
217 'compare' => 'LIKE',
218 ),
219 array(
220 'key' => '_tt_apointment_description',
221 'value' => $search,
222 'compare' => 'LIKE',
223 ),
224 array(
225 'key' => '_tt_apointment_location',
226 'value' => $search,
227 'compare' => 'LIKE',
228 ),
229 array(
230 'key' => '_tt_apointment_duration',
231 'value' => $search,
232 'compare' => 'LIKE',
233 ),
234 array(
235 'key' => '_tt_apointment_schedule',
236 'value' => $search,
237 'compare' => 'LIKE',
238 ),
239 ),
240 // @codingStandardsIgnoreEnd
241 )
242 );
243
244 // Prepare items for response.
245 $items = [];
246
247 foreach ( $appointments->posts as $item ) {
248 $items[] = $this->prepare_item( $item->ID );
249 }
250
251 $data = [
252 'success' => 1,
253 'status' => 200,
254 'data' => [
255 'total' => $appointments->found_posts,
256 'items' => $items,
257 ],
258 ];
259
260 return rest_ensure_response( $data );
261 }
262
263 public function filter_items( $request ) {
264 $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
265 $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
266 $staff = ! empty( $request['staff_id'] ) ? intval( $request['staff_id'] ) : 0;
267 $category = ! empty( $request['category'] ) ? intval( $request['category'] ) : 0;
268 $visibility = ! empty( $request['visibility'] ) ? sanitize_text_field( $request['visibility'] ) : '';
269
270 $per_page = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
271 $paged = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
272
273 $appoint = Appointment::all( [
274 'posts_per_page' => $per_page,
275 'paged' => $paged,
276 'visibility' => $visibility,
277 'staff' => $staff,
278 'category' => $category,
279 ] );
280
281 $items = [];
282
283 foreach ( $appoint['items'] as $item ) {
284 $items[] = $this->prepare_item( $item->ID );
285 }
286
287 $data = [
288 'success' => 1,
289 'status' => 200,
290 'data' => [
291 'total' => $appoint['total'],
292 'items' => $items,
293 ],
294 ];
295
296 return rest_ensure_response( $data );
297 }
298
299 /**
300 * Create appointment
301 *
302 * @param WP_Rest_Request $request
303 *
304 * @return JSON Newly created appointment data
305 */
306 public function create_item( $request ) {
307 /**
308 * Added temporary for leagacy sass. It will remove in future.
309 */
310
311 $meetings_count = Appointment::all();
312 $data = json_decode( $request->get_body(), true );
313
314 $response = [
315 'success' => 0,
316 'status_code' => 403,
317 'message' => esc_html__( 'Something went wrong', 'timetics' ),
318 'data' => [],
319 ];
320
321 if ( ! empty( $data['price'] ) && apply_filters( 'timetics/staff/appointment/price_check', false, $data['price'] ) == true ) {
322 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'price_check' ), 403 );
323 }
324
325 if ( apply_filters( 'timetics/staff/appointment/count_check', false, $meetings_count ) == true ) {
326 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'count_check' ), 403 );
327 }
328
329 $type = ! empty( $data['type'] ) ? sanitize_text_field( $data['type'] ) : '';
330
331 if ( apply_filters( 'timetics/staff/appointment/type_check', false, $type ) == true ) {
332 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'type_check' ), 403 );
333 }
334
335 $categories = ! empty( $data['categories'] ) ? $data['categories'] : '';
336
337 if ( apply_filters( 'timetics/staff/appointment/category_check', false, $categories ) == true ) {
338 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'category_check' ), 403 );
339 }
340
341 $staff = ! empty( $data['staff'] ) ? array_map( 'intval', $data['staff'] ) : [];
342
343 if ( apply_filters( 'timetics/staff/appointment/staff_check', false, $staff ) == true ) {
344 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'staff_check' ), 403 );
345 }
346
347 $custom_fields = ! empty( $data['custom_fields'] ) ? $data['custom_fields'] : [];
348
349 if ( apply_filters( 'timetics/staff/appointment/custom_field_check', false, $custom_fields ) == true ) {
350 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'custom_field_check' ), 403 );
351 }
352
353 $recurring_limit = ! empty( $data['recurring_limit'] ) ? $data['recurring_limit'] : [];
354
355 if ( apply_filters( 'timetics/staff/appointment/recurring_limit_check', false, $recurring_limit ) == true ) {
356
357 return new WP_HTTP_Response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'recurring_limit_check' ), 403 );
358 }
359
360 // End
361
362 return $this->save_appointment( $request );
363 }
364
365 /**
366 * Update appointment
367 *
368 * @param WP_Rest_Request $request
369 *
370 * @return JSON Updated appointment data
371 */
372 public function update_item( $request ) {
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 * Get single appointment
440 *
441 * @param WP_Rest_Requesr $request
442 *
443 * @return JSON Single appointment data
444 */
445 public function get_item( $request ) {
446 $appoinment_id = (int) $request['appointment_id'];
447 $appoint = new Appointment( $appoinment_id );
448
449 if ( ! $appoint->is_appointment() ) {
450
451 $data = [
452 'status_code' => 404,
453 'message' => esc_html__( 'Invalid appointment id.', 'timetics' ),
454 'data' => [],
455 ];
456
457 return new WP_HTTP_Response( $data, 404 );
458 }
459
460 $response = [
461 'status_code' => 200,
462 'message' => esc_html__( 'Successfully retrieved appointments', 'timetics' ),
463 'data' => $this->prepare_item( $appoint ),
464 ];
465
466 return rest_ensure_response( $response );
467 }
468
469 /**
470 * Delete single appointment
471 *
472 * @param WP_Rest_Request $request
473 *
474 * @return
475 */
476 public function delete_item( $request ) {
477 $appoinment_id = (int) $request['appointment_id'];
478 $appoint = new Appointment( $appoinment_id );
479
480 $current_user_id = get_current_user_id();
481
482 if ( $appoint->get_author() != $current_user_id ) {
483 $data = [
484 'success' => 0,
485 'message' => __( 'You are not allowed to delete this meeting.', 'timetics' ),
486 ];
487
488 return new WP_HTTP_Response( $data, 403 );
489 }
490
491 if ( ! $appoint->is_appointment() ) {
492 return [
493 'status_code' => 404,
494 'message' => esc_html__( 'Invalid appointment id.', 'timetics' ),
495 'data' => [],
496 ];
497 }
498
499 $appoint->delete();
500
501 $response = [
502 'status_code' => 201,
503 'message' => esc_html__( 'Successfully deleted appointment', 'timetics' ),
504 'data' => [
505 'item' => $appoinment_id,
506 ],
507 ];
508
509 return rest_ensure_response( $response );
510 }
511
512 /**
513 * Delete multiples
514 *
515 * @param WP_Rest_Request $request
516 *
517 * @return JSON
518 */
519 public function bulk_delete( $request ) {
520 $appointments = json_decode( $request->get_body(), true );
521
522 foreach ( $appointments as $appoint ) {
523 $appoint = new Appointment( $appoint );
524
525 if ( ! $appoint->is_appointment() ) {
526 $data = [
527 'success' => 0,
528 'status' => 404,
529 'message' => esc_html__( 'Invalid appointment id.', 'timetics' ),
530 'data' => [],
531 ];
532
533 return new WP_HTTP_Response( $data, 404 );
534 }
535
536 $appoint->delete();
537 }
538
539 return rest_ensure_response( [
540 'success' => 1,
541 'status' => 201,
542 'message' => esc_html__( 'Successfully deleted all appointments', 'timetics' ),
543 'data' => [
544 'items' => $appointments,
545 ],
546 ] );
547 }
548
549 /**
550 * Duplicate appointment
551 *
552 * @since 1.0.0
553 *
554 * @param object $request
555 *
556 * @return JSON
557 */
558 public function duplicate_item( $request ) {
559 /**
560 * Added temporary for leagacy sass. It will remove in future.
561 */
562
563 $meetings_count = Appointment::all();
564
565 $response = [
566 'success' => 0,
567 'status_code' => 502,
568 'message' => esc_html__( 'Something went wrong', 'timetics' ),
569 'data' => [],
570 ];
571
572 if ( apply_filters( 'timetics/staff/appointment/count_check', false, $meetings_count ) == true ) {
573 return rest_ensure_response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'count_check' ) );
574 }
575
576 $custom_fields = ! empty( $data['custom_fields'] ) ? $data['custom_fields'] : [];
577
578 if ( apply_filters( 'timetics/staff/appointment/custom_field_check', false, $custom_fields ) == true ) {
579 return rest_ensure_response( apply_filters( 'timetics/admin/appointment/error_data', $response, 'custom_field_check' ) );
580 }
581
582 $appoinment_id = (int) $request['appointment_id'];
583 $appoint = new Appointment( $appoinment_id );
584
585 if ( ! $appoint->is_appointment() ) {
586 return new WP_HTTP_Response(
587 [
588 'success' => 0,
589 'status_code' => 404,
590 'message' => esc_html__( 'Invalid appointment id.', 'timetics' ),
591 'data' => [],
592 ],
593 404
594 );
595 }
596
597 $appoint->duplicate();
598
599 $item = $this->prepare_item( $appoint );
600
601 $response = [
602 'success' => 1,
603 'status_code' => 201,
604 'message' => esc_html__( 'Successfully duplicated appointment', 'timetics' ),
605 'data' => $item,
606 ];
607
608 return rest_ensure_response( $response );
609 }
610
611 /**
612 * Save appointment
613 *
614 * @param WP_Rest_Request $request
615 * @param integer $id Appointment id
616 *
617 * @return JSON Updated appoitment data
618 */
619 public function save_appointment( $request, $id = 0 ) {
620 $appoint = new Appointment( $id );
621
622 $data = json_decode( $request->get_body(), true );
623
624 $data = apply_filters( 'timetics_meeting_data', $data );
625
626 $name = ! empty( $data['name'] ) ? sanitize_text_field( $data['name'] ) : $appoint->get_name();
627 $type = ! empty( $data['type'] ) ? sanitize_text_field( $data['type'] ) : $appoint->get_type();
628 $description = ! empty( $data['description'] ) ? sanitize_text_field( $data['description'] ) : '';
629 $staff = ! empty( $data['staff'] ) ? array_map( 'intval', $data['staff'] ) : $appoint->get_staff();
630 $locations = ! empty( $data['locations'] ) ? $data['locations'] : $appoint->get_locations();
631 $duration = ! empty( $data['duration'] ) ? sanitize_text_field( $data['duration'] ) : '';
632 $schedule = ! empty( $data['schedule'] ) ? $data['schedule'] : $appoint->get_schedule();
633 $blocked_schedule = ! empty( $data['blocked_schedule'] ) ? $data['blocked_schedule'] : $appoint->get_blocked_schedule();
634 $price = ! empty( $data['price'] ) ? $data['price'] : '';
635 $categories = ! empty( $data['categories'] ) ? $data['categories'] : '';
636 $buffer_time = ! empty( $data['buffer_time'] ) ? $data['buffer_time'] : '';
637 $timezone = ! empty( $data['timezone'] ) ? $data['timezone'] : '';
638 $availability = ! empty( $data['availability'] ) ? $data['availability'] : '';
639 $visibility = ! empty( $data['visibility'] ) ? strtolower( $data['visibility'] ) : 'enabled';
640 $notifications = ! empty( $data['notifications'] ) ? $data['notifications'] : '';
641 $fleunt_crm_webhook = ! empty( $data['fleunt_crm_webhook'] ) ? $data['fleunt_crm_webhook'] : '';
642 $fluent_hook_overwrite = ! empty( $data['fluent_hook_overwrite'] ) ? (bool) $data['fluent_hook_overwrite'] : false;
643 $pabbly_hook_overwrite = ! empty( $data['pabbly_hook_overwrite'] ) ? (bool) $data['pabbly_hook_overwrite'] : false;
644 $zapier_hook_overwrite = ! empty( $data['zapier_hook_overwrite'] ) ? (bool) $data['zapier_hook_overwrite'] : false;
645 $pabbly_webook = ! empty( $data['pabbly_webook'] ) ? $data['pabbly_webook'] : '';
646 $zapier_webook = ! empty( $data['zapier_webook'] ) ? $data['zapier_webook'] : '';
647 $min_notice_time = ! empty( $data['min_notice_time'] ) ? $data['min_notice_time'] : '';
648 $custom_fields = ! empty( $data['custom_fields'] ) ? $data['custom_fields'] : [];
649 $guest_enabled = ! empty( $data['guest_enabled'] ) ? intval( $data['guest_enabled'] ) : false;
650 $guest_limit = ! empty( $data['guest_limit'] ) ? intval( $data['guest_limit'] ) : 1;
651 $capacity = ! empty( $data['capacity'] ) ? intval( $data['capacity'] ) : 1;
652 $action = $id ? 'update' : 'created';
653
654 if ( $id ) {
655 $current_user_id = get_current_user_id();
656 $dulicate = $appoint->get_duplicate_nuber();
657
658 if ( $appoint->get_author() != $current_user_id ) {
659 $data = [
660 'success' => 0,
661 'message' => __( 'You are not allowed to update this meeting.', 'timetics' ),
662 ];
663
664 return new WP_HTTP_Response( $data, 403 );
665 }
666
667 if ( $dulicate && strpos( $name, '-Duplicate' ) == 0 ) {
668 $appoint->update([
669 'duplicate' => 0
670 ]);
671 }
672 }
673
674 if ( is_array( $price ) ) {
675 $ticket_quantity = 0;
676
677 foreach ( $price as &$ticket ) {
678 if ( empty( $ticket['ticket_price'] ) ) {
679 $ticket['ticket_price'] = 0;
680 }
681 if ( ! empty( $ticket['ticket_quantity'] ) ) {
682 $ticket_quantity += intval( $ticket['ticket_quantity'] );
683 }
684 }
685
686 $capacity = $ticket_quantity;
687 }
688
689 $validate_data = [
690 'name' => $name,
691 'type' => $type,
692 'locations' => $locations,
693 'schedule' => $schedule,
694 'blocked_schedule' => $blocked_schedule,
695 'staff' => $staff,
696
697 ];
698 // Validate input data.
699 $validate = $this->validate( $validate_data, [
700 'name',
701 'type',
702 'locations',
703 'schedule',
704 'staff',
705 ] );
706
707 if ( ! timetics_is_valid_timezone( $timezone ) ) {
708 return new WP_Error( 'timezone_error', __( 'Your timezone is invaid.', 'timetics' ) );
709 }
710
711 $lolcation_errors = $this->get_location_errors( $locations, $staff );
712
713 if ( $lolcation_errors ) {
714 $data = [
715 'status_code' => 409,
716 'success' => 0,
717 'message' => $lolcation_errors,
718 'data' => [],
719 ];
720
721 return new WP_HTTP_Response( $data, 409 );
722 }
723
724 if ( is_wp_error( $validate ) ) {
725 $data = [
726 'status_code' => 409,
727 'success' => 0,
728 'message' => $validate->get_error_messages(),
729 'data' => [],
730 ];
731
732 return new WP_HTTP_Response( $data, 409 );
733 }
734
735 // Save appointment.
736 $appointment_data = [
737 'name' => str_replace( '-Duplicate', '', $name ),
738 'description' => $description,
739 'type' => $type,
740 'locations' => $locations,
741 'staff' => $staff,
742 'duration' => $duration,
743 'price' => $price,
744 'capacity' => $capacity,
745 'schedule' => $schedule,
746 'blocked_schedule' => $blocked_schedule,
747 'categories' => $categories,
748 'timezone' => $timezone,
749 'availability' => $availability,
750 'visibility' => $visibility,
751 'buffer_time' => $buffer_time,
752 'notifications' => $notifications,
753 'fleunt_crm_webhook' => $fleunt_crm_webhook,
754 'fluent_hook_overwrite' => $fluent_hook_overwrite,
755 'pabbly_hook_overwrite' => $pabbly_hook_overwrite,
756 'zapier_hook_overwrite' => $zapier_hook_overwrite,
757 'pabbly_webook' => $pabbly_webook,
758 'zapier_webook' => $zapier_webook,
759 'min_notice_time' => $min_notice_time,
760 'custom_fields' => $custom_fields,
761 'guest_enabled' => $guest_enabled,
762 'guest_limit' => $guest_limit,
763
764 ];
765
766 $appointment_data = apply_filters( 'timetics_meeting_insert_data', $data, $appointment_data );
767
768 $appoint->set_props( $appointment_data );
769 $appoint->save();
770
771 // Assign meeting category.
772 wp_set_post_terms( $appoint->get_id(), $categories, 'timetics-meeting-category' );
773
774 do_action( 'timetics_meeting_after_insert', $appoint, $data );
775
776 // Prepare response data.
777 $item = $this->prepare_item( $appoint );
778
779 $response = [
780 'status_code' => 201,
781 'success' => 1,
782 'message' => sprintf( esc_html__( 'Succssfully %s appointment', 'timetics' ), $action ),
783 'data' => $item,
784 ];
785
786 return rest_ensure_response( $response );
787 }
788
789 /**
790 * Prepare item for response
791 *
792 * @param integer $appoinment_id
793 *
794 * @return array
795 */
796 public function prepare_item( $appoint_id, $timezone = '' ) {
797 $appointment = new Appointment( $appoint_id );
798 $dulicate = $appointment->get_duplicate_nuber();
799
800 $dulicate_text = $dulicate ? ' -Duplicate' : '';
801 $custom_fields = $appointment->get_custom_fields();
802 $data = [
803 'id' => $appointment->get_id(),
804 'name' => $appointment->get_name() . $dulicate_text,
805 'image' => $appointment->get_image(),
806 // 'link' => $appointment->get_link(),
807 'description' => $appointment->get_description(),
808 'type' => $appointment->get_type(),
809 'locations' => $appointment->get_locations(),
810 'schedule' => $appointment->get_schedule(),
811 'blocked_schedule' => $appointment->get_blocked_schedule(),
812 'price' => $appointment->get_price(),
813 'categories' => $appointment->get_category_ids(),
814 'staff' => $appointment->get_staff(),
815 'buffer_time' => $appointment->get_buffer_time(),
816 'timezone' => $appointment->get_timezone(),
817 'availability' => $appointment->get_availability(),
818 'visibility' => $appointment->get_visibility(),
819 'duration' => $appointment->get_duration(),
820 'notifications' => $appointment->get_notifications(),
821 'capacity' => $appointment->get_capacity(),
822 'fluent_hook_overwrite' => $appointment->get_fluent_hook_overwrite(),
823 'fleunt_crm_webhook' => $appointment->get_fleunt_crm_webhook(),
824 'pabbly_hook_overwrite' => $appointment->get_pabbly_hook_overwrite(),
825 'pabbly_webook' => $appointment->get_pabbly_webook(),
826 'zapier_hook_overwrite' => $appointment->get_zapier_hook_overwrite(),
827 'zapier_webook' => $appointment->get_zapier_webook(),
828 'min_notice_time' => $appointment->get_min_notice_time(),
829 'custom_fields' => $custom_fields ?: [],
830 'permalink' => get_permalink( $appointment->get_id() ),
831 'guest_enabled' => $appointment->get_guest_enabled(),
832 'guest_limit' => $appointment->get_guest_limit(),
833 'author' => $appointment->get_author(),
834 ];
835
836 return apply_filters( 'timetics_meeting_json_data', $data, $appointment );
837 }
838
839 /**
840 * Validate location with zoom and google connection
841 *
842 * @param array $locations
843 * @param array $staffs
844 *
845 * @return array
846 */
847 public function get_location_errors( $locations, $staffs ) {
848
849 $errors = [];
850
851 foreach ( $staffs as $staff_id ) {
852 $staff = new Staff( $staff_id );
853 foreach ( $locations as $location ) {
854 switch ( $location['location_type'] ) {
855 case 'google-meet':
856 if ( ! timetics_is_google_meet_connected( $staff_id ) ) {
857 $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' ) );
858 }
859 break;
860 case 'zoom':
861 if ( ! timetics_is_zoom_connected( $staff_id ) ) {
862 $errors[] = sprintf( '%s %s', $staff->get_display_name(), esc_html__( 'is not connected to zoom. Please connect to zoom then try again', 'timetics' ) );
863 }
864 break;
865 }
866 }
867 }
868
869 return $errors;
870 }
871 }
872