PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / trunk
LatePoint – Calendar Booking Plugin for Appointments and Events vtrunk
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 / service_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 14 hours ago bundle_meta_model.php 3 months ago bundle_model.php 1 week ago cart_item_model.php 3 months ago cart_meta_model.php 3 months ago cart_model.php 2 weeks ago connector_model.php 3 months ago customer_meta_model.php 3 months ago customer_model.php 1 month ago invoice_model.php 2 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 2 days ago off_period_model.php 3 months ago order_intent_meta_model.php 3 months ago order_intent_model.php 1 week 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
service_model.php
638 lines
1 <?php
2 class OsServiceModel extends OsModel {
3 public $id,
4 $name = '',
5 $short_description,
6 $selection_image_id,
7 $description_image_id,
8 $is_price_variable,
9 $price_min,
10 $price_max,
11 $charge_amount,
12 $deposit_amount,
13 $duration_name = '',
14 $duration = 60,
15 $buffer_before,
16 $buffer_after,
17 $category_id,
18 $override_default_booking_status = false,
19 $status,
20 $bg_color,
21 $order_number,
22 $visibility = LATEPOINT_SERVICE_VISIBILITY_VISIBLE,
23 $capacity_min = 1,
24 $capacity_max = 1,
25 $timeblock_interval,
26 $is_custom_price = false,
27 $is_custom_hours = false,
28 $is_custom_duration = false,
29 $meta_class = 'OsServiceMetaModel',
30 $services_agents_table_name,
31 $is_deposit_required,
32 $earliest_possible_booking,
33 $latest_possible_booking,
34 $deposit_value,
35 $updated_at,
36 $created_at;
37
38 function __construct( $id = false ) {
39 parent::__construct();
40 $this->table_name = LATEPOINT_TABLE_SERVICES;
41 $this->services_agents_table_name = LATEPOINT_TABLE_AGENTS_SERVICES;
42 $this->nice_names = array(
43 'name' => __( 'Service Name', 'latepoint' ),
44 'short_description' => __( 'Service Short Description', 'latepoint' ),
45 'selection_image_id' => __( 'Service Selection Image', 'latepoint' ),
46 'description_image_id' => __( 'Service Description Image', 'latepoint' ),
47 'is_price_variable' => __( 'Variable Price', 'latepoint' ),
48 'price_min' => __( 'Minimum Price', 'latepoint' ),
49 'price_max' => __( 'Maximum Price', 'latepoint' ),
50 'charge_amount' => __( 'Charge Amount', 'latepoint' ),
51 'deposit_amount' => __( 'Deposit Amount', 'latepoint' ),
52 'duration_name' => __( 'Duration Name', 'latepoint' ),
53 'duration' => __( 'Service Duration', 'latepoint' ),
54 'buffer_before' => __( 'Buffer Before', 'latepoint' ),
55 'buffer_after' => __( 'Buffer After', 'latepoint' ),
56 'bg_color' => __( 'Background Color', 'latepoint' ),
57 'category_id' => __( 'Service Category', 'latepoint' ),
58 );
59
60 if ( $id ) {
61 $this->load_by_id( $id );
62 }
63 }
64
65 protected function params_to_save( $role = 'admin' ) {
66 $params_to_save = array(
67 'id',
68 'name',
69 'short_description',
70 'category_id',
71 'selection_image_id',
72 'is_price_variable',
73 'price_min',
74 'price_max',
75 'charge_amount',
76 'deposit_amount',
77 'duration_name',
78 'duration',
79 'buffer_before',
80 'buffer_after',
81 'bg_color',
82 'timeblock_interval',
83 'override_default_booking_status',
84 'order_number',
85 'visibility',
86 'status',
87 'earliest_possible_booking',
88 'latest_possible_booking',
89 'capacity_min',
90 'capacity_max',
91 'description_image_id',
92 );
93 return $params_to_save;
94 }
95
96 protected function allowed_params( $role = 'admin' ) {
97 $allowed_params = array(
98 'id',
99 'name',
100 'short_description',
101 'category_id',
102 'selection_image_id',
103 'is_price_variable',
104 'price_min',
105 'price_max',
106 'charge_amount',
107 'deposit_amount',
108 'duration_name',
109 'duration',
110 'buffer_before',
111 'buffer_after',
112 'bg_color',
113 'timeblock_interval',
114 'override_default_booking_status',
115 'order_number',
116 'visibility',
117 'earliest_possible_booking',
118 'latest_possible_booking',
119 'status',
120 'capacity_min',
121 'capacity_max',
122 'description_image_id',
123 );
124 return $allowed_params;
125 }
126
127
128 public function prepare_data_before_it_is_set( $data ) {
129 if ( isset( $data['name'] ) ) {
130 $data['name'] = sanitize_text_field( $data['name'] );
131 }
132 if ( isset( $data['short_description'] ) ) {
133 $data['short_description'] = wp_kses_post( $data['short_description'] );
134 }
135
136
137 return $data;
138 }
139
140 public function get_default_booking_status() {
141 if ( ! empty( $this->override_default_booking_status ) ) {
142 $all_statuses = OsBookingHelper::get_statuses_list();
143 if ( isset( $all_statuses[ $this->override_default_booking_status ] ) ) {
144 return $this->override_default_booking_status;
145 }
146 }
147 return OsBookingHelper::get_default_booking_status();
148 }
149
150 public function get_category_name() {
151 if ( $this->category_id ) {
152 $category = new OsServiceCategoryModel( $this->category_id );
153 if ( $category->exists() ) {
154 return $category->name;
155 }
156 }
157 return '';
158 }
159
160
161 // determine how much capacity service can accept before the slot is blocked
162 public function get_capacity_needed_before_slot_is_blocked(): int {
163 $capacity_min = $this->capacity_min ? $this->capacity_min : 1;
164 $capacity_max = $this->capacity_max ? $this->capacity_max : 1;
165 return ( $this->get_meta_by_key( 'block_timeslot_when_minimum_capacity_met', 'off' ) == 'on' ) ? $capacity_min : $capacity_max;
166 }
167
168 public function get_timeblock_interval() {
169 if ( ! $this->timeblock_interval ) {
170 $this->timeblock_interval = OsSettingsHelper::get_default_timeblock_interval();
171 }
172 return $this->timeblock_interval;
173 }
174
175 public function filter_allowed_records(): OsModel {
176 if ( ! OsRolesHelper::are_all_records_allowed( 'service' ) ) {
177 $this->filter_where_conditions( [ 'id' => OsRolesHelper::get_allowed_records( 'service' ) ] );
178 }
179 return $this;
180 }
181
182
183 protected function before_create() {
184 }
185
186 public function should_show_capacity_selector() {
187 return ( ( $this->capacity_max != $this->capacity_min ) && ( $this->get_meta_by_key( 'fixed_total_attendees', 'off' ) != 'on' ) );
188 }
189
190 public function is_group_service() {
191 return ( $this->capacity_max > 1 );
192 }
193
194 public function get_all_durations_arr() {
195 $durations = [
196 [
197 'id' => 'default',
198 'name' => $this->duration_name,
199 'duration' => $this->duration,
200 'charge_amount' => $this->charge_amount,
201 'deposit_amount' => $this->deposit_amount,
202 ],
203 ];
204 $durations = array_merge( $durations, $this->get_extra_durations() );
205 return $durations;
206 }
207
208 public function get_extra_durations() {
209 $durations = [];
210 $extra_durations = $this->get_meta_by_key( 'durations', false );
211 if ( $extra_durations ) {
212 $extra_durations_arr = json_decode( $extra_durations, true );
213 if ( ! empty( $extra_durations_arr ) ) {
214 foreach ( $extra_durations_arr as $duration_id => $extra_duration ) {
215 $durations[] = [
216 'id' => $duration_id,
217 'name' => ( $extra_duration['name'] ?? '' ),
218 'duration' => $extra_duration['duration'],
219 'charge_amount' => $extra_duration['charge_amount'],
220 'deposit_amount' => $extra_duration['deposit_amount'],
221 ];
222 }
223 }
224 }
225 return $durations;
226 }
227
228 public function get_full_amount_for_duration( $duration = false ) {
229 if ( $duration && $duration != $this->duration ) {
230 $extra_durations = $this->get_extra_durations();
231 foreach ( $extra_durations as $extra_duration ) {
232 if ( $extra_duration['duration'] == $duration ) {
233 return $extra_duration['charge_amount'];
234 }
235 }
236 }
237 return $this->charge_amount;
238 }
239
240 public function get_deposit_amount_for_duration( $duration = false ) {
241 if ( $duration && $duration != $this->duration ) {
242 $extra_durations = $this->get_extra_durations();
243 foreach ( $extra_durations as $extra_duration ) {
244 if ( $extra_duration['duration'] == $duration ) {
245 return $extra_duration['deposit_amount'];
246 }
247 }
248 }
249 return $this->deposit_amount;
250 }
251
252 protected function set_defaults() {
253 if ( empty( $this->category_id ) ) {
254 $this->category_id = 0;
255 }
256 if ( empty( $this->buffer_before ) ) {
257 $this->buffer_before = 0;
258 }
259 if ( empty( $this->buffer_after ) ) {
260 $this->buffer_after = 0;
261 }
262 if ( empty( $this->price_min ) ) {
263 $this->price_min = 0;
264 }
265 if ( empty( $this->price_max ) ) {
266 $this->price_max = 0;
267 }
268 if ( empty( $this->charge_amount ) ) {
269 $this->charge_amount = 0;
270 }
271 if ( empty( $this->deposit_amount ) ) {
272 $this->deposit_amount = 0;
273 }
274 if ( empty( $this->is_deposit_required ) ) {
275 $this->is_deposit_required = false;
276 }
277 if ( empty( $this->status ) ) {
278 $this->status = LATEPOINT_SERVICE_STATUS_ACTIVE;
279 }
280 if ( empty( $this->bg_color ) ) {
281 $this->bg_color = $this->generate_new_bg_color();
282 }
283 }
284
285 public function save_custom_schedule( $work_periods ) {
286 foreach ( $work_periods as &$work_period ) {
287 $work_period['service_id'] = $this->id;
288 }
289 unset( $work_period );
290 OsWorkPeriodsHelper::save_work_periods( $work_periods );
291 }
292
293 public function delete_custom_schedule() {
294 $work_periods_model = new OsWorkPeriodModel();
295 $work_periods = $work_periods_model->where(
296 array(
297 'service_id' => $this->id,
298 'agent_id' => 0,
299 'location_id' => 0,
300 'custom_date' => 'IS NULL',
301 )
302 )->get_results_as_models();
303 if ( is_array( $work_periods ) ) {
304 foreach ( $work_periods as $work_period ) {
305 $work_period->delete();
306 }
307 }
308 }
309
310 public function generate_new_bg_color() {
311 $services = new OsServiceModel();
312 $service_colors_results = $services->select( 'bg_color' )->group_by( 'bg_color' )->get_results( ARRAY_A );
313 $services_used_colors = array_map(
314 function ( $service ) {
315 return $service['bg_color'];
316 },
317 $service_colors_results
318 );
319 $default_colors = OsServiceHelper::get_default_colors();
320 $colors_left = array_diff( $default_colors, $services_used_colors );
321 if ( ! empty( $colors_left ) ) {
322 // reset array
323 $colors_left = array_values( $colors_left );
324 $bg_color = $colors_left[0];
325 } else {
326 $bg_color = '#3d52ea';
327 }
328 return $bg_color;
329 }
330
331
332 public function delete( $id = false ) {
333 if ( ! $id && isset( $this->id ) ) {
334 $id = $this->id;
335 }
336 if ( $id && $this->db->delete( $this->table_name, array( 'id' => $id ), array( '%d' ) ) ) {
337 $this->db->delete( LATEPOINT_TABLE_AGENTS_SERVICES, array( 'service_id' => $id ), array( '%d' ) );
338 $this->db->delete( LATEPOINT_TABLE_WORK_PERIODS, array( 'service_id' => $id ), array( '%d' ) );
339 $this->db->delete( LATEPOINT_TABLE_SERVICE_META, array( 'object_id' => $id ), array( '%d' ) );
340 $this->db->delete( LATEPOINT_TABLE_BOOKINGS, array( 'service_id' => $id ), array( '%d' ) );
341 do_action( 'latepoint_service_deleted', $id );
342 return true;
343 } else {
344 return false;
345 }
346 }
347
348 protected function params_to_sanitize() {
349 return [
350 'charge_amount' => 'money',
351 'deposit_amount' => 'money',
352 'price_min' => 'money',
353 'price_max' => 'money',
354 ];
355 }
356
357 public function is_hidden() {
358 return ( $this->visibility == LATEPOINT_SERVICE_VISIBILITY_HIDDEN );
359 }
360
361 public function should_be_active() {
362 return $this->where( [ 'status' => LATEPOINT_SERVICE_STATUS_ACTIVE ] );
363 }
364
365 public function should_not_be_hidden() {
366 return $this->where( [ 'visibility !=' => LATEPOINT_SERVICE_VISIBILITY_HIDDEN ] );
367 }
368
369 public function is_active() {
370 return ( $this->status == LATEPOINT_SERVICE_STATUS_ACTIVE );
371 }
372
373
374 protected function get_price_min_formatted() {
375 if ( $this->price_min > 0 ) {
376 return OsMoneyHelper::format_price( $this->price_min );
377 } else {
378 return OsMoneyHelper::format_price( 0 );
379 }
380 }
381
382
383 public function get_selection_image_url() {
384 $default_service_image_url = LATEPOINT_IMAGES_URL . 'service-image.png';
385 return OsImageHelper::get_image_url_by_id( $this->selection_image_id, 'thumbnail', $default_service_image_url );
386 }
387
388 public function get_description_image_url() {
389 $default_service_image_url = LATEPOINT_IMAGES_URL . 'service-image.png';
390 return OsImageHelper::get_image_url_by_id( $this->description_image_id, 'full', $default_service_image_url );
391 }
392
393
394 public function connect_to_agent( $agent_id, $location_id ) {
395 $agent_connection_row = $this->db->get_row( $this->db->prepare( 'SELECT id FROM ' . $this->services_agents_table_name . ' WHERE service_id = %d AND agent_id = %d AND location_id = %d', array( $this->id, $agent_id, $location_id ) ) );
396 if ( $agent_connection_row ) {
397 // update
398 } else {
399 $insert_data = array(
400 'agent_id' => $agent_id,
401 'service_id' => $this->id,
402 'location_id' => $location_id,
403 );
404 if ( $this->db->insert( $this->services_agents_table_name, $insert_data ) ) {
405 return $this->db->insert_id;
406 }
407 }
408 }
409
410 public function save_durations( $durations ) {
411 foreach ( $durations as &$duration ) {
412 $duration['charge_amount'] = OsParamsHelper::sanitize_param( $duration['charge_amount'], 'money' );
413 $duration['deposit_amount'] = OsParamsHelper::sanitize_param( $duration['deposit_amount'], 'money' );
414 }
415 unset( $duration );
416 $this->save_meta_by_key( 'durations', wp_json_encode( $durations ) );
417 return true;
418 }
419
420
421
422 public function delete_meta_by_key( $meta_key ) {
423 if ( $this->is_new_record() ) {
424 return false;
425 }
426
427 $meta = new OsServiceMetaModel();
428 return $meta->delete_by_key( $meta_key, $this->id );
429 }
430
431 public function get_meta_by_key( $meta_key, $default = false ) {
432 if ( $this->is_new_record() ) {
433 return $default;
434 }
435
436 $meta = new OsServiceMetaModel();
437 return $meta->get_by_key( $meta_key, $this->id, $default );
438 }
439
440 public function save_meta_by_key( $meta_key, $meta_value ) {
441 if ( $this->is_new_record() ) {
442 return false;
443 }
444
445 $meta = new OsServiceMetaModel();
446 return $meta->save_by_key( $meta_key, $meta_value, $this->id );
447 }
448
449 public function save_agents() {
450 foreach ( $this->agents as $agent ) {
451 $agent_connection_row = $this->db->get_row( $this->db->prepare( 'SELECT id FROM ' . $this->services_agents_table_name . ' WHERE service_id = %d AND agent_id = %d', array( $this->id, $agent->id ) ) );
452 if ( $agent_connection_row ) {
453 $update_data = array(
454 'is_custom_hours' => $agent->is_custom_hours,
455 'is_custom_price' => $agent->is_custom_price,
456 'is_custom_duration' => $agent->is_custom_duration,
457 );
458 $this->db->update( $this->services_agents_table_name, $update_data, array( 'id' => $agent_connection_row->id ) );
459 } else {
460 $insert_data = array(
461 'agent_id' => $agent->id,
462 'service_id' => $this->id,
463 'is_custom_hours' => $agent->is_custom_hours,
464 'is_custom_price' => $agent->is_custom_price,
465 'is_custom_duration' => $agent->is_custom_duration,
466 );
467 if ( $this->db->insert( $this->services_agents_table_name, $insert_data ) ) {
468 $agent_connection_row_id = $this->db->insert_id;
469 }
470 }
471 }
472 return true;
473 }
474
475
476
477 public function remove_agents_by_ids( $ids_to_remove = array() ) {
478 if ( $ids_to_remove ) {
479 $query = $this->db->prepare( 'DELETE FROM %i WHERE service_id = %d AND agent_id IN ' . OsModel::where_in_array_to_string( $ids_to_remove ), [ $this->services_agents_table_name, $this->id ] );
480 $this->db->query( $query );
481 }
482 }
483
484
485
486 public function get_agent_ids_to_remove( $new_agents = array() ) {
487 $current_agent_ids = $this->get_current_agent_ids_from_db();
488 $new_agent_ids = array();
489 foreach ( $new_agents as $agent ) {
490 if ( $agent['connected'] == 'yes' ) {
491 $new_agent_ids[] = $agent['id'];
492 }
493 }
494 $agent_ids_to_remove = array_diff( $current_agent_ids, $new_agent_ids );
495 return $agent_ids_to_remove;
496 }
497
498
499 public function save_agents_and_locations( $agents ) {
500 if ( ! $agents ) {
501 return true;
502 }
503 $connections_to_save = [];
504 $connections_to_remove = [];
505 foreach ( $agents as $agent_key => $locations ) {
506 $agent_id = str_replace( 'agent_', '', $agent_key );
507 foreach ( $locations as $location_key => $location ) {
508 $location_id = str_replace( 'location_', '', $location_key );
509 $connection = [
510 'service_id' => $this->id,
511 'agent_id' => $agent_id,
512 'location_id' => $location_id,
513 ];
514 if ( $location['connected'] == 'yes' ) {
515 $connections_to_save[] = $connection;
516 } else {
517 $connections_to_remove[] = $connection;
518 }
519 }
520 }
521 if ( ! empty( $connections_to_save ) ) {
522 foreach ( $connections_to_save as $connection_to_save ) {
523 OsConnectorHelper::save_connection( $connection_to_save );
524 }
525 }
526 if ( ! empty( $connections_to_remove ) ) {
527 foreach ( $connections_to_remove as $connection_to_remove ) {
528 OsConnectorHelper::remove_connection( $connection_to_remove );
529 }
530 }
531 return true;
532 }
533
534 public function get_current_agent_ids_from_db() {
535 $query = $this->db->prepare( 'SELECT agent_id FROM ' . $this->services_agents_table_name . ' WHERE service_id = %d', $this->id );
536 $agent_rows = $this->db->get_results( $query );
537
538 $agent_ids = array();
539
540 if ( $agent_rows ) {
541 foreach ( $agent_rows as $agent_row ) {
542 $agent_ids[] = $agent_row->agent_id;
543 }
544 }
545 return $agent_ids;
546 }
547
548
549 public function get_current_agent_ids() {
550 $agent_ids = array();
551 foreach ( $this->agents as $agent ) {
552 $agent_ids[] = $agent->id;
553 }
554 return $agent_ids;
555 }
556
557
558 public function get_agents() {
559 if ( ! isset( $this->agents ) ) {
560 $query = 'SELECT * FROM ' . $this->services_agents_table_name . ' WHERE service_id = %d GROUP BY agent_id';
561 $query_args = array( $this->id );
562 $agents_rows = $this->get_query_results( $query, $query_args );
563
564 $this->agents = array();
565
566 if ( $agents_rows ) {
567 foreach ( $agents_rows as $agent_row ) {
568 $agent = new OsAgentModel( $agent_row->agent_id );
569 $agent->is_custom_hours = $agent_row->is_custom_hours;
570 $agent->is_custom_price = $agent_row->is_custom_price;
571 $agent->is_custom_duration = $agent_row->is_custom_duration;
572 $this->agents[] = $agent;
573 }
574 }
575 }
576 return $this->agents;
577 }
578
579 public function set_agents( $agent_datas ) {
580 $this->agents = array();
581
582 foreach ( $agent_datas as $agent_data ) {
583 if ( $agent_data['connected'] == 'yes' ) {
584 $agent = new OsAgentModel();
585 $agent->id = $agent_data['id'];
586 $agent->is_custom_hours = $agent_data['is_custom_hours'];
587 $agent->is_custom_price = $agent_data['is_custom_price'];
588 $agent->is_custom_duration = $agent_data['is_custom_duration'];
589 $this->agents[] = $agent;
590 }
591 }
592 return $this;
593 }
594
595
596 public function has_agent( $agent_id ) {
597 return OsConnectorHelper::has_connection(
598 [
599 'service_id' => $this->id,
600 'agent_id' => $agent_id,
601 ]
602 );
603 }
604
605 public function has_agent_and_location( $agent_id, $location_id ) {
606 if ( $this->is_new_record() ) {
607 return false;
608 }
609 return OsConnectorHelper::has_connection(
610 [
611 'service_id' => $this->id,
612 'agent_id' => $agent_id,
613 'location_id' => $location_id,
614 ]
615 );
616 }
617
618 public function count_number_of_connected_locations( $agent_id = false ) {
619 if ( $this->is_new_record() ) {
620 return 0;
621 }
622 $args = [ 'service_id' => $this->id ];
623 if ( $agent_id ) {
624 $args['agent_id'] = $agent_id;
625 }
626 return OsConnectorHelper::count_connections( $args, 'location_id' );
627 }
628
629
630 protected function properties_to_validate() {
631 $validations = array(
632 'name' => array( 'presence' ),
633 'duration' => array( 'presence' ),
634 );
635 return $validations;
636 }
637 }
638