PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.2.11
LatePoint – Calendar Booking Plugin for Appointments and Events v5.2.11
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 / misc / process_event.php
latepoint / lib / misc Last commit date
blocked_period.php 3 months ago booked_period.php 3 months ago booking_request.php 3 months ago booking_resource.php 3 months ago booking_slot.php 3 months ago filter.php 3 months ago process_action.php 3 months ago process_event.php 3 months ago role.php 3 months ago router.php 3 months ago step.php 3 months ago stripe_connect_customer.php 3 months ago time_period.php 3 months ago user.php 3 months ago work_period.php 3 months ago
process_event.php
567 lines
1 <?php
2 /*
3 * Copyright (c) 2022 LatePoint LLC. All rights reserved.
4 */
5
6 namespace LatePoint\Misc;
7
8 class ProcessEvent {
9 public string $type = 'booking_created'; // booking_created, booking_updated, booking_start, booking_end, transaction_created, customer_created
10 public array $trigger_conditions = [];
11 public array $time_offset = [];
12
13 function __construct( $args = [] ) {
14 $allowed_props = self::allowed_props();
15 foreach ( $args as $key => $arg ) {
16 if ( in_array( $key, $allowed_props ) ) {
17 $this->$key = $arg;
18 }
19 }
20 }
21
22
23 public function set_from_params( $event_params ) {
24 $this->type = $event_params['type'];
25 $this->trigger_conditions = ( $event_params['conditional'] == LATEPOINT_VALUE_ON ) ? $event_params['trigger_conditions'] : [];
26 $this->time_offset = ( $event_params['has_time_offset'] == LATEPOINT_VALUE_ON ) ? $event_params['time_offset'] : [];
27 }
28
29 public function get_available_data_sources( array $trigger_conditions = [] ): array {
30 $data_sources = [];
31 switch ( $this->type ) {
32 case 'payment_request_created':
33 $payment_requests = new \OsPaymentRequestModel();
34 $payment_requests = $payment_requests->order_by( 'id desc' )->set_limit( 100 )->get_results_as_models();
35 $payment_requests_for_select = [];
36 foreach ( $payment_requests as $payment_request ) {
37 $name = 'Order ID:' . $payment_request->order_id . ', Invoice ID: ' . $payment_request->invoice_id . ' [' . \OsMoneyHelper::format_price( $payment_request->charge_amount, true, false ) . ' : ' . $payment_request->id . ']';
38 $payment_requests_for_select[] = [
39 'value' => $payment_request->id,
40 'label' => esc_html( $name ),
41 ];
42 }
43
44 $data_sources[] = [
45 'name' => 'payment_request_id',
46 'values' => $payment_requests_for_select,
47 'label' => __( 'Choose a payment request for this test run:', 'latepoint' ),
48 'model' => 'payment_request',
49 ];
50 break;
51 case 'order_created':
52 $orders_for_select = \OsOrdersHelper::get_orders_for_select();
53 $data_sources[] = [
54 'name' => 'order_id',
55 'values' => $orders_for_select,
56 'label' => __( 'Choose an order for this test run:', 'latepoint' ),
57 'model' => 'order',
58 ];
59 break;
60 case 'order_updated':
61 $orders_for_select = \OsOrdersHelper::get_orders_for_select();
62 $data_sources[] = [
63 'name' => 'new_order_id',
64 'values' => $orders_for_select,
65 'label' => __( 'Choose old order to be used for this test run:', 'latepoint' ),
66 'model' => 'order',
67 ];
68 $data_sources[] = [
69 'name' => 'old_order_id',
70 'values' => $orders_for_select,
71 'label' => __( 'Choose new order to be used for this test run:', 'latepoint' ),
72 'model' => 'order',
73 ];
74 break;
75 case 'booking_created':
76 case 'booking_start':
77 case 'booking_end':
78 $bookings_for_select = \OsBookingHelper::get_bookings_for_select();
79 $data_sources[] = [
80 'name' => 'booking_id',
81 'values' => $bookings_for_select,
82 'label' => __( 'Choose a booking for this test run:', 'latepoint' ),
83 'model' => 'booking',
84 ];
85 break;
86 case 'booking_updated':
87 $bookings_for_select = \OsBookingHelper::get_bookings_for_select();
88 $data_sources[] = [
89 'name' => 'new_booking_id',
90 'values' => $bookings_for_select,
91 'label' => __( 'Choose old booking to be used for this test run:', 'latepoint' ),
92 'model' => 'booking',
93 ];
94 $data_sources[] = [
95 'name' => 'old_booking_id',
96 'values' => $bookings_for_select,
97 'label' => __( 'Choose new booking to be used for this test run:', 'latepoint' ),
98 'model' => 'booking',
99 ];
100 break;
101 case 'transaction_created':
102 $transactions = \OsPaymentsHelper::get_transactions_for_select();
103 $data_sources[] = [
104 'name' => 'transaction_id',
105 'values' => $transactions,
106 'label' => __( 'Choose a transaction for this test run:', 'latepoint' ),
107 'model' => 'transaction',
108 ];
109 break;
110 case 'customer_created':
111 $customers = \OsCustomerHelper::get_customers_for_select();
112 $data_sources[] = [
113 'name' => 'customer_id',
114 'values' => $customers,
115 'label' => __( 'Choose a customer for this test run:', 'latepoint' ),
116 'model' => 'customer',
117 ];
118 break;
119 }
120
121 /**
122 * Returns an array of process event data sources
123 *
124 * @since 4.7.0
125 * @hook latepoint_process_event_data_sources
126 *
127 * @param {array} $data_sources Current array of process event data sources
128 * @param {ProcessEvent} $event The ProcessEvent object for which to generate data sources
129 *
130 * @returns {array} Filtered array of process event data sources
131 */
132 return apply_filters( 'latepoint_process_event_data_sources', $data_sources, $this );
133 }
134
135 public function trigger_conditions_form_html() {
136 $html = '';
137 if ( $this->trigger_conditions ) {
138 foreach ( $this->trigger_conditions as $trigger_condition ) {
139 $html .= $this->generate_trigger_condition_form_html( $trigger_condition );
140 }
141 } else {
142 $html .= $this->generate_trigger_condition_form_html();
143 }
144 return $html;
145 }
146
147 public static function get_object_from_property( string $property ): string {
148 return explode( '__', $property )[0] ?? '';
149 }
150
151 public static function get_object_attribute_from_property( string $property ): string {
152 return explode( '__', $property )[1] ?? '';
153 }
154
155 public static function get_model_by_code( string $property_object_name ): \OsModel {
156 $model = new \OsBookingModel();
157 switch ( $property_object_name ) {
158 case 'order':
159 case 'old_order':
160 $model = new \OsOrderModel();
161 break;
162 case 'booking':
163 case 'old_booking':
164 $model = new \OsBookingModel();
165 break;
166 case 'transaction':
167 $model = new \OsTransactionModel();
168 break;
169 case 'customer':
170 $model = new \OsCustomerModel();
171 break;
172 case 'agent':
173 $model = new \OsAgentModel();
174 break;
175 case 'service':
176 $model = new \OsServiceModel();
177 break;
178 case 'payment_request':
179 $model = new \OsPaymentRequestModel();
180 break;
181 }
182
183 /**
184 * Returns an instance of <code>OsModel</code>, based on the supplied object code
185 *
186 * @since 4.7.0
187 * @hook latepoint_process_event_model
188 *
189 * @param {OsModel} $model Current model
190 * @param {string} $property_object_name The object code used to determine the resultant model
191 *
192 * @returns {OsModel} Instance of <code>OsModel</code> based on the supplied object code
193 */
194 return apply_filters( 'latepoint_process_event_model', $model, $property_object_name );
195 }
196
197 public static function get_properties_for_object_code( string $property_object, bool $prepare_for_select = false ): array {
198 $model = self::get_model_by_code( $property_object );
199 $properties = $model->get_properties_to_query();
200 if ( $prepare_for_select ) {
201 $properties_for_select = [];
202 // glue property name and object code together so they are identifiable in a select box
203 foreach ( $properties as $property_code => $property_label ) {
204 $property_full_code = $property_object . '__' . $property_code;
205 $operators = self::trigger_condition_operators_for_property( $property_full_code );
206 if ( ! empty( $operators ) ) {
207 $properties_for_select[] = [
208 'value' => $property_full_code,
209 'label' => $property_label,
210 ];
211 }
212 }
213 return $properties_for_select;
214 } else {
215 return $properties;
216 }
217 }
218
219 public static function get_available_trigger_condition_objects_for_event_type( string $event_type ): array {
220 $objects = [];
221 switch ( $event_type ) {
222 case 'booking_created':
223 case 'booking_start':
224 case 'booking_end':
225 $objects[] = [
226 'code' => 'booking',
227 'model' => 'OsBookingModel',
228 'label' => __( 'Booking', 'latepoint' ),
229 'properties' => [],
230 ];
231 break;
232 case 'booking_updated':
233 $objects[] = [
234 'code' => 'old_booking',
235 'model' => 'OsBookingModel',
236 'label' => __( 'Old Booking', 'latepoint' ),
237 'properties' => [],
238 ];
239 $objects[] = [
240 'code' => 'booking',
241 'model' => 'OsBookingModel',
242 'label' => __( 'New Booking', 'latepoint' ),
243 'properties' => [],
244 ];
245 break;
246 case 'order_updated':
247 $objects[] = [
248 'code' => 'old_order',
249 'model' => 'OsOrderModel',
250 'label' => __( 'Old Order', 'latepoint' ),
251 'properties' => [],
252 ];
253 $objects[] = [
254 'code' => 'order',
255 'model' => 'OsOrderModel',
256 'label' => __( 'New Order', 'latepoint' ),
257 'properties' => [],
258 ];
259 break;
260 case 'order_created':
261 $objects[] = [
262 'code' => 'order',
263 'model' => 'OsOrderModel',
264 'label' => __( 'Order', 'latepoint' ),
265 'properties' => [],
266 ];
267 break;
268 case 'transaction_created':
269 $objects[] = [
270 'code' => 'transaction',
271 'model' => 'OsTransactionModel',
272 'label' => __( 'Transaction', 'latepoint' ),
273 'properties' => [],
274 ];
275 break;
276 case 'customer_created':
277 // $objects[] = ['code' => 'customer', 'model' => 'OsCustomerModel', 'label' => __('Customer', 'latepoint'), 'properties' => []];
278 break;
279 case 'agent_created':
280 $objects[] = [
281 'code' => 'agent',
282 'model' => 'OsAgentModel',
283 'label' => __( 'Agent', 'latepoint' ),
284 'properties' => [],
285 ];
286 break;
287 case 'service_created':
288 $objects[] = [
289 'code' => 'service',
290 'model' => 'OsServiceModel',
291 'label' => __( 'Service', 'latepoint' ),
292 'properties' => [],
293 ];
294 break;
295 }
296
297 /**
298 * Returns an array of condition objects, based on the supplied event type
299 *
300 * @since 4.7.0
301 * @hook latepoint_process_event_condition_objects
302 *
303 * @param {array} $objects Current array of condition objects
304 * @param {string} $event_type The event type for which to generate condition objects
305 *
306 * @returns {array} Filtered array of available condition objects
307 */
308 return apply_filters( 'latepoint_process_event_condition_objects', $objects, $event_type );
309 }
310
311 public function generate_trigger_condition_form_html( $trigger_condition = false ) {
312 $objects = self::get_available_trigger_condition_objects_for_event_type( $this->type );
313 $objects_for_select = [];
314 foreach ( $objects as $object ) {
315 $objects_for_select[] = [
316 'value' => $object['code'],
317 'label' => $object['label'],
318 ];
319 }
320
321 // new condition
322 if ( ! $trigger_condition ) {
323 $selected_object_code = $objects_for_select[0]['value'];
324 $properties_for_select = self::get_properties_for_object_code( $selected_object_code, true );
325 $operators_for_select = self::trigger_condition_operators_for_property( $properties_for_select[0]['value'] );
326 $trigger_condition = [
327 'id' => self::generate_trigger_condition_id(),
328 'property' => $properties_for_select[0]['value'] ?? '',
329 'operator' => $operators_for_select[0]['value'] ?? 'equal',
330 'value' => false,
331 ];
332 } else {
333 $operators_for_select = self::trigger_condition_operators_for_property( $trigger_condition['property'] );
334 $selected_object_code = $trigger_condition['property'] ? explode( '__', $trigger_condition['property'] )[0] : $objects_for_select[0]['value'];
335 $properties_for_select = self::get_properties_for_object_code( $selected_object_code, true );
336 $operators_for_select = self::trigger_condition_operators_for_property( $trigger_condition['property'] );
337 }
338 // if we only have 1 object available - no need to output the select box for it
339 if ( count( $objects_for_select ) > 1 ) {
340 $object_selector_html = \OsFormHelper::select_field(
341 'process[event][trigger_conditions][' . $trigger_condition['id'] . '][object]',
342 false,
343 $objects_for_select,
344 $selected_object_code,
345 [
346 'class' => 'process-condition-object-selector',
347 'data-change-target' => 'process-condition-properties-w',
348 'data-condition-id' => $trigger_condition['id'],
349 'data-route' => \OsRouterHelper::build_route_name( 'processes', 'available_properties_for_object_code' ),
350 ]
351 );
352 } else {
353 $object_selector_html = '';
354 }
355 $html = '<div class="pe-condition" data-condition-id="' . $trigger_condition['id'] . '">' .
356 '<button class="pe-remove-condition"><i class="latepoint-icon latepoint-icon-cross"></i></button>' .
357 $object_selector_html .
358 \OsFormHelper::select_field(
359 'process[event][trigger_conditions][' . $trigger_condition['id'] . '][property]',
360 false,
361 $properties_for_select,
362 $trigger_condition['property'],
363 [
364 'class' => 'process-condition-property-selector',
365 'data-route' => \OsRouterHelper::build_route_name( 'processes', 'available_operators_for_trigger_condition_property' ),
366 ],
367 [ 'class' => 'process-condition-properties-w' ]
368 ) .
369 \OsFormHelper::select_field(
370 'process[event][trigger_conditions][' . $trigger_condition['id'] . '][operator]',
371 false,
372 $operators_for_select,
373 $trigger_condition['operator'],
374 [
375 'class' => 'process-condition-operator-selector',
376 'data-route' => \OsRouterHelper::build_route_name( 'processes', 'available_values_for_trigger_condition_property' ),
377 ],
378 [ 'class' => 'process-condition-operators-w' ]
379 ) .
380 \OsFormHelper::multi_select_field(
381 'process[event][trigger_conditions][' . $trigger_condition['id'] . '][value]',
382 false,
383 \OsProcessesHelper::values_for_trigger_condition_property( $trigger_condition['property'] ),
384 $trigger_condition['value'] ? explode( ',', $trigger_condition['value'] ) : [],
385 [],
386 [
387 'class' => 'process-condition-values-w',
388 'style' => in_array( $trigger_condition['operator'], [ 'changed', 'not_changed' ] ) ? 'display: none;' : '',
389 ]
390 ) .
391 '<div data-os-action="' . \OsRouterHelper::build_route_name( 'processes', 'new_trigger_condition' ) . '"
392 data-os-pass-response="yes"
393 data-os-pass-this="yes"
394 data-os-before-after="none"
395 data-os-params="' . \OsUtilHelper::build_os_params( [ 'event_type' => $this->type ] ) . '"
396 data-os-after-call="latepoint_add_process_condition"><button class="latepoint-btn-outline latepoint-btn"><i class="latepoint-icon latepoint-icon-plus2"></i><span>' . __( 'AND', 'latepoint' ) . '</span></button></div>' .
397 '</div>';
398 return $html;
399 }
400
401 public static function trigger_condition_operators_for_property( string $property = '' ) {
402 $property_object = $property ? explode( '__', $property )[0] : 'booking';
403 $property_attribute = $property ? explode( '__', $property )[1] : '';
404 $operators = [];
405 switch ( $property_object ) {
406 case 'old_order':
407 case 'old_booking':
408 // TODO time range operators instead of removing these opearators completely
409 if ( $property_attribute != 'start_datetime_utc' ) {
410 $operators['equal'] = __( 'was equal to', 'latepoint' );
411 $operators['not_equal'] = __( 'was not equal to', 'latepoint' );
412 }
413 $operators['changed'] = __( 'has changed', 'latepoint' );
414 $operators['not_changed'] = __( 'has not changed', 'latepoint' );
415 break;
416 case 'order':
417 case 'booking':
418 case 'customer':
419 case 'agent':
420 case 'service':
421 case 'transaction':
422 // TODO time range operators instead of removing these opearators completely
423 if ( $property_attribute != 'start_datetime_utc' ) {
424 $operators['equal'] = __( 'is equal to', 'latepoint' );
425 $operators['not_equal'] = __( 'is not equal to', 'latepoint' );
426 }
427 break;
428 }
429
430 /**
431 * Returns an array of operators available for a selected condition property
432 *
433 * @since 4.7.0
434 * @hook latepoint_process_event_trigger_condition_properties
435 *
436 * @param {array} $operators Array of operators
437 * @param {string} $property Property in a format of object_code__object_property (e.g. old_booking__agent_id)
438 * @param {string} $property_object Object name
439 * @param {string} $property_attribute Property of an object
440 *
441 * @returns {array} The array of available operators
442 *
443 */
444 return apply_filters( 'latepoint_process_event_trigger_condition_operators', $operators, $property, $property_object, $property_attribute );
445 }
446
447 public static function trigger_condition_properties_for_type( $event_type ) {
448 $properties = [];
449 switch ( $event_type ) {
450 case 'order_created':
451 $properties = [
452 'order__status' => __( 'Order Status', 'latepoint' ),
453 'order__fulfillment_status' => __( 'Fulfillment Service', 'latepoint' ),
454 'order__payment_status' => __( 'Payment Status', 'latepoint' ),
455 ];
456 break;
457 case 'order_updated':
458 $properties = [
459 'old__order__status' => __( 'Previous Order Status', 'latepoint' ),
460 'old__order__fulfillment_status' => __( 'Previous Fulfillment Service', 'latepoint' ),
461 'old__order__payment_status' => __( 'Previous Payment Status', 'latepoint' ),
462 'order__status' => __( 'Order Status', 'latepoint' ),
463 'order__fulfillment_status' => __( 'Fulfillment Service', 'latepoint' ),
464 'order__payment_status' => __( 'Payment Status', 'latepoint' ),
465 ];
466 break;
467 case 'booking_created':
468 $properties = [
469 'booking__status' => __( 'Booking Status', 'latepoint' ),
470 'booking__service_id' => __( 'Service', 'latepoint' ),
471 'booking__agent_id' => __( 'Agent', 'latepoint' ),
472 ];
473 break;
474 case 'booking_updated':
475 $properties = [
476 'old__booking__status' => __( 'Previous Booking Status', 'latepoint' ),
477 'old__booking__service_id' => __( 'Previous Service', 'latepoint' ),
478 'old__booking__agent_id' => __( 'Previous Agent', 'latepoint' ),
479 'old__booking__start_datetime_utc' => __( 'Start Time', 'latepoint' ),
480 'booking__status' => __( 'Booking Status', 'latepoint' ),
481 'booking__service_id' => __( 'Service', 'latepoint' ),
482 'booking__agent_id' => __( 'Agent', 'latepoint' ),
483 ];
484 break;
485 case 'transaction_created':
486 $properties = [
487 'transaction__payment_method' => __( 'Payment Method', 'latepoint' ),
488 ];
489 break;
490 }
491
492 return apply_filters( 'latepoint_process_event_trigger_condition_properties', $properties, $event_type );
493 }
494
495 public static function get_event_types() {
496 $event_types = [
497 'order_created',
498 'order_updated',
499 'booking_created',
500 'booking_updated',
501 'booking_start',
502 'booking_end',
503 'customer_created',
504 'transaction_created',
505 'payment_request_created',
506 ];
507
508 /**
509 * Returns an array of event types that trigger automation process
510 *
511 * @since 4.7.0
512 * @hook latepoint_process_event_types
513 *
514 * @param {array} $event_types Array of event types
515 *
516 * @returns {array} The array of event types that trigger automation process
517 */
518 return apply_filters( 'latepoint_process_event_types', $event_types );
519 }
520
521
522 public static function get_event_name_for_type( $type ) {
523 $names = [
524 'order_created' => __( 'Order Created', 'latepoint' ),
525 'order_updated' => __( 'Order Updated', 'latepoint' ),
526 'booking_created' => __( 'Booking Created', 'latepoint' ),
527 'booking_updated' => __( 'Booking Updated', 'latepoint' ),
528 'booking_start' => __( 'Booking Started', 'latepoint' ),
529 'booking_end' => __( 'Booking Ended', 'latepoint' ),
530 'customer_created' => __( 'Customer Created', 'latepoint' ),
531 'transaction_created' => __( 'Transaction Created', 'latepoint' ),
532 'payment_request_created' => __( 'Payment Request Created', 'latepoint' ),
533 ];
534
535 /**
536 * Returns an array of process event types mapped to their displayable names
537 *
538 * @since 4.7.0
539 * @hook latepoint_process_event_names
540 *
541 * @param {array} $names Array of event types/names to filter
542 *
543 * @returns {array} Filtered array of event types/names
544 */
545 $names = apply_filters( 'latepoint_process_event_names', $names );
546
547 return $names[ $type ] ?? $type;
548 }
549
550 public static function get_event_types_for_select() {
551 $types = self::get_event_types();
552 $types_for_select = [];
553 foreach ( $types as $type ) {
554 $types_for_select[ $type ] = self::get_event_name_for_type( $type );
555 }
556 return $types_for_select;
557 }
558
559 public static function generate_trigger_condition_id(): string {
560 return 'pec_' . \OsUtilHelper::random_text( 'alnum', 6 );
561 }
562
563 public static function allowed_props(): array {
564 return [ 'id', 'type', 'trigger_conditions', 'time_offset' ];
565 }
566 }
567