# uicore-elements/1.3.17/includes/utils/form-service.php

UiCore Elements – Free widgets and templates for Elementor, version 1.3.17. 940 lines.

- Page: https://pluginprobe.com/plugins/uicore-elements/1.3.17/code/includes/utils/form-service.php
- Raw: https://pluginprobe.com/plugins/uicore-elements/1.3.17/raw/includes/utils/form-service.php
- Modified: 2026-09-15T12:03:04+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/uicore-elements/1.3.17/code/includes/utils/form-service.php#L10-L20`.

```php
<?php

namespace UiCoreElements\Utils;

use UiCoreELements\Utils\Newsletter_Services as Services;

class Email_Exception extends \Exception {}
class Redirect_Exception extends \Exception {}
class Submit_Exception extends \Exception {}
class Newsletter_Service_Exception extends \Exception {}

defined('ABSPATH') || exit();

/**
 * Handles the form submissions and responses
 */

class Contact_Form_Service
{

    protected $form_data,
        $settings,
        $files;

    public function __construct($form_data, $settings, $files)
    {
        $this->form_data = $form_data;
        $this->settings = $settings;
        $this->files = $files;
    }

    public function handle()
    {

        $data = [];
        $responses = [];

        // Checks for reCAPTCHA validation
        if (isset($this->form_data['grecaptcha_token']) && !empty($this->form_data['grecaptcha_token'])) {

            $recaptcha = $this->validate_recaptcha($this->form_data['grecaptcha_token'], $this->form_data['grecaptcha_version']);

            if (!$recaptcha['success']) {
                return [
                    'status' => 'error',
                    'data' => [
                        'message' => esc_html__('reCAPTCHA validation failed.', 'uicore-elements'),
                    ]
                ];
            }
        }

        // Check for honeypot spam
        if (!$this->validate_spam()) {
            return [
                'status' => 'success',
                'data' => [
                    'message' => $this->get_response_message('success') // Fakes a successfull submission
                ]
            ];
        }

        // Run all registered submit actions
        if (isset($this->settings['submit_actions']) && !empty($this->settings['submit_actions'])) {
            foreach ($this->settings['submit_actions'] as $action) {
                try {
                    switch ($action) {
                        case 'email':
                            $data = $this->send_mail($action);
                            $responses['email'] = $data['response'];
                            break;

                        case 'email_2':
                            $data = $this->send_mail($action, $data);
                            $responses['email'] = $data['response'];
                            break;

                        case 'redirect':
                            $responses['redirect'] = $this->redirect();
                            break;

                        case 'popup':
                            $responses['popup'] = $this->popup();
                            break;

                        case 'webhook':
                            $responses['webhook'] = $this->webhook();
                            break;

                        case 'mailchimp':
                            $responses['mailchimp'] = $this->newsletter_service('mailchimp');
                            break;

                        case 'brevo':
                            $responses['brevo'] = $this->newsletter_service('brevo');
                            break;

                        case 'kit':
                            $responses['kit'] = $this->newsletter_service('kit');
                            break;

                        case 'moosend':
                            $responses['moosend'] = $this->newsletter_service('moosend');
                            break;

                        case 'getresponse':
                            $responses['getresponse'] = $this->newsletter_service('getresponse');
                            break;

                        case 'mailerlite':
                            $responses['mailerlite'] = $this->newsletter_service('mailerlite');
                            break;

                        default:
                            throw new Submit_Exception(esc_html__('Unknown submit action: ', 'uicore-elements') . $action . esc_html__('. Check your settings.', 'uicore-elements'));
                    }
                } catch (Email_Exception $e) {
                    $responses['email'] = [
                        'status' => false,
                        'message' => $e->getMessage()
                    ];
                } catch (Redirect_Exception $e) {
                    $responses['redirect'] = [
                        'status' => 'error',
                        'message' => $e->getMessage()
                    ];
                } catch (Newsletter_Service_Exception $e) {
                    $responses['newsletter_service'] = [
                        'status' => 'error',
                        'service' => $action,
                        'message' => $e->getMessage()
                    ];
                } catch (Submit_Exception $e) {
                    $responses['submit'] = [
                        'status' => 'error',
                        'message' => $e->getMessage()
                    ];
                }
                // We're avoiding throwing exception for mailchimp because would require a specific validation function, and is to much for now
            }

            // There's no need to continue without a submit action enabled
        } else {
            return [
                'status' => 'error',
                'data' => [
                    'message' => esc_html__('No submit action enabled.', 'uicore-elements')
                ]
            ];
        }

        // Consider `current_user_can( 'manage_options' )` as filter to return more specific messages on frontend (not tested)

        // Since attachments may be used up to two times (both emails), they need to be deleted only after processing submits
        if (isset($data['attachments']) && !empty($data['attachments']['files'])) {
            register_shutdown_function('unlink', $data['attachments']['files']);
        }

        $output = $this->build_frontend_responses($responses);

        return [
            'status' => $output['status'],
            'data' => $output['data'],
        ];
    }

    /**
     * Mail submition
     */
    protected function send_mail(string $action, array $data = [])
    {

        $attachments = isset($data['attachments']) ? $data['attachments'] : []; // Check if there's attachments from previous mail submit action

        $mail_data = $this->compose_mail_data($action, $attachments); // build mail data

        // Check if there's any attachment error before sending mail
        if (!empty($mail_data['attachments']['errors'])) {
            // throwing exceptions here will block proper data flow. Is best directly returning the error on email action
            return [
                'response' => [
                    'status' => false,
                    'message' => $mail_data['attachments']['errors']
                ],
            ];
        }

        $email = wp_mail(
            $mail_data['email']['to'],
            $mail_data['email']['subject'],
            $mail_data['email']['message'],
            $mail_data['email']['headers'],
            $mail_data['email']['attachments']
        );

        return [
            'response' => [
                'status' => $email ? 'success' : 'error',
                'message' => $email ? $this->get_response_message('success') : $this->get_response_message('mail_error')
            ],
            'attachments' => $mail_data['attachments'] // Return attachments for deletion and error handling
        ];
    }
    protected function compose_mail_data(string $action, array $attachments = [])
    {

        // Set short vars for the data
        $settings = $this->settings;
        $data = $this->form_data;
        $files = $this->files;

        $slug = $action == 'email_2' ? '_2' : ''; // Update controls slugs based on the mail submit type
        $line_break = $settings['email_content_type' . $slug] === 'html' ? '<br>' : "\n"; // Set line break type

        // Replace shortcodes by form data
        $content = $this->replace_content_shortcode($settings['email_content' . $slug], $line_break);

        // Adds the metadata to content
        $content = $this->compose_metadata($content, $settings['form_metadata' . $slug], $line_break);

        // Set empty attachments to avoid undefined errors for widgets without attachment options
        if ($data['widget_type'] !== 'contact-form') {
            $attachments = ['files' => '', 'errors' => ''];
        } else {
            $attachments = !empty($attachments) ? $attachments : $this->prepare_attachments($files); // If theres attachments from previous submit action, use it, otherwhise prepare it from $files,
        }

        // Validate and replace fields shortcodes
        $mail_to = $this->replace_content_shortcode($this->validate_field($settings['email_to' . $slug], 'Recipient (to)'));
        $mail_subject = $this->replace_content_shortcode($this->validate_field($settings['email_subject' . $slug], 'Subject'));
        $mail_name = $this->replace_content_shortcode($this->validate_field($settings['email_from_name' . $slug], 'From Name'));
        $mail_from = $this->replace_content_shortcode($this->validate_field($settings['email_from' . $slug], 'From'));
        $mail_reply = $this->replace_content_shortcode($this->validate_field($settings['email_reply_to' . $slug], 'Reply To'));

        // Build the data
        $mail_data = [
            'to' => $mail_to,
            'subject' => $mail_subject,
            'message' => $content,
            'headers' => [
                'Content-Type: text/' . $settings['email_content_type' . $slug] . '; charset=UTF-8',
                'From: ' . $mail_name . ' <' . $mail_from . '>',
                'Reply-To: ' . $mail_reply,
            ],
            'attachments' => $attachments['files']
        ];

        // Build optional data
        if (!empty($settings['email_to_cc' . $slug])) {
            $mail_data['headers'][] = 'Cc: ' . $this->replace_content_shortcode($settings['email_to_cc' . $slug]);
        }
        if (!empty($settings['email_to_bcc' . $slug])) {
            $mail_data['headers'][] = 'Bcc: ' . $this->replace_content_shortcode($settings['email_to_bcc' . $slug]);
        }

        return [
            'email' => $mail_data,
            'attachments' => $attachments
        ];
    }
    protected function replace_content_shortcode(string $content, string $line_break = '')
    {

        // Set short vars for the data
        $fields = $this->get_setting_fields();
        $form_data = $this->form_data;

        // [all-fieds] shortcode replacement
        if (false !== strpos($content, '[all-fields]')) {
            $text = '';
            // Return formated text as key: value
            foreach ($form_data['form_fields'] as $key => $field) {
                $field_value = is_array($field) ? implode(', ', $field) : $field;
                $text .= !empty($field_value) ? sprintf('%s: %s', $key, $field_value) . $line_break : '';
            }
            $content = str_replace('[all-fields]', $text, $content);
        }

        // Custom [field id="{id}"] shortcode replacement
        foreach ($fields as $field) {
            $shortcode = '[field id="' . $field['custom_id'] . '"]';
            $value = isset($form_data['form_fields'][$field['custom_id']]) ? $form_data['form_fields'][$field['custom_id']] : '';
            $value = is_array($value) ? implode(', ', $value) : $value;
            $content = str_replace($shortcode, $value, $content);
        }

        // Replaces all manual line breaks from content
        if (!empty($line_break)) {
            $content = str_replace(array("\r\n", "\r", "\n"), $line_break, $content);
        }

        return $content;
    }
    protected function prepare_attachments(array $files)
    {
        $attachments = [];
        $errors = '';

        if (!isset($files['form_fields']) || empty($files['form_fields'])) {
            return [
                'files' => '',
                'errors' => ''
            ];
        }

        // Requires wp_handle_upload() file if unavailable
        if (! function_exists('wp_handle_upload')) {
            require_once(ABSPATH . 'wp-admin/includes/file.php');
        }

        // Check if theres a valid file to upload
        foreach ($files['form_fields']['tmp_name'] as $input => $value) {
            if ($files['form_fields']['error'][$input] !== UPLOAD_ERR_NO_FILE) {
                $file = [
                    'name' => $files['form_fields']['name'][$input],
                    'type' => $files['form_fields']['type'][$input],
                    'tmp_name' => $files['form_fields']['tmp_name'][$input],
                    'error' => $files['form_fields']['error'][$input],
                    'size' => $files['form_fields']['size'][$input],
                ];

                // Handle the file upload
                $uploaded_file = wp_handle_upload($file, ['test_form' => false]);

                if (!isset($uploaded_file['error'])) {
                    $attachments = $uploaded_file['file'];
                } else {
                    // Since throwing exceptions here will block the proper data flow, we return the error and let send_mail() handle it
                    $errors = esc_html__('Failed to upload file: ', 'uicore-elements') . $uploaded_file['error'];
                }

                // Break after processing the first valid file
                break;
            }
        }

        return [
            'files' => $attachments,
            'errors' => $errors
        ];
    }
    protected function compose_metadata(string $content, array $metadada, string $line_break)
    {

        if (empty($metadada)) {
            return $content;
        }

        $content = $content . $line_break . $line_break . '--' . $line_break . $line_break; // Adds spacing between content and metadata

        foreach ($metadada as $meta) {
            switch ($meta) {
                case 'date':
                    $content .= sprintf('%s: %s', 'Date', wp_date('Y-m-d') . $line_break);
                    break;

                case 'time':
                    $content .= sprintf('%s: %s', 'Time', wp_date('H:i:s') . $line_break);
                    break;

                case 'remote_ip':
                    $content .= isset($_SERVER['REMOTE_ADDR'])
                        ? sprintf('%s: %s', 'IP', sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) . $line_break)
                        : '';
                    break;

                case 'user_agent':
                    $content .= isset($_SERVER['HTTP_USER_AGENT'])
                        ?  sprintf('%s: %s', 'User Agent', sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) . $line_break)
                        : '';
                    break;

                case 'page_url':
                    $content .= isset($_SERVER['HTTP_REFERER'])
                        ?  sprintf('%s: %s', 'Page URL', sanitize_text_field(wp_unslash($_SERVER['HTTP_REFERER'])) . $line_break)
                        : '';
                    break;
            }
        }

        return $content;
    }

    /**
     * Extra submissions
     */
    protected function redirect()
    {

        $validation = $this->validate_url($this->settings['redirect_to']);

        // Above function exception blocks this execution
        return [
            'status' => 'success',
            'url' => esc_url($validation['url']),
            'delay' => 1500,
            'message' => esc_html($this->get_response_message('redirect'))
        ];
    }
    protected function popup()
    {
        $action = $this->settings['popup_action'];

        if ($action === 'open') {
            return [
                'status'  => 'success',
                'action'  => sanitize_text_field($action),
                'id'      => sanitize_text_field($this->settings['open_popup']),
                'message' => sanitize_text_field($this->get_response_message('popup'))
            ];
        }

        return [
            'status'  => 'success',
            'action'  => sanitize_text_field($action),
            'message' => sanitize_text_field($this->get_response_message('popup'))
        ];
    }
    protected function webhook(): array
    {
        $request = $this->build_webhook_request();

        $response = wp_remote_post($request['url'], $request['args']);

        if (is_wp_error($response)) {
            return [
                'status' => 'error',
                'message' => $response->get_error_message(),
            ];
        }

        $status_code = (int) wp_remote_retrieve_response_code($response);

        if ($status_code < 200 || $status_code >= 300) {
            $body = wp_remote_retrieve_body($response);
            $body = is_string($body) ? trim(wp_strip_all_tags($body)) : '';
            $body = $body ? wp_html_excerpt($body, 160, '...') : esc_html__('Unexpected response from webhook endpoint.', 'uicore-elements');

            return [
                'status' => 'error',
                'message' => sprintf(
                    /* translators: 1: HTTP status code, 2: Response body excerpt. */
                    esc_html__('Webhook request failed with HTTP %1$s: %2$s', 'uicore-elements'),
                    $status_code,
                    $body
                ),
            ];
        }

        return [
            'status' => 'success',
            'message' => esc_html__('Webhook sent successfully.', 'uicore-elements'),
        ];
    }
    protected function newsletter_service(string $service)
    {
        $settings = $this->settings;
        $data     = $this->get_submission_data_to_service_fields();

        $api_key = get_option('uicore_elements_newsletter_service_key');
        $fields  = $data['fields'];
        $list    = array_map('trim', explode(',', $settings['mailchimp_audience_id']));
        $custom_fields = $data['custom_fields'];

        $instance = new Services($api_key, $fields, $list, $custom_fields);
        $response = $instance->handle($service);

        return $response;
    }

    /**
     * Validations
     */
    protected function validate_recaptcha(string $token, string $version)
    {

        // Check if secret and site key are set
        if (!get_option('uicore_elements_recaptcha_secret_key') || !get_option('uicore_elements_recaptcha_site_key')) {
            return [
                'success' => false,
                'message' => esc_html__('reCAPTCHA API keys are not set.', 'uicore-elements')
            ];
        }

        $data = [
            'secret' => get_option('uicore_elements_recaptcha_secret_key'),
            'response' => sanitize_text_field($token)
        ];

        $response = wp_remote_post("https://www.google.com/recaptcha/api/siteverify", [
            'body' => $data,
            'timeout' => 15,
        ]);

        if (is_wp_error($response)) {
            return [
                'success' => false,
                'message' => $response->get_error_message()
            ];
        }

        $captcha = json_decode(wp_remote_retrieve_body($response));

        if ($version === 'V3') {
            return ['success' => ($captcha->success && $captcha->score >= 0.5) ? true : false];
        }

        // V2 default
        return ['success' => $captcha->success];
    }
    protected function validate_spam()
    {
        // `ui-e-h-p` is the key for the honeypot
        return (isset($this->form_data['ui-e-h-p']) && !empty($this->form_data['ui-e-h-p'])) ? false : true;
    }
    protected function validate_url(string $url)
    {
        if (empty($url)) {
            throw new Redirect_Exception(esc_html($this->get_response_message('redirect_no_url')));
        }

        return [
            'status' => true,
            'url' => $url,
        ];
    }
    protected function validate_webhook(string $url)
    {
        if (empty($url)) {
            throw new Submit_Exception(esc_html__('Webhook URL is empty.', 'uicore-elements'));
        }

        $url = esc_url_raw($url);

        if (!$url || !wp_http_validate_url($url)) {
            throw new Submit_Exception(esc_html__('Webhook URL is invalid.', 'uicore-elements'));
        }

        return $url;
    }
    protected function validate_field(string $field, string $label)
    {
        if (empty($field)) {
            throw new Submit_Exception(esc_html($this->get_response_message('empty_field', esc_html($label))));
        }
        return $field;
    }

    /**
     * Helpers
     */
    protected function get_setting_fields()
    {
        // Used to determine if the widget fields are repeaters with custom IDS or fixed fields, and if fixed fields
        // compose them into an array similar to repeaters, to simplify shortcode replacement function

        switch ($this->form_data['widget_type']) {

            case 'newsletter':
                return [
                    ['custom_id' => 'email'],
                    ['custom_id' => 'name'],
                ];
                break;

            // Dynamic fields values
            default:
                return $this->settings['form_fields'];
                break;
        }
    }
    protected function get_submission_data_to_service_fields(): array
    {
        $settings = $this->settings;
        $widget = $this->form_data['widget_type'];

        // Newsletter widget works only with email and perpahs name
        if ($widget === 'newsletter') {
            return [
                'fields' => [
                    'email' => $this->replace_content_shortcode('[field id="email"]'),
                    'name' => $this->replace_content_shortcode('[field id="name"]'),
                ],
                'custom_fields' => []
            ];
        }

        // Contact Form case has custom fields and allows fields ID change

        $repeater_fields = $settings['newsletter_service_custom_fields'];

        $fields = [
            'email'     => 'mailchimp_email_id',
            'name'      => 'mailchimp_fname_id',
            'last_name' => 'mailchimp_lname_id',
            'phone'     => 'mailchimp_phone_id',
            'birthday'  => 'mailchimp_birthday_id',
        ];

        $custom_fields = [];

        // Build custom field stack
        if (is_array($repeater_fields) && !empty($repeater_fields)) {
            foreach ($repeater_fields as $field) {
                $custom_fields[$field['field_name']] = [
                    'value' => $this->replace_content_shortcode($field['field_id']), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                    'method' => $this->get_custom_field_sanitization_method($field['field_type']), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                ];
            }
        }

        // Remove not used fields from the stack, and extract the content of used fields, if they're using shortcodes
        foreach ($fields as $data => $field) {
            if (isset($settings[$field]) && !empty($settings[$field])) {
                $fields[$data] = $this->replace_content_shortcode($settings[$field]);
            } else if ($data !== 'email' && isset($field[$data])) {
                unset($field[$data]);
            }
        }

        return [
            'fields' => $fields,
            'custom_fields' => $custom_fields
        ];
    }
    protected function get_custom_field_sanitization_method(string $type): string
    {
        // Values are default wp or custom methods from our newsletter services class,
        // while $type should be field type options from form component class
        switch ($type) {
            case 'email':
                return 'sanitize_email';
            case 'phone':
                return 'sanitize_phone';
            case 'birthday':
                return 'sanitize_birthday';
            default:
                return 'sanitize_text_field';
        }
    }
    protected function all_submissions_succedded($responses)
    {
        foreach ($responses as $submission => $data) {
            // Redirect and popup actions failure shouldn't return `error` to main status because is not properly a submission action, so we skip it.
            if (in_array($submission, ['redirect', ' popup'])) {
                continue;
            }
            if (
                isset($data['status']) &&
                (
                    $data['status'] === 'error' ||
                    $data['status'] === false
                )
            ) {
                return false;
            }
        }
        return true;
    }
    public static function get_form_submit_options()
    {

        $options =  [
            'email'  => esc_html__('Email', 'uicore-elements'),
            'email_2' => esc_html__('Email 2', 'uicore-elements'),
            'redirect' => esc_html__('Redirect', 'uicore-elements'),
            'webhook' => esc_html__('Webhook', 'uicore-elements')
        ];

        // Uicore Framework dependent actions
        if (defined('UICORE_ASSETS')) {
            $options['popup'] = esc_html('Popup', 'uicore-elements');
        }

        $services = Services::get_services_list();

        if (is_array($services) || empty($services)) {
            $options = array_merge($options, $services);
        }

        return $options;
    }

    /**
     * Webhook Helpers
     */
    protected function build_webhook_request(): array
    {
        $url = $this->replace_content_shortcode($this->validate_field($this->settings['webhook_url'] ?? '', 'Webhook URL'));
        $url = $this->validate_webhook($url);

        $advanced_data = ($this->settings['webhook_advanced_data'] ?? '') === 'true';
        $args = [
            'timeout' => 15,
        ];

        if ($advanced_data) {
            $args['headers'] = [
                'Content-Type' => 'application/json; charset=UTF-8',
            ];
            $args['body'] = wp_json_encode($this->get_advanced_webhook_payload());
        } else {
            $args['body'] = [
                'widget_type' => sanitize_text_field($this->form_data['widget_type'] ?? ''),
                'fields' => $this->get_submission_fields_payload(),
                'meta' => $this->get_webhook_meta_payload(),
            ];
        }

        return [
            'url' => $url,
            'args' => $args,
        ];
    }
    protected function get_advanced_webhook_payload(): array
    {
        return $this->sanitize_recursive_payload($this->form_data);
    }
    protected function get_webhook_meta_payload(): array
    {
        $meta = [
            'widget_id' => sanitize_text_field($this->form_data['widget_id'] ?? ''),
            'submitted_at' => wp_date('c'),
        ];

        if (!empty($this->form_data['post_id'])) {
            $meta['post_id'] = absint($this->form_data['post_id']);
        }

        if (isset($_SERVER['HTTP_REFERER'])) {
            $meta['page_url'] = esc_url_raw(wp_unslash($_SERVER['HTTP_REFERER']));
        }

        return $meta;
    }
    protected function get_submission_fields_payload(): array
    {
        $payload = [];

        foreach ($this->get_setting_fields() as $field) {
            if (empty($field['custom_id'])) {
                continue;
            }

            $field_id = $field['custom_id'];
            $value = $this->form_data['form_fields'][$field_id] ?? '';

            if (is_array($value)) {
                $payload[$field_id] = array_map('sanitize_text_field', $value);
                continue;
            }

            $payload[$field_id] = sanitize_text_field($value);
        }

        return $payload;
    }
    protected function sanitize_recursive_payload($value)
    {
        if (is_array($value)) {
            foreach ($value as $key => $item) {
                $value[sanitize_text_field((string) $key)] = $this->sanitize_recursive_payload($item);
                if ((string) $key !== sanitize_text_field((string) $key)) {
                    unset($value[$key]);
                }
            }

            return $value;
        }

        return sanitize_text_field((string) $value);
    }

    /**
     * Responses
     */
    // Also used by form widget(s), therefore public and static
    public static function get_default_messages()
    {
        return [
            // main messages
            'success'    => esc_html__('Your submission was successful.', 'uicore-elements'),
            'error'      => esc_html__('Your submission failed because of an error.', 'uicore-elements'),
            'mail_error' => esc_html__('Failed to send email.', 'uicore-elements'),
            'required'   => esc_html__('Fill all required fields.', 'uicore-elements'),
            'redirect'   => esc_html__('Redirecting...', 'uicore-elements'),
        ];
    }
    protected function get_response_message(string $status, string $dinamic_data = '')
    {
        // non-customizable messages (for settings debugging only)
        $default_messages = [
            'invalid_status'    => esc_html__('Invalid status message.', 'uicore-elements'),
            'redirect_no_url'   => esc_html__('Redirection failed. No URL set.', 'uicore-elements'),
            'empty_field'       => esc_html__('The following field is empty: ', 'uicore-elements') . $dinamic_data,
        ];

        if ($this->settings['custom_messages'] === 'yes') {
            $messages = [
                'success' => esc_html($this->settings['success_message']),
                'error' => esc_html($this->settings['error_message']),
                'mail_error' => esc_html($this->settings['mail_error_message']),
                'redirect' => esc_html($this->settings['redirect_message']),
            ];
        } else {
            $messages = self::get_default_messages();
        }

        $messages = array_merge($default_messages, $messages);

        return isset($messages[$status]) ? $messages[$status] : $messages['invalid_status'];
    }
    protected function build_frontend_responses($responses)
    {
        $data = [];

        // Mail response
        if (isset($responses['email']) && $responses['email']['status'] !== 'success') {
            $data['email'] = $responses['email'];
        }

        // Mail attachment response - is always an error
        if (isset($responses['email']) && isset($responses['email']['attachment'])) {
            $data['attachment'] = $responses['attachment'];
        }

        // Submit Actions response - is always an error
        if (isset($responses['submit'])) {
            $data['submit'] = $responses['submit'];
        }

        if (isset($responses['webhook']) && $responses['webhook']['status'] !== 'success') {
            $data['submit'] = $responses['webhook'];
        }

        // Newsletter Services responses
        $data = $this->build_services_responses($responses);

        // Main response
        $status = $this->all_submissions_succedded($responses) ? 'success' : 'error';
        $data['message'] = $this->get_response_message($status);

        // Below responses should work only if all previous submitions hasn't failed
        if (isset($responses['redirect']) && $status === 'success') {
            $data['redirect'] = $responses['redirect'];
        }
        if (isset($responses['popup']) && $status === 'success') {
            $data['popup'] = $responses['popup'];
        }

        // The only successfull response that should be sent is 'main' and 'redirect'
        return [
            'status' => $status,
            'data' => $data
        ];
    }

    protected function build_services_responses($responses)
    {
        $success = true;
        $service = '';
        $status = '';
        $detail = '';

        if (isset($responses['mailchimp'])) {
            // We know mailchimp failed if status is an integer
            // If one response fail, in multiple list cases, returns the failure
            foreach ($responses['mailchimp'] as $response) {
                if (is_int($response['status'])) {
                    $success = false;
                    $service = 'Mailchimp';
                    $status = 'HTTP: ' . $response['status'];
                    $detail = $response['detail'];
                    break;
                }
            }
        } else if (isset($responses['brevo'])) {
            // We know Brevo failed if 'code' is set in the response
            if (isset($responses['brevo']['code'])) {
                $success = false;
                $service = 'Brevo';
                $status = 'Error: ' . $responses['brevo']['code'];
                $detail = $responses['brevo']['message'] ?? '';
            }
        } else if (isset($responses['getresponse'])) {
            // We know GetResponse failed if 'httpStatus' is set in the response
            foreach ($responses['getresponse'] as $response) {
                if (isset($response['httpStatus'])) {
                    $success = false;
                    $service = 'GetResponse';
                    $status = 'HTTP: ' . $response['httpStatus'];
                    $detail = 'Error: ' . $response['code'] . ' - ' . $response['message'];
                    break;
                }
            }
        } else if (isset($responses['kit'])) {
            // We know Kit failed if 'error' is set in the response
            foreach ($responses['kit'] as $response) {
                if (isset($response['error'])) {
                    $success = false;
                    $service = 'Kit';
                    $status = 'Error: ' . $response['error'];
                    $detail = $response['message'];
                    break;
                }
            }
        } else if (isset($responses['moosend'])) {
            // We know Moosend failed if 'Error' is set in the response
            foreach ($responses['moosend'] as $response) {
                if (!empty($response['Error'])) {
                    $success = false;
                    $service = 'Moosend';
                    $status = 'HTTP: ' . $response['Code'];
                    $detail = $response['Error'];
                    break;
                }
            }
        } else if (isset($responses['mailerlite'])) {
            // We know MailerLite failed if 'message' is set in the response
            if (isset($responses['mailerlite']['message'])) {
                $success = false;
                $service = 'MailerLite';
                $status = 'Error';
                $detail = $responses['mailerlite']['message'] ?? '';
            }
        }

        // Return the error response if the service fails
        if ($success === false) {
            $data['newsletter_service'] = [
                'status' => 'error',
                /* translators: 1: Service Provider, 2: Service Error code, 3: Service Status Response */
                'message' => sprintf(esc_html__('[%1$s] %2$s - %3$s', 'uicore-elements'), $service, $status, $detail)
            ];
        }

        return [];
    }
}

```
