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_action.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_action.php
701 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 ) ) {
22 $this->$key = $arg;
23 }
24 }
25 if ( empty( $this->id ) ) {
26 $this->id = self::generate_id();
27 }
28 switch ( $this->type ) {
29 case 'send_email':
30 $this->settings['to_email'] = $this->settings['to_email'] ?? '';
31 $this->settings['subject'] = $this->settings['subject'] ?? '';
32 $this->settings['content'] = $this->settings['content'] ?? '';
33 break;
34 case 'send_sms':
35 $this->settings['to_phone'] = $this->settings['to_phone'] ?? '';
36 $this->settings['content'] = $this->settings['content'] ?? '';
37 break;
38 case 'send_whatsapp':
39 $this->settings['to_phone'] = $this->settings['to_phone'] ?? '';
40 $this->settings['content'] = $this->settings['content'] ?? '';
41 break;
42 }
43 }
44
45 public function is_attach_calendar() {
46 return ! empty( $this->settings['attach_calendar'] ) && \OsUtilHelper::is_on( $this->settings['attach_calendar'] );
47 }
48
49 public function get_nice_type_name() {
50 return self::get_action_name_for_type( $this->type );
51 }
52
53 public function get_descriptive_setting() {
54 switch ( $this->type ) {
55 case 'send_email':
56 return $this->settings['to_email'] ?? '';
57 case 'send_sms':
58 return $this->settings['to_phone'] ?? '';
59 case 'send_whatsapp':
60 return $this->settings['to_phone'] ?? '';
61 }
62 }
63
64 public function generate_replacement_vars() {
65 $this->replacement_vars = \OsReplacerHelper::generate_replacement_vars_from_data_objects( $this->selected_data_objects );
66 }
67
68 public function set_from_params( $params ) {
69 if ( ! empty( $params['id'] ) ) {
70 $this->id = $params['id'];
71 }
72 if ( ! empty( $params['type'] ) ) {
73 $this->type = $params['type'];
74 }
75 if ( ! empty( $params['settings'] ) ) {
76 $this->settings = $params['settings'];
77 }
78 if ( ! empty( $params['event'] ) ) {
79 $this->event = new ProcessEvent( [ 'type' => $params['event']['type'] ] );
80 }
81 }
82
83 public function load_settings_from_template( $template_id ) {
84 $templates = \OsNotificationsHelper::load_templates_for_action_type( $this->type );
85 foreach ( $templates as $template ) {
86 if ( $template['id'] == $template_id ) {
87 switch ( $this->type ) {
88 case 'send_email':
89 $this->settings['to_email'] = $template['to_email'];
90 $this->settings['subject'] = $template['subject'];
91 $this->settings['content'] = $template['content'];
92 break;
93 case 'send_sms':
94 $this->settings['to_phone'] = $template['to_phone'];
95 $this->settings['content'] = $template['content'];
96 break;
97 case 'send_whatsapp':
98 $this->settings['to_phone'] = $template['to_phone'];
99 $this->settings['content'] = $template['content'];
100 break;
101 }
102
103 /**
104 * Returns an array of process action settings, based on a selected template
105 *
106 * @since 4.7.0
107 * @hook latepoint_process_action_settings
108 *
109 * @param {array} $settings Array of settings to filter
110 * @param {array} $template Array of data representing selected template
111 * @param {ProcessAction} $action Instance of <code>ProcessAction</code> for which settings are being generated
112 *
113 * @returns {array} Filtered array of process action settings
114 */
115 $this->settings = apply_filters( 'latepoint_process_action_settings', $this->settings, $template, $this );
116 break;
117 }
118 }
119 }
120
121 public static function generate_form( ProcessAction $action, string $process_id = '' ): string {
122 $descriptive_setting = $action->get_descriptive_setting() ? '<div class="process-action-descriptive-setting">' . $action->get_descriptive_setting() . '</div>' : '';
123 $html = '<div class="process-action-form pa-type-' . $action->type . ' pa-status-' . $action->status . '" data-id="' . $action->id . '">';
124 $html .= '<div class="process-action-heading">
125 <div class="process-action-status"></div>
126 <div class="process-action-icon"></div>
127 <div class="process-action-name">' . self::get_action_name_for_type( $action->type ) . '</div>
128 ' . $descriptive_setting . '
129 <div class="process-action-chevron"><i class="latepoint-icon latepoint-icon-chevron-down"></i></div>
130 <a href="#" class="process-action-remove os-remove-process-action"
131 data-os-prompt="' . __( 'Are you sure you want to delete this action?', 'latepoint' ) . '"><i class="latepoint-icon latepoint-icon-cross"></i></a>
132 </div>';
133 $html .= '<div class="process-action-content">';
134 $html .= '<div class="os-row">';
135 $html .= \OsFormHelper::select_field(
136 'process[actions][' . $action->id . '][type]',
137 __( 'Action Type', 'latepoint' ),
138 \LatePoint\Misc\ProcessAction::get_action_types_for_select(),
139 $action->type,
140 [
141 'class' => 'process-action-type',
142 'data-action-id' => $action->id,
143 'data-process-id' => $process_id,
144 'data-route' => \OsRouterHelper::build_route_name( 'processes', 'load_action_settings' ),
145 ],
146 [ 'class' => 'os-col-10' ]
147 );
148 $html .= \OsFormHelper::select_field(
149 'process[actions][' . $action->id . '][status]',
150 __( 'Status', 'latepoint' ),
151 [
152 LATEPOINT_STATUS_ACTIVE => __( 'Active', 'latepoint' ),
153 LATEPOINT_STATUS_DISABLED => __( 'Disabled', 'latepoint' ),
154 ],
155 $action->status,
156 false,
157 [ 'class' => 'os-col-2' ]
158 );
159 $html .= '</div>';
160 $html .= '<div class="process-action-settings">';
161 $html .= self::generate_settings_fields( $action, $process_id );
162 $html .= '</div>';
163 $html .= '<div class="process-buttons">
164 <a href="#" class="latepoint-btn latepoint-btn-danger pull-left os-remove-process-action"
165 data-os-prompt="' . __( 'Are you sure you want to delete this action?', 'latepoint' ) . '" >' . __( 'Delete', 'latepoint' ) . '</a>
166 <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>
167 </div>';
168 $html .= '</div>';
169 $html .= '</div>';
170 return $html;
171 }
172
173
174 public static function generate_settings_fields( ProcessAction $action, string $process_id = '' ) {
175 $html = '';
176
177 if ( in_array( $action->type, [ 'send_email', 'send_sms' ] ) ) {
178 $html .= '<div class="process-action-controls-wrapper">';
179 $html .= '<a href="#" data-os-after-call="latepoint_init_template_library" data-os-params="' . \OsUtilHelper::build_os_params(
180 [
181 'action_id' => $action->id,
182 'action_type' => $action->type,
183 'process_id' => $process_id,
184 ]
185 ) . '" 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>';
186 $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>';
187 $html .= '</div>';
188 }
189
190 switch ( $action->type ) {
191 case 'send_email':
192 $html .= '<div class="os-row">';
193 $html .= \OsFormHelper::text_field(
194 'process[actions][' . $action->id . '][settings][to_email]',
195 __( 'To Email', 'latepoint' ),
196 $action->settings['to_email'],
197 [
198 'theme' => 'simple',
199 'placeholder' => __( 'To email address', 'latepoint' ),
200 ],
201 [ 'class' => 'os-col-6' ]
202 );
203 $html .= \OsFormHelper::text_field(
204 'process[actions][' . $action->id . '][settings][subject]',
205 __( 'Email Subject', 'latepoint' ),
206 $action->settings['subject'],
207 [
208 'theme' => 'simple',
209 'placeholder' => __( 'Email Subject', 'latepoint' ),
210 ],
211 [ 'class' => 'os-col-6' ]
212 );
213 $html .= '</div>';
214 $html .= \OsFormHelper::textarea_field(
215 'process[actions][' . $action->id . '][settings][content]',
216 false,
217 $action->settings['content'],
218 [
219 'id' => 'process_actions_' . $action->id . '_settings_content',
220 'class' => 'os-wp-editor-textarea',
221 ]
222 );
223 $html .= \OsFormHelper::toggler_field( 'process[actions][' . $action->id . '][settings][attach_calendar]', __( 'Attach Booking Calendar', 'latepoint' ), $action->is_attach_calendar() );
224 $html .= \OsFormHelper::multiple_files_uploader_field( 'process[actions][' . $action->id . '][settings][attachments]', esc_html__( '+ Attach File', 'latepoint' ), esc_html__( 'Remove File', 'latepoint' ), $action->get_attachments() );
225 break;
226 case 'send_sms':
227 if ( \OsSmsHelper::get_sms_processors() ) {
228 $html .= \OsFormHelper::text_field(
229 'process[actions][' . $action->id . '][settings][to_phone]',
230 __( 'To Phone Number', 'latepoint' ),
231 $action->settings['to_phone'],
232 [
233 'theme' => 'simple',
234 'placeholder' => __( 'Phone Number', 'latepoint' ),
235 ]
236 );
237 $html .= \OsFormHelper::textarea_field(
238 'process[actions][' . $action->id . '][settings][content]',
239 __( 'Message Content', 'latepoint' ),
240 $action->settings['content'],
241 [
242 'theme' => 'simple',
243 'placeholder' => __( 'Message', 'latepoint' ),
244 'rows' => 4,
245 ]
246 );
247 } else {
248 $html = \OsUtilHelper::generate_missing_addon_link( __( 'You have to enable an SMS processor to send text messages. Available in a premium version.', 'latepoint' ) );
249 }
250 break;
251 case 'send_whatsapp':
252 if ( \OsWhatsappHelper::get_whatsapp_processors() ) {
253 $html .= '<div class="latepoint-whatsapp-templates-loader" data-route="' . esc_attr( \OsRouterHelper::build_route_name( 'whatsapp', 'load_templates_for_action' ) ) . '" data-selected-template-id="' . esc_attr( $action->settings['template_id'] ?? '' ) . '" data-process-id="' . esc_attr( $process_id ) . '" data-process-action-id="' . esc_attr( $action->id ) . '"></div>';
254 $html .= '<div class="latepoint-whatsapp-templates-holder">' . \OsFormHelper::get_hidden_fields_for_array( $action->settings, 'process[actions][' . $action->id . ']' ) . '</div>';
255
256 } else {
257 $html = \OsUtilHelper::generate_missing_addon_link( __( 'You have to enable a WhatsApp processor to send messages. Available in a premium version.', 'latepoint' ) );
258 }
259 break;
260 case 'trigger_webhook':
261 $html = \OsUtilHelper::generate_missing_addon_link( __( 'Requires upgrade to a premium version', 'latepoint' ) );
262 break;
263 }
264
265 /**
266 * Filters HTML code (after) for Process Action settings form
267 *
268 * @since 4.7.0
269 * @hook latepoint_process_action_settings_fields_html_after
270 *
271 * @param {string} $html HTML content of the settings form
272 * @param {ProcessAction} $action ProcessAction object for which this settings form is being generated
273 *
274 * @returns {string} HTML content of the settings form
275 */
276 return apply_filters( 'latepoint_process_action_settings_fields_html_after', $html, $action );
277 }
278
279 public static function generate_id(): string {
280 return 'pa_' . \OsUtilHelper::random_text( 'alnum', 6 );
281 }
282
283 public function settings_form() {
284 $html = '';
285 switch ( $this->type ) {
286 case 'send_email':
287 $html .= \OsFormHelper::text_field(
288 'action[actions][' . $this->id . '][to]',
289 '',
290 $this->settings['to'],
291 [
292 'theme' => 'simple',
293 'placeholder' => __( 'Email To', 'latepoint' ),
294 ]
295 );
296 break;
297 case 'send_sms':
298 $html .= \OsFormHelper::text_field(
299 'action[actions][' . $this->id . '][to]',
300 '',
301 $this->settings['to'],
302 [
303 'theme' => 'simple',
304 'placeholder' => __( 'SMS To', 'latepoint' ),
305 ]
306 );
307 break;
308 case 'send_whatsapp':
309 $html .= \OsFormHelper::text_field(
310 'action[actions][' . $this->id . '][to]',
311 '',
312 $this->settings['to'],
313 [
314 'theme' => 'simple',
315 'placeholder' => __( 'WhatsApp Message To', 'latepoint' ),
316 ]
317 );
318 break;
319 case 'trigger_webhook':
320 $html .= \OsFormHelper::text_field(
321 'action[actions][' . $this->id . '][url]',
322 '',
323 $this->settings['url'],
324 [
325 'theme' => 'simple',
326 'placeholder' => __( 'Webhook URL', 'latepoint' ),
327 ]
328 );
329 break;
330 }
331
332 return apply_filters( 'latepoint_process_action_settings_form_html', $html, $this );
333 }
334
335
336 public static function get_action_types() {
337 $action_types = [ 'send_email', 'send_sms', 'trigger_webhook', 'send_whatsapp' ];
338
339 /**
340 * Returns an array of process action types that can be executed when an event is triggered
341 *
342 * @since 4.7.0
343 * @hook latepoint_process_action_types
344 *
345 * @param {array} $action_types Array of action types to filter
346 *
347 * @returns {array} Filtered array of action types
348 */
349 return apply_filters( 'latepoint_process_action_types', $action_types );
350 }
351
352 public static function get_action_name_for_type( $type ) {
353 $names = [
354 'send_email' => __( 'Send Email', 'latepoint' ),
355 'send_sms' => __( 'Send SMS', 'latepoint' ),
356 'trigger_webhook' => __( 'HTTP Request (Webhook)', 'latepoint' ),
357 'send_whatsapp' => __( 'Send WhatsApp Message', 'latepoint' ),
358 ];
359
360 /**
361 * Returns an array of process action types mapped to their displayable names
362 *
363 * @since 4.7.0
364 * @hook latepoint_process_action_names
365 *
366 * @param {array} $names Array of action types/names to filter
367 *
368 * @returns {array} Filtered array of action types/names
369 */
370 $names = apply_filters( 'latepoint_process_action_names', $names );
371
372 return $names[ $type ] ?? __( 'n/a', 'latepoint' );
373 }
374
375 public static function get_action_types_for_select() {
376 $types = self::get_action_types();
377 $types_for_select = [];
378 foreach ( $types as $type ) {
379 $types_for_select[ $type ] = self::get_action_name_for_type( $type );
380 }
381 return $types_for_select;
382 }
383
384 public function prepare_data_for_run() {
385 $this->generate_replacement_vars();
386 foreach ( $this->selected_data_objects as $data_object ) {
387 switch ( $data_object['model'] ) {
388 case 'order':
389 $this->prepared_data_for_run['activity_data']['order_id'] = $data_object['id'];
390 if ( ! empty( $data_object['model_ready'] ) ) {
391 $this->prepared_data_for_run['activity_data']['customer_id'] = $data_object['model_ready']->customer_id;
392 }
393 break;
394 case 'booking':
395 $this->prepared_data_for_run['activity_data']['booking_id'] = $data_object['id'];
396 if ( ! empty( $data_object['model_ready'] ) ) {
397 $this->prepared_data_for_run['activity_data']['agent_id'] = $data_object['model_ready']->agent_id;
398 $this->prepared_data_for_run['activity_data']['service_id'] = $data_object['model_ready']->service_id;
399 $this->prepared_data_for_run['activity_data']['customer_id'] = $data_object['model_ready']->customer_id;
400 }
401 break;
402 case 'customer':
403 $this->prepared_data_for_run['activity_data']['customer_id'] = $data_object['id'];
404 break;
405 case 'transaction':
406 $this->prepared_data_for_run['activity_data']['transaction_id'] = $data_object['id'];
407 break;
408 case 'payment_request':
409 $this->prepared_data_for_run['activity_data']['payment_request_id'] = $data_object['id'];
410 break;
411 }
412 }
413
414 $this->replacement_vars['sender_type'] = $this->type;
415
416 switch ( $this->type ) {
417 case 'send_email':
418 $this->prepared_data_for_run['to'] = \OsReplacerHelper::replace_all_vars( $this->settings['to_email'], $this->replacement_vars );
419 $this->prepared_data_for_run['subject'] = \OsReplacerHelper::replace_all_vars( $this->settings['subject'], $this->replacement_vars );
420 $this->prepared_data_for_run['content'] = \OsReplacerHelper::replace_all_vars( $this->settings['content'], $this->replacement_vars );
421 $this->prepared_data_for_run['attachments'] = [];
422
423 if ( $this->is_attach_calendar() ) {
424 $booking = $this->find_booking_from_selected_data();
425
426 if ( $booking ) {
427 $ical_temp_file = $this->create_ical_temp_file( $booking );
428
429 if ( $ical_temp_file ) {
430 $this->prepared_data_for_run['attachments'][] = $ical_temp_file;
431 $this->prepared_data_for_run['_attachments_temp_files'] = [ $ical_temp_file ];
432 }
433 }
434 }
435 $attachments = $this->get_attachments();
436 if ( ! empty( $attachments ) ) {
437 foreach ( $attachments as $attachment_id ) {
438 $file_path = get_attached_file( $attachment_id );
439 if ( $file_path && file_exists( $file_path ) ) {
440 $this->prepared_data_for_run['attachments'][] = $file_path;
441 } else {
442 \OsDebugHelper::log( 'Attachment file not found: ' . $file_path, 'error' );
443 }
444 }
445 }
446
447 break;
448 case 'send_sms':
449 $this->prepared_data_for_run['to'] = \OsReplacerHelper::replace_all_vars( $this->settings['to_phone'], $this->replacement_vars );
450 $this->prepared_data_for_run['content'] = \OsReplacerHelper::replace_all_vars( $this->settings['content'], $this->replacement_vars );
451 break;
452 case 'send_whatsapp':
453 $this->prepared_data_for_run['to'] = \OsReplacerHelper::replace_all_vars( $this->settings['to_phone'], $this->replacement_vars );
454 $this->prepared_data_for_run['data']['type'] = 'template';
455 $this->prepared_data_for_run['data']['template_id'] = $this->settings['template_id'];
456 $this->prepared_data_for_run['data']['template_language'] = $this->settings['template_language'];
457 $this->prepared_data_for_run['data']['template_parameter_format'] = $this->settings['template_parameter_format'];
458 $this->prepared_data_for_run['data']['template_category'] = $this->settings['template_category'];
459 $this->prepared_data_for_run['data']['template_name'] = $this->settings['template_name'];
460
461 $selected_template = \OsWhatsappHelper::get_template( $this->settings['template_id'] );
462
463 $this->prepared_data_for_run['data']['variables'] = $this->settings['variables'] ?? [];
464 if ( ! empty( $this->settings['variables'] ) ) {
465 foreach ( $this->settings['variables'] as $type => $variables ) {
466 $parameters = [];
467 foreach ( $variables as $key => $value ) {
468 $clean_key = str_replace( [ '{{', '}}' ], '', $key );
469 $replaced_value = \OsReplacerHelper::replace_all_vars( $value, $this->replacement_vars );
470 if ( is_numeric( $clean_key ) ) {
471 $parameters[] = [
472 'type' => 'text',
473 'text' => $replaced_value,
474 ];
475 } else {
476 $parameters[] = [
477 'type' => 'text',
478 'text' => $replaced_value,
479 'parameter_name' => $clean_key,
480 ];
481 }
482 }
483 if ( strtolower( $type ) == 'buttons' ) {
484 // each button has to have a separate component element, only URL typed buttons have variables in them
485 foreach ( $parameters as $index => $parameter ) {
486 $this->prepared_data_for_run['data']['components'][] = [
487 'type' => 'button',
488 'index' => $index,
489 'sub_type' => 'url',
490 'parameters' => $parameters,
491 ];
492 }
493 } else {
494 $this->prepared_data_for_run['data']['components'][] = [
495 'type' => $type,
496 'parameters' => $parameters,
497 ];
498 }
499 }
500 }
501
502 $content_by_type['header'] = \OsWhatsappHelper::get_template_component_value_by_key( $selected_template, 'HEADER', 'text' );
503 $content_by_type['body'] = \OsWhatsappHelper::get_template_component_value_by_key( $selected_template, 'BODY', 'text' );
504 $content_by_type['buttons'] = \OsWhatsappHelper::get_template_component_value_by_key( $selected_template, 'BUTTONS', 'buttons' );
505
506
507 foreach ( $content_by_type as $content_type => $content ) {
508 if ( $content_type == 'buttons' ) {
509 if ( ! empty( $content ) ) {
510 foreach ( $content as $button ) {
511 // only URL can have variables
512 if ( $button['type'] == 'URL' ) {
513 $button['url'] = empty( $this->settings['variables'][ $content_type ] ) ? $button['url'] : \OsReplacerHelper::replace_all_vars( str_replace( array_keys( $this->settings['variables'][ $content_type ] ), array_values( $this->settings['variables'][ $content_type ] ), $button['url'] ), $this->replacement_vars );
514 }
515 $this->prepared_data_for_run[ 'content_for_' . $content_type ][] = $button;
516 }
517 } else {
518 $this->prepared_data_for_run[ 'content_for_' . $content_type ] = [];
519 }
520 } else {
521 $this->prepared_data_for_run[ 'content_for_' . $content_type ] = empty( $this->settings['variables'][ $content_type ] ) ? $content : \OsReplacerHelper::replace_all_vars( str_replace( array_keys( $this->settings['variables'][ $content_type ] ), array_values( $this->settings['variables'][ $content_type ] ), $content ), $this->replacement_vars );
522 }
523 }
524 break;
525 }
526
527 /**
528 * Prepare data for action run
529 *
530 * @since 4.7.0
531 * @hook latepoint_process_prepare_data_for_run
532 *
533 * @param {ProcessAction} $action ProcessAction that was executed
534 *
535 * @returns {ProcessAction} $action ProcessAction with prepared data for action run
536 */
537 return apply_filters( 'latepoint_process_prepare_data_for_run', $this );
538 }
539
540
541 /**
542 * @param $prepare_data
543 * @return array [status => '', 'message' => '']
544 */
545 public function run( $prepare_data = true ) {
546 $result = [
547 'status' => LATEPOINT_STATUS_SUCCESS,
548 'message' => __( 'Nothing to run', 'latepoint' ),
549 ];
550 if ( $prepare_data ) {
551 $this->prepare_data_for_run();
552 }
553
554 switch ( $this->type ) {
555 case 'send_email':
556 $notification_type = 'email';
557 $result = \OsNotificationsHelper::send( $notification_type, $this->prepared_data_for_run );
558 break;
559 case 'send_sms':
560 $notification_type = 'sms';
561 $result = \OsNotificationsHelper::send( $notification_type, $this->prepared_data_for_run );
562 break;
563 case 'send_whatsapp':
564 $notification_type = 'whatsapp';
565 $result = \OsNotificationsHelper::send( $notification_type, $this->prepared_data_for_run );
566 break;
567 }
568
569 $tmp_files = $this->prepared_data_for_run['_attachments_temp_files'] ?? [];
570 foreach ( $tmp_files as $tmp_file ) {
571 if ( file_exists( $tmp_file ) ) {
572 @unlink( $tmp_file );
573 };
574 }
575
576 /**
577 * ProcessAction run result
578 *
579 * @since 4.7.0
580 * @hook latepoint_process_action_run
581 *
582 * @param {array} $result The array of data describing the status of the action run
583 * @param {ProcessAction} $action ProcessAction that was executed
584 *
585 * @returns {array} The array of descriptive data, possibly transformed by additional hooked ProcessAction handlers
586 */
587 return apply_filters( 'latepoint_process_action_run', $result, $this );
588 }
589
590
591 /**
592 * @return string
593 */
594 public function generate_preview() {
595 if ( empty( $this->prepared_data_for_run ) ) {
596 $this->prepare_data_for_run();
597 // nothing was generated, probably because there is no object attached
598 if ( empty( $this->prepared_data_for_run ) ) {
599 return '<div class="action-preview-error">' . __( 'You have to create a booking to be able to test this action.', 'latepoint' ) . '</div>';
600 }
601 }
602 $html = '<div class="action-preview-content-wrapper">';
603 $preview_content_html = '';
604 switch ( $this->type ) {
605 case 'send_email':
606 $preview_content_html .= '<div class="action-preview-subject"><span class="os-label">' . __( 'Subject:', 'latepoint' ) . '</span> ' . $this->prepared_data_for_run['subject'] . '</div>';
607 $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>';
608 $preview_content_html .= '<div class="action-preview-content">' . $this->prepared_data_for_run['content'] . '</div>';
609 break;
610 case 'send_sms':
611 $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>';
612 $preview_content_html .= '<div class="action-preview-content">' . $this->prepared_data_for_run['content'] . '</div>';
613 break;
614 case 'send_whatsapp':
615 $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>';
616 $preview_content_html .= '<div class="action-preview-content">';
617 $preview_content_html .= '<div class="latepoint-whatsapp-template-preview-messages">';
618 $preview_content_html .= '<div class="latepoint-whatsapp-template-preview-message">';
619 $preview_content_html .= '<div class="latepoint-whatsapp-template-preview-message-header">' . $this->prepared_data_for_run['content_for_header'] . '</div>';
620 $preview_content_html .= '<div class="latepoint-whatsapp-template-preview-message-body">' . $this->prepared_data_for_run['content_for_body'] . '</div>';
621 if ( $this->prepared_data_for_run['content_for_buttons'] ) {
622 $preview_content_html .= '<div class="latepoint-whatsapp-template-preview-message-buttons">';
623 foreach ( $this->prepared_data_for_run['content_for_buttons'] as $button ) {
624 switch ( $button['type'] ) {
625 case 'PHONE_NUMBER':
626 $preview_content_html .= '<a href="tel:' . esc_url( $button['phone_number'] ) . '" class="latepoint-whatsapp-template-preview-message-button"><i class="latepoint-icon latepoint-icon-phone"></i>' . esc_html( $button['text'] ) . '</a>';
627 break;
628 case 'URL':
629 $preview_content_html .= '<a href="' . esc_url( $button['url'] ) . '" class="latepoint-whatsapp-template-preview-message-button"><i class="latepoint-icon latepoint-icon-external-link"></i>' . esc_html( $button['text'] ) . '</a>';
630 break;
631 }
632 }
633 $preview_content_html .= '</div>';
634 }
635 $preview_content_html .= '</div>';
636 $preview_content_html .= '</div>';
637 $preview_content_html .= '</div>';
638 break;
639 }
640
641 /**
642 * Generates a preview html for ProcessAction testing
643 *
644 * @since 4.7.0
645 * @hook latepoint_process_action_generate_preview
646 *
647 * @param {string} $preview_content_html HTML that goes inside of a preview
648 * @param {ProcessAction} $action ProcessAction that is being tested
649 *
650 * @returns {string} HTML that goes inside of a preview
651 */
652 $preview_content_html = apply_filters( 'latepoint_process_action_generate_preview', $preview_content_html, $this );
653 $html .= $preview_content_html;
654 $html .= '</div>';
655 return $html;
656 }
657
658 private function find_booking_from_selected_data() {
659 foreach ( $this->selected_data_objects as $data_object ) {
660 if ( $data_object['model'] === 'booking' && ! empty( $data_object['model_ready'] ) ) {
661 return $data_object['model_ready'];
662 }
663 }
664 return null;
665 }
666
667 private function create_ical_temp_file( $booking ) {
668 try {
669 $ical_content = \OsBookingHelper::generate_ical_event_string( $booking );
670 if ( empty( $ical_content ) ) {
671 throw new \Exception( 'iCal content is empty' );
672 }
673
674 $temp_file = tempnam( sys_get_temp_dir(), 'latepoint_ical_' );
675 $ical_temp_file = $temp_file . '.ics';
676 rename( $temp_file, $ical_temp_file );
677
678 if ( file_put_contents( $ical_temp_file, $ical_content ) !== false ) {
679 return $ical_temp_file;
680 } else {
681 throw new \Exception( 'Failed to write iCal content to file' );
682 }
683 } catch ( \Exception $e ) {
684 \OsDebugHelper::log( 'Failed to create iCal file: ' . $e->getMessage(), 'error' );
685 }
686
687 return null;
688 }
689
690 public static function replace_variables( $test ) {
691 }
692
693 public static function allowed_props(): array {
694 return [ 'id', 'type', 'settings', 'status' ];
695 }
696
697 public function get_attachments() {
698 return ! empty( $this->settings['attachments'] ) ? explode( ',', $this->settings['attachments'] ) : [];
699 }
700 }
701