PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.6.2
LatePoint – Calendar Booking Plugin for Appointments and Events v5.6.2
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 / models / booking_model.php
latepoint / lib / models Last commit date
activity_model.php 3 months ago agent_meta_model.php 3 months ago agent_model.php 3 months ago booking_meta_model.php 3 months ago booking_model.php 1 month ago bundle_meta_model.php 3 months ago bundle_model.php 3 months ago cart_item_model.php 3 months ago cart_meta_model.php 3 months ago cart_model.php 3 weeks ago connector_model.php 3 months ago customer_meta_model.php 3 months ago customer_model.php 1 month ago invoice_model.php 3 weeks ago join_bundles_services_model.php 3 months ago location_category_model.php 3 months ago location_model.php 3 months ago meta_model.php 3 months ago model.php 3 months ago off_period_model.php 3 months ago order_intent_meta_model.php 3 months ago order_intent_model.php 3 months ago order_item_model.php 3 months ago order_meta_model.php 3 months ago order_model.php 1 month ago otp_model.php 3 months ago payment_request_model.php 3 months ago process_job_model.php 3 months ago process_model.php 1 month ago recurrence_model.php 3 months ago service_category_model.php 3 months ago service_meta_model.php 3 months ago service_model.php 3 months ago session_model.php 3 months ago settings_model.php 3 months ago step_settings_model.php 3 months ago transaction_intent_model.php 3 months ago transaction_model.php 3 months ago transaction_refund_model.php 3 months ago work_period_model.php 3 months ago
booking_model.php
1317 lines
1 <?php
2
3 /**
4 * @property OsCustomerModel $customer
5 * @property OsAgentModel $agent
6 * @property OsServiceModel $service
7 * @property OsLocationModel $location
8 */
9 class OsBookingModel extends OsModel {
10 public $id,
11 $booking_code,
12 $service_id,
13 $customer_id,
14 $agent_id,
15 $location_id,
16 $recurrence_id,
17 $buffer_before = 0,
18 $buffer_after = 0,
19 $status,
20 $start_date,
21 $end_date,
22 $start_time,
23 $end_time,
24 $start_datetime_utc,
25 $end_datetime_utc,
26 $duration,
27 $total_attendees = 1,
28 $total_attendees_sum = 1,
29 $total_customers = 1,
30 $cart_item_id = null,
31 $order_item_id,
32 $server_timezone,
33 $customer_timezone,
34 $meta_class = 'OsBookingMetaModel',
35 $keys_to_manage = [],
36 $generate_recurrent_sequence = [],
37 $updated_at,
38 $created_at;
39
40 function __construct( $id = false ) {
41 parent::__construct();
42 $this->table_name = LATEPOINT_TABLE_BOOKINGS;
43 $this->nice_names = array(
44 'service_id' => __( 'Service', 'latepoint' ),
45 'agent_id' => __( 'Agent', 'latepoint' ),
46 );
47
48 if ( $id ) {
49 $this->load_by_id( $id );
50 }
51 }
52
53
54 /**
55 * @return mixed|void
56 *
57 * Returns full amount to charge in database format 1999.0000
58 *
59 */
60 public function full_amount_to_charge() {
61 return OsBookingHelper::calculate_full_amount_for_booking( $this );
62 }
63
64 /**
65 * @return mixed|void
66 *
67 * Returns deposit amount to charge in database format 1999.0000
68 *
69 */
70 public function deposit_amount_to_charge() {
71 return OsBookingHelper::calculate_deposit_amount_to_charge( $this );
72 }
73
74
75 public function get_key_to_manage_for( string $for ): string {
76 if ( $this->is_new_record() ) {
77 return '';
78 }
79 if ( ! empty( $this->keys_to_manage[ $for ] ) ) {
80 return $this->keys_to_manage[ $for ];
81 }
82 $key = OsMetaHelper::get_booking_meta_by_key( 'key_to_manage_for_' . $for, $this->id );
83 if ( empty( $key ) ) {
84 $key = OsUtilHelper::generate_key_to_manage();
85 OsMetaHelper::save_booking_meta_by_key( 'key_to_manage_for_' . $for, $key, $this->id );
86 }
87 $this->keys_to_manage[ $for ] = $key;
88 return $key;
89 }
90
91 public function manage_by_key_url( string $for = 'customer' ): string {
92 return OsBookingHelper::generate_direct_manage_booking_url( $this, $for );
93 }
94
95 public function get_service_name_for_summary() {
96 $service_name = $this->service_id ? $this->service->name : '';
97
98 /**
99 * Get service name to be displayed on a booking summary
100 *
101 * @param {string} $service_name Service name to be filtered
102 * @param {OsBookingModel} $booking Booking model which service name is requested
103 *
104 * @returns {string} Filtered service name
105 * @since 5.0.0
106 * @hook latepoint_booking_get_service_name_for_summary
107 *
108 */
109 return apply_filters( 'latepoint_booking_get_service_name_for_summary', $service_name, $this );
110 }
111
112 public function get_order() {
113 if ( $this->order_item_id ) {
114 if ( ! isset( $this->order_item ) || ( $this->order_item->id != $this->order_item_id ) ) {
115 $this->order_item = new OsOrderItemModel( $this->order_item_id );
116 if ( ! isset( $this->order ) || ( $this->order->id != $this->order_item->order_id ) ) {
117 $this->order = new OsOrderModel( $this->order_item->order_id );
118 }
119 }
120 } else {
121 $this->order = new OsOrderModel();
122 }
123
124 return $this->order;
125 }
126
127 public function get_order_item() {
128 if ( ! isset( $this->order_item ) ) {
129 $this->order_item = new OsOrderItemModel( $this->order_item_id );
130 }
131 return $this->order_item;
132 }
133
134 public function filter_allowed_records(): OsModel {
135 if ( ! OsRolesHelper::are_all_records_allowed() ) {
136 if ( ! OsRolesHelper::are_all_records_allowed( 'agent' ) ) {
137 $this->filter_where_conditions( [ 'agent_id' => OsRolesHelper::get_allowed_records( 'agent' ) ] );
138 }
139 if ( ! OsRolesHelper::are_all_records_allowed( 'location' ) ) {
140 $this->filter_where_conditions( [ 'location_id' => OsRolesHelper::get_allowed_records( 'location' ) ] );
141 }
142 if ( ! OsRolesHelper::are_all_records_allowed( 'service' ) ) {
143 $this->filter_where_conditions( [ 'service_id' => OsRolesHelper::get_allowed_records( 'service' ) ] );
144 }
145 }
146
147 return $this;
148 }
149
150 public function properties_to_query(): array {
151 return [
152 'service_id' => __( 'Service', 'latepoint' ),
153 'agent_id' => __( 'Agent', 'latepoint' ),
154 'status' => __( 'Status', 'latepoint' ),
155 'start_datetime_utc' => __( 'Start Time', 'latepoint' ),
156 'order_item_counts' => __( 'Order Item Counts', 'latepoint' ),
157 ];
158 }
159
160 public function generate_item_data() {
161 return wp_json_encode( $this->generate_params_for_booking_form() );
162 }
163
164
165 public function generate_params_for_booking_form() {
166 $params = [
167 'id' => $this->id,
168 'customer_id' => $this->customer_id,
169 'agent_id' => $this->agent_id,
170 'location_id' => $this->location_id,
171 'service_id' => $this->service_id,
172 'recurrence_id' => $this->recurrence_id,
173 'start_date' => $this->start_date,
174 'start_time' => $this->start_time,
175 'end_date' => $this->end_date,
176 'end_time' => $this->end_time,
177 'status' => $this->status,
178 'buffer_before' => $this->buffer_before,
179 'buffer_after' => $this->buffer_after,
180 'duration' => $this->duration,
181 'generate_recurrent_sequence' => $this->generate_recurrent_sequence,
182 ];
183
184 /**
185 * Returns an array of params generated from OsBookingModel to be used in a booking form
186 *
187 * @param {array} $params Array of booking params
188 * @param {OsBookingModel} $booking Instance of <code>OsBookingModel</code> that params are being generated for
189 *
190 * @returns {array} Filtered array of booking params
191 * @since 5.0.0
192 * @hook latepoint_generated_params_for_booking_form
193 *
194 */
195 return apply_filters( 'latepoint_generated_params_for_booking_form', $params, $this );
196 }
197
198 public function get_formatted_price() {
199 $order_item = new OsOrderItemModel( $this->order_item_id );
200 return OsMoneyHelper::format_price( $order_item->get_total() );
201 }
202
203 public function generate_first_level_data_vars(): array {
204 $vars = [
205 'id' => $this->id,
206 'booking_code' => $this->booking_code,
207 'start_datetime' => $this->format_start_date_and_time_rfc3339(),
208 'end_datetime' => $this->format_end_date_and_time_rfc3339(),
209 'service_name' => $this->service->name,
210 'duration' => $this->duration,
211 'customer_comment' => $this->order->customer_comment,
212 'status' => $this->status,
213 'start_date' => $this->format_start_date(),
214 'start_time' => OsTimeHelper::minutes_to_hours_and_minutes( $this->start_time ),
215 'timezone' => OsTimeHelper::get_wp_timezone_name(),
216 'agent' => $this->agent->get_data_vars(),
217 'created_datetime' => $this->format_created_datetime_rfc3339(),
218 'manage_booking_for_agent' => OsBookingHelper::generate_direct_manage_booking_url( $this, 'agent' ),
219 'manage_booking_for_customer' => OsBookingHelper::generate_direct_manage_booking_url( $this, 'customer' ),
220 ];
221 return $vars;
222 }
223
224 public function generate_data_vars(): array {
225 $vars = $this->get_first_level_data_vars();
226
227 $vars['customer'] = $this->customer->get_data_vars();
228 $vars['transactions'] = [];
229 $vars['order'] = $this->order->get_first_level_data_vars();
230
231 $transactions = $this->order->get_transactions();
232 if ( $transactions ) {
233 foreach ( $transactions as $transaction ) {
234 $vars['transactions'][] = $transaction->get_data_vars();
235 }
236 }
237
238 return $vars;
239 }
240
241
242 public function is_ready_for_summary() {
243 return ( $this->agent_id && $this->agent_id != LATEPOINT_ANY_AGENT && OsAgentHelper::count_agents() > 1 ) || $this->service_id;
244 }
245
246 public function is_part_of_bundle(): bool {
247 if ( $this->order_item_id ) {
248 $order_item = new OsOrderItemModel( $this->order_item_id );
249
250 return $order_item->is_bundle();
251 }
252
253 return false;
254 }
255
256 public function is_upcoming(): bool {
257 if ( empty( $this->start_datetime_utc ) ) {
258 return false;
259 }
260 $start_time_utc = new OsWpDateTime( $this->start_datetime_utc, new DateTimeZone( 'UTC' ) );
261 $now_time_utc = new OsWpDateTime( 'now', new DateTimeZone( 'UTC' ) );
262
263 return ( $start_time_utc > $now_time_utc );
264 }
265
266 public function set_utc_datetimes( bool $save = false ) {
267 if ( empty( $this->start_date ) || empty( $this->end_date ) || empty( $this->start_time ) || empty( $this->end_time ) ) {
268 return;
269 }
270 $this->start_datetime_utc = $this->get_start_datetime( 'UTC' )->format( LATEPOINT_DATETIME_DB_FORMAT );
271 $this->end_datetime_utc = $this->get_end_datetime( 'UTC' )->format( LATEPOINT_DATETIME_DB_FORMAT );
272 if ( $save ) {
273 $this->update_attributes(
274 [
275 'start_datetime_utc' => $this->start_datetime_utc,
276 'end_datetime_utc' => $this->end_datetime_utc,
277 ]
278 );
279 }
280 }
281
282
283 public function delete( $id = false ) {
284 if ( ! $id && isset( $this->id ) ) {
285 $id = $this->id;
286 }
287
288 $booking_metas = new OsBookingMetaModel();
289 $booking_metas->delete_where( [ 'object_id' => $id ] );
290 $process_jobs = new OsProcessJobModel();
291 $process_jobs->delete_where(
292 [
293 'object_id' => $id,
294 'object_model_type' => 'booking',
295 ]
296 );
297
298
299 return parent::delete( $id );
300 }
301
302 public function delete_meta_by_key( $meta_key ) {
303 if ( $this->is_new_record() ) {
304 return true;
305 }
306
307 $meta = new OsBookingMetaModel();
308
309 return $meta->delete_by_key( $meta_key, $this->id );
310 }
311
312 public function get_url_for_add_to_calendar_button( string $calendar_type ): string {
313 switch ( $calendar_type ) {
314 case 'google':
315 $url = 'https://calendar.google.com/calendar/render';
316 $params = [
317 'action' => 'TEMPLATE',
318 'text' => $this->service->name,
319 'dates' => $this->get_start_datetime_object( new DateTimeZone( 'UTC' ) )->format( 'Ymd\THis\Z' ) . '/' . $this->get_end_datetime_object( new DateTimeZone( 'UTC' ) )->format( 'Ymd\THis\Z' ),
320 ];
321 if ( ! empty( $this->location->full_address ) ) {
322 $params['location'] = $this->location->full_address;
323 }
324 break;
325 case 'outlook':
326 $url = 'https://outlook.office.com/calendar/0/deeplink/compose';
327 $params = [
328 'path' => '/calendar/action/compose',
329 'rru' => 'addevent',
330 'startdt' => $this->get_start_datetime_object( new DateTimeZone( 'UTC' ) )->format( 'Y-m-d\TH:i:s\Z' ),
331 'enddt' => $this->get_end_datetime_object( new DateTimeZone( 'UTC' ) )->format( 'Y-m-d\TH:i:s\Z' ),
332 'subject' => $this->service->name,
333 ];
334 break;
335 }
336 /**
337 * Generate params for the add to calendar link
338 *
339 * @param {array} $params Array of parameters that will be converted into a param query
340 * @param {string} $calendar_type Type of calendar the link is requested for
341 * @param {OsBookingModel} $booking A booking object
342 * @returns {array} The filtered array of appointment attributes
343 *
344 * @since 4.8.1
345 * @hook latepoint_build_add_to_calendar_link_params
346 *
347 */
348 $params = apply_filters( 'latepoint_build_add_to_calendar_link_params', $params, $calendar_type, $this );
349
350 $url = $url . '?' . http_build_query( $params );
351
352 /**
353 * URL for the link for a button to add appointment to calendar
354 *
355 * @param {array} $params Array of parameters that will be converted into a param query
356 * @param {string} $calendar_type Type of calendar the link is requested for
357 * @param {OsBookingModel} $booking A booking object
358 * @returns {string} The filtered url of adding appointment to calendar
359 *
360 * @since 4.8.1
361 * @hook latepoint_build_add_to_calendar_link_url
362 *
363 */
364 return apply_filters( 'latepoint_build_add_to_calendar_link_url', $url, $calendar_type, $this );
365 }
366
367 public function get_ical_download_link( $key = false ) {
368 return ( $key ) ? OsRouterHelper::build_admin_post_link(
369 [
370 'manage_booking_by_key',
371 'ical_download',
372 ],
373 [ 'key' => $key ]
374 ) : OsRouterHelper::build_admin_post_link(
375 [
376 'customer_cabinet',
377 'ical_download',
378 ],
379 [ 'latepoint_booking_id' => $this->id ]
380 );
381 }
382
383 public function get_print_link( $key = false ) {
384 return ( $key ) ? OsRouterHelper::build_admin_post_link( [ 'manage_booking_by_key', 'print' ], [ 'key' => $key ] ) : OsRouterHelper::build_admin_post_link( [ 'customer_cabinet', 'print_booking_info' ], [ 'latepoint_booking_id' => $this->id ] );
385 }
386
387 public function get_meta_by_key( $meta_key, $default = false ) {
388 if ( $this->is_new_record() ) {
389 return $default;
390 }
391
392 $meta = new OsBookingMetaModel();
393
394 return $meta->get_by_key( $meta_key, $this->id, $default );
395 }
396
397 public function get_coupon_code() {
398 $order = $this->get_order();
399 return $order->coupon_code;
400 }
401
402 public function get_coupon_discount(): string {
403 $order_item = $this->get_order_item();
404 $coupon_discount = $order_item->get_coupon_discount();
405 return $coupon_discount > 0 ? OsMoneyHelper::format_price( $order_item->get_coupon_discount() ) : '';
406 }
407
408 public function save_meta_by_key( $meta_key, $meta_value ) {
409 if ( $this->is_new_record() ) {
410 return false;
411 }
412
413 $meta = new OsBookingMetaModel();
414
415 return $meta->save_by_key( $meta_key, $meta_value, $this->id );
416 }
417
418 public function calculate_end_date() {
419 if ( empty( $this->start_time ) || empty( $this->start_date ) ) {
420 return $this->start_date;
421 }
422 if ( ( $this->start_time + $this->get_total_duration() ) >= ( 24 * 60 ) ) {
423 $date_obj = new OsWpDateTime( $this->start_date );
424 $end_date = $date_obj->modify( '+1 day' )->format( 'Y-m-d' );
425 } else {
426 $end_date = $this->start_date;
427 }
428
429 return $end_date;
430 }
431
432
433 public function calculate_end_time() {
434 $end_time = (int) $this->start_time + (int) $this->get_total_duration();
435 // continues to next day?
436 if ( $end_time > ( 24 * 60 ) ) {
437 $end_time = $end_time - ( 24 * 60 );
438 }
439
440 return $end_time;
441 }
442
443 public function calculate_end_date_and_time() {
444 $this->end_time = $this->calculate_end_time();
445 $this->end_date = $this->calculate_end_date();
446 }
447
448 public function after_data_was_set( $data ) {
449 if ( empty( $this->end_time ) ) {
450 $this->calculate_end_date_and_time();
451 }
452 if ( empty( $this->end_date ) ) {
453 $this->calculate_end_date();
454 }
455 }
456
457 public function set_buffers() {
458 if ( $this->service_id ) {
459 $service = new OsServiceModel( $this->service_id );
460 if ( $service ) {
461 $this->buffer_before = $service->buffer_before;
462 $this->buffer_after = $service->buffer_after;
463 }
464 }
465 }
466
467 public function get_total_duration( $calculate_from_start_and_end = false ) {
468 if ( $calculate_from_start_and_end ) {
469 if ( $this->start_date == $this->end_date ) {
470 // same day
471 $total_duration = $this->end_time - $this->start_time;
472 } else {
473 // TODO calculate how many days difference there is, if difference is more than 1 day - account for that
474 $total_duration = 60 * 24 - $this->start_time + $this->end_time;
475 }
476 } else {
477 if ( $this->duration ) {
478 $total_duration = $this->duration;
479 } else {
480 $total_duration = ( $this->service_id ) ? $this->service->duration : 60;
481 }
482 $total_duration = apply_filters( 'latepoint_calculated_total_duration', $total_duration, $this );
483 }
484
485 return (int) $total_duration;
486 }
487
488
489 public function get_nice_created_at( $include_time = true ) {
490 $format = $include_time ? OsSettingsHelper::get_readable_date_format() . ' ' . OsSettingsHelper::get_readable_time_format() : OsSettingsHelper::get_readable_date_format();
491 $utc_date = date_create_from_format( LATEPOINT_DATETIME_DB_FORMAT, $this->created_at );
492 $wp_timezone_date = $utc_date->setTimezone( OsTimeHelper::get_wp_timezone() );
493
494 return date_format( $wp_timezone_date, $format );
495 }
496
497 public function is_bookable( array $settings = [] ): bool {
498
499 $defaults = [
500 'skip_customer_check' => false,
501 'log_errors' => true,
502 ];
503
504 $settings = OsUtilHelper::merge_default_atts( $defaults, $settings );
505
506 $customer = $this->customer_id ? new OsCustomerModel( $this->customer_id ) : false;
507 // check if customer has to be assigned to a booking, or a guest booking is fine at this point
508 if ( $settings['skip_customer_check'] ) {
509 $customer_requirement_satisfied = true;
510 } else {
511 $customer_requirement_satisfied = ( $this->customer_id && $customer && $customer->id && ( $this->customer_id == $customer->id ) );
512 }
513
514 // agent, service and customer should be set
515 if ( $this->service_id && $this->agent_id && $customer_requirement_satisfied ) {
516
517 if ( $this->agent_id == LATEPOINT_ANY_AGENT && $this->location_id == LATEPOINT_ANY_LOCATION ) {
518 // both location and agent are set to any
519 $connections = new OsConnectorModel();
520 $connection_groups = $connections->select( LATEPOINT_TABLE_AGENTS_SERVICES . '.agent_id, ' . LATEPOINT_TABLE_AGENTS_SERVICES . '.location_id' )
521 ->where(
522 [
523 'service_id' => $this->service_id,
524 LATEPOINT_TABLE_AGENTS . '.status' => LATEPOINT_AGENT_STATUS_ACTIVE,
525 LATEPOINT_TABLE_LOCATIONS . '.status' => LATEPOINT_LOCATION_STATUS_ACTIVE,
526 ]
527 )
528 ->join( LATEPOINT_TABLE_AGENTS, [ 'id' => LATEPOINT_TABLE_AGENTS_SERVICES . '.agent_id' ] )
529 ->join( LATEPOINT_TABLE_LOCATIONS, [ 'id' => LATEPOINT_TABLE_AGENTS_SERVICES . '.location_id' ] )
530 ->get_results( ARRAY_A );
531 if ( empty( $connection_groups ) ) {
532 // no active locations and agents are connected to this service
533 $this->add_error( 'send_to_step', __( 'Unfortunately there are no active resources that can offer selected service, please select another service.', 'latepoint' ), 'booking__service' );
534
535 return false;
536 } else {
537 foreach ( $connection_groups as $connection ) {
538 $this->location_id = $connection['location_id'];
539 $this->agent_id = OsBookingHelper::get_any_agent_for_booking_by_rule( $this );
540 // available agent found in this location - break the loop
541 if ( $this->agent_id ) {
542 break;
543 }
544 }
545 if ( ! $this->agent_id ) {
546 $this->add_error( 'send_to_step', __( 'Unfortunately the selected time slot is not available anymore, please select another timeslot.', 'latepoint' ), 'booking__datepicker' );
547
548 return false;
549 }
550 }
551 } elseif ( $this->agent_id == LATEPOINT_ANY_AGENT ) {
552 $this->agent_id = OsBookingHelper::get_any_agent_for_booking_by_rule( $this );
553 if ( ! $this->agent_id ) {
554 $this->add_error( 'send_to_step', __( 'Unfortunately the selected time slot is not available anymore, please select another timeslot.', 'latepoint' ), 'booking__datepicker' );
555
556 return false;
557 }
558 } elseif ( $this->location_id == LATEPOINT_ANY_LOCATION ) {
559 $this->location_id = OsBookingHelper::get_any_location_for_booking_by_rule( $this );
560 if ( ! $this->location_id ) {
561 $this->add_error( 'send_to_step', __( 'Unfortunately the selected time slot is not available anymore, please select another timeslot.', 'latepoint' ), 'booking__datepicker' );
562
563 return false;
564 }
565 } else {
566 // check if booking time is still available
567 if ( ! OsBookingHelper::is_booking_request_available( \LatePoint\Misc\BookingRequest::create_from_booking_model( $this ) ) ) {
568 // translators: %1$s is the timeslot date and time
569 // translators: %2$s is the service name
570 $error_message = sprintf( __( 'Unfortunately the selected time slot "%1$s" for "%2$s" is not available anymore, please select another timeslot.', 'latepoint' ), $this->get_nice_start_datetime_for_customer(), $this->service->name );
571 $this->add_error( 'send_to_step', $error_message, 'booking__datepicker' );
572
573 return false;
574 }
575 }
576
577 if ( ! $this->validate( false, [ 'order_item_id', 'status', 'customer_id' ] ) ) {
578 return false;
579 }
580
581 return true;
582 } else {
583 if ( ! $this->service_id ) {
584 $this->add_error( 'missing_service', __( 'You have to select a service', 'latepoint' ) );
585 }
586 if ( ! $this->agent_id ) {
587 $this->add_error( 'missing_agent', __( 'You have to select an agent', 'latepoint' ) );
588 }
589 if ( ! $this->customer_id && ! $settings['skip_customer_check'] ) {
590 $this->add_error( 'missing_customer', __( 'Customer Not Found', 'latepoint' ) );
591 if ( $settings['log_errors'] ) {
592 OsDebugHelper::log( 'Customer not found', 'customer_error', print_r( $customer, true ) );
593 }
594 }
595 if ( ! $customer && ! $settings['skip_customer_check'] ) {
596 $this->add_error( 'missing_customer', __( 'You have to be logged in', 'latepoint' ) );
597 if ( $settings['log_errors'] ) {
598 OsDebugHelper::log( 'Customer not logged in', 'customer_error', print_r( $customer, true ) );
599 }
600 }
601 if ( $settings['log_errors'] ) {
602 OsDebugHelper::log( 'Error saving booking', 'booking_error', 'Agent: ' . $this->agent_id . ', Service: ' . $this->service_id . ', Booking Customer: ' . $this->customer_id );
603 }
604
605 return false;
606 }
607 }
608
609
610 public function get_nice_status() {
611 return OsBookingHelper::get_nice_status_name( $this->status );
612 }
613
614 public function get_latest_bookings_sorted_by_status( $args = array() ) {
615 $args = array_merge(
616 array(
617 'service_id' => false,
618 'customer_id' => false,
619 'agent_id' => false,
620 'location_id' => false,
621 'limit' => false,
622 'offset' => false,
623 ),
624 $args
625 );
626
627 $bookings = new OsBookingModel();
628 $query_args = array();
629 if ( $args['service_id'] ) {
630 $query_args['service_id'] = $args['service_id'];
631 }
632 if ( $args['customer_id'] ) {
633 $query_args['customer_id'] = $args['customer_id'];
634 }
635 if ( $args['agent_id'] ) {
636 $query_args['agent_id'] = $args['agent_id'];
637 }
638 if ( $args['location_id'] ) {
639 $query_args['location_id'] = $args['location_id'];
640 }
641 if ( $args['limit'] ) {
642 $bookings->set_limit( $args['limit'] );
643 }
644 if ( $args['offset'] ) {
645 $bookings->set_offset( $args['offset'] );
646 }
647
648 return $bookings->where( $query_args )->should_not_be_cancelled()->order_by( "status != '" . LATEPOINT_BOOKING_STATUS_PENDING . "' asc, start_date asc, start_time asc" )->get_results_as_models();
649 }
650
651
652 public function should_not_be_cancelled() {
653 return $this->where( [ $this->table_name . '.status !=' => LATEPOINT_BOOKING_STATUS_CANCELLED ] );
654 }
655
656 public function should_be_cancelled() {
657 return $this->where( [ $this->table_name . '.status' => LATEPOINT_BOOKING_STATUS_CANCELLED ] );
658 }
659
660 public function should_be_approved() {
661 return $this->where( [ $this->table_name . '.status' => LATEPOINT_BOOKING_STATUS_APPROVED ] );
662 }
663
664 public function should_be_in_future() {
665 return $this->where(
666 [
667 'OR' => [
668 'start_date >' => OsTimeHelper::today_date( 'Y-m-d' ),
669 'AND' => [
670 'start_date' => OsTimeHelper::today_date( 'Y-m-d' ),
671 'start_time >' => OsTimeHelper::get_current_minutes(),
672 ],
673 ],
674 ]
675 );
676 }
677
678
679 public function get_upcoming_bookings( $agent_id = false, $customer_id = false, $service_id = false, $location_id = false, int $limit = 3 ) {
680 $bookings = new OsBookingModel();
681 $args = array(
682 'OR' => array(
683 'start_date >' => OsTimeHelper::today_date( 'Y-m-d' ),
684 'AND' => array(
685 'start_date' => OsTimeHelper::today_date( 'Y-m-d' ),
686 'start_time >' => OsTimeHelper::get_current_minutes(),
687 ),
688 ),
689 );
690 if ( $service_id ) {
691 $args['service_id'] = $service_id;
692 }
693 if ( $customer_id ) {
694 $args['customer_id'] = $customer_id;
695 }
696 if ( $agent_id ) {
697 $args['agent_id'] = $agent_id;
698 }
699 if ( $location_id ) {
700 $args['location_id'] = $location_id;
701 }
702
703 $args = OsAuthHelper::get_current_user()->clean_query_args( $args );
704 $allowed_statuses = OsCalendarHelper::get_booking_statuses_to_display_on_calendar();
705 if ( empty( $allowed_statuses ) ) {
706 return [];
707 }
708
709 return $bookings->select( '*, count(id) as total_customers, sum(total_attendees) as total_attendees_sum' )
710 ->where_in( 'status', $allowed_statuses )
711 ->group_by( 'start_datetime_utc, agent_id, service_id, location_id' )
712 ->where( $args )
713 ->set_limit( $limit )
714 ->order_by( 'start_datetime_utc asc' )
715 ->get_results_as_models();
716 }
717
718 public function get_nice_start_time_for_customer() {
719 return $this->format_start_date_and_time( OsTimeHelper::get_time_format(), false, $this->get_customer_timezone() );
720 }
721
722 public function get_nice_end_time_for_customer() {
723 return $this->format_end_date_and_time( OsTimeHelper::get_time_format(), false, $this->get_customer_timezone() );
724 }
725
726 public function get_nice_start_date_for_customer( $customer_timezone = false, $hide_year = false ) {
727 if ( ! $customer_timezone ) {
728 $customer_timezone = $this->get_customer_timezone();
729 }
730 return OsUtilHelper::translate_months( $this->format_start_date_and_time( OsSettingsHelper::get_readable_date_format( $hide_year ), false, $customer_timezone ) );
731 }
732
733 public function get_nice_start_datetime_for_customer( $customer_timezone = false ) {
734 if ( ! $customer_timezone ) {
735 $customer_timezone = $this->get_customer_timezone();
736 }
737 return OsUtilHelper::translate_months( $this->format_start_date_and_time( OsSettingsHelper::get_readable_datetime_format(), false, $customer_timezone ) );
738 }
739
740 public function get_start_datetime_for_customer(): OsWpDateTime {
741 return $this->get_start_datetime( $this->get_customer_timezone_name() );
742 }
743 public function get_end_datetime_for_customer(): OsWpDateTime {
744 return $this->get_end_datetime( $this->get_customer_timezone_name() );
745 }
746
747 public function get_customer_timezone(): DateTimeZone {
748 if ( OsSettingsHelper::is_on( 'steps_show_timezone_selector' ) ) {
749 return ( $this->customer_id ) ? $this->customer->get_selected_timezone_obj() : OsTimeHelper::get_timezone_from_session();
750 } else {
751 return OsTimeHelper::get_wp_timezone();
752 }
753 }
754 public function get_customer_timezone_name(): string {
755 if ( OsSettingsHelper::is_on( 'steps_show_timezone_selector' ) ) {
756 return ( $this->customer_id ) ? $this->customer->get_selected_timezone_name() : OsTimeHelper::get_timezone_name_from_session();
757 } else {
758 return OsTimeHelper::get_wp_timezone_name();
759 }
760 }
761
762 /**
763 *
764 * Returns time in WP timezone, because start_time is stored in WP timezone, do not use it for customer facing outputs
765 *
766 * @return string|null
767 */
768 public function get_nice_start_time() {
769 return OsTimeHelper::minutes_to_hours_and_minutes( $this->start_time );
770 }
771
772 /**
773 *
774 * Returns time in WP timezone, because end_time is stored in WP timezone, do not use it for customer facing outputs
775 *
776 * @return string|null
777 */
778 public function get_nice_end_time() {
779 return OsTimeHelper::minutes_to_hours_and_minutes( $this->end_time );
780 }
781
782 /**
783 *
784 * Returns time in WP timezone, because start_date is stored in WP timezone, do not use it for customer facing outputs
785 *
786 * @return string|null
787 */
788 public function get_nice_end_date( $hide_year_if_current = false ) {
789 $datetime = OsWpDateTime::os_createFromFormat( 'Y-m-d', $this->end_date );
790 OsTimeHelper::format_to_nice_date( $datetime, $hide_year_if_current );
791 }
792
793 /**
794 *
795 * Returns time in WP timezone, because end_date is stored in WP timezone, do not use it for customer facing outputs
796 *
797 * @return string|null
798 */
799 public function get_nice_start_date( $hide_year_if_current = false ): string {
800 $datetime = OsWpDateTime::os_createFromFormat( 'Y-m-d', $this->start_date );
801 return OsTimeHelper::format_to_nice_date( $datetime, $hide_year_if_current );
802 }
803
804
805
806 /**
807 *
808 * Returns time in WP timezone, because start_date is stored in WP timezone, do not use it for customer facing outputs
809 *
810 * @param $hide_if_today bool
811 * @param $hide_year_if_current bool
812 *
813 * @return string
814 */
815 public function get_nice_start_datetime( bool $hide_if_today = true, bool $hide_year_if_current = true ): string {
816 if ( $hide_if_today && $this->start_date == OsTimeHelper::today_date( 'Y-m-d' ) ) {
817 $date = __( 'Today', 'latepoint' );
818 } else {
819 $date = $this->get_nice_start_date( $hide_year_if_current );
820 }
821
822 return implode( ', ', array_filter( [ $date, $this->get_nice_start_time() ] ) );
823 }
824
825
826 public function is_bundle_scheduling(): bool {
827 return ! empty( $this->order_item_id );
828 }
829
830 public function get_connected_recurring_bookings(): array {
831 if ( empty( $this->recurrence_id ) || $this->is_new_record() ) {
832 return [];
833 }
834 $bookings = new OsBookingModel();
835 return $bookings->where(
836 [
837 'recurrence_id' => $this->recurrence_id,
838 'id !=' => $this->id,
839 ]
840 )->order_by( 'start_datetime_utc asc' )->get_results_as_models();
841 }
842
843 public function get_nice_datetime_for_summary( string $viewer = 'customer' ) {
844 $nice_datetime = '';
845 if ( $this->start_date ) {
846 $nice_datetime = $this->get_nice_start_datetime( false );
847 if ( OsSettingsHelper::is_on( 'show_booking_end_time' ) && ! empty( $this->end_time ) && ! empty( $this->start_time ) ) {
848 $nice_datetime = $nice_datetime . ' - ' . $this->get_nice_end_time();
849 }
850 }
851 /**
852 * Get a formatted start and end time (if needed)
853 *
854 * @since 5.1.0
855 * @hook latepoint_get_nice_datetime_for_summary
856 *
857 * @param {string} $statuses Nice datetime
858 * @param {OsBookingModel} $booking An object of booking model
859 *
860 * @returns {string} Filtered nice datetime
861 */
862 $nice_datetime = apply_filters( 'latepoint_get_nice_datetime_for_summary', $nice_datetime, $this, $viewer );
863 return $nice_datetime;
864 }
865
866
867 public function format_end_date_and_time( $format = LATEPOINT_DATETIME_DB_FORMAT, $input_timezone = false, $output_timezone = false ) {
868 if ( ! $input_timezone ) {
869 $input_timezone = OsTimeHelper::get_wp_timezone();
870 }
871 if ( ! $output_timezone ) {
872 $output_timezone = OsTimeHelper::get_wp_timezone();
873 }
874
875 $date = OsWpDateTime::os_createFromFormat( LATEPOINT_DATETIME_DB_FORMAT, $this->end_date . ' ' . OsTimeHelper::minutes_to_army_hours_and_minutes( $this->end_time ) . ':00', $input_timezone );
876 $date->setTimeZone( $output_timezone );
877
878 return OsUtilHelper::translate_months( $date->format( $format ) );
879 }
880
881 public function format_start_date() {
882 if ( empty( $this->start_date ) ) {
883 $date = new OsWpDateTime();
884 $this->start_date = $date->format( 'Y-m-d' );
885 } else {
886 $date = OsWpDateTime::os_createFromFormat( 'Y-m-d', $this->start_date );
887 }
888
889 return $date->format( OsSettingsHelper::get_date_format() );
890 }
891
892 public function format_start_date_and_time( $format = LATEPOINT_DATETIME_DB_FORMAT, $input_timezone = false, $output_timezone = false ) {
893 if ( ! $input_timezone ) {
894 $input_timezone = OsTimeHelper::get_wp_timezone();
895 }
896 if ( ! $output_timezone ) {
897 $output_timezone = OsTimeHelper::get_wp_timezone();
898 }
899
900 if ( is_null( $this->start_time ) || $this->start_time === '' ) {
901 // no time set yet (could be because summary is reloaded when date is picked, before the time is picked)
902 $date = OsWpDateTime::os_createFromFormat( 'Y-m-d', $this->start_date );
903 if ( $date ) {
904 return OsUtilHelper::translate_months( $date->format( OsSettingsHelper::get_readable_date_format() ) );
905 } else {
906 return __( 'Invalid Date/Time', 'latepoint' );
907 }
908 } else {
909 // both date & time are set, update timezone and translate
910 $date = OsWpDateTime::os_createFromFormat( LATEPOINT_DATETIME_DB_FORMAT, $this->start_date . ' ' . OsTimeHelper::minutes_to_army_hours_and_minutes( $this->start_time ) . ':00', $input_timezone );
911 if ( $date ) {
912 $date->setTimeZone( $output_timezone );
913
914 return OsUtilHelper::translate_months( $date->format( $format ) );
915 } else {
916 return __( 'Invalid Date/Time', 'latepoint' );
917 }
918 }
919 }
920
921 public function format_start_date_and_time_rfc3339() {
922 return $this->format_start_date_and_time( \DateTime::RFC3339 );
923 }
924
925 public function format_end_date_and_time_rfc3339() {
926 return $this->format_end_date_and_time( \DateTime::RFC3339 );
927 }
928
929 public function format_start_date_and_time_for_google() {
930 return $this->format_start_date_and_time( \DateTime::RFC3339 );
931 }
932
933 public function format_end_date_and_time_for_google() {
934 return $this->format_end_date_and_time( \DateTime::RFC3339 );
935 }
936
937 /*
938 * Checks if the booking has passed
939 */
940 public function time_status() {
941 try {
942 $now_datetime = OsTimeHelper::now_datetime_utc();
943 if ( empty( $this->start_datetime_utc ) || empty( $this->end_datetime_utc ) ) {
944 $this->set_utc_datetimes( true );
945 }
946 $booking_start = new OsWpDateTime( $this->start_datetime_utc, new DateTimeZone( 'UTC' ) );
947 $booking_end = new OsWpDateTime( $this->end_datetime_utc, new DateTimeZone( 'UTC' ) );
948 if ( ( $now_datetime <= $booking_end ) && ( $now_datetime >= $booking_start ) ) {
949 return 'now';
950 } elseif ( $now_datetime <= $booking_start ) {
951 return 'upcoming';
952 } else {
953 return 'past';
954 }
955 } catch ( Exception $e ) {
956 return 'past';
957 }
958 }
959
960 public function start_datetime_in_format( string $format, string $output_in_timezone_name ): string {
961 if ( empty( $this->start_datetime_utc ) ) {
962 return '';
963 }
964 $booking_start_datetime = OsTimeHelper::date_from_db( $this->start_datetime_utc );
965 $booking_start_datetime->setTimezone( new DateTimeZone( $output_in_timezone_name ) );
966 return $booking_start_datetime->format( $format );
967 }
968
969 public function is_start_date_and_time_set(): bool {
970 return ( $this->start_date != '' && $this->start_time != '' );
971 }
972
973 protected function get_time_left() {
974 $now_datetime = new OsWpDateTime( 'now' );
975 $booking_datetime = OsWpDateTime::os_createFromFormat( LATEPOINT_DATETIME_DB_FORMAT, $this->format_start_date_and_time() );
976 $css_class = 'left-days';
977
978 if ( $booking_datetime ) {
979 $diff = $now_datetime->diff( $booking_datetime );
980 if ( $diff->d > 0 || $diff->m > 0 || $diff->y > 0 ) {
981 $left = $diff->format( '%a ' . __( 'days', 'latepoint' ) );
982 } else {
983 if ( $diff->h > 0 ) {
984 $css_class = 'left-hours';
985 $left = $diff->format( '%h ' . __( 'hours', 'latepoint' ) );
986 } else {
987 $css_class = 'left-minutes';
988 $left = $diff->format( '%i ' . __( 'minutes', 'latepoint' ) );
989 }
990 }
991 } else {
992 $left = 'n/a';
993 }
994
995 return '<span class="time-left ' . esc_attr( $css_class ) . '">' . esc_html( $left ) . '</span>';
996 }
997
998
999 protected function get_agent() {
1000 if ( $this->agent_id ) {
1001 if ( ! isset( $this->agent ) || ( isset( $this->agent ) && ( $this->agent->id != $this->agent_id ) ) ) {
1002 $this->agent = new OsAgentModel( $this->agent_id );
1003 }
1004 } else {
1005 $this->agent = new OsAgentModel();
1006 }
1007
1008 return $this->agent;
1009 }
1010
1011 public function get_agent_full_name() {
1012 if ( $this->agent_id == LATEPOINT_ANY_AGENT ) {
1013 return __( 'Any Available Agent', 'latepoint' );
1014 } else {
1015 return $this->agent->full_name;
1016 }
1017 }
1018
1019
1020 public function get_location() {
1021 if ( $this->location_id ) {
1022 // if location has not been initialized yet, or location_id is different from the one initialized - init again
1023 if ( empty( $this->location ) || ( $this->location->id != $this->location_id ) ) {
1024 $this->location = new OsLocationModel( $this->location_id );
1025 }
1026 } else {
1027 $this->location = new OsLocationModel();
1028 }
1029
1030 return $this->location;
1031 }
1032
1033 protected function get_customer() {
1034 if ( $this->customer_id ) {
1035 if ( ! isset( $this->customer ) || ( isset( $this->customer ) && ( $this->customer->id != $this->customer_id ) ) ) {
1036 $this->customer = new OsCustomerModel( $this->customer_id );
1037 }
1038 } else {
1039 $this->customer = new OsCustomerModel();
1040 }
1041
1042 return $this->customer;
1043 }
1044
1045
1046 protected function get_service() {
1047 if ( $this->service_id ) {
1048 if ( ! isset( $this->service ) || ( isset( $this->service ) && ( $this->service->id != $this->service_id ) ) ) {
1049 $this->service = new OsServiceModel( $this->service_id );
1050 }
1051 } else {
1052 $this->service = new OsServiceModel();
1053 }
1054
1055 return $this->service;
1056 }
1057
1058 public function get_nice_start_date_in_timezone( string $timezone_name = '', $hide_year_if_current = false ): string {
1059 $datetime = $this->get_start_datetime( $timezone_name );
1060 return OsTimeHelper::format_to_nice_date( $datetime, $hide_year_if_current );
1061 }
1062
1063 public function get_nice_end_date_in_timezone( string $timezone_name = '', $hide_year_if_current = false ): string {
1064 $datetime = $this->get_end_datetime( $timezone_name );
1065 return OsTimeHelper::format_to_nice_date( $datetime, $hide_year_if_current );
1066 }
1067
1068 public function get_nice_start_time_in_timezone( string $timezone_name = '' ): string {
1069 $datetime = $this->get_start_datetime( $timezone_name );
1070 return OsTimeHelper::format_to_nice_time( $datetime );
1071 }
1072
1073 public function get_nice_end_time_in_timezone( string $timezone_name = '' ): string {
1074 $datetime = $this->get_end_datetime( $timezone_name );
1075 return OsTimeHelper::format_to_nice_time( $datetime );
1076 }
1077
1078 public function get_start_datetime_object( ?DateTimeZone $timezone = null ) {
1079 if ( empty( $timezone ) ) {
1080 $timezone = OsTimeHelper::get_wp_timezone();
1081 }
1082 if ( empty( $this->start_datetime_utc ) ) {
1083 // fix data, probably an older booking from the time when we didn't store UTC date
1084 $this->start_datetime_utc = $this->generate_start_datetime_in_db_format();
1085 }
1086 $booking_start_datetime = OsTimeHelper::date_from_db( $this->start_datetime_utc );
1087 if ( $booking_start_datetime ) {
1088 $booking_start_datetime->setTimezone( $timezone );
1089 } else {
1090 OsDebugHelper::log( 'Error generating start date and time for booking ID: ' . $this->id, 'corrupt_booking_data' );
1091 }
1092
1093 return $booking_start_datetime;
1094 }
1095
1096 public function get_end_datetime_object( ?DateTimeZone $timezone = null ) {
1097 if ( empty( $timezone ) ) {
1098 $timezone = OsTimeHelper::get_wp_timezone();
1099 }
1100 if ( empty( $this->end_datetime_utc ) ) {
1101 // fix data, probably an older booking from the time when we didn't store UTC date
1102 $this->end_datetime_utc = $this->generate_end_datetime_in_db_format();
1103 }
1104 $booking_end_datetime = OsTimeHelper::date_from_db( $this->end_datetime_utc );
1105 if ( $booking_end_datetime ) {
1106 $booking_end_datetime->setTimezone( $timezone );
1107 } else {
1108 OsDebugHelper::log( 'Error generating end date and time for booking ID: ' . $this->id, 'corrupt_booking_data' );
1109 }
1110
1111 return $booking_end_datetime;
1112 }
1113
1114 public function get_start_datetime( string $set_timezone = 'UTC' ): OsWpDateTime {
1115 try {
1116 // start_time and start_date is legacy stored in wordpress timezone
1117 $dateTime = new OsWpDateTime( $this->start_date . ' 00:00:00', OsTimeHelper::get_wp_timezone() );
1118 if ( $this->start_time > 0 ) {
1119 $dateTime->modify( '+' . $this->start_time . ' minutes' );
1120 }
1121 if ( $set_timezone ) {
1122 $dateTime->setTimezone( new DateTimeZone( $set_timezone ) );
1123 }
1124 return $dateTime;
1125 } catch ( Exception $e ) {
1126 return new OsWpDateTime( 'now' );
1127 }
1128 }
1129
1130 public function get_end_datetime( string $set_timezone = 'UTC' ): OsWpDateTime {
1131 try {
1132 // start_time and start_date is legacy stored in wordpress timezone
1133 $dateTime = new OsWpDateTime( $this->end_date . ' 00:00:00', OsTimeHelper::get_wp_timezone() );
1134 if ( $this->end_time > 0 ) {
1135 $dateTime->modify( '+' . $this->end_time . ' minutes' );
1136 }
1137 if ( $set_timezone ) {
1138 $dateTime->setTimezone( new DateTimeZone( $set_timezone ) );
1139 }
1140 return $dateTime;
1141 } catch ( Exception $e ) {
1142 return new OsWpDateTime( 'now' );
1143 }
1144 }
1145
1146 public function generate_start_datetime_in_db_format( string $timezone = 'UTC' ): string {
1147 $dateTime = $this->get_start_datetime( $timezone );
1148
1149 return $dateTime->format( LATEPOINT_DATETIME_DB_FORMAT );
1150 }
1151
1152
1153 public function generate_end_datetime_in_db_format( string $timezone = 'UTC' ): string {
1154 $dateTime = $this->get_end_datetime( $timezone );
1155
1156 return $dateTime->format( LATEPOINT_DATETIME_DB_FORMAT );
1157 }
1158
1159
1160 protected function before_save() {
1161 // TODO check for uniqueness
1162 if ( empty( $this->booking_code ) ) {
1163 $this->booking_code = strtoupper( OsUtilHelper::random_text( 'distinct', 7 ) );
1164 }
1165 if ( empty( $this->end_date ) ) {
1166 $this->end_date = $this->calculate_end_date();
1167 }
1168 if ( empty( $this->status ) ) {
1169 $this->status = $this->get_default_booking_status();
1170 }
1171 if ( empty( $this->total_attendees ) ) {
1172 $this->total_attendees = 1;
1173 }
1174 if ( empty( $this->duration ) && $this->service_id ) {
1175 $service = new OsServiceModel( $this->service_id );
1176 $this->duration = $service->duration;
1177 }
1178 }
1179
1180 public function get_default_booking_status() {
1181 return OsBookingHelper::get_default_booking_status( $this->service_id );
1182 }
1183
1184 public function update_status( $new_status ) {
1185 if ( $new_status == $this->status ) {
1186 return true;
1187 } else {
1188 if ( ! in_array( $new_status, array_keys( OsBookingHelper::get_statuses_list() ) ) ) {
1189 $this->add_error( 'invalid_booking_status', 'Invalid booking status' );
1190
1191 return false;
1192 }
1193 $old_booking = clone $this;
1194 $this->status = $new_status;
1195 $result = $this->update_attributes( [ 'status' => $new_status ] );
1196 if ( $result ) {
1197 do_action( 'latepoint_booking_updated', $this, $old_booking );
1198
1199 return true;
1200 } else {
1201 return false;
1202 }
1203 }
1204 }
1205
1206 public function convert_start_datetime_into_server_timezone( string $input_timezone, bool $set_as_customer_timezone = true ) {
1207 $this->server_timezone = OsTimeHelper::get_wp_timezone_name();
1208 if ( $set_as_customer_timezone ) {
1209 $this->customer_timezone = $input_timezone;
1210 }
1211 if ( $this->is_start_date_and_time_set() && $this->server_timezone != $input_timezone ) {
1212
1213 try {
1214 // convert from submitted customer timezone into WP timezone
1215 $start_datetime = new OsWpDateTime( $this->start_date . ' 00:00:00', new DateTimeZone( $input_timezone ) );
1216 if ( $this->start_time > 0 ) {
1217 $start_datetime->modify( '+' . $this->start_time . ' minutes' );
1218 }
1219 $start_datetime->setTimezone( OsTimeHelper::get_wp_timezone() );
1220 $this->start_date = $start_datetime->format( 'Y-m-d' );
1221 $this->start_time = OsTimeHelper::convert_datetime_to_minutes( $start_datetime );
1222
1223 } catch ( Exception $e ) {
1224 }
1225 }
1226 }
1227
1228 public function save_avatar( $image_id = false ) {
1229 if ( ( false === $image_id ) && $this->image_id ) {
1230 $image_id = $this->image_id;
1231 }
1232 if ( $image_id && $this->post_id ) {
1233 set_post_thumbnail( $this->post_id, $image_id );
1234 $this->image_id = $image_id;
1235 }
1236
1237 return $this->image_id;
1238 }
1239
1240
1241 protected function allowed_params( $role = 'admin' ) {
1242 $allowed_params = array(
1243 'service_id',
1244 'booking_code',
1245 'agent_id',
1246 'customer_id',
1247 'location_id',
1248 'start_date',
1249 'end_date',
1250 'start_time',
1251 'end_time',
1252 'start_datetime_utc',
1253 'end_datetime_utc',
1254 'buffer_before',
1255 'duration',
1256 'buffer_after',
1257 'total_attendees',
1258 'total_attendees_sum',
1259 'total_customers',
1260 'cart_item_id',
1261 'order_item_id',
1262 'status',
1263 'form_id',
1264 'server_timezone',
1265 'customer_timezone',
1266 'generate_recurrent_sequence',
1267 'recurrence_id',
1268 );
1269
1270 return $allowed_params;
1271 }
1272
1273
1274 protected function params_to_save( $role = 'admin' ) {
1275 $params_to_save = array(
1276 'service_id',
1277 'booking_code',
1278 'agent_id',
1279 'customer_id',
1280 'location_id',
1281 'start_date',
1282 'end_date',
1283 'start_time',
1284 'end_time',
1285 'start_datetime_utc',
1286 'end_datetime_utc',
1287 'duration',
1288 'buffer_before',
1289 'buffer_after',
1290 'total_attendees',
1291 'status',
1292 'order_item_id',
1293 'server_timezone',
1294 'customer_timezone',
1295 'recurrence_id',
1296 );
1297
1298 return $params_to_save;
1299 }
1300
1301
1302 protected function properties_to_validate() {
1303 $validations = array(
1304 'order_item_id' => array( 'presence' ),
1305 'service_id' => array( 'presence' ),
1306 'agent_id' => array( 'presence' ),
1307 'location_id' => array( 'presence' ),
1308 'customer_id' => array( 'presence' ),
1309 'start_date' => array( 'presence' ),
1310 'end_date' => array( 'presence' ),
1311 'status' => array( 'presence' ),
1312 );
1313
1314 return $validations;
1315 }
1316 }
1317