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