[Back] <?php
/*
* Copyright (c) 2022 LatePoint LLC. All rights reserved.
*/
namespace LatePoint\Misc;
class ProcessAction{
public string $id;
public string $type = 'send_email';
public string $status = 'active';
public ?array $settings = [];
public array $prepared_data_for_run = [];
public array $replacement_vars = [];
public array $selected_data_objects = []; // example ['model' => 'booking', 'id' => INT]
public ProcessEvent $event;
function __construct($args = []){
$allowed_props = self::allowed_props();
foreach($args as $key => $arg){
if(in_array($key, $allowed_props)) $this->$key = $arg;
}
if(empty($this->id)) $this->id = self::generate_id();
switch($this->type){
case 'send_email':
$this->settings['to_email'] = $this->settings['to_email'] ?? '';
$this->settings['subject'] = $this->settings['subject'] ?? '';
$this->settings['content'] = $this->settings['content'] ?? '';
break;
case 'send_sms':
$this->settings['to_phone'] = $this->settings['to_phone'] ?? '';
$this->settings['content'] = $this->settings['content'] ?? '';
break;
case 'send_whatsapp':
$this->settings['to_phone'] = $this->settings['to_phone'] ?? '';
$this->settings['content'] = $this->settings['content'] ?? '';
break;
}
}
public function is_attach_calendar( ) {
return !empty($this->settings['attach_calendar']) && \OsUtilHelper::is_on($this->settings['attach_calendar']);
}
public function get_nice_type_name(){
return self::get_action_name_for_type($this->type);
}
public function get_descriptive_setting(){
switch($this->type) {
case 'send_email':
return $this->settings['to_email'] ?? '';
case 'send_sms':
return $this->settings['to_phone'] ?? '';
case 'send_whatsapp':
return $this->settings['to_phone'] ?? '';
}
}
public function generate_replacement_vars(){
$this->replacement_vars = \OsReplacerHelper::generate_replacement_vars_from_data_objects($this->selected_data_objects);
}
public function set_from_params($params){
if(!empty($params['id'])) $this->id = $params['id'];
if(!empty($params['type'])) $this->type = $params['type'];
if(!empty($params['settings'])) $this->settings = $params['settings'];
if(!empty($params['event'])) $this->event = new ProcessEvent(['type' => $params['event']['type']]);
}
public function load_settings_from_template($template_id){
$templates = \OsNotificationsHelper::load_templates_for_action_type($this->type);
foreach($templates as $template){
if($template['id'] == $template_id){
switch($this->type){
case 'send_email':
$this->settings['to_email'] = $template['to_email'];
$this->settings['subject'] = $template['subject'];
$this->settings['content'] = $template['content'];
break;
case 'send_sms':
$this->settings['to_phone'] = $template['to_phone'];
$this->settings['content'] = $template['content'];
break;
case 'send_whatsapp':
$this->settings['to_phone'] = $template['to_phone'];
$this->settings['content'] = $template['content'];
break;
}
/**
* Returns an array of process action settings, based on a selected template
*
* @since 4.7.0
* @hook latepoint_process_action_settings
*
* @param {array} $settings Array of settings to filter
* @param {array} $template Array of data representing selected template
* @param {ProcessAction} $action Instance of <code>ProcessAction</code> for which settings are being generated
*
* @returns {array} Filtered array of process action settings
*/
$this->settings = apply_filters('latepoint_process_action_settings', $this->settings, $template, $this);
break;
}
}
}
public static function generate_form(ProcessAction $action, string $process_id = ''): string{
$descriptive_setting = $action->get_descriptive_setting() ? '<div class="process-action-descriptive-setting">'.$action->get_descriptive_setting().'</div>' : '';
$html = '<div class="process-action-form pa-type-'.$action->type.' pa-status-'.$action->status.'" data-id="'.$action->id.'">';
$html.= '<div class="process-action-heading">
<div class="process-action-status"></div>
<div class="process-action-icon"></div>
<div class="process-action-name">'.self::get_action_name_for_type($action->type).'</div>
'.$descriptive_setting.'
<div class="process-action-chevron"><i class="latepoint-icon latepoint-icon-chevron-down"></i></div>
<a href="#" class="process-action-remove os-remove-process-action"
data-os-prompt="'.__('Are you sure you want to delete this action?', 'latepoint').'"><i class="latepoint-icon latepoint-icon-cross"></i></a>
</div>';
$html.= '<div class="process-action-content">';
$html.= '<div class="os-row">';
$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-process-id' => $process_id, 'data-route' => \OsRouterHelper::build_route_name('processes', 'load_action_settings')], ['class' => 'os-col-10']);
$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']);
$html.= '</div>';
$html.= '<div class="process-action-settings">';
$html.= self::generate_settings_fields($action, $process_id);
$html.= '</div>';
$html.= '<div class="process-buttons">
<a href="#" class="latepoint-btn latepoint-btn-danger pull-left os-remove-process-action"
data-os-prompt="'.__('Are you sure you want to delete this action?', 'latepoint').'" >'.__('Delete', 'latepoint').'</a>
<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>
</div>';
$html.= '</div>';
$html.= '</div>';
return $html;
}
public static function generate_settings_fields(ProcessAction $action, string $process_id = ''){
$html = '';
if(in_array($action->type, ['send_email', 'send_sms'])){
$html.= '<div class="process-action-controls-wrapper">';
$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, 'process_id' => $process_id]).'" 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>';
$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>';
$html.= '</div>';
}
switch($action->type){
case 'send_email':
$html.= '<div class="os-row">';
$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']);
$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']);
$html.= '</div>';
$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']);
$html.= \OsFormHelper::toggler_field('process[actions]['.$action->id.'][settings][attach_calendar]', __('Attach Booking Calendar', 'latepoint'), $action->is_attach_calendar());
$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() );
break;
case 'send_sms':
if(\OsSmsHelper::get_sms_processors()){
$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')]);
$html.= \OsFormHelper::textarea_field('process[actions]['.$action->id.'][settings][content]', __('Message Content', 'latepoint'), $action->settings['content'], ['theme' => 'simple', 'placeholder' => __('Message', 'latepoint'), 'rows' => 4]);
}else{
$html = \OsUtilHelper::generate_missing_addon_link(__('You have to enable an SMS processor to send text messages. Available in a premium version.', 'latepoint'));
}
break;
case 'send_whatsapp':
if(\OsWhatsappHelper::get_whatsapp_processors()){
$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>';
$html.= '<div class="latepoint-whatsapp-templates-holder">'.\OsFormHelper::get_hidden_fields_for_array($action->settings, 'process[actions]['.$action->id.']').'</div>';
}else{
$html = \OsUtilHelper::generate_missing_addon_link(__('You have to enable a WhatsApp processor to send messages. Available in a premium version.', 'latepoint'));
}
break;
case 'trigger_webhook':
$html = \OsUtilHelper::generate_missing_addon_link(__('Requires upgrade to a premium version', 'latepoint'));
break;
}
/**
* Filters HTML code (after) for Process Action settings form
*
* @since 4.7.0
* @hook latepoint_process_action_settings_fields_html_after
*
* @param {string} $html HTML content of the settings form
* @param {ProcessAction} $action ProcessAction object for which this settings form is being generated
*
* @returns {string} HTML content of the settings form
*/
return apply_filters('latepoint_process_action_settings_fields_html_after', $html, $action);
}
public static function generate_id(): string{
return 'pa_'.\OsUtilHelper::random_text('alnum', 6);
}
public function settings_form(){
$html = '';
switch($this->type){
case 'send_email':
$html.= \OsFormHelper::text_field('action[actions]['.$this->id.'][to]', '', $this->settings['to'], ['theme' => 'simple', 'placeholder' => __('Email To', 'latepoint')]);
break;
case 'send_sms':
$html.= \OsFormHelper::text_field('action[actions]['.$this->id.'][to]', '', $this->settings['to'], ['theme' => 'simple', 'placeholder' => __('SMS To', 'latepoint')]);
break;
case 'send_whatsapp':
$html.= \OsFormHelper::text_field('action[actions]['.$this->id.'][to]', '', $this->settings['to'], ['theme' => 'simple', 'placeholder' => __('WhatsApp Message To', 'latepoint')]);
break;
case 'trigger_webhook':
$html.= \OsFormHelper::text_field('action[actions]['.$this->id.'][url]', '', $this->settings['url'], ['theme' => 'simple', 'placeholder' => __('Webhook URL', 'latepoint')]);
break;
}
return apply_filters('latepoint_process_action_settings_form_html', $html, $this);
}
public static function get_action_types(){
$action_types = ['send_email', 'send_sms', 'trigger_webhook', 'send_whatsapp'];
/**
* Returns an array of process action types that can be executed when an event is triggered
*
* @since 4.7.0
* @hook latepoint_process_action_types
*
* @param {array} $action_types Array of action types to filter
*
* @returns {array} Filtered array of action types
*/
return apply_filters('latepoint_process_action_types', $action_types);
}
public static function get_action_name_for_type($type){
$names = [
'send_email' => __('Send Email', 'latepoint'),
'send_sms' => __('Send SMS', 'latepoint'),
'trigger_webhook' => __('HTTP Request (Webhook)', 'latepoint'),
'send_whatsapp' => __('Send WhatsApp Message', 'latepoint')
];
/**
* Returns an array of process action types mapped to their displayable names
*
* @since 4.7.0
* @hook latepoint_process_action_names
*
* @param {array} $names Array of action types/names to filter
*
* @returns {array} Filtered array of action types/names
*/
$names = apply_filters('latepoint_process_action_names', $names);
return $names[$type] ?? __('n/a', 'latepoint');
}
public static function get_action_types_for_select(){
$types = self::get_action_types();
$types_for_select = [];
foreach($types as $type){
$types_for_select[$type] = self::get_action_name_for_type($type);
}
return $types_for_select;
}
public function prepare_data_for_run(){
$this->generate_replacement_vars();
foreach($this->selected_data_objects as $data_object){
switch($data_object['model']) {
case 'order':
$this->prepared_data_for_run['activity_data']['order_id'] = $data_object['id'];
if(!empty($data_object['model_ready'])){
$this->prepared_data_for_run['activity_data']['customer_id'] = $data_object['model_ready']->customer_id;
}
break;
case 'booking':
$this->prepared_data_for_run['activity_data']['booking_id'] = $data_object['id'];
if(!empty($data_object['model_ready'])){
$this->prepared_data_for_run['activity_data']['agent_id'] = $data_object['model_ready']->agent_id;
$this->prepared_data_for_run['activity_data']['service_id'] = $data_object['model_ready']->service_id;
$this->prepared_data_for_run['activity_data']['customer_id'] = $data_object['model_ready']->customer_id;
}
break;
case 'customer':
$this->prepared_data_for_run['activity_data']['customer_id'] = $data_object['id'];
break;
case 'transaction':
$this->prepared_data_for_run['activity_data']['transaction_id'] = $data_object['id'];
break;
case 'payment_request':
$this->prepared_data_for_run['activity_data']['payment_request_id'] = $data_object['id'];
break;
}
}
$this->replacement_vars['sender_type'] = $this->type;
switch($this->type) {
case 'send_email':
$this->prepared_data_for_run['to'] = \OsReplacerHelper::replace_all_vars($this->settings['to_email'], $this->replacement_vars);
$this->prepared_data_for_run['subject'] = \OsReplacerHelper::replace_all_vars($this->settings['subject'], $this->replacement_vars);
$this->prepared_data_for_run['content'] = \OsReplacerHelper::replace_all_vars($this->settings['content'], $this->replacement_vars);
$this->prepared_data_for_run['attachments'] = [];
if ($this->is_attach_calendar()) {
$booking = $this->find_booking_from_selected_data();
if ($booking) {
$ical_temp_file = $this->create_ical_temp_file($booking);
if ($ical_temp_file) {
$this->prepared_data_for_run['attachments'][] = $ical_temp_file;
$this->prepared_data_for_run['_attachments_temp_files'] = [$ical_temp_file];
}
}
}
$attachments = $this->get_attachments();
if (!empty($attachments)) {
foreach ( $attachments as $attachment_id ) {
$file_path = get_attached_file($attachment_id);
if ($file_path && file_exists($file_path)) {
$this->prepared_data_for_run['attachments'][] = $file_path;
} else {
\OsDebugHelper::log('Attachment file not found: ' . $file_path, 'error');
}
}
}
break;
case 'send_sms':
$this->prepared_data_for_run['to'] = \OsReplacerHelper::replace_all_vars($this->settings['to_phone'], $this->replacement_vars);
$this->prepared_data_for_run['content'] = \OsReplacerHelper::replace_all_vars($this->settings['content'], $this->replacement_vars);
break;
case 'send_whatsapp':
$this->prepared_data_for_run['to'] = \OsReplacerHelper::replace_all_vars($this->settings['to_phone'], $this->replacement_vars);
$this->prepared_data_for_run['data']['type'] = 'template';
$this->prepared_data_for_run['data']['template_id'] = $this->settings['template_id'];
$this->prepared_data_for_run['data']['template_language'] = $this->settings['template_language'];
$this->prepared_data_for_run['data']['template_parameter_format'] = $this->settings['template_parameter_format'];
$this->prepared_data_for_run['data']['template_category'] = $this->settings['template_category'];
$this->prepared_data_for_run['data']['template_name'] = $this->settings['template_name'];
$selected_template = \OsWhatsappHelper::get_template($this->settings['template_id']);
$this->prepared_data_for_run['data']['variables'] = $this->settings['variables'] ?? [];
if(!empty($this->settings['variables'])){
foreach($this->settings['variables'] as $type => $variables){
$parameters = [];
foreach($variables as $key => $value){
$clean_key = str_replace(['{{', '}}'], '', $key);
$replaced_value = \OsReplacerHelper::replace_all_vars($value, $this->replacement_vars);
if(is_numeric($clean_key)){
$parameters[] = ['type' => 'text', 'text' => $replaced_value];
}else{
$parameters[] = ['type' => 'text', 'text' => $replaced_value, 'parameter_name' => $clean_key];
}
}
if(strtolower($type) == 'buttons'){
// each button has to have a separate component element, only URL typed buttons have variables in them
foreach($parameters as $index => $parameter){
$this->prepared_data_for_run['data']['components'][] = [
'type' => 'button',
'index' => $index,
'sub_type' => 'url',
'parameters' => $parameters
];
}
}else{
$this->prepared_data_for_run['data']['components'][] = ['type' => $type, 'parameters' => $parameters];
}
}
}
$content_by_type['header'] = \OsWhatsappHelper::get_template_component_value_by_key($selected_template, 'HEADER', 'text');
$content_by_type['body'] = \OsWhatsappHelper::get_template_component_value_by_key($selected_template, 'BODY', 'text');
$content_by_type['buttons'] = \OsWhatsappHelper::get_template_component_value_by_key($selected_template, 'BUTTONS', 'buttons');
foreach($content_by_type as $content_type => $content){
if($content_type == 'buttons'){
if(!empty($content)){
foreach($content as $button){
// only URL can have variables
if($button['type'] == 'URL') $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);
$this->prepared_data_for_run['content_for_'.$content_type][] = $button;
}
}else{
$this->prepared_data_for_run['content_for_'.$content_type] = [];
}
}else{
$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);
}
}
break;
}
/**
* Prepare data for action run
*
* @since 4.7.0
* @hook latepoint_process_prepare_data_for_run
*
* @param {ProcessAction} $action ProcessAction that was executed
*
* @returns {ProcessAction} $action ProcessAction with prepared data for action run
*/
return apply_filters('latepoint_process_prepare_data_for_run', $this);
}
/**
* @param $prepare_data
* @return array [status => '', 'message' => '']
*/
public function run($prepare_data = true){
$result = [
'status' => LATEPOINT_STATUS_SUCCESS,
'message' => __('Nothing to run', 'latepoint')
];
if($prepare_data) $this->prepare_data_for_run();
switch($this->type) {
case 'send_email':
$notification_type = 'email';
$result = \OsNotificationsHelper::send($notification_type, $this->prepared_data_for_run);
break;
case 'send_sms':
$notification_type = 'sms';
$result = \OsNotificationsHelper::send($notification_type, $this->prepared_data_for_run);
break;
case 'send_whatsapp':
$notification_type = 'whatsapp';
$result = \OsNotificationsHelper::send($notification_type, $this->prepared_data_for_run);
break;
}
$tmp_files = $this->prepared_data_for_run['_attachments_temp_files'] ?? [];
foreach ( $tmp_files as $tmp_file ) {
if ( file_exists( $tmp_file ) ) {
@unlink( $tmp_file );
};
}
/**
* ProcessAction run result
*
* @since 4.7.0
* @hook latepoint_process_action_run
*
* @param {array} $result The array of data describing the status of the action run
* @param {ProcessAction} $action ProcessAction that was executed
*
* @returns {array} The array of descriptive data, possibly transformed by additional hooked ProcessAction handlers
*/
return apply_filters('latepoint_process_action_run', $result, $this);
}
/**
* @return string
*/
public function generate_preview(){
if(empty($this->prepared_data_for_run)){
$this->prepare_data_for_run();
// nothing was generated, probably because there is no object attached
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>';
}
$html = '<div class="action-preview-content-wrapper">';
$preview_content_html = '';
switch($this->type){
case 'send_email':
$preview_content_html.= '<div class="action-preview-subject"><span class="os-label">'.__('Subject:', 'latepoint').'</span> '.$this->prepared_data_for_run['subject'].'</div>';
$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>';
$preview_content_html.= '<div class="action-preview-content">'.$this->prepared_data_for_run['content'].'</div>';
break;
case 'send_sms':
$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>';
$preview_content_html.= '<div class="action-preview-content">'.$this->prepared_data_for_run['content'].'</div>';
break;
case 'send_whatsapp':
$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>';
$preview_content_html.= '<div class="action-preview-content">';
$preview_content_html.= '<div class="latepoint-whatsapp-template-preview-messages">';
$preview_content_html.= '<div class="latepoint-whatsapp-template-preview-message">';
$preview_content_html.= '<div class="latepoint-whatsapp-template-preview-message-header">'.$this->prepared_data_for_run['content_for_header'].'</div>';
$preview_content_html.= '<div class="latepoint-whatsapp-template-preview-message-body">'.$this->prepared_data_for_run['content_for_body'].'</div>';
if($this->prepared_data_for_run['content_for_buttons']){
$preview_content_html.= '<div class="latepoint-whatsapp-template-preview-message-buttons">';
foreach($this->prepared_data_for_run['content_for_buttons'] as $button){
switch($button['type']){
case 'PHONE_NUMBER':
$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>';
break;
case 'URL':
$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>';
break;
}
}
$preview_content_html.= '</div>';
}
$preview_content_html.= '</div>';
$preview_content_html.= '</div>';
$preview_content_html.= '</div>';
break;
}
/**
* Generates a preview html for ProcessAction testing
*
* @since 4.7.0
* @hook latepoint_process_action_generate_preview
*
* @param {string} $preview_content_html HTML that goes inside of a preview
* @param {ProcessAction} $action ProcessAction that is being tested
*
* @returns {string} HTML that goes inside of a preview
*/
$preview_content_html = apply_filters('latepoint_process_action_generate_preview', $preview_content_html, $this);
$html.= $preview_content_html;
$html.= '</div>';
return $html;
}
private function find_booking_from_selected_data() {
foreach ($this->selected_data_objects as $data_object) {
if ($data_object['model'] === 'booking' && !empty($data_object['model_ready'])) {
return $data_object['model_ready'];
}
}
return null;
}
private function create_ical_temp_file( $booking ) {
try {
$ical_content = \OsBookingHelper::generate_ical_event_string( $booking );
if ( empty( $ical_content ) ) {
throw new \Exception( 'iCal content is empty' );
}
$temp_file = tempnam(sys_get_temp_dir(), 'latepoint_ical_');
$ical_temp_file = $temp_file . '.ics';
rename($temp_file, $ical_temp_file);
if ( file_put_contents( $ical_temp_file, $ical_content ) !== false ) {
return $ical_temp_file;
} else {
throw new \Exception( 'Failed to write iCal content to file' );
}
} catch ( \Exception $e ) {
\OsDebugHelper::log( 'Failed to create iCal file: ' . $e->getMessage(), 'error' );
}
return null;
}
public static function replace_variables($test){
}
public static function allowed_props(): array{
return ['id', 'type', 'settings', 'status'];
}
public function get_attachments() {
return !empty($this->settings['attachments']) ? explode(',', $this->settings['attachments']) : [];
}
}