PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.1.2
LatePoint – Calendar Booking Plugin for Appointments and Events v5.1.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 / misc / process_action.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 1 year 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_action.php
381 lines
1 <?php
2 /*
3 * Copyright (c) 2022 LatePoint LLC. All rights reserved.
4 */
5
6 namespace LatePoint\Misc;
7
8 class ProcessAction{
9 public string $id;
10 public string $type = 'send_email';
11 public string $status = 'active';
12 public ?array $settings = [];
13 public array $prepared_data_for_run = [];
14 public array $replacement_vars = [];
15 public array $selected_data_objects = []; // example ['model' => 'booking', 'id' => INT]
16 public ProcessEvent $event;
17
18 function __construct($args = []){
19 $allowed_props = self::allowed_props();
20 foreach($args as $key => $arg){
21 if(in_array($key, $allowed_props)) $this->$key = $arg;
22 }
23 if(empty($this->id)) $this->id = self::generate_id();
24 switch($this->type){
25 case 'send_email':
26 $this->settings['to_email'] = $this->settings['to_email'] ?? '';
27 $this->settings['subject'] = $this->settings['subject'] ?? '';
28 $this->settings['content'] = $this->settings['content'] ?? '';
29 break;
30 case 'send_sms':
31 $this->settings['to_phone'] = $this->settings['to_phone'] ?? '';
32 $this->settings['content'] = $this->settings['content'] ?? '';
33 break;
34 }
35 }
36
37 public function get_nice_type_name(){
38 return self::get_action_name_for_type($this->type);
39 }
40
41 public function get_descriptive_setting(){
42 switch($this->type) {
43 case 'send_email':
44 return $this->settings['to_email'] ?? '';
45 case 'send_sms':
46 return $this->settings['to_phone'] ?? '';
47 }
48 }
49
50 public function generate_replacement_vars(){
51 $this->replacement_vars = \OsReplacerHelper::generate_replacement_vars_from_data_objects($this->selected_data_objects);
52 }
53
54 public function set_from_params($params){
55 if(!empty($params['id'])) $this->id = $params['id'];
56 if(!empty($params['type'])) $this->type = $params['type'];
57 if(!empty($params['settings'])) $this->settings = $params['settings'];
58 if(!empty($params['event'])) $this->event = new ProcessEvent(['type' => $params['event']['type']]);
59 }
60
61 public function load_settings_from_template($template_id){
62 $templates = \OsNotificationsHelper::load_templates_for_action_type($this->type);
63 foreach($templates as $template){
64 if($template['id'] == $template_id){
65 switch($this->type){
66 case 'send_email':
67 $this->settings['to_email'] = $template['to_email'];
68 $this->settings['subject'] = $template['subject'];
69 $this->settings['content'] = $template['content'];
70 break;
71 case 'send_sms':
72 $this->settings['to_phone'] = $template['to_phone'];
73 $this->settings['content'] = $template['content'];
74 break;
75 }
76
77 /**
78 * Returns an array of process action settings, based on a selected template
79 *
80 * @since 4.7.0
81 * @hook latepoint_process_action_settings
82 *
83 * @param {array} $settings Array of settings to filter
84 * @param {array} $template Array of data representing selected template
85 * @param {ProcessAction} $action Instance of <code>ProcessAction</code> for which settings are being generated
86 *
87 * @returns {array} Filtered array of process action settings
88 */
89 $this->settings = apply_filters('latepoint_process_action_settings', $this->settings, $template, $this);
90 break;
91 }
92 }
93 }
94
95 public static function generate_form(ProcessAction $action): string{
96 $descriptive_setting = $action->get_descriptive_setting() ? '<div class="process-action-descriptive-setting">'.$action->get_descriptive_setting().'</div>' : '';
97 $html = '<div class="process-action-form pa-type-'.$action->type.' pa-status-'.$action->status.'" data-id="'.$action->id.'">';
98 $html.= '<div class="process-action-heading">
99 <div class="process-action-status"></div>
100 <div class="process-action-icon"></div>
101 <div class="process-action-name">'.self::get_action_name_for_type($action->type).'</div>
102 '.$descriptive_setting.'
103 <div class="process-action-chevron"><i class="latepoint-icon latepoint-icon-chevron-down"></i></div>
104 <a href="#" class="process-action-remove os-remove-process-action"
105 data-os-prompt="'.__('Are you sure you want to delete this action?', 'latepoint').'"><i class="latepoint-icon latepoint-icon-cross"></i></a>
106 </div>';
107 $html.= '<div class="process-action-content">';
108 $html.= '<div class="os-row">';
109 $html.= \OsFormHelper::select_field('process[actions]['.$action->id.'][type]', __('Action Type', 'latepoint'), \LatePoint\Misc\ProcessAction::get_action_types_for_select(), $action->type, ['class' => 'process-action-type', 'data-action-id' => $action->id, 'data-route' => \OsRouterHelper::build_route_name('processes', 'load_action_settings')], ['class' => 'os-col-10']);
110 $html.= \OsFormHelper::select_field('process[actions]['.$action->id.'][status]', __('Status', 'latepoint'), [LATEPOINT_STATUS_ACTIVE => __('Active', 'latepoint'), LATEPOINT_STATUS_DISABLED => __('Disabled', 'latepoint')], $action->status, false, ['class' => 'os-col-2']);
111 $html.= '</div>';
112 $html.= '<div class="process-action-settings">';
113 $html.= self::generate_settings_fields($action);
114 $html.= '</div>';
115 $html.= '<div class="process-buttons">
116 <a href="#" class="latepoint-btn latepoint-btn-danger pull-left os-remove-process-action"
117 data-os-prompt="'.__('Are you sure you want to delete this action?', 'latepoint').'" >'.__('Delete', 'latepoint').'</a>
118 <a href="#" data-route="'.\OsRouterHelper::build_route_name('processes', 'action_test_preview').'" class="latepoint-btn latepoint-btn-secondary os-run-process-action" ><i class="latepoint-icon latepoint-icon-play-circle"></i><span>'.__('Test this action', 'latepoint').'</span></a>
119 </div>';
120 $html.= '</div>';
121 $html.= '</div>';
122 return $html;
123 }
124
125
126 public static function generate_settings_fields(ProcessAction $action){
127 $html = '';
128
129 if(in_array($action->type, ['send_email', 'send_sms'])){
130 $html.= '<div class="process-action-controls-wrapper">';
131 $html.= '<a href="#" data-os-after-call="latepoint_init_template_library" data-os-params="'.\OsUtilHelper::build_os_params(['action_id'=>$action->id, 'action_type'=>$action->type]).'" data-os-lightbox-classes="width-1000" data-os-action="'.\OsRouterHelper::build_route_name('notifications', 'templates_index').'" href="#" data-os-output-target="side-panel" class="latepoint-btn latepoint-btn-outline latepoint-btn-sm"><i class="latepoint-icon latepoint-icon-book"></i><span>'.__('Load from template', 'latepoint').'</span></a>';
132 $html.= '<a href="#" class="latepoint-btn latepoint-btn-outline latepoint-btn-sm open-template-variables-panel"><i class="latepoint-icon latepoint-icon-zap"></i><span>'.__('Show smart variables', 'latepoint').'</span></a>';
133 $html.= '</div>';
134 }
135
136 switch($action->type){
137 case 'send_email':
138 $html.= '<div class="os-row">';
139 $html.= \OsFormHelper::text_field('process[actions]['.$action->id.'][settings][to_email]', __('To Email', 'latepoint'), $action->settings['to_email'], ['theme' => 'simple', 'placeholder' => __('To email address', 'latepoint')], ['class' => 'os-col-6']);
140 $html.= \OsFormHelper::text_field('process[actions]['.$action->id.'][settings][subject]', __('Email Subject', 'latepoint'), $action->settings['subject'], ['theme' => 'simple', 'placeholder' => __('Email Subject', 'latepoint')], ['class' => 'os-col-6']);
141 $html.= '</div>';
142 $html.= \OsFormHelper::textarea_field('process[actions]['.$action->id.'][settings][content]', false, $action->settings['content'], ['id' => 'process_actions_'.$action->id.'_settings_content', 'class' => 'os-wp-editor-textarea']);
143 break;
144 case 'send_sms':
145 if(\OsSmsHelper::get_sms_processors()){
146 $html.= \OsFormHelper::text_field('process[actions]['.$action->id.'][settings][to_phone]', __('To Phone Number', 'latepoint'), $action->settings['to_phone'], ['theme' => 'simple', 'placeholder' => __('Phone Number', 'latepoint')]);
147 $html.= \OsFormHelper::textarea_field('process[actions]['.$action->id.'][settings][content]', __('Message Content', 'latepoint'), $action->settings['content'], ['theme' => 'simple', 'placeholder' => __('Message', 'latepoint'), 'rows' => 4]);
148 }else{
149 $html = \OsUtilHelper::generate_missing_addon_link(__('You have to install an SMS processor addon to send text messages.', 'latepoint'));
150 }
151 break;
152 case 'trigger_webhook':
153 $html = \OsUtilHelper::generate_missing_addon_link(__('Requires upgrade to a premium version', 'latepoint'));
154 break;
155 }
156
157 /**
158 * Filters HTML code (after) for Process Action settings form
159 *
160 * @since 4.7.0
161 * @hook latepoint_process_action_settings_fields_html_after
162 *
163 * @param {string} $html HTML content of the settings form
164 * @param {ProcessAction} $action ProcessAction object for which this settings form is being generated
165 *
166 * @returns {string} HTML content of the settings form
167 */
168 return apply_filters('latepoint_process_action_settings_fields_html_after', $html, $action);
169 }
170
171 public static function generate_id(): string{
172 return 'pa_'.\OsUtilHelper::random_text('alnum', 6);
173 }
174
175 public function settings_form(){
176 $html = '';
177 switch($this->type){
178 case 'send_email':
179 $html.= \OsFormHelper::text_field('action[actions]['.$this->id.'][to]', '', $this->settings['to'], ['theme' => 'simple', 'placeholder' => __('Email To', 'latepoint')]);
180 break;
181 case 'send_sms':
182 $html.= \OsFormHelper::text_field('action[actions]['.$this->id.'][to]', '', $this->settings['to'], ['theme' => 'simple', 'placeholder' => __('SMS To', 'latepoint')]);
183 break;
184 case 'trigger_webhook':
185 $html.= \OsFormHelper::text_field('action[actions]['.$this->id.'][url]', '', $this->settings['url'], ['theme' => 'simple', 'placeholder' => __('Webhook URL', 'latepoint')]);
186 break;
187 }
188
189 return apply_filters('latepoint_process_action_settings_form_html', $html, $this);
190 }
191
192
193 public static function get_action_types(){
194 $action_types = ['send_email', 'send_sms', 'trigger_webhook'];
195
196 /**
197 * Returns an array of process action types that can be executed when an event is triggered
198 *
199 * @since 4.7.0
200 * @hook latepoint_process_action_types
201 *
202 * @param {array} $action_types Array of action types to filter
203 *
204 * @returns {array} Filtered array of action types
205 */
206 return apply_filters('latepoint_process_action_types', $action_types);
207 }
208
209 public static function get_action_name_for_type($type){
210 $names = [
211 'send_email' => __('Send Email', 'latepoint'),
212 'send_sms' => __('Send SMS', 'latepoint'),
213 'trigger_webhook' => __('HTTP Request (Webhook)', 'latepoint')
214 ];
215
216 /**
217 * Returns an array of process action types mapped to their displayable names
218 *
219 * @since 4.7.0
220 * @hook latepoint_process_action_names
221 *
222 * @param {array} $names Array of action types/names to filter
223 *
224 * @returns {array} Filtered array of action types/names
225 */
226 $names = apply_filters('latepoint_process_action_names', $names);
227
228 return $names[$type] ?? __('n/a', 'latepoint');
229 }
230
231 public static function get_action_types_for_select(){
232 $types = self::get_action_types();
233 $types_for_select = [];
234 foreach($types as $type){
235 $types_for_select[$type] = self::get_action_name_for_type($type);
236 }
237 return $types_for_select;
238 }
239
240 public function prepare_data_for_run(){
241 $this->generate_replacement_vars();
242 foreach($this->selected_data_objects as $data_object){
243 switch($data_object['model']) {
244 case 'order':
245 $this->prepared_data_for_run['activity_data']['order_id'] = $data_object['id'];
246 if(!empty($data_object['model_ready'])){
247 $this->prepared_data_for_run['activity_data']['customer_id'] = $data_object['model_ready']->customer_id;
248 }
249 break;
250 case 'booking':
251 $this->prepared_data_for_run['activity_data']['booking_id'] = $data_object['id'];
252 if(!empty($data_object['model_ready'])){
253 $this->prepared_data_for_run['activity_data']['agent_id'] = $data_object['model_ready']->agent_id;
254 $this->prepared_data_for_run['activity_data']['service_id'] = $data_object['model_ready']->service_id;
255 $this->prepared_data_for_run['activity_data']['customer_id'] = $data_object['model_ready']->customer_id;
256 }
257 break;
258 case 'customer':
259 $this->prepared_data_for_run['activity_data']['customer_id'] = $data_object['id'];
260 break;
261 case 'transaction':
262 $this->prepared_data_for_run['activity_data']['transaction_id'] = $data_object['id'];
263 break;
264 case 'payment_request':
265 $this->prepared_data_for_run['activity_data']['payment_request_id'] = $data_object['id'];
266 break;
267 }
268 }
269
270 switch($this->type) {
271 case 'send_email':
272 $this->prepared_data_for_run['to'] = \OsReplacerHelper::replace_all_vars($this->settings['to_email'], $this->replacement_vars);
273 $this->prepared_data_for_run['subject'] = \OsReplacerHelper::replace_all_vars($this->settings['subject'], $this->replacement_vars);
274 $this->prepared_data_for_run['content'] = \OsReplacerHelper::replace_all_vars($this->settings['content'], $this->replacement_vars);
275 break;
276 case 'send_sms':
277 $this->prepared_data_for_run['to'] = \OsReplacerHelper::replace_all_vars($this->settings['to_phone'], $this->replacement_vars);
278 $this->prepared_data_for_run['content'] = \OsReplacerHelper::replace_all_vars($this->settings['content'], $this->replacement_vars);
279 break;
280 }
281
282 /**
283 * Prepare data for action run
284 *
285 * @since 4.7.0
286 * @hook latepoint_process_prepare_data_for_run
287 *
288 * @param {ProcessAction} $action ProcessAction that was executed
289 *
290 * @returns {ProcessAction} $action ProcessAction with prepared data for action run
291 */
292 return apply_filters('latepoint_process_prepare_data_for_run', $this);
293 }
294
295
296 /**
297 * @param $prepare_data
298 * @return array [status => '', 'message' => '']
299 */
300 public function run($prepare_data = true){
301 $result = [
302 'status' => LATEPOINT_STATUS_SUCCESS,
303 'message' => __('Nothing to run', 'latepoint')
304 ];
305 if($prepare_data) $this->prepare_data_for_run();
306
307 switch($this->type) {
308 case 'send_email':
309 $notification_type = 'email';
310 $result = \OsNotificationsHelper::send($notification_type, $this->prepared_data_for_run);
311 break;
312 case 'send_sms':
313 $notification_type = 'sms';
314 $result = \OsNotificationsHelper::send($notification_type, $this->prepared_data_for_run);
315 break;
316 }
317
318
319 /**
320 * ProcessAction run result
321 *
322 * @since 4.7.0
323 * @hook latepoint_process_action_run
324 *
325 * @param {array} $result The array of data describing the status of the action run
326 * @param {ProcessAction} $action ProcessAction that was executed
327 *
328 * @returns {array} The array of descriptive data, possibly transformed by additional hooked ProcessAction handlers
329 */
330 return apply_filters('latepoint_process_action_run', $result, $this);
331 }
332
333
334 /**
335 * @return string
336 */
337 public function generate_preview(){
338 if(empty($this->prepared_data_for_run)){
339 $this->prepare_data_for_run();
340 // nothing was generated, probably because there is no object attached
341 if(empty($this->prepared_data_for_run)) return '<div class="action-preview-error">'.__('You have to create a booking to be able to test this action.', 'latepoint').'</div>';
342 }
343 $html = '<div class="action-preview-content-wrapper">';
344 $preview_content_html = '';
345 switch($this->type){
346 case 'send_email':
347 $preview_content_html.= '<div class="action-preview-subject"><span class="os-label">'.__('Subject:', 'latepoint').'</span> '.$this->prepared_data_for_run['subject'].'</div>';
348 $preview_content_html.= '<div class="action-preview-to"><span class="os-label">'.__('To:', 'latepoint').'</span><span class="os-value">'.esc_html($this->prepared_data_for_run['to']).'</div>';
349 $preview_content_html.= '<div class="action-preview-content">'.$this->prepared_data_for_run['content'].'</div>';
350 break;
351 case 'send_sms':
352 $preview_content_html.= '<div class="action-preview-to"><span class="os-label">'.__('To:', 'latepoint').'</span><span class="os-value">'.esc_html($this->prepared_data_for_run['to']).'</span></div>';
353 $preview_content_html.= '<div class="action-preview-content">'.$this->prepared_data_for_run['content'].'</div>';
354 break;
355 }
356
357 /**
358 * Generates a preview html for ProcessAction testing
359 *
360 * @since 4.7.0
361 * @hook latepoint_process_action_generate_preview
362 *
363 * @param {string} $preview_content_html HTML that goes inside of a preview
364 * @param {ProcessAction} $action ProcessAction that is being tested
365 *
366 * @returns {string} HTML that goes inside of a preview
367 */
368 $preview_content_html = apply_filters('latepoint_process_action_generate_preview', $preview_content_html, $this);
369 $html.= $preview_content_html;
370 $html.= '</div>';
371 return $html;
372 }
373
374 public static function replace_variables($test){
375
376 }
377
378 public static function allowed_props(): array{
379 return ['id', 'type', 'settings', 'status'];
380 }
381 }