PluginProbe ʕ •ᴥ•ʔ
Appointment Booking Plugin – LatePoint | Calendar & Scheduling for WordPress / 5.6.1
Appointment Booking Plugin – LatePoint | Calendar & Scheduling for WordPress v5.6.1
5.6.10 5.6.9 5.6.8 5.6.7 5.6.6 5.6.5 5.6.4 5.6.3 5.6.2 5.6.1 5.6.0 5.5.2 5.5.1 5.5.0 5.4.2 trunk 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.91 5.1.92 5.1.93 5.1.94 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1
latepoint / lib / controllers / bookings_controller.php
latepoint / lib / controllers Last commit date
activities_controller.php 3 months ago auth_controller.php 4 months ago booking_form_settings_controller.php 4 months ago bookings_controller.php 2 months ago calendars_controller.php 4 months ago carts_controller.php 4 months ago controller.php 4 months ago customer_cabinet_controller.php 3 months ago customers_controller.php 4 months ago dashboard_controller.php 3 months ago default_agent_controller.php 4 months ago events_controller.php 4 months ago form_fields_controller.php 4 months ago integrations_controller.php 4 months ago invoices_controller.php 2 months ago manage_booking_by_key_controller.php 4 months ago manage_order_by_key_controller.php 4 months ago notifications_controller.php 4 months ago orders_controller.php 4 months ago pro_controller.php 3 months ago process_jobs_controller.php 4 months ago processes_controller.php 2 months ago razorpay_connect_controller.php 2 months ago search_controller.php 4 months ago services_controller.php 4 months ago settings_controller.php 3 months ago steps_controller.php 4 months ago stripe_connect_controller.php 3 months ago support_topics_controller.php 4 months ago todos_controller.php 4 months ago transactions_controller.php 4 months ago wizard_controller.php 3 months ago
bookings_controller.php
612 lines
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit; // Exit if accessed directly.
4 }
5
6
7 if ( ! class_exists( 'OsBookingsController' ) ) :
8
9
10 class OsBookingsController extends OsController {
11
12 private $booking;
13
14 function __construct() {
15 parent::__construct();
16 $this->views_folder = LATEPOINT_VIEWS_ABSPATH . 'bookings/';
17 $this->vars['page_header'] = OsMenuHelper::get_menu_items_by_id( 'appointments' );
18 $this->vars['breadcrumbs'][] = array(
19 'label' => __( 'Appointments', 'latepoint' ),
20 'link' => OsRouterHelper::build_link( [ 'bookings', 'pending_approval' ] ),
21 );
22 }
23
24 public function view_booking_log() {
25 $activities = new OsActivityModel();
26 $activities = $activities->where( [ 'booking_id' => absint( $this->params['booking_id'] ) ] )->order_by( 'id desc' )->get_results_as_models();
27
28 $booking = new OsBookingModel( $this->params['booking_id'] );
29
30 $this->vars['booking'] = $booking;
31 $this->vars['activities'] = $activities;
32
33 $this->format_render( __FUNCTION__ );
34 }
35
36 public function grouped_bookings_quick_view() {
37 if ( ! isset( $this->params['booking_id'] ) ) {
38 return false;
39 }
40
41 $booking = new OsBookingModel( $this->params['booking_id'] );
42 $this->vars['booking'] = $booking;
43
44 $group_bookings = new OsBookingModel();
45 $group_bookings = $group_bookings->where(
46 [
47 'start_time' => $booking->start_time,
48 'start_date' => $booking->start_date,
49 'service_id' => $booking->service_id,
50 'location_id' => $booking->location_id,
51 'agent_id' => $booking->agent_id,
52 ]
53 )->should_not_be_cancelled()->get_results_as_models();
54 $total_attendees = 0;
55 if ( $group_bookings ) {
56 foreach ( $group_bookings as $group_booking ) {
57 $total_attendees = $total_attendees + $group_booking->total_attendees;
58 }
59 }
60 $this->vars['total_attendees'] = $total_attendees;
61 $this->vars['group_bookings'] = $group_bookings;
62 $this->format_render( __FUNCTION__ );
63 }
64
65 public function pending_approval() {
66 $this->vars['page_header'] = __( 'Pending Appointments', 'latepoint' );
67 $this->vars['breadcrumbs'][] = array(
68 'label' => __( 'Pending Appointments', 'latepoint' ),
69 'link' => false,
70 );
71
72 $page_number = isset( $this->params['page_number'] ) ? $this->params['page_number'] : 1;
73 $per_page = OsSettingsHelper::get_number_of_records_per_page();
74 $offset = ( $page_number > 1 ) ? ( ( $page_number - 1 ) * $per_page ) : 0;
75
76 $bookings = new OsBookingModel();
77 $query_args = [ 'status' => OsBookingHelper::get_booking_statuses_for_pending_page() ];
78
79 $bookings->where( $query_args )->filter_allowed_records();
80
81 $count_total_bookings = clone $bookings;
82 $total_bookings = $count_total_bookings->count();
83
84 $this->vars['bookings'] = $bookings->set_limit( $per_page )->set_offset( $offset )->order_by( 'id desc' )->get_results_as_models();
85
86 $total_pages = ceil( $total_bookings / $per_page );
87
88 $this->vars['total_pages'] = $total_pages;
89 $this->vars['total_bookings'] = $total_bookings;
90 $this->vars['per_page'] = $per_page;
91 $this->vars['current_page_number'] = $page_number;
92
93 $this->vars['showing_from'] = ( ( $page_number - 1 ) * $per_page ) ? ( ( $page_number - 1 ) * $per_page ) : 1;
94 $this->vars['showing_to'] = min( $page_number * $per_page, $this->vars['total_bookings'] );
95
96 $this->format_render( __FUNCTION__ );
97 }
98
99 public function customize_table() {
100 $this->vars['selected_columns'] = OsSettingsHelper::get_selected_columns_for_bookings_table();
101 $this->vars['available_columns'] = OsSettingsHelper::get_available_columns_for_bookings_table();
102 $this->vars['ordered_columns'] = OsSettingsHelper::get_ordered_bookings_table_columns();
103
104 $this->format_render( __FUNCTION__ );
105 }
106
107 public function index() {
108
109 $this->vars['page_header'] = false;
110 $this->vars['breadcrumbs'][] = array(
111 'label' => __( 'All', 'latepoint' ),
112 'link' => false,
113 );
114
115 $page_number = isset( $this->params['page_number'] ) ? $this->params['page_number'] : 1;
116 $per_page = OsSettingsHelper::get_number_of_records_per_page();
117 $offset = ( $page_number > 1 ) ? ( ( $page_number - 1 ) * $per_page ) : 0;
118
119 $customer = new OsCustomerModel();
120
121 $bookings = new OsBookingModel();
122 $query_args = [];
123
124 $selected_columns = OsSettingsHelper::get_selected_columns_for_bookings_table();
125 $available_columns = OsSettingsHelper::get_available_columns_for_bookings_table();
126 $ordered_columns = OsSettingsHelper::get_ordered_bookings_table_columns();
127
128 $filter = $this->params['filter'] ?? false;
129
130 $order_by = [
131 'key' => 'booking_id',
132 'direction' => 'desc',
133 'column' => 'id',
134 ];
135
136 // TABLE SEARCH FILTERS
137 if ( $filter ) {
138 if ( ! empty( $filter['records_ordered_by_key'] ) && ! empty( $filter['records_ordered_by_direction'] ) ) {
139 if ( in_array( $filter['records_ordered_by_direction'], [ 'desc', 'asc' ] ) ) {
140 $order_by['direction'] = $filter['records_ordered_by_direction'];
141 }
142 $order_by['key'] = $filter['records_ordered_by_key'];
143 switch ( $filter['records_ordered_by_key'] ) {
144 case 'booking_id':
145 $order_by['column'] = 'id';
146 break;
147 case 'booking_start_datetime':
148 $order_by['column'] = 'start_datetime_utc';
149 break;
150 case 'booking_created_on':
151 $order_by['column'] = 'created_at';
152 break;
153 case 'booking_time_left':
154 $order_by['column'] = 'start_datetime_utc';
155 break;
156 }
157 }
158 if ( ! empty( $filter['service_id'] ) ) {
159 $query_args['service_id'] = $filter['service_id'];
160 }
161 if ( ! empty( $filter['agent_id'] ) ) {
162 $query_args['agent_id'] = $filter['agent_id'];
163 }
164 if ( ! empty( $filter['location_id'] ) ) {
165 $query_args['location_id'] = $filter['location_id'];
166 }
167 if ( ! empty( $filter['time_status'] ) ) {
168 switch ( $filter['time_status'] ) {
169 case 'now':
170 $query_args['start_datetime_utc <='] = OsTimeHelper::now_datetime_utc_in_db_format();
171 $query_args['end_datetime_utc >='] = OsTimeHelper::now_datetime_utc_in_db_format();
172 break;
173 case 'upcoming':
174 $query_args['start_datetime_utc >='] = OsTimeHelper::now_datetime_utc_in_db_format();
175 break;
176 case 'past':
177 $query_args['end_datetime_utc <='] = OsTimeHelper::now_datetime_utc_in_db_format();
178 break;
179 }
180 }
181 if ( ! empty( $filter['status'] ) ) {
182 $query_args[ LATEPOINT_TABLE_BOOKINGS . '.status' ] = $filter['status'];
183 }
184 if ( ! empty( $filter['payment_status'] ) ) {
185 $query_args[ LATEPOINT_TABLE_BOOKINGS . '.payment_status' ] = $filter['payment_status'];
186 }
187 if ( ! empty( $filter['id'] ) ) {
188 $query_args[ LATEPOINT_TABLE_BOOKINGS . '.id' ] = $filter['id'];
189 }
190 if ( ! empty( $filter['created_date_from'] ) && ! empty( $filter['created_date_to'] ) ) {
191 $query_args[ LATEPOINT_TABLE_BOOKINGS . '.created_at >=' ] = $filter['created_date_from'] . ' 00:00:00';
192 $query_args[ LATEPOINT_TABLE_BOOKINGS . '.created_at <=' ] = $filter['created_date_to'] . ' 23:59:59';
193 }
194 if ( ! empty( $filter['booking_date_from'] ) && ! empty( $filter['booking_date_to'] ) ) {
195 $query_args[ LATEPOINT_TABLE_BOOKINGS . '.start_date >=' ] = $filter['booking_date_from'];
196 $query_args[ LATEPOINT_TABLE_BOOKINGS . '.start_date <=' ] = $filter['booking_date_to'];
197 }
198
199 $selected_columns = OsSettingsHelper::get_selected_columns_for_bookings_table();
200 if ( ! empty( $filter['order'] ) ) {
201 $bookings->select( LATEPOINT_TABLE_BOOKINGS . '.*' );
202 $bookings->join( LATEPOINT_TABLE_ORDER_ITEMS, [ 'id' => LATEPOINT_TABLE_BOOKINGS . '.order_item_id' ] );
203 $bookings->join( LATEPOINT_TABLE_ORDERS, [ 'id' => LATEPOINT_TABLE_ORDER_ITEMS . '.order_id' ] );
204 if ( ! empty( $filter['order']['payment_status'] ) ) {
205 $bookings->select( LATEPOINT_TABLE_ORDERS . '.payment_status' );
206 $query_args[ LATEPOINT_TABLE_ORDERS . '.payment_status' ] = $filter['order']['payment_status'];
207 }
208 }
209 if ( ! empty( $filter['customer'] ) ) {
210 $bookings->select( LATEPOINT_TABLE_BOOKINGS . '.*' );
211 if ( ! empty( $filter['customer']['full_name'] ) ) {
212 $bookings->select( LATEPOINT_TABLE_CUSTOMERS . '.first_name, ' . LATEPOINT_TABLE_CUSTOMERS . '.last_name' );
213 $query_args[ 'concat_ws(" ", ' . LATEPOINT_TABLE_CUSTOMERS . '.first_name,' . LATEPOINT_TABLE_CUSTOMERS . '.last_name) LIKE' ] = '%' . $filter['customer']['full_name'] . '%';
214 $this->vars['customer_name_query'] = $filter['customer']['full_name'];
215 }
216 $bookings->join( LATEPOINT_TABLE_CUSTOMERS, [ 'id' => LATEPOINT_TABLE_BOOKINGS . '.customer_id' ] );
217
218
219 if ( ! empty( $selected_columns['customer'] ) ) {
220 $meta_filter = [];
221 foreach ( $selected_columns['customer'] as $customer_column_key ) {
222
223 if ( isset( $available_columns['customer'][ $customer_column_key ] ) && ! empty( $filter['customer'][ $customer_column_key ] ) ) {
224
225 if ( in_array( $customer_column_key, $customer->get_params_to_save() ) ) {
226 // native field
227 $bookings->select( LATEPOINT_TABLE_CUSTOMERS . '.' . $customer_column_key );
228 $query_args[ LATEPOINT_TABLE_CUSTOMERS . '.' . $customer_column_key . ' LIKE' ] = '%' . $filter['customer'][ $customer_column_key ] . '%';
229 } else {
230 // meta field
231 $meta_filter[ $customer_column_key ] = $filter['customer'][ $customer_column_key ];
232 }
233 }
234 }
235 if ( count( $meta_filter ) ) {
236 $customers_ids = OsMetaHelper::get_customers_by_filter( $meta_filter ) ?: [ - 1 ];
237 $query_args[ LATEPOINT_TABLE_CUSTOMERS . '.id IN' ] = $customers_ids;
238 }
239 }
240 }
241 // filters for custom selected columns, only related to booking fields
242 if ( ! empty( $selected_columns['booking'] ) ) {
243 foreach ( $selected_columns['booking'] as $booking_column_key ) {
244 if ( ! empty( $available_columns['booking'][ $booking_column_key ] ) && ! empty( $filter[ $booking_column_key ] ) ) {
245 $query_args[ $booking_column_key . ' LIKE' ] = '%' . $filter[ $booking_column_key ] . '%';
246 }
247 }
248 }
249 }
250
251 $this->vars['agents_list'] = OsAgentHelper::get_agents_list( true );
252 $this->vars['locations_list'] = OsLocationHelper::get_locations_list( true );
253 $this->vars['services_list'] = OsServiceHelper::get_services_list( true );
254
255 $this->vars['selected_columns'] = $selected_columns;
256 $this->vars['available_columns'] = $available_columns;
257 $this->vars['ordered_columns'] = $ordered_columns;
258
259 $this->vars['records_ordered_by_key'] = $order_by['key'];
260 $this->vars['records_ordered_by_direction'] = $order_by['direction'];
261
262 // OUTPUT CSV IF REQUESTED
263 if ( isset( $this->params['download'] ) && $this->params['download'] == 'csv' ) {
264 $csv_filename = 'all_bookings_' . OsUtilHelper::random_text() . '.csv';
265
266 header( 'Content-Type: text/csv' );
267 header( "Content-Disposition: attachment; filename={$csv_filename}" );
268
269 $labels_row = [
270 __( 'ID', 'latepoint' ),
271 __( 'Service', 'latepoint' ),
272 __( 'Start Date & Time', 'latepoint' ),
273 __( 'Duration', 'latepoint' ),
274 __( 'Customer', 'latepoint' ),
275 __( 'Customer Phone', 'latepoint' ),
276 __( 'Customer Email', 'latepoint' ),
277 __( 'Agent', 'latepoint' ),
278 __( 'Agent Phone', 'latepoint' ),
279 __( 'Agent Email', 'latepoint' ),
280 __( 'Status', 'latepoint' ),
281 __( 'Price', 'latepoint' ),
282 __( 'Booked On', 'latepoint' ),
283 ];
284
285
286 $bookings_data = [];
287 $bookings_data[] = $labels_row;
288
289
290 $bookings_arr = $bookings->where( $query_args )->filter_allowed_records()->order_by( $order_by['column'] . ' ' . $order_by['direction'] )->get_results_as_models();
291
292 if ( $bookings_arr ) {
293 foreach ( $bookings_arr as $booking ) {
294 $order_item = new OsOrderItemModel( $booking->order_item_id );
295 $values_row = [
296 $booking->id,
297 $booking->service->name,
298 $booking->nice_start_datetime,
299 $booking->get_total_duration(),
300 $booking->customer->full_name,
301 $booking->customer->phone,
302 $booking->customer->email,
303 $booking->agent->full_name,
304 $booking->agent->phone,
305 $booking->agent->email,
306 $booking->nice_status,
307 OsMoneyHelper::format_price( $order_item->get_total(), true, false ),
308 $booking->nice_created_at,
309 ];
310 $values_row = apply_filters( 'latepoint_booking_row_for_csv_export', $values_row, $booking, $this->params );
311 $bookings_data[] = $values_row;
312 }
313 }
314
315 $bookings_data = apply_filters( 'latepoint_bookings_data_for_csv_export', $bookings_data, $this->params );
316 OsCSVHelper::array_to_csv( $bookings_data );
317
318 return;
319 }
320
321 $query_args = OsRolesHelper::filter_allowed_records_from_arguments_or_filter( $query_args );
322 $bookings->where( $query_args )->filter_allowed_records();
323 $count_total_bookings = clone $bookings;
324 $total_bookings = $count_total_bookings->count();
325
326 $this->vars['bookings'] = $bookings->set_limit( $per_page )->set_offset( $offset )->order_by( $order_by['column'] . ' ' . $order_by['direction'] )->get_results_as_models();
327 $this->vars['total_bookings'] = $total_bookings;
328 $total_pages = ceil( $total_bookings / $per_page );
329
330 $this->vars['total_pages'] = $total_pages;
331 $this->vars['per_page'] = $per_page;
332 $this->vars['current_page_number'] = $page_number;
333 $this->vars['total_records'] = $total_bookings;
334
335 $this->vars['showing_from'] = ( ( $page_number - 1 ) * $per_page ) ? ( ( $page_number - 1 ) * $per_page ) : 1;
336 $this->vars['showing_to'] = min( $page_number * $per_page, $this->vars['total_bookings'] );
337
338 $this->format_render(
339 [
340 'json_view_name' => '_table_body',
341 'html_view_name' => __FUNCTION__,
342 ],
343 [],
344 [
345 'total_pages' => $total_pages,
346 'showing_from' => $this->vars['showing_from'],
347 'showing_to' => $this->vars['showing_to'],
348 'total_records' => $total_bookings,
349 ]
350 );
351 }
352
353 function quick_availability() {
354
355 $trigger_form_booking_id = $this->params['trigger_form_booking_id'];
356 $trigger_form_order_item_id = $this->params['trigger_form_order_item_id'];
357
358 $booking = OsOrdersHelper::create_booking_object_from_booking_data_form( $this->params['order_items'][ $trigger_form_order_item_id ]['bookings'][ $trigger_form_booking_id ] );
359
360 $calendar_start_date = isset( $this->params['start_date'] ) ? new OsWpDateTime( $this->params['start_date'] ) : new OsWpDateTime( $booking->start_date );
361 // show one more day before so the current selection does not look weird
362 if ( isset( $this->params['previous_days'] ) ) {
363 $calendar_end_date = clone $calendar_start_date;
364 $calendar_start_date->modify( '-60 days' );
365 } else {
366 if ( ! isset( $this->params['show_days_only'] ) ) {
367 $calendar_start_date->modify( '-1 day' );
368 }
369 $calendar_end_date = clone $calendar_start_date;
370 $calendar_end_date->modify( '+60 days' );
371 }
372
373 if ( OsAuthHelper::get_current_user()->is_single_record_allowed( 'agent' ) ) {
374 $booking->agent_id = OsRolesHelper::get_allowed_records( 'agent' )[0];
375 }
376
377 $work_periods = OsWorkPeriodsHelper::get_work_periods(
378 new \LatePoint\Misc\Filter(
379 [
380 'date_from' => $calendar_start_date->format( 'Y-m-d' ),
381 'date_to' => $calendar_end_date->format( 'Y-m-d' ),
382 'service_id' => $booking->service_id,
383 'agent_id' => $booking->agent_id,
384 'location_id' => $booking->location_id,
385 ]
386 )
387 );
388 $work_start_end = OsWorkPeriodsHelper::get_work_start_end_time( $work_periods );
389
390 $booking_request = \LatePoint\Misc\BookingRequest::create_from_booking_model( $booking );
391 $settings = [];
392 $settings['accessed_from_backend'] = true;
393 if ( ! $booking->is_new_record() ) {
394 $settings['exclude_booking_ids'] = [ $booking->id ];
395 }
396 $resources = OsResourceHelper::get_resources_grouped_by_day( $booking_request, $calendar_start_date, $calendar_end_date, $settings );
397 $work_boundaries = OsResourceHelper::get_work_boundaries_for_groups_of_resources( $resources );
398
399 $this->vars['trigger_form_booking_id'] = $trigger_form_booking_id;
400 $this->vars['trigger_form_order_item_id'] = $trigger_form_order_item_id;
401
402 $this->vars['booking'] = $booking;
403 $this->vars['work_boundaries'] = $work_boundaries;
404 $this->vars['show_days_only'] = isset( $this->params['show_days_only'] ) ? true : false;
405
406 $this->vars['timeblock_interval'] = $booking->service->get_timeblock_interval();
407 $this->vars['calendar_start_date'] = $calendar_start_date;
408 $this->vars['calendar_end_date'] = $calendar_end_date;
409 $this->vars['booking_request'] = $booking_request;
410 $this->vars['resources'] = $resources;
411
412 $agents = new OsAgentModel();
413 $this->vars['agents'] = $agents->filter_allowed_records()->get_results_as_models();
414
415 $this->format_render( __FUNCTION__ );
416 }
417
418
419 /**
420 * Maximum number of appointments accepted in a single bulk-delete request.
421 * Acts as a guard against accidental or malicious oversized payloads.
422 */
423 const BULK_DESTROY_MAX_IDS = 100;
424
425 /**
426 * Bulk-delete appointments by ID.
427 *
428 * Expects POST params:
429 * - _wpnonce: nonce for action 'bulk_destroy_bookings'.
430 * - ids: array of booking IDs (or comma-separated string).
431 *
432 * Verifies the user can delete bookings, validates input, then attempts to
433 * delete each ID after a per-record capability check. Fires the standard
434 * latepoint_booking_will_be_deleted / latepoint_booking_deleted hooks per
435 * successful deletion and logs activity.
436 *
437 * Responds with JSON containing status, message, deleted_ids, failed_ids,
438 * deleted_count and failed_count.
439 *
440 * @return void
441 */
442 public function bulk_destroy() {
443 $this->check_nonce( 'bulk_destroy_bookings' );
444
445 if ( ! OsRolesHelper::can_user_perform_model_action( 'OsBookingModel', 'delete' ) ) {
446 $this->send_json(
447 array(
448 'status' => LATEPOINT_STATUS_ERROR,
449 'message' => __( 'You do not have permission to delete appointments.', 'latepoint' ),
450 )
451 );
452 return;
453 }
454
455 $raw_ids = $this->params['ids'] ?? array();
456 if ( ! is_array( $raw_ids ) ) {
457 $raw_ids = explode( ',', (string) $raw_ids );
458 }
459
460 $ids = array();
461 foreach ( $raw_ids as $raw_id ) {
462 $id = absint( $raw_id );
463 if ( $id ) {
464 $ids[ $id ] = $id;
465 }
466 }
467
468 if ( empty( $ids ) ) {
469 $this->send_json(
470 array(
471 'status' => LATEPOINT_STATUS_ERROR,
472 'message' => __( 'No appointments selected.', 'latepoint' ),
473 )
474 );
475 return;
476 }
477
478 if ( count( $ids ) > self::BULK_DESTROY_MAX_IDS ) {
479 $this->send_json(
480 array(
481 'status' => LATEPOINT_STATUS_ERROR,
482 'message' => sprintf(
483 /* translators: %d: maximum number of appointments allowed in a single bulk action */
484 __( 'Too many appointments selected. Please delete in batches of %d or fewer.', 'latepoint' ),
485 self::BULK_DESTROY_MAX_IDS
486 ),
487 )
488 );
489 return;
490 }
491
492 ignore_user_abort( true );
493 if ( function_exists( 'set_time_limit' ) ) {
494 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
495 @set_time_limit( 0 );
496 }
497
498 $deleted_ids = array();
499 $failed_ids = array();
500
501 foreach ( $ids as $id ) {
502 $booking = new OsBookingModel( $id );
503 if ( $booking->is_new_record() ) {
504 $failed_ids[] = $id;
505 continue;
506 }
507 if ( ! OsRolesHelper::can_user_make_action_on_model_record( $booking, 'delete' ) ) {
508 $failed_ids[] = $id;
509 continue;
510 }
511
512 /**
513 * Fires right before a booking is about to be deleted via bulk delete.
514 *
515 * @param {integer} $booking_id ID of the booking that will be deleted.
516 * @since 5.2.0
517 * @hook latepoint_booking_will_be_deleted
518 */
519 do_action( 'latepoint_booking_will_be_deleted', $id );
520
521 if ( $booking->delete() ) {
522 /**
523 * Fires right after a booking has been deleted via bulk delete.
524 *
525 * @param {integer} $booking_id ID of the booking that was deleted.
526 * @since 5.2.0
527 * @hook latepoint_booking_deleted
528 */
529 do_action( 'latepoint_booking_deleted', $id );
530 OsActivitiesHelper::log_booking_deleted( $booking );
531 $deleted_ids[] = $id;
532 } else {
533 $failed_ids[] = $id;
534 }
535 }
536
537 $deleted_count = count( $deleted_ids );
538 $failed_count = count( $failed_ids );
539
540 if ( $deleted_count && ! $failed_count ) {
541 $status = LATEPOINT_STATUS_SUCCESS;
542 $message = sprintf(
543 /* translators: %d: number of appointments deleted */
544 _n( '%d appointment deleted successfully.', '%d appointments deleted successfully.', $deleted_count, 'latepoint' ),
545 $deleted_count
546 );
547 } elseif ( $deleted_count && $failed_count ) {
548 $status = LATEPOINT_STATUS_SUCCESS;
549 $message = sprintf(
550 /* translators: 1: number of appointments deleted, 2: number of appointments that could not be deleted */
551 __( '%1$d appointment(s) deleted. %2$d could not be deleted.', 'latepoint' ),
552 $deleted_count,
553 $failed_count
554 );
555 } else {
556 $status = LATEPOINT_STATUS_ERROR;
557 $message = sprintf(
558 /* translators: %d: number of appointments that could not be deleted */
559 _n( '%d appointment could not be deleted.', '%d appointments could not be deleted.', $failed_count, 'latepoint' ),
560 $failed_count
561 );
562 }
563
564 $this->send_json(
565 array(
566 'status' => $status,
567 'message' => $message,
568 'deleted_ids' => $deleted_ids,
569 'failed_ids' => $failed_ids,
570 'deleted_count' => $deleted_count,
571 'failed_count' => $failed_count,
572 )
573 );
574 }
575
576
577 function change_status() {
578
579 if ( filter_var( $this->params['id'], FILTER_VALIDATE_INT ) ) {
580 $this->check_nonce( 'change_status_booking_' . $this->params['id'] );
581 $booking_id = $this->params['id'];
582 $new_status = $this->params['status'];
583 $booking = new OsBookingModel( $booking_id );
584 if ( ! OsRolesHelper::can_user_make_action_on_model_record( $booking, 'edit' ) ) {
585 exit;
586 }
587
588 if ( $booking->update_status( $new_status ) ) {
589 $status = LATEPOINT_STATUS_SUCCESS;
590 $response_html = __( 'Appointment Status Updated', 'latepoint' );
591 } else {
592 $status = LATEPOINT_STATUS_ERROR;
593 $response_html = __( 'Error Updating Booking Status!', 'latepoint' ) . ' ' . implode( ',', $booking->get_error_messages() );
594 }
595 } else {
596 $status = LATEPOINT_STATUS_ERROR;
597 $response_html = __( 'Error Updating Booking Status! Invalid ID', 'latepoint' );
598 }
599
600 if ( $this->get_return_format() == 'json' ) {
601 $this->send_json(
602 array(
603 'status' => $status,
604 'message' => $response_html,
605 )
606 );
607 }
608 }
609 }
610
611 endif;
612