<?php

if (!defined('ABSPATH')) exit; // Exit if accessed directly

if (!class_exists('wpMailPlugin')) {
    class wpMailPlugin extends wpMailCheckinit {

        var $name = 'Newsletters';
        var $plugin_base;
        var $pre = 'wpml';
        var $version = '4.11';
        var $dbversion = '1.2.3';
        var $debugging = false;			//set to "true" to turn on debugging
        var $debug_level = 2; 			//set to 1 for only database errors and var dump; 2 for PHP errors as well
        var $post_errors = array();
        var $intervals = array();
        var $menus = array();
        var $submenus = array();
        var $cache = array();
        public $import_process;
        public $queue_process_1;
        public $queue_process_2;
        public $queue_process_3;
        public $dbupdate_process;
        public $fullurl;
        public $referer;
        public $api_key;
        public $table;
        public $fields;
        public $Link;
        public $plugin_name;
        public $Click;
        public $Subscribeform;
        public $Option;
        public $SubscribersOption;
        public $Content;
        public $Latestpost;
        public $Latestpostssubscription;
        public $History;
        public $Order;
        public $Post;
        public $Template;
        public $SubscribersList;
        public $Country;
        public $Group;
        public $Autoresponder;
        public $Autoresponderemail;
        public $AutorespondersList;
        public $AutorespondersForm;
        public $FieldsForm;
        public $SubscriberMeta;
        public $tables_tv;
        public $indexes;
        public $Bounce;
        public $Subscriber;
        public $Unsubscribe;
        public $Mailinglist;
        public $FieldsList;
        public $Field;
        public $HistoriesList;
        public $HistoriesAttachment;
        public $Email;
        public $Theme;
        public $table_query;
        public $watermark;
        public $hidden_type;
        public $insertid;
        public $insert_id;
        public $hidden_value;
        public $newfieldoptions;
        public $caption;
        public $fieldoptions;
        public $filetypes;
        public $filesizelimit;
        public $errormessage;
        public $invalidmessage;
        public $display;
        public $validation;
        public $regex;
        public $order;
        public $errors = [];
        public $data;
        public $history_id;


        var $sections = array(
            //'about'						=>	"newsletters-about",
            'welcome'					=> 	"newsletters",
            'submitserial'				=>	"newsletters-submitserial",
            'gdpr'						=>	"newsletters-gdpr",
            'forms'						=>	"newsletters-forms",
            'send'						=>	"newsletters-create",
            'autoresponders'			=>	"newsletters-autoresponders",
            'autoresponderemails'		=>	"newsletters-autoresponderemails",
            'lists'						=>	"newsletters-lists",
            'groups'					=>	"newsletters-groups",
            'subscribers'				=>	"newsletters-subscribers",
            'fields'					=>	"newsletters-fields",
            'importexport'				=>	"newsletters-importexport",
            'themes'					=>	"newsletters-themes",
            'templates'					=>	"newsletters-templates",
            'templates_save'			=>	"newsletters-templates-save",
            'queue'						=>	"newsletters-queue",
            'history'					=>	"newsletters-history",
            'emails'					=>	"newsletters-emails",
            'links'						=>	"newsletters-links",
            'clicks'					=>	"newsletters-links-clicks",
            'orders'					=>	"newsletters-orders",
            'settings'					=>	"newsletters-settings",
            'settings_subscribers'		=>	"newsletters-settings-subscribers",
            'settings_templates'		=>	"newsletters-settings-templates",
            'settings_system'			=>	"newsletters-settings-system",
            'settings_tasks'			=>	"newsletters-settings-tasks",
            'settings_updates'			=>	"newsletters-settings-updates",
            'settings_api'				=>	"newsletters-settings-api",
            'extensions'				=>	"newsletters-extensions",
            'extensions_settings'		=>	"newsletters-extensions-settings",
            'support'					=>	"newsletters-support",
            'view_logs'				    =>	"newsletters-view-logs",
        );

        var $blocks = array(
            'newsletters_admin_send_sendtoroles'
        );

        var $extensions = array();

        var $classes = array(
            'Subscriber',
            'Bounce',
            'Unsubscribe',
            'Mailinglist',
            //'Queue',
            //'Latestpost',
            'FieldsList',
            'Field',
            //'History',
            'HistoriesList',
            'HistoriesAttachment',
            'Email',
            //'wpmlOrder',
            //'Post',
            'Theme',
            //'Template',
            //'SubscribersList',
            //'wpmlCountry',
            //'Autoresponder',
            //'AutorespondersList',
            //'Autoresponderemail',
            //'wpmlGroup',
        );

        var $models = array('Link', 'Click', 'Subscribeform', 'Option', 'SubscribersOption', 'Content', 'Latestpost',
            'Latestpostssubscription', 'History', 'Order', 'Post', 'Template', 'SubscribersList', 'Country', 'Group', 'Autoresponder',
            'Autoresponderemail', 'AutorespondersList', 'AutorespondersForm', 'FieldsForm', 'SubscriberMeta');

        var $helpers = array('Checkinit', 'Html', 'Form', 'Metabox', 'Shortcode', 'Authnews', 'Db');
        var $tables = array();
        var $tablenames = array();

        function __construct() {
            // this is the parent

            include($this -> plugin_base() . DS . 'vendors' . DS . 'processing' . DS . 'wp-import-process.php');
            if (class_exists('WPML_WP_Import_Process')) {
                $this -> import_process = new WPML_WP_Import_Process();
            }

            include($this -> plugin_base() . DS . 'vendors' . DS . 'processing' . DS . 'wp-queue-process.php');
            if (class_exists('WPML_WP_Queue_Process')) {
                $this -> queue_process_1 = new WPML_WP_Queue_Process();
            }

            include($this -> plugin_base() . DS . 'vendors' . DS . 'processing' . DS . 'wp-queue-process_2.php');
            if (class_exists('WPML_WP_Queue_Process_2')) {
                $this -> queue_process_2 = new WPML_WP_Queue_Process_2();
            }

            include($this -> plugin_base() . DS . 'vendors' . DS . 'processing' . DS . 'wp-queue-process_3.php');
            if (class_exists('WPML_WP_Queue_Process_3')) {
                $this -> queue_process_3 = new WPML_WP_Queue_Process_3();
            }

            include($this -> plugin_base() . DS . 'vendors' . DS . 'processing' . DS . 'wp-dbupdate-process.php');
            if (class_exists('WPML_WP_Dbupdate_Process')) {
                $this -> dbupdate_process = new WPML_WP_Dbupdate_Process();
            }
        }

        public function __call($method = null, $args = null) {
            global $Db;

            if (!empty($method) && in_array($method, $this -> models)) {
                $class = $this -> pre . $method;

                if (!class_exists($class)) {
                    $file = $this -> plugin_base() . DS . 'models' . DS . strtolower($method) . '.php';
                    if (file_exists($file)) {
                        include($file);
                    }
                }

                if (empty($this -> {$method}) || !is_object($this -> {$method})) {
                    if (class_exists($class)) {
                        $newmethod = new $class($args);
                        $this -> {$method} = $newmethod;

                        switch ($method) {
                            case 'Order'					:
                            case 'Option'					:
                            case 'Country'					:
                                global ${'wpml' . $method};
                                ${'wpml' . $method} = $newmethod;
                                break;
                            default 						:
                                global ${$method};
                                ${$method} = $newmethod;
                                break;
                        }

                        return $newmethod;
                    }
                } else {

                    if (empty($this -> {$method} -> data)) {
                        if (!empty($Db -> {$method} -> data)) {
                            $this -> {$method} -> data = $Db -> {$method} -> data;
                        }
                    }

                    if (empty($this -> {$method} -> insertid) && !empty($Db -> {$method} -> insertid)) {
                        $this -> {$method} -> insertid = $Db -> {$method} -> insertid;
                    }

                    if (empty($this -> {$method} -> errors) && !empty($this -> {$method} -> {$method} -> errors)) {
                        $this -> {$method} -> errors = $this -> {$method} -> {$method} -> errors;
                    }

                    if (empty($this -> {$method} -> data) && !empty($this -> {$method} -> {$method} -> data)) {
                        $this -> {$method} -> data = $this -> {$method} -> {$method} -> data;
                    }

                    if (empty($this -> {$method} -> model)) {
                        $this -> {$method} -> model = $method;
                    }

                    return $this -> {$method};
                }
            }

            return false;
        }

        /**
         * Register the plugin
         * Sets the plugin name and base directory for universal use.
         * @param STRING. Name of the plugin
         * @param STRING. Base directory of the plugin
         *
         */
        function register_plugin($name = null, $base = null) {
            $this -> api_key = $this -> get_option('api_key');
            $this -> plugin_name = basename(NEWSLETTERS_DIR);
            $this -> plugin_base = rtrim(dirname($base), DS);
            $this -> plugin_file = plugin_basename($base);

            $log_file_path = $this -> prepare_log_file();
            if (!defined('NEWSLETTERS_LOG_FILE')) { define("NEWSLETTERS_LOG_FILE", $log_file_path); }
            $this -> sections = apply_filters('newsletters_sections', (object) $this -> sections);
            $this -> set_timezone();
            $this -> extensions = $this -> get_extensions();

            ### Get our models ready for action!
            $this -> initialize_classes();

            global $wpdb;
            $wpdb -> query("SET sql_mode = '';");

            $debugging = get_option('tridebugging');
            $this -> debugging = (empty($debugging)) ? $this -> debugging : false;

            if(!is_file(NEWSLETTERS_LOG_FILE)){
                file_put_contents(NEWSLETTERS_LOG_FILE, '');     // Save our content to the file.
            }

            $this -> debugging($this -> debugging);
            //add_action('plugins_loaded', array($this, 'ci_initialize'));
            $this -> add_action('plugins_loaded');

            if (is_admin() && !defined('DOING_AJAX')) {
                global $extensions;
                require_once($this -> plugin_base() . DS . 'includes' . DS . 'extensions.php');
                $this -> extensions = $extensions;
            }
        }

        function prepare_log_file() {
            $default_log_filename = 'newsletters.log';
            $stored_log_filename = $this -> get_option('log_filename');
            $log_dir = $this -> plugin_base();
            $default_log_path = $log_dir . DS . $default_log_filename;

            $log_filename = (!empty($stored_log_filename) ? $stored_log_filename : $default_log_filename);
            $needs_new_filename = (empty($stored_log_filename) || $log_filename === $default_log_filename);

            if ($needs_new_filename) {
                $log_filename = $this -> generate_log_filename();

                if (!$this -> update_option('log_filename', $log_filename)) {
                    $this -> add_option('log_filename', $log_filename);
                }
            }

            $log_file_path = $log_dir . DS . $log_filename;

            if (file_exists($default_log_path) && $default_log_path !== $log_file_path) {
                @rename($default_log_path, $log_file_path); // phpcs:ignore
            }

            if (!file_exists($log_file_path)) {
                file_put_contents($log_file_path, '');
            }

            return $log_file_path;
        }

        function generate_log_filename() {
            if (function_exists('wp_generate_password')) {
                $random_prefix = wp_generate_password(40, false, false);
            } else {
                $bytes = function_exists('random_bytes') ? random_bytes(32) : openssl_random_pseudo_bytes(32);
                $random_prefix = substr(bin2hex($bytes), 0, 40);
            }

            $random_prefix = preg_replace('/[^A-Za-z0-9]/', '', $random_prefix);

            return $random_prefix . '-newsletters.log';
        }

        protected function get_log_htaccess_candidates() {
            $candidates = array();

            if (defined('ABSPATH')) {
                $candidates[] = rtrim(ABSPATH, '\\/') . DS . '.htaccess';
            }

            $candidates[] = dirname(NEWSLETTERS_LOG_FILE) . DS . '.htaccess';

            return array_unique($candidates);
        }

        protected function get_log_htaccess_path() {
            $candidates = $this -> get_log_htaccess_candidates();

            foreach ($candidates as $candidate) {
                $candidate_dir = dirname($candidate);

                if ((file_exists($candidate) && is_writable($candidate)) || (!file_exists($candidate) && is_writable($candidate_dir))) {
                    return $candidate;
                }
            }

            return reset($candidates);
        }

        protected function get_log_htaccess_rule($log_filename = null) {
            $log_filename = (!empty($log_filename)) ? $log_filename : basename(NEWSLETTERS_LOG_FILE);
            $log_filename = preg_replace('/[^A-Za-z0-9._-]/', '', $log_filename);

            return '<Files "' . $log_filename . '">' . PHP_EOL . 'Order Allow,Deny' . PHP_EOL . 'Deny from all' . PHP_EOL . 'Require all denied' . PHP_EOL . '</Files>' . PHP_EOL;
        }

        protected function is_log_file_protected($htaccess_path = null) {
            $paths = (!empty($htaccess_path)) ? array($htaccess_path) : $this -> get_log_htaccess_candidates();

            $log_filename = preg_replace('/[^A-Za-z0-9._-]/', '', basename(NEWSLETTERS_LOG_FILE));
            $rule_pattern = '/<(Files|FilesMatch)\s+"[^"<>]*' . preg_quote($log_filename, '/') . '[^"<>]*"\s*>/i';

            foreach ($paths as $path) {
                if (!file_exists($path)) {
                    continue;
                }

                $contents = @file_get_contents($path);

                if ($contents === false) {
                    continue;
                }

                if (preg_match($rule_pattern, $contents)) {
                    return true;
                }
            }

            return false;
        }

        protected function add_log_htaccess_rule($htaccess_path = null) {
            $htaccess_path = (!empty($htaccess_path)) ? $htaccess_path : $this -> get_log_htaccess_path();
            $rule = $this -> get_log_htaccess_rule();

            if ($this -> is_log_file_protected($htaccess_path)) {
                return true;
            }

            $htaccess_dir = dirname($htaccess_path);

            if (empty($htaccess_path)) {
                return false;
            }

            if (file_exists($htaccess_path) && !is_writable($htaccess_path)) {
                return false;
            }

            if (!file_exists($htaccess_path) && (!is_dir($htaccess_dir) || !is_writable($htaccess_dir))) {
                return false;
            }

            $prefix = (file_exists($htaccess_path) && filesize($htaccess_path) > 0) ? PHP_EOL : '';

            return false !== @file_put_contents($htaccess_path, $prefix . $rule, FILE_APPEND);
        }

        function clear_memcached() {
            if (class_exists('Memcached')) {
                $cache = new Memcached();
                $cache -> addServer('localhost', '11211');
                $keys = $cache -> getAllKeys();

                if (!empty($keys)) {
                    $cache -> getDelayed($keys);
                    $store = $cache -> fetchAll();
                    $keys = $cache -> getAllKeys();

                    $pattern = "/(newsletters)/si";
                    foreach ($keys as $item) {
                        if (preg_match($pattern, $item, $matches)) {
                            $cache -> delete($item);
                        }
                    }
                }
            }
        }

        function set_cache($hash = null, $data = null, $type = 'query') {
            if (is_null($hash)) {
				return true;
			}
            wp_cache_set($hash, maybe_serialize($data), 'newsletters');
            return true;
        }

        function get_cache($hash = null, $type = 'query') {

            if ($data = wp_cache_get($hash, 'newsletters')) {
                return maybe_unserialize($data);
            }

            return false;
        }

        function delete_cache($hash = null, $type = 'query') {

            if (wp_cache_delete($hash, 'newsletters')) {
                return true;
            }

            return false;
        }

        function delete_all_cache($type = 'query') {

            if (wp_cache_flush()) {
                return true;
            }

            return false;
        }

        function qp_do_crons() {
            do_action('WPML_WP_Queue_Process_cron');
            do_action('WPML_WP_Queue_Process_2_cron');
            do_action('WPML_WP_Queue_Process_3_cron');
        }

        function qp_reset_data() {
            for ($q = 1; $q <= 3; $q++) {
                $this -> {'queue_process_' . $q} -> reset_data();
            }
        }

        function qp_save() {
            for ($q = 1; $q <= 3; $q++) {
                $this -> {'queue_process_' . $q} -> save();
            }
        }

        function qp_dispatch() {
            for ($q = 1; $q <= 3; $q++) {
                $this -> {'queue_process_' . $q} -> dispatch();
            }
        }

        function qp_get_queued_count() {

            if ($newsletters_queue_count = get_transient('newsletters_queue_count')) {
                return $newsletters_queue_count;
            }

            $count = 0;
            for ($q = 1; $q <= 3; $q++) {
                $count += $this -> {'queue_process_' . $q} -> get_queued_count();
            }

            set_transient('newsletters_queue_count', $count, (2 * MINUTE_IN_SECONDS));
            return $count;
        }

        function qp_get_specific_batch($key = null) {
            return $this -> queue_process_1 -> get_specific_batch($key);
        }

        function qp_update($key = null, $data = null) {
            $this -> queue_process_1 -> update($key, $data);
        }

        function qp_delete($key = null) {
            $this -> queue_process_1 -> delete($key);
        }

        function qp_do_specific_item($item = null, $override = false) {
            $this -> queue_process_1 -> do_specific_item($item, $override);
        }

        function qp_unlock() {
            for ($q = 1; $q <= 3; $q++) {
                $this -> {'queue_process_' . $q} -> unlock();
            }
        }

        function qp_cancel_all_processes() {
            for ($q = 1; $q <= 3; $q++) {
                $this -> {'queue_process_' . $q} -> cancel_all_processes();
            }
        }

        function qp_get_batches($onlykeys = false, $onlyerrors = false, $number = false, $key = null) {
            $batches = array();
            for ($q = 1; $q <= 3; $q++) {
                $newbatches = $this -> {'queue_process_' . $q} -> get_batches($onlykeys, $onlyerrors, $number, $key);
                $batches = array_merge($batches, $newbatches);
            }

            return $batches;
        }


        function qp_get_batches_show($onlykeys = false, $onlyerrors = false, $number = false, $key = null) {
            $batches = array();
            //error_log(json_encode($this -> {'queue_process_1'}));
            //for ($q = 1; $q <= 3; $q++) {
                $newbatches = $this -> {'queue_process_1'} -> get_batches_show($onlykeys, $onlyerrors, $number, $key);
                $batches = array_merge($batches, $newbatches);
           // }

            return $batches;
        }



        function newsletters_get_number_of_emails_on_intervals_statement() {

            $interval_number_of_emails = $this -> get_option('emailsperinterval');

            if(!empty($interval_number_of_emails)) {
                if($interval_number_of_emails > 2)
                {
                    return 3;
                }
                else {
                    return $interval_number_of_emails;
                }
            }

            return 1;
        }

        function qp_scheduling()
        {
            global $Shortcode;

            $get_number_of_emails_on_intervals = $Shortcode->newsletters_get_number_of_emails_on_intervals();
            if ((!empty($get_number_of_emails_on_intervals)) && $get_number_of_emails_on_intervals == 1) {
                for ($q = 1; $q <= 1; $q++) {
                    $this->{'queue_process_' . $q}->scheduling();
                }
            } else if ((!empty($get_number_of_emails_on_intervals)) && $get_number_of_emails_on_intervals == 2) {
                for ($q = 1; $q <= 2; $q++) {
                    $this->{'queue_process_' . $q}->scheduling();
                }
            } else if ((!empty($get_number_of_emails_on_intervals)) && $get_number_of_emails_on_intervals > 2) {
                for ($q = 1; $q <= 3; $q++) {
                    $this->{'queue_process_' . $q}->scheduling();
                }
            }

        }

        function get_country_by_ip($ipaddress = null) {
            global $Html;

            $ipcountry = false;

            if (!empty($ipaddress)) {
                $ipaddress = esc_html($ipaddress);
                if (function_exists('wp_remote_get')) {
                    $random = rand(1, 3);
                    switch ($random) {
                        case 1					:
                            $url = 'https://www.iplocate.io/api/lookup/' . $ipaddress;
                            if ($response = wp_remote_get($url)) {
                                $ipinfo = wp_remote_retrieve_body($response);
                                $ipinfo = json_decode($ipinfo);
                                if (!empty($ipinfo) && empty($ipinfo -> error)) {
                                    $ipcountry = $ipinfo -> country_code;
                                }
                            }
                            break;
                        case 2					:
                            $url = 'http://api.hostip.info/country.php?ip=' . $ipaddress;
                            if ($response = wp_remote_get($url)) {
                                $ipinfo = wp_remote_retrieve_body($response);
                                if (!empty($ipinfo) && $ipinfo != "XX") {
                                    $ipcountry = $ipinfo;
                                }
                            }
                            break;
                        case 3					:
                            $url = 'http://www.geoplugin.net/php.gp?ip=' . $ipaddress;
                            if ($response = wp_remote_get($url)) {
                                $ipinfo = wp_remote_retrieve_body($response);
                                if (!empty($ipinfo)) {
                                    $ipinfo = maybe_unserialize($ipinfo);
                                    if ( is_array( $ipinfo ) ) $ipcountry = $ipinfo['geoplugin_countryCode'];
                                }
                            }
                            break;
                    }
                }
            }

            return apply_filters('newsletters_ipcountry', $ipcountry, $ipaddress);
        }

        function get_useragent() {
            require($this -> plugin_base() . DS . 'vendor' . DS . 'autoload.php');
            $detect = new Mobile_Detect();

            $agent = false;

            if ($useragents = $detect -> getUserAgents()) {
                foreach ($useragents as $useragent => $regex) {
                    if (!empty($_SERVER['HTTP_USER_AGENT'])) {
                        if (strpos( $_SERVER['HTTP_USER_AGENT'], $useragent) !== false) {
                            $agent = $useragent;
                        }
                    }
                }
            }

            return $agent;
        }

        function get_device() {
            $device = false;

            require($this -> plugin_base() . DS . 'vendor' . DS . 'autoload.php');
            $detect = new Mobile_Detect();

            if ($detect -> isTablet()) {
                $device = "tablet";
            } elseif ($detect -> isMobile()) {
                $device = "mobile";
            } else {
                $device = "desktop";
            }

            return apply_filters('newsletters_device', $device, $detect);
        }

        function is_php_module($module = null) {

            if (!function_exists('phpinfo')) {
                return false;
            }

            if (!empty($module)) {
                ob_start();
                phpinfo(INFO_MODULES);
                $contents = ob_get_clean();

                if (strpos($contents, $module) !== false) {
                    return true;
                }
            }

            return false;
        }

        function media_insert($html = null, $id = null, $attachment = null) {
            $align = get_post_meta($id, '_wpmlalign', true);
            $hspace = get_post_meta($id, '_wpmlhspace', true);

            if (!empty($align) || !empty($hspace)) {
                if (class_exists('DOMDocument')) {
                    $dom = new DOMDocument();
                    $dom -> loadHTML($html);

                    foreach ($dom -> getElementsByTagName('img') as $img) {
                        if (!empty($align) && $align != "none") {
                            $img -> setAttribute('align', $align);
                        }

                        if (!empty($hspace)) {
                            $img -> setAttribute('hspace', $hspace);
                        }
                    }

                    $html = $dom -> saveHTML();
                    $html = trim(preg_replace(array("/^\<\!DOCTYPE.*?<html><body>/si", "!</body></html>$!si"), "", $html));
                }
            }

            return $html;
        }

        function attachment_fields_to_save($post = null, $attachment = null) {

            if (!empty($attachment[$this -> pre . 'align'])) {
                update_post_meta($post['ID'], '_wpmlalign', $attachment[$this -> pre . 'align']);
            } else {
                delete_post_meta($post['ID'], '_wpmlalign');
            }

            if (!empty($attachment[$this -> pre . 'hspace'])) {
                update_post_meta($post['ID'], '_wpmlhspace', $attachment[$this -> pre . 'hspace']);
            } else {
                delete_post_meta($post['ID'], '_wpmlhspace');
            }

            return $post;
        }

        function attachment_fields_to_edit($form_fields = null, $post = null) {
            $align = get_post_meta($post -> ID, "_wpmlalign", true);
            $hspace = get_post_meta($post -> ID, "_wpmlhspace", true);

            $html = '<label for="attachments_' . $post -> ID . '_wpmlalign_none"><input ' . ((empty($align) || (!empty($align) && $align == "none")) ? 'checked="checked"' : '') . ' style="width:auto;" type="radio" name="attachments[' . $post -> ID . '][wpmlalign]" value="none" id="attachments_' . $post -> ID . '_wpmlalign_none" /> ' . __('None', 'wp-mailinglist') . '</label>';
            $html .= ' <label for="attachments_' . $post -> ID . '_wpmlalign_left"><input ' . ((!empty($align) && $align == "left") ? 'checked="checked"' : '') . ' style="width:auto;" type="radio" name="attachments[' . $post -> ID . '][wpmlalign]" value="left" id="attachments_' . $post -> ID . '_wpmlalign_left" /> ' . __('Left', 'wp-mailinglist') . '</label>';
            $html .= ' <label for="attachments_' . $post -> ID . '_wpmlalign_right"><input ' . ((!empty($align) && $align == "right") ? 'checked="checked"' : '') . ' style="width:auto;" type="radio" name="attachments[' . $post -> ID . '][wpmlalign]" value="right" id="attachments_' . $post -> ID . '_wpmlalign_right" /> ' . __('Right', 'wp-mailinglist') . '</label>';

            $form_fields['wpmlalign'] = array(
                'label' =>  __('Email Align', 'wp-mailinglist'),
                'input' =>  'html',
                'html'	=>	$html,
                'value'	=>	$align,
                'show_in_modal'		=>	true,
                'show_in_edit'		=>	true,
            );

            $form_fields['wpmlhspace'] = array(
                'label'	=>	__('Email Hspace', 'wp-mailinglist'),
                'input'	=>	'html',
                'html'	=>	'<input type="text" style="width:45px;" class="widefat" name="attachments[' . $post -> ID . '][wpmlhspace]" value="' . $hspace . '" id="attachments_' . $post -> ID . '_wpmlhspace" /> px',
                'value'	=>	$hspace,
                'show_in_modal'		=>	true,
                'show_in_edit'		=>	true,
            );

            return $form_fields;
        }

        function debugging($debug = false) {
            global $wpdb;

            if (!empty($debug) && $debug == true) {
                if (!defined('WP_DEBUG')) { define('WP_DEBUG', true); }
                $wpdb -> show_errors();

                if (!empty($this -> debug_level) && $this -> debug_level == 2) {
                    error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
                    @ini_set('display_errors', 1);
                    @ini_set("log_errors", 1);
                }
            } else {
                //Get the current server log configuration and apply the same values accordingly
                $wpdb_errors = false;
                $error_reporting = error_reporting();
                $display_errors = @ini_get( 'display_errors' );
                $log_errors = @ini_get( 'log_errors' );
                $wpdb->show_errors( $wpdb_errors ); // When $wpdb_errors is false, this is the same as calling hide_errors()
                error_reporting( $error_reporting  & ~E_NOTICE & ~E_WARNING ); // set this to error_reporting( $error_reporting); if you want to see the warnings and notices too
                @ini_set( 'display_errors', $display_errors );
                @ini_set( 'log_errors', $log_errors );

            }
        }

        function after_plugin_row($plugin_name = null) {

            $validation_status = $this -> ci_serial_valid();
            if (is_array($validation_status)  && $validation_status['expired']) {
                ?>
                <tr class="plugin-update-tr active" id="<?php echo $this -> plugin_name; ?>-update" data-slug="<?php echo $this -> plugin_name; ?>" data-plugin="<?php echo $this -> plugin_file; ?>">
                    <td colspan="4" class="plugin-update colspanchange">
                        <div class="update-message notice inline notice-warning notice-alt">
                            <p>
                                <?php
                                if($validation_status['disable_pro_features']) {
                                    echo sprintf(__('Your serial key has expired. You are now running %s LITE. To remove limits, you can renew your %s or %s.', 'wp-mailinglist'), $this->name, '<a target="_blank" href="https://tribulant.com/downloads/">' . __('renew your license', 'wp-mailinglist') . '</a>', '<a target="_blank" href="https://tribulant.com/downloads/">' . __('upgrade to Lifetime', 'wp-mailinglist') . '</a>');
                                }
                                else {
                                    echo sprintf(__('Your license has expired. To receive further updates, you can %s or %s.', 'wp-mailinglist'),  '<a target="_blank" href="https://tribulant.com/downloads/">' . __('renew your license', 'wp-mailinglist') . '</a>', '<a target="_blank" href="https://tribulant.com/downloads/">' . __('upgrade to Lifetime', 'wp-mailinglist') . '</a>');
                                }
                                ?>
                            </p>
                        </div>
                    </td>
                </tr>
                <?php
            }

            if ($this->has_update() ) {
                $key = $this -> get_option('serialkey');
                $update = $this -> vendor('update');
                $version_info = $update -> get_version_info();
                if (!empty($version_info) && (!$validation_status || is_array($validation_status))) {
                    ?>

                    <tr class="plugin-update-tr active" id="<?php echo $this -> plugin_name; ?>-update" data-slug="<?php echo $this -> plugin_name; ?>" data-plugin="<?php echo $this -> plugin_file; ?>">

                        <td colspan="4" class="plugin-update colspanchange">
                            <div class="update-message notice inline notice-warning notice-alt">
                                <p>

                                    <?php

                                    echo __('There is a new update available for this plugin.', 'wp-mailinglist');
                                        $upgrade_url = admin_url('admin.php?page=' . $this -> sections -> settings_updates);
                                        echo ' ' .  sprintf(__('Go to %s page for more info.', 'wp-mailinglist'),  '<a href="' . $upgrade_url . '">' . __('Update', 'wp-mailinglist') . '</a>');
                                    ?>

                                </p>
                            </div>
                        </td>
                    </tr>

                    <?php
                }
            }
        }

        /**
         * This function outputs the changelog on the 'Plugins' page when the "View Details" link is clicked.
         */
        function display_changelog() {
            if (!empty($_GET['plugin']) && ($_GET['plugin'] == $this -> plugin_name || $_GET['plugin'] == "newsletters-lite")) {
                $section = esc_html($_GET['section']);
                switch ($section) {
                    case 'changelog'				:
                        if (apply_filters('newsletters_updates', true)) {
                            $update = $this -> vendor('update');
                            $changelog = $update -> get_changelog();
                            $this -> render('changelog', array('changelog' => $changelog), true, 'admin');
                        }

                        exit();
                        break;
                }
            }
        }

        function has_update($cache = true) {
           // if (apply_filters('newsletters_updates', true)) {
                $update = $this -> vendor('update');
                $version_info = $update -> get_version_info($cache);
                return version_compare($this -> version, $version_info["version"], '<');
          //  }

            return false;
        }

        function check_update($option, $cache = true) {

            if (apply_filters('newsletters_updates', true)) {
                if ($update = $this -> vendor('update')) {
                    $version_info = $update -> get_version_info($cache);

                    if (!$version_info) { return $option; }
                    $plugin_path = $this -> plugin_file;

                    if(empty($option -> response[$plugin_path])) {
                        if (is_null($option) || !$option) {
                            $option = new \stdClass();
                            $option->response = [];
                            $option->response[$plugin_path] = new \stdClass();
                        }
                        elseif (!is_array($option->response)) {
                            $option->response = [];
                            $option->response[$plugin_path] = new \stdClass();
                        }
                        else {
                            $option->response[$plugin_path] = new \stdClass();
                        }
                    }

                    //Empty response means that the key is invalid. Do not queue for upgrade
                    if(empty($version_info['is_valid_key']) || version_compare($this -> version, $version_info["version"], '>=')){
                        unset($option -> response[$plugin_path]);
                    } else {
                        $option -> response[$plugin_path] -> url = "https://tribulant.com";
                        $option -> response[$plugin_path] -> slug = 'newsletters-lite';
                        $option -> response[$plugin_path] -> plugin = $plugin_path;
                        $option -> response[$plugin_path] -> package = $version_info['url'];
                        //$option -> response[$plugin_path] -> package = 'https://downloads.wordpress.org/plugin/newsletters-lite.zip';
                        $option -> response[$plugin_path] -> new_version = $version_info["version"];
                        $option -> response[$plugin_path] -> id = "0";
                    }
                }
            }

            return $option;
        }

        function ajax_importfile() {

            check_ajax_referer('importfile', 'security');

            if (!current_user_can('newsletters_importexport')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $Db, $Html, $Field;

            ob_start();

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

            // IMPORTANT: Don't use sanitize_text_field on tmp_name as it removes backslashes from Windows paths!
            $uploadedfile = array(
                'name'     => isset($_FILES['file']['name']) ? sanitize_file_name($_FILES['file']['name']) : '',
                'type'     => isset($_FILES['file']['type']) ? sanitize_text_field($_FILES['file']['type']) : '',
                'tmp_name' => isset($_FILES['file']['tmp_name']) ? $_FILES['file']['tmp_name'] : '', // Don't sanitize!
                'error'    => isset($_FILES['file']['error']) ? (int)$_FILES['file']['error'] : 0,
                'size'     => isset($_FILES['file']['size']) ? (int)$_FILES['file']['size'] : 0,
            );

            $upload_overrides = array(
                'test_form' 	=> 	false,
                'test_type'		=>	false,
                'ext'			=>	'csv',
                'type'			=>	'text/csv',
            );

            
            if (!empty($uploadedfile['tmp_name']) && is_readable($uploadedfile['tmp_name']) && !is_uploaded_file($uploadedfile['tmp_name'])) {
                $upload_dir = wp_get_upload_dir();
                if (!empty($upload_dir['basedir'])) {
                    $temp_file = $upload_dir['basedir'] . '/' . uniqid('newsletters_import_') . '.csv';
                    if (copy($uploadedfile['tmp_name'], $temp_file)) {
                        $original_tmp = $uploadedfile['tmp_name'];
                        $uploadedfile['tmp_name'] = $temp_file;
                        register_shutdown_function(function() use ($temp_file) {
                            if (file_exists($temp_file)) {
                                @unlink($temp_file);
                            }
                        });
                    } else {
                    }
                } else {
                    error_log('Could not get upload basedir');
                }
            } else {
            }

            $movefile = wp_handle_upload($uploadedfile, $upload_overrides);

            if ($movefile && !isset($movefile['error'])) {
                $csvtypes = array('text/comma-separated-values', 'data/csv', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.ms-excel', 'application/octet-stream', 'application/vnd.msexcel', 'text/anytext', 'text/plain');
                $vcardtypes = array('text/x-vcard', 'application/vcard', 'text/anytext', 'text/directory', 'application/x-versit', 'text/x-versit', 'text/x-vcalendar');
                $filetype = wp_check_filetype($movefile['file']);

                $delimiter = $Html -> detectDelimiter($movefile['file']);
        
			    // Check license for subscriber import limit (500 in lite version without valid license)
			    global $Subscriber;
			    $serial_validation_status = $this -> ci_serial_valid();
			    $license_is_valid = (!is_array($serial_validation_status) && $serial_validation_status);
			    
			    // Get current subscriber count
			    $Db -> model = $Subscriber -> model;
			    $current_subscriber_count = $Db -> count();
			    
			    // Lite version limit: 500 subscribers without valid license
			    $import_limit = 500;
			    $subscribers_can_import = max(0, $import_limit - $current_subscriber_count);
			    
                $rows = 3;
                $done = 1;
                $headingdone = false;
                $fields = $Field -> get_all();
                $field_slugs = (!empty($fields)) ? wp_list_pluck($fields, 'slug') : array();
                $existing_field_slugs = array_map('strtolower', $field_slugs);

                $serial_validation_status = $this -> ci_serial_valid();
                $custom_field_creation_enabled = (!is_array($serial_validation_status) && $serial_validation_status);
                if (is_array($serial_validation_status) && !empty($serial_validation_status['disable_pro_features'])) {
                    $custom_field_creation_enabled = false;
                }

                $reserved_field_slugs = array('email', 'ip_address', 'created');

                $generateSlug = function($value) use ($Html) {
                    $sanitized = $Html -> sanitize($value, '');
                    $sanitized = $sanitized ?? '';
                    $slug = strtolower(preg_replace('/[^a-z]/', '', $sanitized));

                    if (empty($slug)) {
                        $slug = 'customfield';
                    }

                    return $slug;
                };

                if (!empty($filetype['type']) && in_array($filetype['type'], $csvtypes)) {
                    $preview = '';
                    $preview .= '<h3>' . __('Preview of File', 'wp-mailinglist') . '</h3>';

                    if ($fp = file($movefile['file'])) {
                        $count = count($fp);
                        $preview .= '<p>' . sprintf(
                            esc_html__('The file contains %s records in total.', 'wp-mailinglist'),
                            '<b>' . esc_html(number_format_i18n($count)) . '</b>'
                        );
                        
                        // Show eligible subscriber count when license is invalid
                        if (!$license_is_valid) {
                            $preview .= ' ' . sprintf(
                                esc_html__('Remaining, the first %s subscribers will import due to Lite version limit.', 'wp-mailinglist'),
                                '<b>' . esc_html(number_format_i18n($subscribers_can_import)) . '</b>'
                            );
                        }
                        $preview .= '</p>';				    	// Add warning if license is invalid and file has too many records
                            if (!$license_is_valid && $count > $import_limit) {
                                $preview .= '<div class="ui-state-highlight ui-corner-all" style="margin:10px 0; padding:12px;">';
                                $preview .= '<p><i class="fa fa-info-circle"></i> <strong>' . esc_html__('Lite Version Limit:', 'wp-mailinglist') . '</strong> ' . sprintf(
                                    esc_html__('Only %s subscribers will work in the Lite version without a valid license. Your file contains %s records.', 'wp-mailinglist'),
                                    '<b>' . esc_html(number_format_i18n($import_limit)) . '</b>',
                                    '<b>' . esc_html(number_format_i18n($count)) . '</b>'
                                ) . ' ';
                                $preview .= '<a href="' . esc_url(admin_url('admin.php?page=newsletters-lite-upgrade')) . '" style="color:#0073aa;">' . esc_html__('Upgrade to PRO', 'wp-mailinglist') . '</a></p>';
                                $preview .= '</div>';
                            }
                    }

                    $headers = array();
                    $sampleRows = array();
                    $normalizeKey = function($value) {
                        $value = preg_replace("/[^A-Za-z0-9\-\_\s'\"-]/", '', $value);
                        $value = strtolower($value);

                        return str_replace(array('-', '_', ' ', "'", '"'), '', $value);
                    };

                $normalizedFields = array();
                $normalizedFieldMap = array();

                if (!empty($fields)) {
                        foreach ($fields as $field) {
                            $normalizedKeys = array_filter(array_unique(array(
                                $normalizeKey($field -> slug),
                                $normalizeKey($field -> title),
                            )));

                            $normalizedFields[] = array(
                                'slug'    => $field -> slug,
                                'keys'    => $normalizedKeys,
                            );

                            foreach ($normalizedKeys as $normalizedKey) {
                                $normalizedFieldMap[$normalizedKey] = $field -> slug;
                            }
                        }
                }

                    if (($fh = fopen($movefile['file'], "r")) !== false) {
                        while (($row = fgetcsv($fh, 1000, $delimiter, '"', "\\")) !== false && $done <= $rows) {
                            if (empty($headingdone)) {
                                $headers = $row;
                                $headingdone = true;
                            } else {
                                $sampleRows[] = $row;
                            }

                            $done++;
                        }
                    }

                    if (empty($headers) && !empty($sampleRows)) {
                        $headers = array_map(function($index) {
                            return sprintf(__('Column %s', 'wp-mailinglist'), ($index + 1));
                        }, array_keys($sampleRows[0]));
                    }

                    $columnCount = count($headers);

                    $validSampleRows = array();
                    $mismatchedSampleLengths = array();

                    if (!empty($sampleRows)) {
                        foreach ($sampleRows as $sampleRow) {
                            $rowLength = count($sampleRow);

                            if ($rowLength === $columnCount) {
                                $validSampleRows[] = $sampleRow;
                            } else {
                                $mismatchedSampleLengths[] = $rowLength;
                            }
                        }

                        if (!empty($validSampleRows)) {
                            $sampleRows = $validSampleRows;
                        } elseif ($columnCount > 0) {
                            $paddedSampleRows = array();

                            foreach ($sampleRows as $sampleRow) {
                                $rowLength = count($sampleRow);

                                if ($rowLength < $columnCount) {
                                    $sampleRow = array_pad($sampleRow, $columnCount, '');
                                } elseif ($rowLength > $columnCount) {
                                    $sampleRow = array_slice($sampleRow, 0, $columnCount);
                                }

                                $paddedSampleRows[] = $sampleRow;
                            }

                            $sampleRows = $paddedSampleRows;
                        }
                    }

                    $preview .= '<div class="newsletters-import-preview">';
                    $preview .= '<p class="newsletters-import-mapping-note">' . __('If the example values do not line up with the column names, please double-check the CSV for the correct number of columns and ensure there are no unintended commas splitting fields.', 'wp-mailinglist') . '</p>';

                    if (!empty($mismatchedSampleLengths) && $columnCount > 0) {
                        $uniqueMismatchedLengths = array_values(array_unique($mismatchedSampleLengths));
                        $lengthsLabel = implode(', ', array_map(function($length) {
                            return '<b>' . intval($length) . '</b>';
                        }, $uniqueMismatchedLengths));

                        $preview .= '<p class="newsletters-import-mapping-note">' . sprintf(__('The header shows %1$s columns but some sample rows only contain %2$s. Example data will only use rows with the expected column count. Please verify your delimiter and ensure each row has the same number of commas.', 'wp-mailinglist'), '<b>' . intval($columnCount) . '</b>', $lengthsLabel) . '</p>';
                    }
                    $preview .= '<div class="newsletters-import-mapping-list">';
                    $columnLabels = array();

                    for ($i = 1; $i <= $columnCount; $i++) {
                        $selectedValue = '';
                        $rawHeader = (isset($headers[$i - 1]) && $headers[$i - 1] !== '') ? trim($headers[$i - 1]) : '';
                        $columnLabel = ($rawHeader !== '') ? $rawHeader : sprintf(__('Column %s', 'wp-mailinglist'), $i);
                        $columnheading = $normalizeKey($rawHeader);
                        $firstname_matches = array_map($normalizeKey, array('firstname', 'first', 'first_name', 'firstname', 'namefirst', 'givenname', 'fname', 'firstn'));
                        $lastname_matches = array_map($normalizeKey, array('lastname', 'last', 'last_name', 'surname', 'familyname', 'lname'));
                        $email_matches = array_map($normalizeKey, array('email', 'mail', 'emailaddress', 'e_mail', 'e-mail'));
                        $ip_matches = array_map($normalizeKey, array('ip', 'ipaddress', 'ip_address'));
                        $created_matches = array_map($normalizeKey, array('created', 'createddate', 'datecreated', 'created_at', 'createdat'));
                        $phone_matches = array_map($normalizeKey, array('phone', 'phonenumber', 'telephonenumber', 'telephone', 'tel', 'mobile', 'mobilenumber', 'cell', 'cellnumber', 'cellphone', 'mobilephone'));
                        $consent_matches = array_map($normalizeKey, array('consent', 'permission', 'gdpr', 'agree', 'agreement', 'optin', 'optinconsent', 'marketingconsent', 'dataconsent'));
                        $mailinglist_matches = array_unique(array(
                            $normalizeKey('mailinglists'),
                            $normalizeKey('mailing list/s'),
                            $normalizeKey('mailing list'),
                            $normalizeKey('mailing list(s)'),
                        ));

                        $matchField = function($matches) use ($columnheading, $normalizedFields) {
                            foreach ($normalizedFields as $fieldData) {
                                foreach ($fieldData['keys'] as $normalizedKey) {
                                    if ($columnheading === $normalizedKey && (empty($matches) || in_array($normalizedKey, $matches, true))) {
                                        return $fieldData['slug'];
                                    }

                                    if (in_array($columnheading, $matches, true) && in_array($normalizedKey, $matches, true)) {
                                        return $fieldData['slug'];
                                    }
                                }
                            }

                            return '';
                        };

                        if (!empty($columnheading)) {
                            if (in_array($columnheading, $email_matches, true)) {
                                $selectedValue = 'email';
                            }

                            if (empty($selectedValue) && in_array($columnheading, $ip_matches, true)) {
                                $selectedValue = 'ip_address';
                            }

                            if (empty($selectedValue) && in_array($columnheading, $created_matches, true)) {
                                $selectedValue = 'created';
                            }

                            if (empty($selectedValue)) {
                                $potentialMatch = $matchField($firstname_matches);
                                if (!empty($potentialMatch)) {
                                    $selectedValue = $potentialMatch;
                                }
                            }

                            if (empty($selectedValue)) {
                                $potentialMatch = $matchField($lastname_matches);
                                if (!empty($potentialMatch)) {
                                    $selectedValue = $potentialMatch;
                                }
                            }

                            if (empty($selectedValue)) {
                                $potentialMatch = $matchField($phone_matches);
                                if (!empty($potentialMatch)) {
                                    $selectedValue = $potentialMatch;
                                }
                            }

                            if (empty($selectedValue)) {
                                $potentialMatch = $matchField($consent_matches);
                                if (!empty($potentialMatch)) {
                                    $selectedValue = $potentialMatch;
                                }
                            }

                            if (empty($selectedValue)) {
                                if (isset($normalizedFieldMap[$columnheading])) {
                                    $selectedValue = $normalizedFieldMap[$columnheading];
                                }
                            }

                            if (empty($selectedValue)) {
                                $potentialMatch = $matchField(array());
                                if (!empty($potentialMatch)) {
                                    $selectedValue = $potentialMatch;
                                }
                            }
                        }

                        $sampleValue = '';
                        foreach ($sampleRows as $sampleRow) {
                            if (isset($sampleRow[$i - 1]) && $sampleRow[$i - 1] !== '') {
                                $sampleValue = $sampleRow[$i - 1];
                                break;
                            }
                        }

                        $isMailingListColumn = (!empty($columnheading) && in_array($columnheading, $mailinglist_matches, true));
                        if ($isMailingListColumn) {
                            $selectedValue = 'mailinglists';
                        }
                        $selectAttributes = '';

                        $generatedSlug = $generateSlug($rawHeader ?: $columnLabel);
                        $isReservedField = in_array(strtolower($generatedSlug), $reserved_field_slugs, true) || (!empty($selectedValue) && in_array($selectedValue, $reserved_field_slugs, true));
                        $hasMapping = !empty($selectedValue);
                        $canCreateField = ($custom_field_creation_enabled && !$hasMapping && !empty($rawHeader) && !$isMailingListColumn && !$isReservedField && !in_array(strtolower($generatedSlug), $existing_field_slugs, true));

                        $columnLabels[] = array(
                            'value' => $i,
                            'label' => sanitize_text_field($columnLabel),
                            'is_mailing_list' => $isMailingListColumn,
                        );

                        $preview .= '<div class="newsletters-import-mapping-row">';
                        $preview .= '<span class="newsletters-import-mapping-title">' . esc_html($columnLabel) . '</span>';

                        $preview .= '<select class="newsletters-import-mapping-select" data-column-index="' . $i . '" name="columns[' . $i . ']"' . $selectAttributes . '>';
                        $preview .= '<option value="">' . __('- Do not import -', 'wp-mailinglist') . '</option>';
                        $preview .= '<option value="email"' . selected($selectedValue, 'email', false) . '>' . __('Email Address', 'wp-mailinglist') . '</option>';
                        $preview .= '<option value="ip_address"' . selected($selectedValue, 'ip_address', false) . '>' . __('IP Address', 'wp-mailinglist') . '</option>';
                        $preview .= '<option value="created"' . selected($selectedValue, 'created', false) . '>' . __('Created Date', 'wp-mailinglist') . '</option>';
                            foreach ($fields as $field) {
                                $preview .= '<option value="' . $field -> slug . '"' . selected($selectedValue, $field -> slug, false) . '>' . __($field -> title) . '</option>';
                            }

                        $preview .= '<option value="mailinglists"' . selected($selectedValue, 'mailinglists', false) . '>' . __('Mailing Lists', 'wp-mailinglist') . '</option>';
                        $preview .= '</select>';



                            if ($sampleValue !== '') {
                                $preview .= '<span class="newsletters-import-mapping-sample">' . sprintf(__('Example: %s', 'wp-mailinglist'), esc_html($sampleValue)) . '</span>';
                            } else {
                                $preview .= '<span class="newsletters-import-mapping-sample"></span>';
                            }

                        $preview .= '<div class="newsletters-import-mapping-action" data-column-index="' . $i . '">';
                        $preview .= '<input type="hidden" name="column_headers[' . $i . ']" value="' . esc_attr($rawHeader) . '" />';
                        $preview .= '<input type="hidden" name="column_slugs[' . $i . ']" value="' . esc_attr($generatedSlug) . '" />';

                        $preview .= '<div class="newsletters-import-create-field-container" data-column-index="' . $i . '" data-reserved-field="' . ($isReservedField ? '1' : '0') . '"' . ($hasMapping ? ' style="display:none;"' : '') . '>';

                        if ($canCreateField) {
                            $preview .= '<label class="newsletters-import-create-field">';
                            $preview .= '<input type="checkbox" data-column-index="' . $i . '" name="create_fields[' . $i . ']" value="' . esc_attr($generatedSlug) . '" />';
                            $preview .= '<span>' . __('Create custom field', 'wp-mailinglist') . '</span>';
                            $preview .= '</label>';
                        } elseif (!$custom_field_creation_enabled) {
                            $preview .= '<label class="newsletters-import-create-field">';
                            $preview .= '<input type="checkbox" disabled="disabled" />';
                            $preview .= '<span><a href="' . esc_url_raw(admin_url('admin.php?page=newsletters-lite-upgrade')) . '" style="color:#0073aa; text-decoration:none;">(' . __('PRO', 'wp-mailinglist') . ')</a> ' . __('Create custom field', 'wp-mailinglist') . '</span>';
                            $preview .= '</label>';
                        } elseif ($isReservedField) {
                            $preview .= '<span class="newsletters-import-create-field"><span class="disabled-reason">' . __('Reserved column', 'wp-mailinglist') . '</span></span>';
                        } elseif (!empty($rawHeader) && in_array(strtolower($generatedSlug), $existing_field_slugs, true)) {
                            $preview .= '<span class="newsletters-import-create-field"><span class="disabled-reason">' . __('Custom field exists', 'wp-mailinglist') . '</span></span>';
                        } elseif ($isMailingListColumn) {
                            $preview .= '<span class="newsletters-import-create-field"><span class="disabled-reason">' . __('Mapped to mailing lists', 'wp-mailinglist') . '</span></span>';
                        }

                        $preview .= '</div>';

                        $preview .= '</div>';

                        $preview .= '</div>';
                    }

                    $preview .= '</div>';

                    $preview .= '</div>';
                    $preview = $this -> maybe_utf8_encode($preview);

                    $response = array(
					    'success'                       =>      true,
                        'movefile'                      =>      $movefile,
                        'preview'                       =>      $preview,
                        'delimiter'                     =>      $delimiter,
                        'column_labels'                 =>      $columnLabels,
                        'license_valid'                 =>      $license_is_valid,
                        'current_subscribers'           =>      $current_subscriber_count,
                        'import_limit'                  =>      $import_limit,
                        'can_import'                    =>      $subscribers_can_import,
				    );

                } elseif (!empty($filetype['type']) && in_array($filetype['type'], $vcardtypes)) {
                    ob_start();

                    $preview = '';

                    include_once($this -> plugin_base() . DS . 'vendors' . DS . 'class.vcard.php');
                    $conv = new vcard_convert();
                    $conv -> fromFile($movefile['file']);
                    $data = $conv -> toCSV(',', false, false, null);

                    $fileName = 'vcard.csv';
                    $filePath = $Html -> uploads_path() . DS . $this -> plugin_name . DS;
                    $fileFull = $filePath . $fileName;
                    $fh = fopen($fileFull, "w");

                    if ($fh) {
                        fwrite($fh, $data);
                        fclose($fh);
                    } else {
                        $preview .= sprintf(__('CSV file could not be created! Check "%s" permissions!', 'wp-mailinglist'), $filePath);
                    }

                    $uploadedfile = array(
                        'file'				=>	$fileFull,
                        'type'				=>	false,
                        'url'				=>	false,
                    );

                    $delimiter = $Html -> detectDelimiter($fileFull);

                    if (($fh = fopen($fileFull, "r")) !== false) {
                        $preview .= '<h3>' . __('Preview of File', 'wp-mailinglist') . '</h3>';

                        if ($fp = file($fileFull)) {
                            $count = count($fp);
                            $preview .= '<p>' . sprintf(
                                esc_html__('The file contains %s records in total.', 'wp-mailinglist'),
                                '<b>' . esc_html(number_format_i18n($count)) . '</b>'
                            );
                            
                            // Show eligible subscriber count when license is invalid
                            if (!$license_is_valid) {
                                $preview .= ' ' . sprintf(
                                    esc_html__('Remaining, the first %s subscribers will import due to Lite version limit.', 'wp-mailinglist'),
                                    '<b>' . esc_html(number_format_i18n($subscribers_can_import)) . '</b>'
                                );
                            }
                            $preview .= '</p>';					    	// Add warning if license is invalid and file has too many records
                            if (!$license_is_valid && $count > $import_limit) {
                                $preview .= '<div class="ui-state-highlight ui-corner-all" style="margin:10px 0; padding:12px;">';
                                $preview .= '<p><i class="fa fa-info-circle"></i> <strong>' . esc_html__('Lite Version Limit:', 'wp-mailinglist') . '</strong> ' . sprintf(
                                    esc_html__('Only %s subscribers will work in the Lite version without a valid license. Your file contains %s records.', 'wp-mailinglist'),
                                    '<b>' . esc_html(number_format_i18n($import_limit)) . '</b>',
                                        '<b>' . esc_html(number_format_i18n($count)) . '</b>'
                                    ) . ' ';
                                    $preview .= '<a href="' . esc_url(admin_url('admin.php?page=newsletters-lite-upgrade')) . '" style="color:#0073aa;">' . esc_html__('Upgrade to PRO', 'wp-mailinglist') . '</a></p>';
                                    $preview .= '</div>';
                            }
                        }

                        $preview .= '<table class="widefat">';

                        while (($row = fgetcsv($fh, 1000, $delimiter)) !== false && $done <= $rows) {
                            if (empty($headingdone)) {
                                $preview .= '<thead>';
                                $preview .= '<tr>';
                                for ($i = 1; $i <= count($row); $i++) {
                                    $preview .= '<th>' . sprintf(__('Column %s', 'wp-mailinglist'), $i) . '</th>';
                                }
                                $preview .= '</tr>';

                                $preview .= '<tr>';
                                for ($i = 1; $i <= count($row); $i++) {
                                    $preview .= '<td>';
                                    $preview .= '<select name="columns[' . $i . ']">';
                                    $preview .= '<option value="">' . __('- Do not import -', 'wp-mailinglist') . '</option>';
                                    $preview .= '<option value="email">' . __('Email Address', 'wp-mailinglist') . '</option>';
                                    $preview .= '<option value="ip_address">' . __('IP Address', 'wp-mailinglist') . '</option>';
                                    $preview .= '<option value="created">' . __('Created Date', 'wp-mailinglist') . '</option>';
                                    if (!empty($fields)) {
                                        foreach ($fields as $field) {
                                            $preview .= '<option value="' . $field -> slug . '">' . __($field -> title) . '</option>';
                                        }
                                    }
                                    $preview .= '</select>';
                                    $preview .= '</td>';
                                }
                                $preview .= '</tr>';

                                $preview .= '</thead>';
                                $preview .= '<tbody>';
                                $headingdone = true;
                            }

                            $class = (empty($class)) ? 'alternate' : '';
                            $preview .= '<tr class="' . $class . '">';
                            foreach ($row as $cell) {
                                $preview .= '<td>' . $cell . '</td>';
                            }
                            $preview .= '</tr>';
                            $done++;
                        }

                        $preview .= '</tbody></table>';
                    } else {
                        $preview .= '<p>' . __('CSV file cannot be open for reading', 'wp-mailinglist') . '</p>';
                    }

                    echo $preview;
                    $preview = ob_get_clean();
                    $preview = $this -> maybe_utf8_encode($preview);

                    $response = array(
						'success'			=>	true,
						'movefile'			=>	$uploadedfile,
						'preview'			=>	$preview,
						'delimiter'			=>	$delimiter,
						'license_valid'		=>	$license_is_valid,
						'current_subscribers'	=>	$current_subscriber_count,
						'import_limit'		=>	$import_limit,
						'can_import'		=>	$subscribers_can_import,
					);
                } else {
                    error_log('File type check failed. Expected CSV types, got: ' . $filetype['type']);
                    $response = array(
                        'success'			=>	false,
                        'errormessage'		=>	__('File type is not allowed.', 'wp-mailinglist'),
                    );
                }
            } else {
                error_log('Upload failed with error: ' . $movefile['error']);
			    error_log('movefile array: ' . print_r($movefile, true));
                $response = array(
                    'success'			=>	false,
                    'errormessage'		=>	$movefile['error'],
                );
            }

            $process = ob_get_clean();
            echo json_encode($response);

            exit();
            die();
        }

        function maybe_utf8_encode($content = null) {
            if (function_exists('mb_detect_encoding')) {
                $encoding = mb_detect_encoding($content, mb_detect_order(), true);
                if (empty($encoding) || $encoding != "UTF-8") {
                    $content = mb_convert_encoding($content, 'UTF-8', $encoding ? $encoding : 'ISO-8859-1');
                }
            }

            return $content;
        }

        function ajax_importmultiple() {

            check_ajax_referer('importmultiple', 'security');

            if (!current_user_can('newsletters_importexport')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $wpdb, $Db, $Subscriber, $SubscribersList, $Unsubscribe, $Bounce, $Mailinglist;

            if (!empty($_REQUEST['subscribers'])) {

				$raw_subscribers = map_deep(wp_unslash($_REQUEST['subscribers']), 'sanitize_text_field');
				$chunk_size = count($raw_subscribers);
				$this -> log_error(sprintf('[ImportMultiple] Starting AJAX import chunk with %d subscribers', $chunk_size));

                $this -> qp_reset_data();

                foreach ($raw_subscribers as $skey => $subscriber) {
					$log_context = sprintf('[ImportMultiple] Chunk index %d', $skey);
                    $subscriber = stripslashes_deep($subscriber);
                    if (empty($subscriber)) {
                        continue;
                    }
                    $subscriber['justsubscribe'] = true;
                    $email = isset($subscriber['email']) ? $subscriber['email'] : '';

					if (empty($email)) {
						$this -> log_error($log_context . ' missing email, skipping this record.');
						continue;
					}

					$mailinglists = isset($subscriber['mailinglists']) ? $subscriber['mailinglists'] : array();
					if (is_string($mailinglists)) {
						$mailinglists = array_filter(array_map('trim', explode(';', $mailinglists)));
					} elseif (!is_array($mailinglists)) {
						$mailinglists = array();
					}

					if (!empty($mailinglists)) {
						$mailinglists = array_values(array_filter(array_map('intval', (array) $mailinglists)));
					}

					if (empty($subscriber['afterlists']) && !empty($mailinglists)) {
                        $subscriber['afterlists'] = array();
                        foreach ($mailinglists as $list_value) {
                            $list_value = trim((string) $list_value);
                            if ($list_value === '') {
                                continue;
                            }

                            $l = false;
                            if (is_numeric($list_value)) {
                                $l = $Mailinglist -> get((int) $list_value);
                            } else {
                                $Db -> model = $Mailinglist -> model;
                                $l = $Db -> find(array('title' => $list_value));
                            }

                            if (!empty($l)) {
                                $subscriber['afterlists'][] = array(
                                    'id'        =>  (int) $l -> id,
                                    'active'    =>  'Y',
                                    'paid'      =>  'N',
                                );
                            }
                        }
                    }

                    if (!empty($subscriber['afterlists']) && is_array($subscriber['afterlists'])) {
						$mailinglists = array();
						foreach ($subscriber['afterlists'] as $afterlist) {
							if (isset($afterlist['id'])) {
								$mailinglists[] = (int) $afterlist['id'];
							}
						}
						$subscriber['mailinglists'] = array_values(array_unique(array_filter($mailinglists)));
					} else {
						$subscriber['mailinglists'] = array();
						$mailinglists = array();
					}

					$mailinglists = $subscriber['mailinglists'];
                    $confirmation_subject = ! empty($_REQUEST['confirmation_subject']) ? wp_kses_post(wp_unslash($_REQUEST['confirmation_subject'])) : '';
                    $confirmation_email = ! empty($_REQUEST['confirmation_email']) ? wp_kses_post(wp_unslash($_REQUEST['confirmation_email'])) : '';
                    $import_preventbu = ! empty($_REQUEST['import_preventbu']) ? sanitize_text_field($_REQUEST['import_preventbu']) : '';
                    $import_overwrite = ! empty($_REQUEST['import_overwrite']) ? sanitize_text_field($_REQUEST['import_overwrite']) : '';

                    //if ($current_id = $Subscriber -> email_exists($email) && $import_overwrite == "Y") {
                    try {
                        $Db -> model = $Unsubscribe -> model;
                        if (empty($import_preventbu) || $import_preventbu == "N" || ($import_preventbu == "Y" && !$Db -> find(array('email' => $email)))) {
                            $Db -> model = $Bounce -> model;
                            if (empty($import_preventbu) || $import_preventbu == "N" || ($import_preventbu == "Y" && !$Db -> find(array('email' => $email)))) {
                                if (!empty($subscriber)) {
                                    $subscriber['fromregistration'] = true;
                                    $subscriber['username'] = $email;

                                    $skipsubscriberupdate = false;

                                    if ($current_id = $Subscriber -> email_exists($email)) {
                                        $subscriber['id'] = $current_id;

                                        if (empty($import_overwrite) || $import_overwrite == "N") {
                                            $skipsubscriberupdate = true;
                                        } else {
                                            $skipsubscriberupdate = false;
                                        }
                                    } else {
                                        $skipsubscriberupdate = false;
                                        $subscriber['id'] = false;
                                    }

                                    $this -> log_error(sprintf('%s attempting to save subscriber %s (lists: %s)', $log_context, $email, implode(',', $subscriber['mailinglists'])));

									if ($skipsubscriberupdate && !empty($current_id)) {
										$success = "Y<|>" . $email;
										$message = __('Subscriber exists, not updating/overwriting', 'wp-mailinglist');
									} else {

                                    if ($Subscriber -> save($subscriber, true, false, $skipsubscriberupdate)) {
                                        $subscriber_id = $Subscriber -> insertid;
                                        $afterlists = $subscriber['afterlists'];

                                        if (!empty($afterlists)) {
                                            foreach ($afterlists as $mailinglist) {
                                                if (empty($mailinglist)) {
                                                    continue;
                                                }
                                                $sl_data = array('subscriber_id' => $subscriber_id, 'list_id' => $mailinglist['id'], 'paid' => $mailinglist['paid'], 'active' => $mailinglist['active']);
                                                $sl_query = $SubscribersList -> save($sl_data, false, true);

                                                if (!empty($sl_query)) {
                                                    $wpdb -> query($sl_query);
                                                }
                                            }
                                        }

                                        if ($subscriber['active'] == "N") {
                                            if (!empty($mailinglists)) {
                                                $allmailinglists = $mailinglists;
                                                $Db -> model = $Subscriber -> model;
                                                $sub = $Db -> find(array('id' => $subscriber_id));

                                                foreach ($allmailinglists as $mailinglist_id) {
                                                    $subject = $confirmation_subject;
                                                    $message = $confirmation_email;

                                                    $message = wpautop($message);
                                                    $message = $this -> process_set_variables($sub, false, $message, false, false, true);

                                                    $queue_process_data = array(
                                                        'subscriber_id'				=>	$sub -> id,
                                                        'subject'					=>	$subject,
                                                        'message'					=>	$message,
                                                        'attachments'				=>	false,
                                                        'post_id'					=>	false,
                                                        'history_id'				=>	false,
                                                        'theme_id'					=>	$this -> default_theme_id('system'),
                                                        'senddate'					=>	false,
                                                    );

                                                    $this -> queue_process_1 -> push_to_queue($queue_process_data);
                                                }
                                            }
                                        }

                                        $success = "Y<|>" . $email;
                                        $message = __('Subscriber was imported.', 'wp-mailinglist');
                                    } else {
                                        $error_message = implode(" | ", $Subscriber -> errors);
                                        $this -> log_error(sprintf('%s failed saving %s: %s', $log_context, $email, $error_message));
                                        $success = "N<|>" . $email;
                                        $message = $error_message;
                                    }
                                }
                            } else {
                                $success = "N<|>" . $email;
                                    $message = __('No subscriber data is available.', 'wp-mailinglist');
                                }
                            } else {
                                $success = "N<|>" . $email;
                                $message = __('Subscriber has previously bounced', 'wp-mailinglist');
                            }
                        } else {
                            $success = "N<|>" . $email;
                            $message = __('Subscriber has previously unsubscribed', 'wp-mailinglist');
                        
                        }

                        echo $success . "<|>" . $message . "<||>";
                    } catch (Throwable $import_exception) {
						$error_msg = sprintf('%s exception importing %s: %s on line %s', $log_context, $email, $import_exception -> getMessage(), $import_exception -> getLine());
						$this -> log_error($error_msg);
						echo wp_kses_post("N<|>" . $email) . "<|>" . wp_kses_post($import_exception -> getMessage()) . "<||>";
					}
                }

                $this -> qp_save();
                $this -> qp_dispatch();
                $this -> log_error(sprintf('[ImportMultiple] Finished AJAX import chunk with %d subscribers', $chunk_size));
            } else {
                $success = "N<|>" . $email;
                $message = __('No data was posted, blank row?', 'wp-mailinglist');
                echo $success . "<|>" . $message . "<||>";
            }

            exit();
            die();
        }


        function ajax_builderon() {
            define('DOING_AJAX', true);
            define('SHORTINIT', true);

            $builderon = (empty($_POST['status']) || $_POST['status'] == "false") ? false : true;
            update_user_option(get_current_user_id(), 'newsletters_builderon', $builderon);

            exit();
            die();
        }


        function ajax_admin_mode() {

            check_admin_referer('admin_mode', 'security');

            if (!current_user_can('newsletters_settings')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            $user_id = get_current_user_id();
            $mode = (empty($_POST['mode'])) ? 'standard' : sanitize_text_field($_POST['mode']);
            update_user_option($user_id, 'newsletters_admin_mode', $mode);

            exit();
            die();
        }

        function ajax_get_country() {
            global $Subscriber, $Html;

            check_ajax_referer('get_country', 'security');

            $success = false;
            $data = array();

            if (current_user_can('newsletters_subscribers')) {
                if (!empty($_POST['subscriber_id'])) {
                    $subscriber_id = (int) sanitize_text_field($_POST['subscriber_id']);
                    $data['subscriber_id'] = $subscriber_id;
                    if ($subscriber = $Subscriber -> get($subscriber_id)) {
                        if (!empty($subscriber -> ip_address)) {
                            if ($ipcountry = $this -> get_country_by_ip($subscriber -> ip_address)) {
                                $country = $ipcountry;

                                $Subscriber -> save_field('country', $country, $subscriber -> id);

                                $data['country'] = $country;
                                $data['flag'] = $Html -> flag_by_country($country);
                                $success = true;
                            }
                        }
                    }
                }
            } else {
                $success = false;
                $data['message'] = __('You do not have permission', 'wp-mailinglist');
            }

            $data['success'] = $success;
            echo json_encode($data);

            exit();
            die();
        }

        public function get_ai_default_commands() {
            return array(
                'rewrite_system'             => "You are a text rewriting assistant. Rewrite the provided text according to the user's instructions and output only the final rewritten content without introductions or explanations. Use valid HTML for headings, lists, bold text, and other formatting when appropriate. Do not use the long dash (—) or special characters such as *, _, #, or backticks.",
                'generate_system'            => "You are a text generator for newsletter emails. When given text to rewrite, expand, or improve, output only the final version of the text without introductions, explanations, or closing statements. Use valid HTML for headings, lists, bold text, and other formatting when appropriate. Do not use the long dash (—) or special characters such as *, _, #, or backticks.",
                'rewrite_selected_template'  => "Rewrite the following text:\n\n%selected%\n\n%prompt%",
                'existing_content_template'  => "Existing content:\n%editor%\n\n%prompt%",
            );
        }

        function ajax_chatgpt_models() {
            if (!current_user_can('manage_options')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }
            $response_data = array(
                'success' => false,
                'models'  => array(),
                'message' => '',
            );
            $api_key = $this->get_option('ai_chatgpt_api_key');
            if (empty($api_key)) {
                $response_data['message'] = __('Please add a ChatGPT API key in the settings.', 'wp-mailinglist');
                echo wp_json_encode($response_data);
                exit();
            }
            $response = wp_remote_get('https://api.openai.com/v1/models', array(
                'timeout' => apply_filters('newsletters_ai_timeout', 300),
                'headers' => array(
                    'Authorization' => 'Bearer ' . $api_key,
                ),
            ));
            if (is_wp_error($response)) {
                $response_data['message'] = $response->get_error_message();
                echo wp_json_encode($response_data);
                exit();
            }
            $body          = wp_remote_retrieve_body($response);
            $response_code = wp_remote_retrieve_response_code($response);
            $json          = json_decode($body, true);
            if ($response_code >= 400) {
                if (!empty($json['error']['message'])) {
                    $response_data['message'] = $json['error']['message'];
                } else {
                    $response_data['message'] = __('Unable to load ChatGPT models. Please check your API key.', 'wp-mailinglist');
                }
                echo wp_json_encode($response_data);
                exit();
            }
            if (!empty($json['data']) && is_array($json['data'])) {
                foreach ($json['data'] as $model) {
                    if (!empty($model['id']) && strpos($model['id'], 'gpt') !== false) {
                        $response_data['models'][] = sanitize_text_field($model['id']);
                    }
                }
            }
            if (!empty($response_data['models'])) {
                $response_data['models'] = array_values(array_unique($response_data['models']));
                sort($response_data['models'], SORT_NATURAL | SORT_FLAG_CASE);
                $response_data['success'] = true;
            } else {
                $response_data['message'] = __('No ChatGPT models are available. Please verify your API key.', 'wp-mailinglist');
            }
            echo wp_json_encode($response_data);
            exit();
        }


        function ajax_ai_generate() {
            if (!current_user_can('manage_options')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            $model   = (isset($_POST['model'])) ? sanitize_text_field($_POST['model']) : '';
            $prompt  = (isset($_POST['prompt'])) ? sanitize_textarea_field(stripslashes($_POST['prompt'])) : '';
            $editor   = (isset($_POST['editor'])) ? sanitize_textarea_field(wp_unslash($_POST['editor'])) : '';
            $rewrite  = (!empty($_POST['rewrite']) && sanitize_text_field($_POST['rewrite']) === '1');
            $assistant_disabled = ($this->get_option('disable_ai_assistant') == 'Y');
            $rewrite_disabled   = ($this->get_option('disable_ai_rewrite') == 'Y');

            if ($rewrite) {
                if ($rewrite_disabled) {
                    echo json_encode(array('text' => '', 'message' => __('AI Rewrite is disabled.', 'wp-mailinglist')));
                    exit();
                }
            } else {
                if ($assistant_disabled) {
                    echo json_encode(array('text' => '', 'message' => __('AI Assistant is disabled.', 'wp-mailinglist')));
                    exit();
                }
            }
            $selected = (isset($_POST['selected'])) ? sanitize_textarea_field(wp_unslash($_POST['selected'])) : '';

            $ai_defaults        = $this->get_ai_default_commands();
            $override_commands  = ($this->get_option('ai_override_prompts') === 'Y');
            $rewrite_system     = $ai_defaults['rewrite_system'];
            $generate_system    = $ai_defaults['generate_system'];
            $rewrite_template   = $ai_defaults['rewrite_selected_template'];
            $existing_template  = $ai_defaults['existing_content_template'];

            if ($override_commands) {
                $custom_rewrite_system = $this->get_option('ai_command_rewrite');
                if ($custom_rewrite_system !== false && $custom_rewrite_system !== '') {
                    $rewrite_system = $custom_rewrite_system;
                }

                $custom_generate_system = $this->get_option('ai_command_generate');
                if ($custom_generate_system !== false && $custom_generate_system !== '') {
                    $generate_system = $custom_generate_system;
                }

                $custom_rewrite_template = $this->get_option('ai_command_rewrite_selected');
                if ($custom_rewrite_template !== false && $custom_rewrite_template !== '') {
                    $rewrite_template = $custom_rewrite_template;
                }

                $custom_existing_template = $this->get_option('ai_command_existing_content');
                if ($custom_existing_template !== false && $custom_existing_template !== '') {
                    $existing_template = $custom_existing_template;
                }
            }

            if ($rewrite) {
                $who_you_are = $rewrite_system;
            } else {
                $who_you_are = $generate_system;
            }

            $full_prompt = $prompt;
            if ($rewrite && !empty($selected)) {
                $full_prompt_candidate = strtr($rewrite_template, array(
                    '%selected%' => $selected,
                    '%prompt%'   => $prompt,
                ));
                $full_prompt = ($full_prompt_candidate !== '') ? $full_prompt_candidate : $prompt;
            } elseif (!empty($editor)) {
                $full_prompt_candidate = strtr($existing_template, array(
                    '%editor%' => $editor,
                    '%prompt%' => $prompt,
                ));
                $full_prompt = ($full_prompt_candidate !== '') ? $full_prompt_candidate : $prompt;
            }
            $text    = '';
            $message = '';

            if ($model === 'gemini-2.5-flash' || $model === 'gemini-2.5-pro') {
                $api_key = $this->get_option('ai_gemini_pro_api_key');
                if (!empty($api_key)) {
                    $endpoint = 'https://generativelanguage.googleapis.com/v1beta/models/' . $model . ':generateContent';
                    $body     = json_encode(array('contents' => array(array('parts' => array(array('text' => $who_you_are . " \r\n" . $full_prompt))))));
                    $response = wp_remote_post($endpoint, array(
                        'body'    => $body,
                        'timeout' => apply_filters('newsletters_ai_timeout', 300),
                        'headers' => array(
                            'Content-Type'  => 'application/json',
                            'X-goog-api-key'=> $api_key,
                        ),
                    ));
                    if (!is_wp_error($response)) {
                        $json = json_decode(wp_remote_retrieve_body($response), true);
                        if (!empty($json['candidates'][0]['content']['parts'][0]['text'])) {
                            $text = $json['candidates'][0]['content']['parts'][0]['text'];
                        } elseif (!empty($json['error']['message'])) {
                            $message = $json['error']['message'];
                        }
                    } else {
                        $message = $response->get_error_message();
                    }
                } else {
                    $message = __('Please add a Gemini API key in the settings.', 'wp-mailinglist');
                }
            } elseif ($model === 'chatgpt' || $model === 'chatgpt-pro') {
                $api_key = $this->get_option('ai_chatgpt_api_key');
                if (!empty($api_key)) {
                    $cg_model = (isset($_POST['chatgpt_model'])) ? sanitize_text_field($_POST['chatgpt_model']) : 'gpt-4o-mini';
                    $endpoint = 'https://api.openai.com/v1/chat/completions';
                    $body     = json_encode(array(
                        'model'    => $cg_model,
                        'messages' => array(
                            array('role' => 'system', 'content' => $who_you_are),
                            array('role' => 'user', 'content' => $full_prompt),
                        ),
                    ));
                    $response = wp_remote_post($endpoint, array(
                        'body'    => $body,
                        'timeout' => apply_filters('newsletters_ai_timeout', 300),
                        'headers' => array(
                            'Content-Type'  => 'application/json',
                            'Authorization' => 'Bearer ' . $api_key,
                        ),
                    ));
                    if (!is_wp_error($response)) {
                        $json = json_decode(wp_remote_retrieve_body($response), true);
                        if (!empty($json['choices'][0]['message']['content'])) {
                            $text = $json['choices'][0]['message']['content'];
                        } elseif (!empty($json['error']['message'])) {
                            $message = $json['error']['message'];
                        }
                    } else {
                        $message = $response->get_error_message();
                    }
                } else {
                    $message = __('Please add a ChatGPT API key in the settings.', 'wp-mailinglist');
                }
            } elseif ($model === 'deepseek' || $model === 'deepseek-pro') {
                $api_key = $this->get_option('ai_deepseek_pro_api_key');
                if (!empty($api_key)) {
                    $endpoint = 'https://api.deepseek.com/chat/completions';
                    $ds_model = ($model === 'deepseek') ? 'deepseek-chat' : 'deepseek-reasoner';
                    $body     = json_encode(array(
                        'model'    => $ds_model,
                        'messages' => array(
                            array('role' => 'system', 'content' => $who_you_are),
                            array('role' => 'user', 'content' => $full_prompt),
                        ),
                        'stream'   => false,
                    ));
                    $response = wp_remote_post($endpoint, array(
                        'body'    => $body,
                        'timeout' => apply_filters('newsletters_ai_timeout', 300),
                        'headers' => array(
                            'Content-Type'  => 'application/json',
                            'Authorization' => 'Bearer ' . $api_key,
                        ),
                    ));
                    if (!is_wp_error($response)) {
                        $json = json_decode(wp_remote_retrieve_body($response), true);
                        if (!empty($json['choices'][0]['message']['content'])) {
                            $text = $json['choices'][0]['message']['content'];
                        } elseif (!empty($json['error']['message'])) {
                            $message = $json['error']['message'];
                        }
                    } else {
                        $message = $response->get_error_message();
                    }
                } else {
                    $message = __('Please add a Deepseek API key in the settings.', 'wp-mailinglist');
                }
            }

            if (!empty($text)) {
                $text = str_replace(array('—', '–', '*', '_', '#', '`'), '', $text);
                $text = wp_kses_post($text);
            }

            $data = array('text' => $text, 'message' => $message);
            echo json_encode($data);
            exit();
            die();
        }


        function ajax_mailinglist_save() {
            if (!current_user_can('newsletters_lists')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $wpdb, $Db, $Mailinglist, $SubscribersList;

            $success = false;
            $errors = false;

            $fielddiv = esc_html($_GET['fielddiv']);
            $fieldname = esc_html($_GET['fieldname']);

            if (!empty($_POST)) {
                check_ajax_referer($this -> sections -> lists . '_save');

                $_POST['Mailinglist']['privatelist'] = "N";

                if ($Mailinglist -> save($_POST)) {
                    $success = true;
                    $insertid = $Mailinglist -> insertid;
                } else {
                    $errors = $Mailinglist -> errors;
                }

                $checklist = '';
                if ($mailinglists = $Mailinglist -> select(true)) {
                    foreach ($mailinglists as $id => $title) {
                        $Db -> model = $SubscribersList -> model;
                        $checklist .= '<label><input ' . ($id == $insertid || (!empty($_POST['Subscriber']['mailinglists']) && in_array($id, $_POST['Subscriber']['mailinglists'])) ? 'checked="checked"' : '') . ' type="checkbox" name="' . $fieldname . '[]" value="' . esc_attr($id) . '" id="checklist' . $id . '" /> ' . __($title) . ' (' . $Db -> count(array('list_id' => $id)) . ' ' . __('subscribers', 'wp-mailinglist') . ')</label><br/>';
                    }
                }

                $output = array(
                    'success'			=>	$success,
                    'errors'			=>	$errors,
                    'blocks'			=>	array(
                        'form'				=>	$this -> render('mailinglists' . DS . 'save-ajax', array('fielddiv' => $fielddiv, 'fieldname' => $fieldname, 'ajax' => true, 'errors' => $errors, 'success' => $success), false, 'admin'),
                        'checklist'			=>	$checklist,
                    ),
                );

                echo json_encode($output);
            } else {
                $this -> render('mailinglists' . DS . 'save-ajax', array('fielddiv' => $fielddiv, 'fieldname' => $fieldname), true, 'admin');
            }

            exit();
            die();
        }


	    function ajax_categories_by_post_type() {

		    // Verify nonce and permissions.
		    check_ajax_referer( 'get_post_type_categories_nonce', 'security' );
		    if ( ! current_user_can( 'edit_posts' ) ) {
			    wp_die( __( 'You do not have permission', 'wp-mailinglist' ) );
		    }

		    header( 'Content-Type: application/json' );

		    // Get and sanitize the post type from POST or REQUEST.
		    $post_type = '';
		    if ( ! empty( $_POST['post_type'] ) ) {
			    $post_type = sanitize_text_field( wp_unslash( $_POST['post_type'] ) );
                if('shop_order_placehold' === $_POST['post_type'])
                {
	                $post_type = 'post';
                }
		    } elseif ( ! empty( $_REQUEST['post_type'] ) ) {
			    $post_type = sanitize_text_field( wp_unslash( $_REQUEST['post_type'] ) );
			    if('shop_order_placehold' === $_REQUEST['post_type'])
			    {
				    $post_type = 'post';
			    }
		    }

		    if ( empty( $post_type ) ) {
			    wp_send_json_error( 'No post type provided' );
		    }

		    // Determine the taxonomy to use.
		    if ( 'post' === $post_type ) {
			    // For standard posts, use the built-in "category"
			    $taxonomy = 'category';
		    } else {
			    // For custom post types, get all registered taxonomies as objects.
			    $taxonomies = get_object_taxonomies( $post_type, 'objects' );
			    $taxonomy   = '';

			    // Choose one taxonomy – for example, the first one that is hierarchical.
			    if ( ! empty( $taxonomies ) ) {
				    foreach ( $taxonomies as $tax_obj ) {
					    if ( ! empty( $tax_obj->hierarchical ) ) {
						    $taxonomy = $tax_obj->name;
						    break;
					    }
				    }
			    }

			    // Fallback: if no hierarchical taxonomy is found, return an empty list.
			    if ( empty( $taxonomy ) ) {
				    wp_send_json( array( array( 'text' => __( '- Select -', 'wp-mailinglist' ), 'value' => false ) ) );
			    }
		    }

		    // Retrieve the terms for the selected taxonomy.
		    // For the 'post' post type, you might want to include even empty categories.
		    $args = array(
			    'taxonomy'   => $taxonomy,
			    'hide_empty' => ( 'post' === $post_type ? false : true ),
		    );
		    $terms = get_terms( $args );

		    // Build the listbox values array.
		    $values = array();
		    $values[] = array( 'text' => __( '- Select -', 'wp-mailinglist' ), 'value' => false );
		    if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) {
			    foreach ( $terms as $term ) {
				    $values[] = array( 'text' => $term->name, 'value' => $term->term_id );
			    }
		    }

		    wp_send_json( $values );
		    exit();
	    }

	    function ajax_posts_by_category() {

		    // Verify the nonce.
		    check_ajax_referer( 'posts_by_category', 'security' );

		    // Check user capabilities.
		    if ( ! current_user_can( 'edit_posts' ) ) {
			    wp_die( __( 'You do not have permission', 'wp-mailinglist' ) );
		    }

		    header( 'Content-Type: application/json' );

		    $posts_by_category = array();

		    // Set up default query arguments.
		    $arguments = array(
			    'numberposts' => -1,
			    'orderby'     => 'post_date',
			    'order'       => 'DESC',
			    'post_type'   => 'post',
			    'post_status' => 'publish',
		    );

		    // Sanitize and retrieve the category (term) ID.
		    $category_id = 0;
		    if ( ! empty( $_REQUEST['cat_id'] ) && intval( $_REQUEST['cat_id'] ) > 0 ) {
			    // Use absint to ensure it is an integer.
			    $category_id = absint( $_REQUEST['cat_id'] );
		    }

		    // Sanitize the post type if provided.
		    if ( ! empty( $_REQUEST['post_type'] ) ) {
			    $arguments['post_type'] = sanitize_text_field( $_REQUEST['post_type'] );
			    if('shop_order_placehold' === $_REQUEST['post_type'])
			    {
				    $arguments['post_type'] = 'post';
			    }
		    }

		    // Handle language, if provided.
		    if ( ! empty( $_REQUEST['language'] ) ) {
			    $language = sanitize_text_field( $_REQUEST['language'] );
			    $arguments['lang'] = $language;
			    $arguments['language'] = $language;
			    // This method is assumed to be defined in your class.
			    $this->language_set( $language );
		    }

		    // Build the tax_query if a valid category_id is provided.
		    if ( $category_id ) {

			    $tax_query = array();

			    // If the post type is 'post', use the default 'category' taxonomy.
			    if ( 'post' === $arguments['post_type'] ) {

				    // Double-check that the term exists in the category taxonomy.
				    $term = get_term_by( 'id', $category_id, 'category' );
				    if ( $term && ! is_wp_error( $term ) ) {
					    $tax_query[] = array(
						    'taxonomy' => 'category',
						    'field'    => 'term_id',
						    'terms'    => $category_id,
					    );
				    }

			    } else {
				    // For custom post types, get all registered taxonomies as objects.
				    $taxonomies = get_object_taxonomies( $arguments['post_type'], 'objects' );

				    if ( ! empty( $taxonomies ) ) {
					    foreach ( $taxonomies as $tax_obj ) {
						    // Check if the term exists in this taxonomy.
						    $term = get_term_by( 'id', $category_id, $tax_obj->name );
						    if ( $term && ! is_wp_error( $term ) ) {
							    $tax_query[] = array(
								    'taxonomy' => $tax_obj->name,
								    'field'    => 'term_id',
								    'terms'    => $category_id,
							    );
						    }
					    }
				    }
			    }

			    // If we found at least one taxonomy where the term exists, add the tax_query.
			    if ( ! empty( $tax_query ) ) {
				    // Use OR so that posts from any matching taxonomy are returned.
				    $arguments['tax_query'] = array_merge( array( 'relation' => 'OR' ), $tax_query );
			    }
		    }

		    // Optional: Log arguments for debugging (remove or comment out on production).

		    // Retrieve the posts.
		    if ( $posts = get_posts( $arguments ) ) {
			    // Add a default prompt option.
			    $posts_by_category[] = array(
				    'text'  => __( '- Select -', 'wp-mailinglist' ),
				    'value' => false,
			    );

			    foreach ( $posts as $post ) {
				    // Use your language methods if needed.
				    if ( $this->language_do() ) {
					    $posts_by_category[] = array(
						    'text'  => __( $this->language_use( $_REQUEST['language'], $post->post_title, false ) ),
						    'value' => $post->ID,
					    );
				    } else {
					    $posts_by_category[] = array(
						    'text'  => __( $post->post_title ),
						    'value' => $post->ID,
					    );
				    }
			    }
		    } else {
			    // No posts found for the given term.
			    $posts_by_category[] = array(
				    'text'  => __( 'No posts in this category', 'wp-mailinglist' ),
				    'value' => false,
			    );
		    }

		    // Output the JSON response.
		    echo json_encode( $posts_by_category );
		    exit();
	    }

        function ajax_getposts() {

            check_ajax_referer('getposts', 'security');

            if (!current_user_can('edit_posts')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            if (!empty($_POST)) {
                $arguments = array(
                    'numberposts'			=>	"-1",
                    'orderby'				=>	"post_title",
                    'order'					=>	"ASC",
                    'post_type'				=>	"post",
                    'post_status'			=>	"publish",
                );

                if (!empty($_POST['posttype'])) { $arguments['post_type'] = sanitize_text_field($_POST['posttype']); }
                if (!empty($_POST['category'])) { $arguments['category'] = sanitize_text_field($_POST['category']); }
                if (!empty($_POST['number'])) { $arguments['numberposts'] = sanitize_text_field($_POST['number']); }
                if (!empty($_POST['orderby'])) { $arguments['orderby'] = sanitize_text_field($_POST['orderby']); }
                if (!empty($_POST['order'])) { $arguments['order'] = sanitize_text_field($_POST['order']); }

                if (!empty($_POST['language'])) {
                    $language = sanitize_text_field($_POST['language']);
                    $arguments['lang'] = $language;
                    $arguments['language'] = $language;
                    $this -> language_set($language);
                }

                if ($posts = get_posts($arguments)) {
                    ?>

                    <ul class="insertfieldslist">
                        <li>
                                    <span class="insertfieldslistcheckbox">
                                        <input onclick="jqCheckAll(this, false, 'insertposts');" type="checkbox" name="checkall_insertposts" id="checkall_insertposts" value="1" />
                                    </span>
                            <span class="">
                                        <label for="checkall_insertposts" style="font-weight:bold;"><?php _e('Select All', 'wp-mailinglist'); ?></label>
                                    </span>
                        </li>
                        <?php foreach ($posts as $post) : ?>
                            <li>
                                <span class="insertfieldslistcheckbox"><input type="checkbox" name="insertposts[]" value="<?php echo esc_attr($post -> ID); ?>" id="insertposts_<?php echo $post -> ID; ?>" /></span>

                                <?php if ($this -> language_do()) : ?>
                                    <span class="insertfieldslistbutton"><a href="" onclick="insert_post('<?php echo $post -> ID; ?>', false); return false;" class="button button-secondary press" title="<?php echo esc_attr(wp_unslash($this -> language_use($_POST['language'], $post -> post_title, false))); ?>"><?php echo $this -> language_use($_POST['language'], $post -> post_title, false); ?></a></span>
                                <?php else : ?>
                                    <span class="insertfieldslistbutton"><a href="" onclick="insert_post('<?php echo $post -> ID; ?>', false); return false;" class="button button-secondary press" title="<?php echo esc_attr(wp_unslash(__($post -> post_title))); ?>"><?php echo __($post -> post_title); ?></a></span>
                                <?php endif; ?>
                            </li>
                        <?php endforeach; ?>
                    </ul>

                    <span>
                                <button onclick="insert_single_multiple();" class="button button-primary" type="button" name="insert" value="1">
                                    <i class="fa-solid fa-check fa-fw"></i> <?php _e('Insert Selected', 'wp-mailinglist'); ?>
                                </button>
                            </span>

                    <?php
                }
            }

            exit();
            die();
        }

        function ajax_newsletters_get_template($template_id = null) {
            check_ajax_referer('newsletters_get_template', 'security');

            $template_id = sanitize_text_field(isset($_POST['template_id']) ? $_POST['template_id'] : '');
            if (!empty($template_id)) {
                global $wpdb;

                $query = "SELECT * FROM `" . $wpdb -> prefix . 'wpmlthemes' . "` WHERE `id` = '" . esc_sql($template_id) . "'";

                $query_hash = md5($query);


                if ($template = $wpdb -> get_row($query)) {
                    $template_content = $template -> content;
                    header('Content-Type: text/html');
                    $content = ob_get_clean();
                    echo do_shortcode(wp_unslash($template_content));
                    exit();
                }


            }
            return '';
            // return wpml_get_themes($conditions, $fields, $order, $limit);
        }

        function ajax_api_newkey() {

            check_ajax_referer('api_newkey', 'security');

            if (!current_user_can('newsletters_settings_api')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            $key = strtoupper(md5(current_time('timestamp')));
            $this -> update_option('api_key', $key);
            echo esc_html($key);

            exit();
            die();
        }

        function ajax_welcomestats() {

            check_ajax_referer('welcomestats', 'security');

            if (!current_user_can('newsletters_welcome')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $wpdb, $Html, $Subscriber, $Email, $Bounce, $Unsubscribe;

            $chart = (empty($_GET['chart'])) ? "bar" : esc_html($_GET['chart']);
            $type = (empty($_GET['type'])) ? "days" : esc_html($_GET['type']);
            $fromdate = (empty($_GET['from'])) ? date_i18n("Y-m-d", strtotime($Html -> gen_date("Y-m-d H:i:s", false, false, true) . " -13 days")) : sanitize_text_field(wp_unslash(esc_sql($_GET['from'])));
			$todate = (empty($_GET['to'])) ? date_i18n("Y-m-d") : sanitize_text_field(wp_unslash(esc_sql($_GET['to'])));
			$history_id = (empty($_GET['history_id'])) ? false : sanitize_text_field(wp_unslash(esc_sql($_GET['history_id'])));


            $history_condition = (!empty($history_id)) ? " `history_id` = '" . $history_id . "' AND" : false;
            $history_condition = apply_filters('newsletters_stats_history_condition', $history_condition, $type, $fromdate, $todate, $history_id);
            $subscribers_condition = apply_filters('newsletters_stats_subscriber_condition', false, $type, $fromdate, $todate, $history_id);
            $clicks_condition = apply_filters('newsletters_stats_clicks_condition', false, $type, $fromdate, $todate, $history_id);
            $emails_condition = apply_filters('newsletters_stats_emails_condition', false, $type, $fromdate, $todate, $history_id);
            $bounces_condition = apply_filters('newsletters_stats_bounces_condition', false, $type, $fromdate, $todate, $history_id);
            $unsubscribes_condition = apply_filters('newsletters_stats_unsubscribes_condition', false, $type, $fromdate, $todate, $history_id);
            $reads_condition = apply_filters('newsletters_stats_reads_condition', false, $type, $fromdate, $todate, $history_id);

            switch ($type) {
                case 'years'			:
                    // Subscribers
                    $query = "SELECT COUNT(`id`) as `subscriberscount`, DATE(`created`) as `date` FROM `" . $wpdb -> prefix . $Subscriber -> table . "` WHERE CAST(`created` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY YEAR(`created`)";
                    $records = $wpdb -> get_results($query);

                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $subscribers_array[date_i18n("Y", strtotime($record -> date))] = $record -> subscriberscount;

                            if (empty($y_max) || (!empty($y_max) && $record -> subscriberscount > $y_max)) {
                                $y_max = $record -> subscriberscount;
                            }
                        }
                    }

                    // Clicks
                    $query = "SELECT COUNT(DISTINCT CASE WHEN user_id != 0 THEN user_id ELSE subscriber_id END) as `clickscount`, DATE(`created`) as `date` FROM `" . $wpdb -> prefix . $this -> Click() -> table . "` WHERE" . $history_condition . " CAST(`created` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY DATE(`created`)";
                    $records = $wpdb -> get_results($query);

                    $clicks_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $clicks_array[date_i18n("Y", strtotime($record -> date))] = $record -> clickscount;

                            if (empty($y_max) || (!empty($y_max) && $record -> clickscount > $y_max)) {
                                $y_max = $record -> clickscount;
                            }
                        }
                    }

                    // Emails Sent
                    $query = "SELECT COUNT(id) as `emailscount`, DATE(created) as `date` FROM " . $wpdb -> prefix . $Email -> table . " WHERE" . $history_condition . " CAST(`created` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY YEAR(`created`)";
                    $records = $wpdb -> get_results($query);

                    $emails_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $emails_array[date_i18n("Y", strtotime($record -> date))] = $record -> emailscount;

                            if (empty($y_right_max) || (!empty($y_right_max) && $record -> emailscount > $y_right_max)) {
                                $y_right_max = $record -> emailscount;
                            }
                        }
                    }

                    // Bounces
                    $query = "SELECT COUNT(id) as `bounces`, SUM(count) as `bouncecount`, DATE(modified) as `date` FROM " . $wpdb -> prefix . $Bounce -> table . " WHERE" . $history_condition . " CAST(`modified` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY YEAR(`modified`)";
                    $records = $wpdb -> get_results($query);

                    $bounces_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $bounces_array[date_i18n("Y", strtotime($record -> date))] = $record -> bouncecount;

                            if (empty($y_right_max) || (!empty($y_right_max) && $record -> bouncecount > $y_right_max)) {
                                $y_right_max = $record -> bouncecount;
                            }
                        }
                    }

                    // Unsubscribes
                    $query = "SELECT COUNT(`id`) AS `unsubscribescount`, DATE(`modified`) AS `date` FROM `" . $wpdb -> prefix . $Unsubscribe -> table . "` WHERE" . $history_condition . " CAST(`modified` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY YEAR(`modified`)";
                    $records = $wpdb -> get_results($query);

                    $unsubscribes_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $unsubscribes_array[date_i18n("Y", strtotime($record -> date))] = $record -> unsubscribescount;

                            if (empty($y_right_max) || (!empty($y_right_max) && $record -> unsubscribescount > $y_right_max)) {
                                $y_right_max = $record -> unsubscribescount;
                            }
                        }
                    }

                    // Reads
                    $query = "SELECT COUNT(id) as `readscount`, DATE(read_date) as `date` FROM " . $wpdb -> prefix . $Email -> table . " WHERE" . $history_condition . " `read` = 'Y' AND CAST(`read_date` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY DATE(`read_date`)";
                    $records = $wpdb -> get_results($query);

                    $reads_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $reads_array[date_i18n("Y", strtotime($record -> date))] = $record -> readscount;

                            if (empty($y_right_max) || (!empty($y_right_max) && $record -> emailscount > $y_right_max)) {
                                $y_right_max = $record -> readscount;
                            }
                        }
                    }

                    $dates_data = array();
                    $subscribers_data = array();
                    $emails_data = array();
                    $bounces_data = array();
                    $unsubscribes_data = array();
                    $reads_data = array();

                    $fromstamp = strtotime($fromdate);
                    $tostamp = strtotime($todate);
                    $yearsdiff = round(abs($tostamp - $fromstamp) / (60 * 60 * 24 * 365));

                    $d = new DateTime($todate);
                    $d -> modify("next year");

                    $j = 0;
                    for ($i = 0; $i <= $yearsdiff; $i++) {
                        $d -> modify("previous year");
                        //$datestring = date_i18n("Y", strtotime("-" . $i . " years", $tostamp));
                        //$dates_data[$j] = date_i18n("Y", strtotime("-" . $i . " years", $tostamp));
                        $datestring = $d -> format("Y");
                        $dates_data[$j] = $d -> format("Y");

                        if (empty($history_id)) {
                            if (!empty($subscribers_array[$datestring])) {
                                $subscribers_data[$j] = $subscribers_array[$datestring];
                            } else {
                                $subscribers_data[$j] = 0;
                            }
                        }

                        if (!empty($clicks_array[$datestring])) {
                            $clicks_data[$j] = $clicks_array[$datestring];
                        } else {
                            $clicks_data[$j] = 0;
                        }

                        if (!empty($emails_array[$datestring])) {
                            $emails_data[$j] = $emails_array[$datestring];
                        } else {
                            $emails_data[$j] = 0;
                        }

                        if (!empty($bounces_array[$datestring])) {
                            $bounces_data[$j] = $bounces_array[$datestring];
                        } else {
                            $bounces_data[$j] = 0;
                        }

                        if (!empty($unsubscribes_array[$datestring])) {
                            $unsubscribes_data[$j] = $unsubscribes_array[$datestring];
                        } else {
                            $unsubscribes_data[$j] = 0;
                        }

                        if (!empty($reads_array[$datestring])) {
                            $reads_data[$j] = $reads_array[$datestring];
                        } else {
                            $reads_data[$j] = 0;
                        }

                        $j++;
                    }

                    $unsubscribes_data = array_reverse($unsubscribes_data);
                    $subscribers_data = array_reverse($subscribers_data);
                    $bounces_data = array_reverse($bounces_data);
                    $clicks_data = array_reverse($clicks_data);
                    $emails_data = array_reverse($emails_data);
                    $dates_data = array_reverse($dates_data);
                    $reads_data = array_reverse($reads_data);
                    break;
                case 'months'			:
                    $query = "SELECT COUNT(`id`) as `subscriberscount`, DATE(`created`) as `date` FROM `" . $wpdb -> prefix . $Subscriber -> table . "` WHERE CAST(`created` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY MONTH(`created`)";
                    $records = $wpdb -> get_results($query);

                    $subscribers_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $subscribers_array[date_i18n("mY", strtotime($record -> date))] = $record -> subscriberscount;

                            if (empty($y_max) || (!empty($y_max) && $record -> subscriberscount > $y_max)) {
                                $y_max = $record -> subscriberscount;
                            }
                        }
                    }

                    // Clicks
                    $query = "SELECT COUNT(DISTINCT CASE WHEN user_id != 0 THEN user_id ELSE subscriber_id END) as `clickscount`, DATE(`created`) as `date` FROM `" . $wpdb -> prefix . $this -> Click() -> table . "` WHERE" . $history_condition . " CAST(`created` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY DATE(`created`)";
                    $records = $wpdb -> get_results($query);

                    $clicks_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $clicks_array[date_i18n("mY", strtotime($record -> date))] = $record -> clickscount;

                            if (empty($y_max) || (!empty($y_max) && $record -> clickscount > $y_max)) {
                                $y_max = $record -> clickscount;
                            }
                        }
                    }

                    // Emails Sent
                    $query = "SELECT COUNT(id) as `emailscount`, DATE(created) as `date` FROM " . $wpdb -> prefix . $Email -> table . " WHERE" . $history_condition . " CAST(`created` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY MONTH(`created`)";
                    $records = $wpdb -> get_results($query);

                    $emails_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $emails_array[date_i18n("mY", strtotime($record -> date))] = $record -> emailscount;

                            if (empty($y_right_max) || (!empty($y_right_max) && $record -> emailscount > $y_right_max)) {
                                $y_right_max = $record -> emailscount;
                            }
                        }
                    }

                    // Bounces
                    $query = "SELECT COUNT(id) as `bounces`, SUM(count) as `bouncecount`, DATE(modified) as `date` FROM " . $wpdb -> prefix . $Bounce -> table . " WHERE" . $history_condition . " CAST(`modified` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY MONTH(`modified`)";
                    $records = $wpdb -> get_results($query);

                    $bounces_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $bounces_array[date_i18n("mY", strtotime($record -> date))] = $record -> bouncecount;

                            if (empty($y_right_max) || (!empty($y_right_max) && $record -> bouncecount > $y_right_max)) {
                                $y_right_max = $record -> bouncecount;
                            }
                        }
                    }

                    // Unsubscribes
                    $query = "SELECT COUNT(`id`) AS `unsubscribescount`, DATE(`modified`) AS `date` FROM `" . $wpdb -> prefix . $Unsubscribe -> table . "` WHERE" . $history_condition . " CAST(`modified` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY MONTH(`modified`)";
                    $records = $wpdb -> get_results($query);

                    $unsubscribes_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $unsubscribes_array[date_i18n("mY", strtotime($record -> date))] = $record -> unsubscribescount;

                            if (empty($y_right_max) || (!empty($y_right_max) && $record -> unsubscribescount > $y_right_max)) {
                                $y_right_max = $record -> unsubscribescount;
                            }
                        }
                    }

                    // Reads
                    $query = "SELECT COUNT(id) as `readscount`, DATE(read_date) as `date` FROM " . $wpdb -> prefix . $Email -> table . " WHERE" . $history_condition . " `read` = 'Y' AND CAST(`read_date` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY DATE(`read_date`)";
                    $records = $wpdb -> get_results($query);

                    $reads_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $reads_array[date_i18n("mY", strtotime($record -> date))] = $record -> readscount;

                            if (empty($y_right_max) || (!empty($y_right_max) && $record -> emailscount > $y_right_max)) {
                                $y_right_max = $record -> readscount;
                            }
                        }
                    }

                    $dates_data = array();
                    $subscribers_data = array();
                    $emails_data = array();
                    $bounces_data = array();
                    $unsubscribes_data = array();
                    $reads_data = array();

                    $fromstamp = strtotime($fromdate);
                    $tostamp = strtotime($todate);
                    $monthsdiff = round(abs($tostamp - $fromstamp) / 2628000);

                    $d = new DateTime($todate);
                    //$d -> modify("next month");

                    $j = 0;
                    for ($i = 0; $i <= $monthsdiff; $i++) {
                        $d -> modify("previous month");

                        //$datestring = date_i18n("mY", strtotime("-" . $i . " month", $tostamp), false);
                        //$dates_data[$j] = date_i18n("F Y", strtotime("-" . $i . " month", $tostamp), false);
                        $datestring = $d -> format("mY");
                        $dates_data[$j] = $d -> format("F Y");

                        if (empty($history_id)) {
                            if (!empty($subscribers_array[$datestring])) {
                                $subscribers_data[$j] = $subscribers_array[$datestring];
                            } else {
                                $subscribers_data[$j] = 0;
                            }
                        }

                        if (!empty($clicks_array[$datestring])) {
                            $clicks_data[$j] = $clicks_array[$datestring];
                        } else {
                            $clicks_data[$j] = 0;
                        }

                        if (!empty($emails_array[$datestring])) {
                            $emails_data[$j] = $emails_array[$datestring];
                        } else {
                            $emails_data[$j] = 0;
                        }

                        if (!empty($bounces_array[$datestring])) {
                            $bounces_data[$j] = $bounces_array[$datestring];
                        } else {
                            $bounces_data[$j] = 0;
                        }

                        if (!empty($unsubscribes_array[$datestring])) {
                            $unsubscribes_data[$j] = $unsubscribes_array[$datestring];
                        } else {
                            $unsubscribes_data[$j] = 0;
                        }

                        if (!empty($reads_array[$datestring])) {
                            $reads_data[$j] = $reads_array[$datestring];
                        } else {
                            $reads_data[$j] = 0;
                        }

                        $j++;
                    }

                    $unsubscribes_data = array_reverse($unsubscribes_data);
                    $subscribers_data = array_reverse($subscribers_data);
                    $bounces_data = array_reverse($bounces_data);
                    $clicks_data = array_reverse($clicks_data);
                    $emails_data = array_reverse($emails_data);
                    $dates_data = array_reverse($dates_data);
                    $reads_data = array_reverse($reads_data);
                    break;
                case 'days'				:
                default 				:

                    // Subscribers
                    $query = "SELECT COUNT(`id`) as `subscriberscount`, DATE(`created`) as `date` FROM `" . $wpdb -> prefix . $Subscriber -> table . "` WHERE " . $subscribers_condition . " CAST(`created` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY DATE(`created`)";
                    $records = $wpdb -> get_results($query);

                    $subscribers_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $subscribers_array[date_i18n("dmY", strtotime($record -> date))] = $record -> subscriberscount;

                            if (empty($y_max) || (!empty($y_max) && $record -> subscriberscount > $y_max)) {
                                $y_max = $record -> subscriberscount;
                            }
                        }
                    }

                    // Clicks
                    $query = "SELECT COUNT(DISTINCT CASE WHEN user_id != 0 THEN user_id ELSE subscriber_id END) as `clickscount`, DATE(`created`) as `date` FROM `" . $wpdb -> prefix . $this -> Click() -> table . "` WHERE " . $clicks_condition . " " . $history_condition . " CAST(`created` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY DATE(`created`)";
                    $records = $wpdb -> get_results($query);

                    $clicks_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $clicks_array[date_i18n("dmY", strtotime($record -> date))] = $record -> clickscount;

                            if (empty($y_max) || (!empty($y_max) && $record -> clickscount > $y_max)) {
                                $y_max = $record -> clickscount;
                            }
                        }
                    }

                    // Emails Sent
                    $query = "SELECT COUNT(id) as `emailscount`, DATE(created) as `date` FROM " . $wpdb -> prefix . $Email -> table . " WHERE " . $emails_condition . " " . $history_condition . " CAST(`created` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY DATE(`created`)";
                    $records = $wpdb -> get_results($query);

                    $emails_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $emails_array[date_i18n("dmY", strtotime($record -> date))] = $record -> emailscount;

                            if (empty($y_right_max) || (!empty($y_right_max) && $record -> emailscount > $y_right_max)) {
                                $y_right_max = $record -> emailscount;
                            }
                        }
                    }

                    // Bounces
                    $query = "SELECT COUNT(id) as `bounces`, SUM(count) as `bouncecount`, DATE(modified) as `date` FROM " . $wpdb -> prefix . $Bounce -> table . " WHERE " . $bounces_condition . " " . $history_condition . " CAST(`modified` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY DATE(`modified`)";
                    $records = $wpdb -> get_results($query);

                    $bounces_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $bounces_array[date_i18n("dmY", strtotime($record -> date))] = $record -> bouncecount;

                            if (empty($y_right_max) || (!empty($y_right_max) && $record -> bouncecount > $y_right_max)) {
                                $y_right_max = $record -> bouncecount;
                            }
                        }
                    }

                    // Unsubscribes
                    $query = "SELECT COUNT(`id`) AS `unsubscribescount`, DATE(`modified`) AS `date` FROM `" . $wpdb -> prefix . $Unsubscribe -> table . "` WHERE " . $unsubscribes_condition . " " . $history_condition . " CAST(`modified` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY DATE(`modified`)";
                    $records = $wpdb -> get_results($query);

                    $unsubscribes_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $unsubscribes_array[date_i18n("dmY", strtotime($record -> date))] = $record -> unsubscribescount;

                            if (empty($y_right_max) || (!empty($y_right_max) && $record -> unsubscribescount > $y_right_max)) {
                                $y_right_max = $record -> unsubscribescount;
                            }
                        }
                    }

                    // Reads
                    $query = "SELECT COUNT(id) as `readscount`, DATE(read_date) as `date` FROM " . $wpdb -> prefix . $Email -> table . " WHERE " . $reads_condition . " " . $history_condition . " `read` = 'Y' AND CAST(`read_date` AS DATE) BETWEEN '" . $fromdate . "' AND '" . $todate . "' GROUP BY DATE(`read_date`)";
                    $records = $wpdb -> get_results($query);

                    $reads_array = array();
                    if (!empty($records)) {
                        foreach ($records as $record) {
                            $reads_array[date_i18n("dmY", strtotime($record -> date))] = $record -> readscount;

                            if (empty($y_right_max) || (!empty($y_right_max) && $record -> emailscount > $y_right_max)) {
                                $y_right_max = $record -> readscount;
                            }
                        }
                    }

                    $dates_data = array();
                    $subscribers_data = array();
                    $clicks_data = array();
                    $emails_data = array();
                    $bounces_data = array();
                    $unsubscribes_data = array();
                    $reads_data = array();

                    $fromstamp = strtotime($fromdate);
                    $tostamp = strtotime($todate);
                    $daysdiff = round(abs($tostamp - $fromstamp) / 86400);

                    $d = new DateTime($todate);
                    $d -> modify("next day");

                    $j = 0;
                    for ($i = 0; $i <= $daysdiff; $i++) {
                        //$datestring = date_i18n("m-d", strtotime("-" . $i . " days", $tostamp));
                        //$dates_data[$j] = date_i18n("M j", strtotime("-" . $i . " days", $tostamp));
                        $d -> modify("previous day");
                        $datestring = $d -> format("dmY");
                        $dates_data[$j] = $d -> format("M j");

                        if (empty($history_id)) {
                            if (!empty($subscribers_array[$datestring])) {
                                $subscribers_data[$j] = $subscribers_array[$datestring];
                            } else {
                                $subscribers_data[$j] = 0;
                            }
                        }

                        if (!empty($clicks_array[$datestring])) {
                            $clicks_data[$j] = $clicks_array[$datestring];
                        } else {
                            $clicks_data[$j] = 0;
                        }

                        if (!empty($emails_array[$datestring])) {
                            $emails_data[$j] = $emails_array[$datestring];
                        } else {
                            $emails_data[$j] = 0;
                        }

                        if (!empty($bounces_array[$datestring])) {
                            $bounces_data[$j] = $bounces_array[$datestring];
                        } else {
                            $bounces_data[$j] = 0;
                        }

                        if (!empty($unsubscribes_array[$datestring])) {
                            $unsubscribes_data[$j] = $unsubscribes_array[$datestring];
                        } else {
                            $unsubscribes_data[$j] = 0;
                        }

                        if (!empty($reads_array[$datestring])) {
                            $reads_data[$j] = $reads_array[$datestring];
                        } else {
                            $reads_data[$j] = 0;
                        }

                        $j++;
                    }

                    $unsubscribes_data = array_reverse($unsubscribes_data);
                    $subscribers_data = array_reverse($subscribers_data);
                    $clicks_data = array_reverse($clicks_data);
                    $bounces_data = array_reverse($bounces_data);
                    $emails_data = array_reverse($emails_data);
                    $dates_data = array_reverse($dates_data);
                    $reads_data = array_reverse($reads_data);
            }

            $data = array();
            $data['labels'] = $dates_data;
            $data['datasets'] = array();

            $data['datasets'][] = array(
                'label'					=>	__('Emails Sent', 'wp-mailinglist'),
                'backgroundColor'		=>	"#4D5360",
                'fill'					=>	false,
                'highlightBackground'			=>	"#616774",
                'borderColor'			=>	"#4D5360",
                'pointColor'			=>	"#4D5360",
                'pointBorderColor'		=>	"#4D5360",
                'pointHighlightBackground'	=>	"#616774",
                'pointHighlightBorder'	=>	"#616774",
                'data'					=>	$emails_data,
            );

            if (empty($history_id)) {
                $data['datasets'][] = array(
                    'label'					=>	__('Subscribers', 'wp-mailinglist'),
                    'backgroundColor'		=>	"#4679bf", //"#46BFBD",
                    'fill'					=>	false,
                    'highlightBackground'			=>	"#4679bf", //"#5AD3D1",
                    'borderColor'			=>	"#4679bf",
                    'pointColor'			=>	"#4679bf",
                    'pointBorderColor'		=>	"#4679bf",
                    'pointHighlightBackground'	=>	"#4679bf",
                    'pointHighlightBorder'	=>	"#4679bf",
                    'data'					=>	$subscribers_data,
                );
            }

            $data['datasets'][] = array(
                'label'					=>	__('Clicks', 'wp-mailinglist'),
                'backgroundColor'		=>	"#949FB1",
                'fill'					=>	false,
                'highlightBackground'			=>	"#A8B3C5",
                'borderColor'			=>	"#949FB1",
                'pointColor'			=>	"#949FB1",
                'pointBorderColor'		=>	"#949FB1",
                'pointHighlightBackground'	=>	"#A8B3C5",
                'pointHighlightBorder'	=>	"#A8B3C5",
                'data'					=>	$clicks_data,
            );

            $data['datasets'][] = array(
                'label'					=>	__('Unsubscribes', 'wp-mailinglist'),
                'backgroundColor'		=>	"#FDB45C",
                'fill'					=>	false,
                'highlightBackground'			=>	"#FFC870",
                'borderColor'			=>	"#FDB45C",
                'pointColor'			=>	"#FDB45C",
                'pointBorderColor'		=>	"#FDB45C",
                'pointHighlightBackground'	=>	"#FFC870",
                'pointHighlightBorder'	=>	"#FFC870",
                'data'					=>	$unsubscribes_data,
            );

            $data['datasets'][] = array(
                'label'					=>	__('Reads', 'wp-mailinglist'),
                'backgroundColor'		=>	"#46BFBD",
                'fill'					=>	false,
                'highlightBackground'			=>	"#5AD3D1",
                'borderColor'			=>	"#46BFBD",
                'pointColor'			=>	"#46BFBD",
                'pointBorderColor'		=>	"#46BFBD",
                'pointHighlightBackground'	=>	"#5AD3D1",
                'pointHighlightBorder'	=>	"#5AD3D1",
                'data'					=>	$reads_data,
            );

            $data['datasets'][] = array(
                'label'					=>	__('Bounces', 'wp-mailinglist'),
                'backgroundColor'		=>	"#F7464A",
                'fill'					=>	false,
                'highlightBackground'			=>	"#FF5A5E",
                'borderColor'			=>	"#F7464A",
                'pointColor'			=>	"#F7464A",
                'pointBorderColor'		=>	"#F7464A",
                'pointHighlightBackground'	=>	"#FF5A5E",
                'pointHighlightBorder'	=>	"#FF5A5E",
                'data'					=>	$bounces_data,
            );

            echo json_encode($data);

            exit();
            die();
        }

        /* Forms Ajax */
        function ajax_forms_createform() {
            global $Field, $wpdb;

            $ajax = false;
            $success = false;
            $errors = false;

            if (!empty($_POST)) {
                check_ajax_referer($this -> sections -> forms . '_createform');

                if (current_user_can('newsletters_forms')) {
                    $subscribeform = $this -> Subscribeform();
                    if ( $subscribeform -> save($_POST[ $subscribeform -> model])) {
                        $object_manual = $this -> getobject($subscribeform -> model);
                        $query = "SELECT MAX(id) FROM  ". $wpdb -> prefix . "wpmlforms ; ";
                        $insertID = $wpdb->get_var( $query );


                        $success = true;
                        $insertid =  $insertID;
                        $this -> Subscribeform() -> insertid = $insertID;
                        // Create the default email address and mailing list fields
                        $emailfield = $Field -> email_field();
                        $fieldform_data = array(
                            'id'						=>	false,
                            'form_id'					=>	$insertid,
                            'field_id'					=>	$emailfield -> id,
                            'order'						=>	1,
                            'label'						=>	false,
                            'caption'					=>	false,
                            'placeholder'				=>	false,
                            'required'					=>	1,
                        );

                        $this -> FieldsForm() -> save($fieldform_data);

                        $listfield = $Field -> list_field();
                        $fieldform_data = array(
                            'id'						=>	false,
                            'form_id'					=>	$insertid,
                            'field_id'					=>	$listfield -> id,
                            'order'						=>	2,
                            'label'						=>	false,
                            'caption'					=>	false,
                            'placeholder'				=>	false,
                            'required'					=>	1,
                        );

                        $this -> FieldsForm() -> save($fieldform_data);
                    }

                    $ajax = true;
                    $errors = $this -> Subscribeform() -> errors;
                } else {
                    $errors[] = __('You do not have permission', 'wp-mailinglist');
                }
            }

            $this -> render('forms' . DS . 'createform', array('ajax' => $ajax, 'success' => $success, 'errors' => $errors), true, 'admin');

            exit();
            die();
        }

        function ajax_forms_addfield() {

            check_ajax_referer('forms_addfield', 'security');

            if (!current_user_can('newsletters_forms')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $wpdb, $Db, $Field;
            $Db -> model = $Field -> model;
            $field = $Db -> find(array('id' => sanitize_text_field($_POST['id'])));

            global $Metabox;
            $form_field = new stdClass();
            $form_field -> field = $field;
            $form_field -> field_id = $field -> id;
            $metabox = array('args' => array('form_field' => $form_field));

            ob_start();
            $Metabox -> forms_field(false, $metabox);
            $content = ob_get_clean();
            $this -> render('forms' . DS . 'field', array('field' => $field, 'form_field' => $form_field, 'content' => $content), true, 'admin');

            exit();
            die();
        }

        function ajax_forms_deletefield() {

            check_ajax_referer('forms_deletefield', 'security');

            if (!current_user_can('newsletters_forms')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            if (!empty($_POST['field_id']) && !empty($_POST['form_id'])) {
                $this -> FieldsForm() -> delete_all(array('field_id' => sanitize_text_field($_POST['field_id']), 'form_id' => sanitize_text_field($_POST['form_id'])));
            }

            exit();
            die();
        }

        function ajax_setvariables() {

            check_ajax_referer('setvariables', 'security');

            if (!current_user_can('newsletters_send')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            $this -> render('setvariables', array('noinsert' => true), true, 'admin');

            exit();
            die();
        }

        function ajax_change_themefolder() {

            check_ajax_referer('change_themefolder', 'security');

            if (!current_user_can('newsletters_settings')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            $message = false;
            if (!empty($_POST['themefolder'])) {
                $this -> update_option('theme_folder', sanitize_text_field($_POST['themefolder']));
                $this -> delete_all_cache('all');
                $this -> theme_folder_functions($_POST['themefolder']);
                $message = __('Theme folder has been changed, please reconfigure styles/scripts below', 'wp-mailinglist');
            }

            $this -> render('settings' . DS . 'defaultscriptsstyles', array('successmessage' => $message), true, 'admin');

            exit();
            die();
        }

        function ajax_delete_option() {

            check_ajax_referer('delete_option', 'security');

            if (!current_user_can('newsletters_fields')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            $success = false;

            if (!empty($_REQUEST['id'])) {
                $id = sanitize_text_field($_REQUEST['id']);
                if ($this -> Option() -> delete($id)) {
                    $success = true;
                }
            }

            echo $success;

            exit();
            die();
        }

        function ajax_pause_queue() {

            check_ajax_referer('pause_queue', 'security');

            if (!current_user_can('newsletters_queue')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            $success = false;

            if (!empty($_POST['status'])) {
                $status = sanitize_text_field($_POST['status']);

                if ($this -> update_option('queue_status', $status)) {
                    $success = true;
                    $this -> delete_option('hidemessage_queue_status');
                }
            }

            echo $success;

            exit();
            die();
        }

        function ajax_executemultiple() {

            check_ajax_referer('executemultiple', 'security');

            if (!current_user_can('newsletters_history')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $wpdb, $Html, $Db, $Subscriber, $HistoriesAttachment;
            $subscribers = (object) stripslashes_deep($_REQUEST['subscribers']);

            if (!empty($subscribers)) {
                $historyquery = "SELECT id, message, subject FROM " . $wpdb -> prefix . $this -> History() -> table . " WHERE id = '" . esc_sql($_REQUEST['history_id']) . "' LIMIT 1";
                $history = $wpdb -> get_row($historyquery);

                if (!empty($history)) {
                    foreach ($subscribers as $subscriber_request) {
                        $subscriber_request = (object)$subscriber_request;

                        if (!empty($subscriber_request -> user_id)) {
                            $user = $this -> userdata($subscriber_request -> user_id);
                            $email = $user -> user_email;
                            $eunique = $Html -> eunique($user, $history -> id);
                            $subscriber = false;
                        } else {
                            $subscriber = $Subscriber -> get($subscriber_request -> id, false);
                            $email = $subscriber -> email;
                            $subscriber -> mailinglist_id = $subscriber_request -> mailinglist_id;
                            $subscriber -> mailinglists = $Subscriber -> mailinglists($subscriber -> id, $subscriber_request -> mailinglists);
                            $eunique = $Html -> eunique($subscriber, $history -> id);
                            $user = false;
                        }

                        $content = $history -> message;
                        $subject = wp_unslash($history -> subject);
                        $history_id = sanitize_text_field($_REQUEST['history_id']);
                        $post_id = sanitize_text_field($_REQUEST['post_id']);
                        $theme_id = sanitize_text_field($_REQUEST['theme_id']);
                        $shortlinks = true;

                        $newattachments = array();
                        $Db -> model = $HistoriesAttachment -> model;
                        if ($attachments = $Db -> find_all(array('history_id' => $history_id))) {
                            foreach ($attachments as $attachment) {
                                $newattachments[] = array(
                                    'id'					=>	$attachment -> id,
                                    'title'					=>	$attachment -> title,
                                    'filename'				=>	$attachment -> filename,
                                );
                            }
                        }

                        $message = $this -> render_email('send', array('message' => $content, 'subject' => $subject, 'subscriber' => $subscriber, 'history_id' => $history_id, 'post_id' => $post_id, 'eunique' => $eunique), false, $this -> htmltf($subscriber -> format), true, $theme_id, true);

                        if ($this -> execute_mail($subscriber, $user, $subject, $message, $newattachments, $history_id, $eunique, true, "newsletter")) {
                            $success = "Y<|>" . $email . "<|>" . __('Success', 'wp-mailinglist') . "<||>";
                        } else {
                            global $mailerrors;
                            $success = "N<|>" . $email . "<|>" . strip_tags($mailerrors) . "<||>";
                        }

                        echo $success;
                    }
                } else {
                    $success = "N<|>" . $email . "<|>" . __('History email could not be read', 'wp-mailinglist') . "<||>";
                    echo $success;
                }
            } else {
                $success = "N<|>" . $email . "<|>" . __('No data was posted', 'wp-mailinglist') . "<||>";
                echo $success;
            }

            exit();
            die();
        }

        function ajax_queuemultiple() {

            check_ajax_referer('queuemultiple', 'security');

            if (!current_user_can('newsletters_queue')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $wpdb, $Html, $Db, $Subscriber, $HistoriesAttachment;

            $subscribers = stripslashes_deep($_REQUEST['subscribers']);

            $this -> qp_reset_data();

            if (!empty($subscribers)) {
                $historyquery = "SELECT id, message, subject FROM " . $wpdb -> prefix . $this -> History() -> table . " WHERE id = '" . esc_sql($_REQUEST['history_id']) . "' LIMIT 1";
                $history = $wpdb -> get_row($historyquery);

                if (!empty($history)) {
                    foreach ($subscribers as $subscriber_request) {
                        $subscriber_request = (object) $subscriber_request;

                        $content = $history -> message;
                        $subject = wp_unslash($history -> subject);
                        $history_id = sanitize_text_field($_REQUEST['history_id']);
                        $post_id = sanitize_text_field($_REQUEST['post_id']);
                        $theme_id = sanitize_text_field($_REQUEST['theme_id']);
                        $senddate = sanitize_text_field($_REQUEST['senddate']);
                        $shortlinks = true;

                        $newattachments = array();
                        $Db -> model = $HistoriesAttachment -> model;
                        if ($attachments = $Db -> find_all(array('history_id' => $history_id))) {
                            foreach ($attachments as $attachment) {
                                $newattachments[] = array(
                                    'id'					=>	$attachment -> id,
                                    'title'					=>	$attachment -> title,
                                    'filename'				=>	$attachment -> filename,
                                );
                            }
                        }

                        if (!empty($subscriber_request -> user_id)) {
                            $subscriber = false;
                            $user = $this -> userdata($subscriber_request -> user_id);
                            $email = $user -> user_email;

                            $queue_process_data = array(
                                'user_id'					=>	$user -> ID,
                                'subject'					=>	$subject,
                                //'message'					=>	$content,
                                'attachments'				=>	$newattachments,
                                'post_id'					=>	$post_id,
                                'history_id'				=>	$history_id,
                                'theme_id'					=>	$theme_id,
                                'senddate'					=>	$senddate,
                            );
                        } else {
                            $user = false;
                            $subscriber = $Subscriber -> get($subscriber_request -> id, false);
                            $email = $subscriber -> email;
                            $subscriber -> mailinglist_id = $subscriber_request -> mailinglist_id;
                            $subscriber -> mailinglists = $Subscriber -> mailinglists($subscriber -> id, $subscriber_request -> mailinglists);

                            $queue_process_data = array(
                                'subscriber_id'				=>	$subscriber -> id,
                                'subject'					=>	$subject,
                                //'message'					=>	$content,
                                'attachments'				=>	$newattachments,
                                'post_id'					=>	$post_id,
                                'history_id'				=>	$history_id,
                                'theme_id'					=>	$theme_id,
                                'senddate'					=>	$senddate,
                            );
                        }

                        $this -> queue_process_1 -> push_to_queue($queue_process_data);
                        $success = "Y<|>" . $email . "<|>" . __('Success', 'wp-mailinglist') . "<||>";
                        echo $success;
                    }
                } else {
                    $success = "N<|>" . $email . "<|>" . __('History email could not be read', 'wp-mailinglist') . "<||>";
                    echo $success;
                }
            } else {
                $success = "N<|>" . $email . "<|>" . __('No data was posted', 'wp-mailinglist') . "<||>";
                echo $success;
            }

            $this -> qp_save();
            $this -> qp_dispatch();

            exit();
            die();
        }

        function ajax_exportmultiple() {

            check_ajax_referer('exportmultiple', 'security');

            if (!current_user_can('newsletters_importexport')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $Html;
            $exportfilename = sanitize_text_field($_REQUEST['exportfile']);
            $exportfilepath = $Html -> uploads_path() . '/' . $this -> plugin_name . '/export/';
            $exportfilefull = $exportfilepath . $exportfilename;

            if ($fp = fopen($exportfilefull, "a")) {
                $csvdelimiter = $this -> get_option('csvdelimiter');
                $delimiter = (empty($_REQUEST['delimiter'])) ? $csvdelimiter : sanitize_text_field($_REQUEST['delimiter']);
                $headings = $_REQUEST['headings'];
                $subscribers = stripslashes_deep($_REQUEST['subscribers']);

                $headings_keys = array();
                foreach ($headings as $hkey => $hval) {
                    $headings_keys[$hkey] = '';
                }

                if (!empty($subscribers)) {
                    foreach ($subscribers as $subscriber) {
                        $subscriber = array_merge($headings_keys, $subscriber);

                        if (!empty($subscriber)) {
                            fputcsv($fp, $subscriber, $delimiter, '"');
                        }

                        echo $subscriber['email'] . "<|>";
                    }
                }

                fclose($fp);
            }

            exit();
            die();
        }

        function ajax_dismissed_notice() {

            check_ajax_referer('dismissed_notice', 'security');

            if (current_user_can('newsletters_welcome')) {
                // Pick up the notice "type" - passed via jQuery (the "data-notice" attribute on the notice)
                $type = sanitize_text_field($_REQUEST['type']);
                // Store it in the options table
                $this -> update_option('dismissed-' . $type, true);
            }

            exit();
            die();
        }

        function ajax_dismiss_forever_notice() {

            check_ajax_referer('dismissed_notice', 'security');

            if (current_user_can('newsletters_welcome')) {
                // Pick up the notice "type" - passed via jQuery (the "data-notice" attribute on the notice)
                $type = sanitize_text_field(wp_unslash($_REQUEST['type']));
                // Store it in the options table

                $this -> update_option('dismiss_forever-showmessage_ratereview', true);
            }

            exit();
            die();
        }


        function ajax_subscribe() {
            global $Subscriber, $Mailinglist, $Html;

            check_ajax_referer('subscribe', 'security');


            //Apply a filter so users can code whether the subscribers should be added or not after a honeypot chekc
            $honeypot_filter = apply_filters( 'wpml_subscriber_add_new', true );
            if (!$honeypot_filter )
            {
                exit ();
                die();
            }


            // No current_user_can required, open on the front-end

            $widget_id = esc_html($_GET['widget_id']);
            $number = esc_html($_GET['number']);
            $instance = $this -> widget_instance($number);

            $newinstance = null;

            if (isset($_POST['instance']) && is_array($_POST['instance'])) {
                $newinstance = esc_html( $_POST['instance']);
            }

            if (!empty($newinstance)) {
                $r = wp_parse_args($newinstance, $instance);
                $instance = $r;
            }

            $action = ($this -> language_do()) ? $this -> language_converturl($_SERVER['REQUEST_URI'], $instance['language']) : $_SERVER['REQUEST_URI'];
            $action = $Html -> retainquery($this -> pre . 'method=optin', $action) . '#' . $widget_id;

            if ($subscriber_id = $Subscriber -> optin($_POST)) {
                // This is not a subscribe form
                if (empty($_POST['form_id'])) {


                    if (!empty($instance['acknowledgement']) && WPMAIL() -> language_do()) {
                        $language_live =   WPMAIL() -> language_current();
                        $instance['acknowledgement'] = WPMAIL() -> language_use($language_live, $instance['acknowledgement']);
                    }

                    echo '<div class="newsletters-acknowledgement">' . wpautop(__($instance['acknowledgement'])) . '</div>';

                    if ($paidlist_id = $Mailinglist -> has_paid_list(sanitize_text_field($_POST['list_id']))) {
                        $subscriber = $Subscriber -> get($subscriber_id, false);
                        $paidlist = $Mailinglist -> get($paidlist_id, false);
                        $this -> redirect($Html -> retainquery('method=paidsubscription&subscriber_id=' . $subscriber -> id . '&list_id=' . $paidlist -> id . '&extend=0', $this -> get_managementpost(true)), false, false, true);
                    }

                    if ($this -> get_option('subscriberedirect') == "Y") {
                        $subscriberedirecturl = $this -> get_option('subscriberedirecturl');

                        if (!empty($_POST['list_id']) && (!is_array($_POST['list_id']) || count($_POST['list_id']) == 1)) {
                            if ($subscribelist = $Mailinglist -> get((int) $_POST['list_id'][0])) {
                                if (!empty($subscribelist -> subredirect)) {
                                    $subscriberedirecturl = __($subscribelist -> subredirect);
                                }
                            }
                        }

                        $this -> redirect($subscriberedirecturl, false, false, true);
                    }
                    // This is a subscribe form
                } elseif (!empty($_POST['form_id'])) {
                    if ($form = $this -> Subscribeform() -> find(array('id' => (int) $_POST['form_id']))) {
                        $subscriber = $Subscriber -> get($subscriber_id, false);

                        if ($paidlist_id = $Mailinglist -> has_paid_list((int) $_POST['list_id'])) {
                            $paidlist = $Mailinglist -> get($paidlist_id, false);
                            $this -> redirect($Html -> retainquery('method=paidsubscription&subscriber_id=' . $subscriber -> id . '&list_id=' . $paidlist -> id . '&extend=0', $this -> get_managementpost(true)), false, false, true);
                        }

                        if (empty($form -> confirmationtype) || $form -> confirmationtype == "message") {
                            if (!empty($form -> confirmation_message)) {
                                echo '<div class="newsletters-acknowledgement">' . wpautop(__($form -> confirmation_message)) . '</div>';
                            }
                        } elseif ($form -> confirmationtype == "redirect") {
                            if (!empty($form -> confirmation_redirect)) {
                                $redirect = do_shortcode(wp_unslash(__($form -> confirmation_redirect)));
                                $redirect = $this -> process_set_variables($subscriber, false, $redirect);
                                $this -> redirect($redirect, false, false, true);
                            }
                        }
                    }
                }
            } else {
                $errors = $Subscriber -> errors;

                if (empty($_POST['form_id'])) {
                    $this -> render('widget', array('action' => $action, 'widget' => $_GET['widget'], 'errors' => $errors, 'args' => $widget, 'instance' => $instance, 'widget_id' => $widget_id, 'number' => $number), true, 'default');
                } elseif (!empty($_POST['form_id'])) {
                    if ($form = $this -> Subscribeform() -> find(array('id' => (int) $_POST['form_id']))) {
                        $this -> render('subscribe', array('form' => $form, 'errors' => $Subscriber -> errors), true, 'default');
                    }
                }
            }

            exit();
            die();
        }

        function ajax_template_iframe() {

            check_ajax_referer('template_iframe', 'security');

            if (!current_user_can('newsletters_templates')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $Db;
            $id = sanitize_text_field($_REQUEST['id']);
            $template = $this -> Template() -> find(array('id' => $id));
            $this -> render('templates' . DS . 'iframe', array('template' => $template), true, 'admin');

            exit();
            die();
        }

        function getbodyandcss($html = null) {
            ob_start();
            $content = '';

            // Check if DOMDocument class exists
            if (!class_exists('DOMDocument')) {
                return $html;
            }

            $d = new DOMDocument;
            $mock = new DOMDocument;
            $d -> loadHTML('<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />' . wp_unslash($html));

            foreach ($d -> getElementsByTagName('style') as $style) {
                $mock -> appendChild($mock -> importNode($style, true));
            }

            $body = $d -> getElementsByTagName('body') -> item(0);
            foreach ($body -> childNodes as $child) {
                $mock -> appendChild($mock -> importNode($child, true));
            }

            $html = $mock -> saveHTML();
            echo $html;

            $output = ob_get_clean();
            return wp_unslash($output);
        }

        function ajax_form_preview() {

            check_ajax_referer('form_preview', 'security');

            if (!current_user_can('newsletters_forms')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            $id = sanitize_text_field($_GET['id']);
            if (!empty($id)) {
                if ($form = $this -> Subscribeform() -> find(array('id' => $id))) {

                    if (!empty($_REQUEST['saveform'])) {
                        if($this -> language_isenabled()) {
                            $languagefields = array('title', 'buttontext', 'confirmation_message', 'confirmation_redirect', 'styling_beforeform', 'styling_afterform', 'etsubject_confirm', 'etmessage_confirm');

                            foreach ($_REQUEST as $pkey => $pval) {
                                // Language fields
                                if (!empty($pval) && in_array($pkey, $languagefields)) {
                                    switch ($key) {
                                        default 					:
                                            if (is_array($pval) && array_filter($pval)) {
                                                $_REQUEST[$pkey] = $this -> language_join($pval);
                                            } else {
                                                $_REQUEST[$pkey] = false;
                                            }
                                            break;
                                    }
                                }
                            }

                            $form = wp_parse_args($_REQUEST, (array) $form);
                            $form = (object) $form;
                        }
                    }

                    ?>

                    <html>
                    <head>
                        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
                        <title><?php echo urldecode(esc_html(isset($_GET['title']) ? $_GET['title'] : '')); ?></title>

                        <?php wp_head(); ?>
                    </head>
                    <body style="background:none;">
                    <div class="entry">
                        <?php $this -> render('subscribe', array('form' => $form), true, 'default'); ?>
                    </div>
                    <div style="display:none;">
                        <?php wp_footer(); ?>
                    </div>
                    </body>
                    </html>

                    <?php
                } else {
                    echo '<p class="newsletters_error">' . __('Form could not be loaded', 'wp-mailinglist') . '</p>';
                }
            } else {
                echo '<p class="newsletters_error">' . __('No form was specified', 'wp-mailinglist') . '</p>';
            }

            exit();
            die();
        }

        function widget_object() {
            $widget = new Newsletters_Widget();
            return $widget;
        }

        function widget_settings() {
            $widget = new Newsletters_Widget();
            $settings = $widget -> get_settings();
            return $settings;
        }

        function widget_instance($number = null, $atts = array()) {
            if (!empty($number)) {
                $widget = new Newsletters_Widget();
                $settings = $widget -> get_settings();

                if (!empty($settings[$number])) {
                    $instance = $settings[$number];

                    if ($this -> language_do()) {
                        $instance['lang'] = $this -> language_current();
                    }
                } else {
                    if ($embed = $this -> get_option('embed')) {
                        $instance = wp_parse_args($atts, $embed);

                        if (empty($instance['list'])) {
                            if ($instance['type'] == "list") {
                                $instance['list'] = $instance['id'];
                            } else {
                                $instance['list'] = $instance['type'];
                                if (empty($instance['lists']) && !empty($instance['id'])) {
                                    $instance['lists'] = $instance['id'];
                                }
                            }
                        }

                        unset($instance['type']);
                        unset($instance['id']);
                    }
                }

                return $instance;
            }

            return false;
        }

        function ajax_getlistfields() {

            check_ajax_referer('refreshfields', 'security');

            // No current_user_can required, this is open to all roles and non-users on the front-end

            global $wpdb, $FieldsList, $Subscriber;
            $widget_id = sanitize_text_field($_GET['widget_id']);
            $instance = map_deep($_POST['instance'], 'sanitize_text_field');

            $Subscriber -> data = $_POST;

            echo '<div class="newsletters-new-fields">';

            if ($fields = $FieldsList -> fields_by_list($_POST['list_id'], "order", "ASC")) {
                foreach ($fields as $field) {
                    $this -> render_field($field -> id, true, $widget_id, true, true, $instance);
                }
            }

            echo '</div>';

            ?>

            <script type="text/javascript">
                jQuery(document).ready(function() {
                    if (jQuery.isFunction(jQuery.fn.select2)) {
                        jQuery('.newsletters select').select2();
                    }

                    jQuery('#<?php echo (int) $widget_id; ?>-form .newsletters-list-checkbox').on('click', function() { newsletters_refreshfields('<?php echo esc_html($widget_id); ?>'); });
                    jQuery('#<?php echo (int) $widget_id; ?>-form .newsletters-list-select').on('change', function() { newsletters_refreshfields('<?php echo esc_html($widget_id); ?>'); });
                });
            </script>

            <?php

            exit();
            die();
        }

        function ajax_testsettings() {

            check_ajax_referer('testsettings', 'security');

            if (!current_user_can('newsletters_settings')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $Subscriber, $Html;
            $errors = array();
            $success = false;

            if (!empty($_GET['init']) && !empty($_POST)) {
                foreach ($_POST as $pkey => $pval) {
                    $this -> update_option($pkey, $pval);

                    switch ($pkey) {
                        case 'smtpfromname'			:
                        case 'smtpfrom'				:
                        case 'excerpt_more'			:
                            if ($this -> language_do()) {
                                $this -> update_option($pkey, $this -> language_join($pval));
                            } else {
                                $this -> update_option($pkey, $pval);
                            }
                            break;
                    }
                }
            }

            if (empty($_GET['init']) && !empty($_POST)) {
                if (empty($_POST['testemail'])) { $errors[] = __('Please fill in an email address', 'wp-mailinglist'); }
                elseif (!$Subscriber -> email_validate($_POST['testemail'])) { $errors[] = __('Please fill in a valid email address', 'wp-mailinglist'); }
                if (empty($_POST['subject'])) { $errors[] = __('Please fill in a subject', 'wp-mailinglist'); }
                if (empty($_POST['message'])) { $errors[] = __('Please fill in a message', 'wp-mailinglist'); }

                if (empty($errors)) {
                    $email = $_POST['testemail'];

                    if (!$subscriber_id = $Subscriber -> email_exists($email)) {
                        $subscriber_data = array('email' => $email);
                        $Subscriber -> save($subscriber_data, false);
                        $subscriber_id = $Subscriber -> insertid;
                    }

                    $subscriber = $Subscriber -> get($subscriber_id, false);

                    $subject = wp_kses_post(wp_unslash($_POST['subject']));
                    $message = wp_kses_post(wp_unslash($_POST['message']));
                    $message = $this -> render_email('send', array('message' => $message, 'subject' => $subject, 'subscriber' => $subscriber), false, true, true, false, true);

                    $attachments = false;
                    if (!empty($_POST['testattachment']) && $_POST['testattachment'] == 1) {
                        $attachments = array(
                            array(
                                'title'					=>	__('Test Attachment', 'wp-mailinglist'),
                                'filename'				=>	$this -> plugin_base() . DS . 'images' . DS . 'testattachment.png',
                            )
                        );
                    }

                    $eunique = $Html -> eunique($subscriber, false, 'test');

                    if ($this -> execute_mail($subscriber, false, $subject, $message, $attachments, false, $eunique, false, "testing")) {
                        $success = true;
                        $errors[] = __('Email was successfully sent, your settings are working!', 'wp-mailinglist');
                    } else {
                        global $mailerrors;
                        $errors[] = $mailerrors;
                    }
                }
            }

            echo '<div id="testsettingswrapper">';
            $this -> render('testsettings', array('errors' => $errors, 'success' => $success), true, 'admin');
            echo '</div>';

            exit();
            die();
        }

        function ajax_mailapi_mandrill_keytest() {

            check_ajax_referer('mailapi_mandrill_keytest', 'security');

            if (!current_user_can('newsletters_settings')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            require_once($this -> plugin_base() . DS . 'vendors' . DS . 'mailapis' . DS . 'mandrill' . DS . 'Mandrill.php');

            try {
                $mandrill = new Mandrill($_POST['key']);
                $result = $mandrill -> users -> ping();
                echo '<span class="newsletters_success"><i class="fa-solid fa-check"></i></span>';
            } catch(Mandrill_Error $e) {
                echo '<span class="newsletters_error"><i class="fa-solid fa-xmark"></i> ' . $e -> getMessage() . '</span>';
            }

            exit(); die();
        }

        function ajax_mailapi_mailgun_action() {

            check_ajax_referer('mailapi_mailgun_action', 'security');

            if (!current_user_can('newsletters_settings')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            if (!empty($_POST['ac'])) {
                $mailgun_apikey = sanitize_text_field($_POST['key']);
                $mailgun_domain = sanitize_text_field($_POST['domain']);
                $mailgun_region = (empty($_POST['region']) || $_POST['region'] == "US") ? 'https://api.mailgun.net' : 'https://api.eu.mailgun.net';

                require($this -> plugin_base() . DS . 'vendor' . DS . 'autoload.php');
                //$mailgun = new Mailgun\Mailgun($mailgun_apikey);
                $mg = Mailgun\Mailgun::create($mailgun_apikey, $mailgun_region);

                switch ($_POST['ac']) {
                    case 'verify'					:
                        try {
                            $result = $mg -> events() -> get($mailgun_domain);
                            $this -> render_message(__('MailGun API key works', 'wp-mailinglist'), false, false);

                        } catch (Exception $e) {
                            $this -> render_error($e -> getMessage(), false, false);
                        }
                        break;
                    case 'checkdomains'				:
                        try {
                            $result = $mg -> domains() -> index();

                            $items = $result -> getDomains();
                            if (!empty($items)) {
                                echo '<p>';
                                foreach ($items as $item) {
                                    $class = (!empty($item -> getState()) && $item -> getState() == "active") ? 'newsletters_success' : 'newsletters_warning';
                                    echo '<span class="' . $class . '">' . $item -> getName() . '</span><br/>';
                                }
                                echo '</p>';
                            } else {
                                $this -> render_error(__('No domains available.', 'wp-mailinglist'), false, false);
                            }
                        } catch (Exception $e) {
                            $this -> render_error($e -> getMessage(), false, false);
                        }
                        break;
                    case 'adddomain'				:
                        try {
                            $password = wp_generate_password(12, false, false);
                            $result = $mg -> domains() -> create($mailgun_domain, $password);

                            $this -> render_message($result -> getMessage(), false, false);
                        } catch (Exception $e) {
                            $this -> render_error($e -> getMessage(), false, false);
                        }
                        break;
                    case 'events'					:
                        try {
                            $result = $mg -> events() -> get($mailgun_domain);
                        } catch (Exception $e) {
                            $this -> render_error($e -> getMessage(), false, false);
                        }
                        break;
                    case 'stats'					:
                        try {
                            $result = $mg -> stats() -> total($mailgun_domain);
                        } catch (Exception $e) {
                            $this -> render_error($e -> getMessage(), false, false);
                        }
                        break;
                }
            }

            exit();
            die();
        }

        function ajax_mailapi_amazonses_action() {

            check_ajax_referer('mailapi_amazonses_action', 'security');

            if (!current_user_can('newsletters_settings')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            $success = false;
            $message = false;
            $error = false;

            if (!empty($_REQUEST['ac'])) {
                require($this -> plugin_base() . DS . 'vendor' . DS . 'autoload.php');

                $signature_version = SimpleEmailService::REQUEST_SIGNATURE_V4;
                $ses = new SimpleEmailService(sanitize_text_field($_REQUEST['key']), sanitize_text_field($_REQUEST['secret']), 'email.' . sanitize_text_field($_REQUEST['region']) . '.amazonaws.com', false, $signature_version);

                switch ($_REQUEST['ac']) {
                    case 'verifyemail'				:
                        $email = __($this -> get_option('smtpfrom'));
                        if ($result = $ses -> verifyEmailAddress($email)) {
                            $success = true;
                            $message = sprintf(__('Email address %s has been verified.', 'wp-mailinglist'), $email);
                        } else {
                            //failed
                            $error = __('Email could not be verified', 'wp-mailinglist');
                        }
                        break;
                    case 'getverifiedemails'		:
                        if ($result = $ses -> listVerifiedEmailAddresses()) {
                            $success = true;

                            $message = __('Currently verified email addresses:', 'wp-mailinglist');
                            $message .= '<ul class="newsletters_success">';
                            foreach ($result['Addresses'] as $address) {
                                $message .= '<li>' . $address . '</li>';
                            }
                            $message .= '</ul>';
                        } else {
                            $error = __('Could not get list of verified email addresses.', 'wp-mailinglist');
                        }
                        break;
                    case 'getsendquota'				:
                        if ($result = $ses -> getSendQuota()) {
                            $success = true;
                            $message = '';
                            $message .= sprintf(__('Max 24 Hour Send: %s', 'wp-mailinglist'), $result['Max24HourSend']);
                            $message .= '<br/>';
                            $message .= sprintf(__('Max Send Rate: %s', 'wp-mailinglist'), $result['MaxSendRate']);
                            $message .= '<br/>';
                            $message .= sprintf(__('Sent in Last 24 Hours: %s', 'wp-mailinglist'), $result['SentLast24Hours']);
                        } else {
                            $error = __('Could not get send quota.', 'wp-mailinglist');
                        }
                        break;
                }
            }

            if (!empty($success)) {
                echo '<p class="newsletters_success">' . $message . '</p>';
            } elseif (!empty($error)) {
                echo '<p class="newsletters_error">' . $error . '</p>';
            }

            exit(); die();
        }

        function ajax_dkimwizard() {

            check_ajax_referer('dkimwizard', 'security');

            if (!current_user_can('newsletters_settings')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            switch ($_POST['goto']) {
                case 'step2'				:
                    $this -> render('dkim' . DS . 'step2', array('domain' => $_POST['domain'], 'selector' => $_POST['selector'], 'public' => $_POST['public'], 'private' => $_POST['private']), true, 'admin');
                    break;
                case 'step3'				:
                    $this -> render('dkim' . DS . 'step3', array('domain' => $_POST['domain'], 'selector' => $_POST['selector'], 'public' => $_POST['public'], 'private' => $_POST['private']), true, 'admin');
                    break;
                case 'step1'				:
                default 					:
                    require_once $this -> plugin_base() . DS . 'vendors' . DS . 'dkim' . DS . 'Crypt' . DS . 'RSA.php';
                    $rsa = new Crypt_RSA();
                    $keys = $rsa -> createKey();

                    $this -> render('dkim' . DS . 'step1', array('domain' => $_POST['domain'], 'selector' => $_POST['selector'], 'public' => $keys['publickey'], 'private' => $keys['privatekey']), true, 'admin');
                    break;
            }

            exit();
            die();
        }

        function get_pop_status() {
            $pop_status = false;

            require($this -> plugin_base() . DS . 'vendor' . DS . 'autoload.php');

            $type = $this -> get_option('bouncepop_type');
            $host = $this -> get_option('bouncepop_host');
            $user = $this -> get_option('bouncepop_user');
            $pass = $this -> get_option('bouncepop_pass');
            $port = $this -> get_option('bouncepop_port');
            $bouncepop_prot = $this -> get_option('bouncepop_prot');
            $ssl = (empty($bouncepop_prot)) ? false : (($bouncepop_prot == "ssl") ? true : false);

            try {
                $mailbox = new PhpImap\Mailbox('{' . $host . ':' . $port . '/' . $type . ((!empty($ssl)) ? '/ssl' : '') . '/novalidate-cert}INBOX', $user, $pass, false);

                try {

                    $status = $mailbox -> checkMailbox();
                    $pop3_status = sprintf(__('There are %s emails in the mailbox', 'wp-mailinglist'), $status -> Nmsgs);

                } catch (Exception $e) {
                    $pop3_status = $e -> getMessage();
                }
            } catch (Exception $e) {
                $pop3_status = $e -> getMessage();
            }

            return $pop3_status;
        }

        function ajax_autocomplete_users() {

            check_ajax_referer('autocomplete_users', 'security');

            if (!current_user_can('list_users')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            $args = array(
                'search'				=>	'*' . sanitize_text_field($_REQUEST['q']) . '*',
            );

            $user_query = new WP_User_Query($args);
            $users = $user_query -> get_results();

            $json = json_encode(array());

            if (!empty($users)) {
                $titles = array();
                $t = 0;
                foreach ($users as $user) {
                    $titles[$t]['id'] = $user -> ID;
                    $titles[$t]['text'] = $user -> display_name;
                    $t++;
                }

                $json = json_encode($titles);
            }

            echo $json;

            exit();
            die();
        }

        function ajax_autocomplete_histories() {

            check_ajax_referer('autocomplete_histories', 'security');

            if (!current_user_can('newsletters_history')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $Db;

            $conditions = array();
            if (!empty($_REQUEST['q'])) {
                $conditions['subject'] = "LIKE '%" . esc_sql($_REQUEST['q']) . "%'";
            }

            if ($histories = $this -> History() -> find_all($conditions)) {
                if (!empty($histories)) {
                    $t = 0;

                    foreach ($histories as $history) {
                        $titles[$t]['id'] = $history -> id;
                        $titles[$t]['text'] = __($history -> subject);
                        $t++;
                    }

                    $json = json_encode($titles);
                }
            }

            echo $json;

            exit();
            die();
        }

        function ajax_testbouncesettings() {

            check_ajax_referer('testbouncesettings', 'security');

            if (!current_user_can('newsletters_settings')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            $success = false;
            $message = '';
            $error = '';

            if (!extension_loaded('imap')) {
                $error = __('The PHP IMAP extension is not installed/active. Ask your hosting provider to enable it in order to use POP/IMAP bounce handling.', 'wp-mailinglist');
                $this -> render('testbouncesettings', array('success' => $success, 'message' => $message, 'error' => $error), true, 'admin');
                exit();
                die();
            }

            require($this -> plugin_base() . DS . 'vendor' . DS . 'autoload.php');

            $type = (empty($_POST['type'])) ? 'imap' : $_POST['type'];
            $host = sanitize_text_field($_POST['host']);
            $user = sanitize_text_field($_POST['user']);
            $pass = sanitize_text_field($_POST['pass']);
            $port = sanitize_text_field($_POST['port']);
            $ssl = (empty($_POST['prot'])) ? false : (($_POST['prot'] == "ssl") ? true : false);

            try {
                $mailbox = new PhpImap\Mailbox('{' . $host . ':' . $port . '/' . $type . ((!empty($ssl)) ? '/ssl' : '') . '/novalidate-cert}INBOX', $user, $pass, false);

                try {

                    $status = $mailbox -> checkMailbox();
                    $message = sprintf(__('There are %s emails in the mailbox', 'wp-mailinglist'), $status -> Nmsgs);
                    $success = true;

                    // Read all messaged into an array:
                    /*$mailsIds = $mailbox->searchMailbox('ALL');
                            if(!$mailsIds) {
                                die('Mailbox is empty');
                            }

                            // Get the first message and save its attachment(s) to disk:
                            $mail = $mailbox->getMail($mailsIds[0]);

                            var_dump($mail);
                            echo "\n\n\n\n\n";
                            var_dump($mail->getAttachments());*/

                } catch (Exception $e) {
                    $error = $e -> getMessage();
                }
            } catch (Exception $e) {
                $error = $e -> getMessage();
            }

            $this -> render('testbouncesettings', array('success' => $success, 'message' => $message, 'error' => $error), true, 'admin');

            exit();
            die();
        }

        function ajax_deletecontentarea() {

            check_ajax_referer('deletecontentarea', 'security');

            if (!current_user_can('newsletters_history')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            if (!empty($_POST['number']) && !empty($_POST['history_id'])) {
                $this -> Content() -> delete_all(array('number' => sanitize_text_field($_POST['number']), 'history_id' => sanitize_text_field($_POST['history_id'])));
            }

            exit();
            die();
        }

        function ajax_order_fields() {

            check_ajax_referer('order_fields', 'security');

            if (!current_user_can('newsletters_fields')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $Db, $FieldsList, $Field;

            if (!empty($_REQUEST)) {
                if (!empty($_REQUEST['fields'])) {
                    foreach ($_REQUEST['fields'] as $order => $field_id) {
                        $Db -> model = $Field -> model;
                        $Db -> save_field('order', $order, array('id' => $field_id));

                        $Db -> model = $FieldsList -> model;
                        $Db -> save_field('order', $order, array('field_id' => $field_id));
                    }

                    _e('Custom fields order has been successfully saved', 'wp-mailinglist');
                } else {
                    _e('No fields are available', 'wp-mailinglist');
                }
            } else {
                _e('No data posted', 'wp-mailinglist');
            }

            exit();
            die();
        }

        function ajax_themeedit() {

            check_ajax_referer('themeedit', 'security');

            if (!current_user_can('newsletters_themes')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $Db, $Theme;
            $success = false;
            $errors = array();

            if (!empty($_REQUEST)) {
                $id = sanitize_text_field($_REQUEST['id']);
                if (!empty($id)) {
                    if (!empty($_REQUEST['Theme'])) {
                        $Db -> model = $Theme -> model;
                        if ($Db -> save($_REQUEST)) {
                            $success = true;
                        } else {
                            $errors = $Theme -> errors;
                        }
                    }

                    $Db -> model = $Theme -> model;
                    $Db -> find(array('id' => $id));
                    $Theme -> data -> paste = $Theme -> data -> content;
                } else {
                    $errors[] = __('No template was specified', 'wp-mailinglist');
                }
            } else {
                $errors[] = __('No data was specified', 'wp-mailinglist');
            }

            $this -> render('themes' . DS . 'save-ajax', array('success' => $success, 'errors' => $errors), true, 'admin');

            exit();
            die();
        }

        function ajax_newsletters_autosave_blockeditor() {

            check_ajax_referer('newsletters_autosave_blockeditor', 'security');

            if (!current_user_can('edit_posts')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $wpdb, $Db, $Html, $Subscriber, $newsletters_presend, $newsletters_emailraw;

            $post_data = $_POST;
            $post_id = $post_data['ID'] = (!empty($_POST['post_ID'])) ? (int) sanitize_text_field($_POST['post_ID']) : false;
            $post = get_post($post_id);
            $save_newsletter = $this -> save_newsletter($post_id, $post, true);

            $history_id = get_post_meta($post_id, '_newsletters_history_id', true);
            if (!empty($history_id)) {
                $_GET['id'] = $history_id;
                $success = false;
                $error = false;

                ob_start();

                $subject = wp_kses_post(wp_unslash($_POST['post_title']));
                $content = wp_kses_post(wp_unslash($_POST['content']));

                $preview = $this -> ajax_historyiframe(true, false, $history_id, false);
                $textpreview = $this -> ajax_historyiframe(true, true, $history_id, false);
                $process = ob_get_clean();

            } else {
                $error = __('No history ID was found', 'wp-mailinglist');
                $success = false;
            }

            $response = array(
                'success'				=>	$success,
                'error'					=>	$error,
                'history_id'			=>	$history_id,
                'post_id'				=>	$post_id,
                'parts'					=>	array(
                    'preview'				=>	array(
                        'url'					=>	add_query_arg(array('newsletters_method' => "newsletter", 'id' => $history_id), home_url()),
                        'html'					=>	$preview,
                        'text'					=>	$textpreview,
                    ),
                ),
            );

            echo json_encode($response);

            exit();
            die();
        }

        function ajax_newsletter_drag_and_drop_builder_save() {

            check_ajax_referer('newsletters_autosave', 'security');

            if (!current_user_can('newsletters_history')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $wpdb, $Db, $Html, $Subscriber, $newsletters_presend, $newsletters_emailraw;
            $using_grapeJs = isset($_POST['using_grapeJS']) ? $_POST['using_grapeJS'] : "";
            $grapeJSContent = isset($_POST['grapejs_content']) ? $_POST['grapejs_content'] : "";
            $post_id = isset($_POST['post_id']) ? $_POST['post_id'] : "";

            update_post_meta($post_id, 'grapejs_content' ,$grapeJSContent);
            update_post_meta($post_id, 'using_grapeJS' , $using_grapeJs);

            return;

        }

        function ajax_newsletters_autosave($internal_call = false) {
            if(!$internal_call) {
                check_ajax_referer('newsletters_autosave', 'security');
            }
            if (!current_user_can('newsletters_history')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $wpdb, $Db, $Html, $Subscriber, $newsletters_presend, $newsletters_emailraw;

            ob_start();

            // Save the history email and get the preview
            $history_data = array(
                'from'				=>	isset($_POST['from']) ? sanitize_text_field($_POST['from']) : "",
                'fromname'			=>	isset($_POST['fromname']) ? sanitize_text_field($_POST['fromname']) : "",
                'post_id'			=>	isset($_POST['post_id']) ? sanitize_text_field($_POST['post_id']) : "",
                'subject'			=>	isset($_POST['subject']) ? wp_kses_post(wp_unslash($_POST['subject'])) : "",
                'message'			=>	isset($_POST['content']) ? (stripslashes($_POST['content'])) : "",
                'text'				=>	((!empty($_POST['customtexton']) && !empty($_POST['customtext'])) ? sanitize_textarea_field($_POST['customtext']) : false),
                'language'			=>	isset($_POST['language']) ? sanitize_text_field($_POST['language']) : "",
                'preheader'			=>	isset($_POST['preheader']) ? sanitize_text_field($_POST['preheader']) : "",
                'status'			=>	isset($_POST['status']) ? sanitize_text_field($_POST['status']) : "",
                'state'			    =>	isset($_POST['state']) ? sanitize_text_field($_POST['state']) : "",
                'theme_id'			=>	isset($_POST['theme_id']) ? sanitize_text_field($_POST['theme_id']) : "",
                'condquery'			=>	isset($_POST['condquery']) ? maybe_serialize(map_deep($_POST['condquery'], 'sanitize_text_field')) : "",
                'conditions'		=>	isset($_POST['fields']) ? maybe_serialize(map_deep($_POST['fields'], 'sanitize_text_field')) : "",
                'conditionsscope'	=>	isset($_POST['fieldsconditionsscope']) ? sanitize_text_field($_POST['fieldsconditionsscope']) : "",
                'daterange'			=>	isset($_POST['daterange']) ? sanitize_text_field($_POST['daterange']) :  "",
                'daterangefrom'		=>	isset($_POST['daterangefrom']) ? sanitize_text_field($_POST['daterangefrom']) : "",
                'daterangeto'		=>	isset($_POST['daterangeto']) ? sanitize_text_field($_POST['daterangeto']) : "",
                'countries'			=>	isset($_POST['countries']) ? map_deep($_POST['countries'], 'sanitize_text_field') : "",
                'selectedcountries'	=>	isset($_POST['selectedcountries']) ? maybe_serialize(map_deep($_POST['selectedcountries'], 'sanitize_text_field')) : "",
                'mailinglists'		=>	isset($_POST['mailinglists']) ? maybe_serialize(map_deep($_POST['mailinglists'], 'sanitize_text_field')) : "",
                'groups'			=>	isset($_POST['groups']) ? maybe_serialize(map_deep($_POST['groups'], 'sanitize_text_field')) : "",
                'roles'				=>	isset($_POST['roles']) ? maybe_serialize(map_deep($_POST['roles'], 'sanitize_text_field')) : "",
                'senddate'			=>	isset($_POST['senddate']) ? sanitize_text_field($_POST['senddate']) : "",
                //'scheduled'			=>	$_POST['scheduled'],
                'scheduled'			=>	"N",
                'format'			=>	isset($_POST['format']) ? sanitize_text_field($_POST['format']) : "",
                'grapejs_content'   =>  isset($_POST['grapejs_content']) ? $_POST['grapejs_content'] : '',
                'using_grapeJS'   =>  isset($_POST['using_grapeJS']) ? $_POST['using_grapeJS'] : ''
            );

            if (isset($_POST['ishistory']) && !empty($_POST['ishistory'])) {
                $history_data['id'] = sanitize_text_field($_POST['ishistory']);
                $history_curr = $this -> History() -> find(array('id' => $history_data['id']));
                $history_data['sent'] = $history_curr -> sent;
            }

            if (isset($_POST['sendrecurring']) && !empty($_POST['sendrecurring'])) {
                if (!empty($_POST['sendrecurringvalue']) && !empty($_POST['sendrecurringinterval']) && !empty($_POST['sendrecurringdate'])) {
                    $history_data['recurring'] = "Y";
                    $history_data['recurringvalue'] = sanitize_text_field($_POST['sendrecurringvalue']);
                    $history_data['recurringinterval'] = sanitize_text_field($_POST['sendrecurringinterval']);

                    /*if (!empty($history_curr) && $_POST['sendrecurringdate'] != $history_curr -> recurringdate) {
                                $history_data['recurringdate'] = date_i18n("Y-m-d H:i:s", (strtotime($_POST['sendrecurringdate'] . " +" . $_POST['sendrecurringvalue'] . " " . $_POST['sendrecurringinterval'])));
                            } else {*/
                    $history_data['recurringdate'] = sanitize_text_field($_POST['sendrecurringdate']);
                    //}

                    $history_data['recurringlimit'] = sanitize_text_field($_POST['sendrecurringlimit']);
                }
            }
            else {
                $history_data['recurring'] = "N";
                $history_data['recurringvalue'] = '0';
                $history_data['recurringinterval'] = '';
                $history_data['recurringdate'] = '0000-00-00 00:00:00';
                $history_data['recurringlimit'] = '0';

            }
            $history_data['recurringsent'] = isset($_POST['recurringsent']) ? sanitize_text_field($_POST['recurringsent']) : "0";
            if ($this -> History() -> save($history_data, false)) {
                $history_id = $this -> History() -> insertid;
                $p_id = $this -> History() -> field('p_id', array('id' => $history_id));

                if (!empty($_POST['contentarea'])) {
                    foreach ($_POST['contentarea'] as $number => $content) {
                        $content_data = array(
                            'number'			=>	$number,
                            'history_id'		=>	$history_id,
                            'content'			=>	$content,
                        );

                        $this -> Content() -> save($content_data, true);
                    }
                }
            }

            $history_id = $this -> History() -> insertid;
            $_GET['id'] = $history_id;
            $preview = $this -> ajax_historyiframe(true, false, false, false);
            $textpreview = $this -> ajax_historyiframe(true, true, false, false);
              $process = ob_get_clean();

            $response = array(
                'history_id'			=>	$history_id,
                'post_id'				=>	$p_id,
                'parts'					=>	array(
                    'preview'				=>	array(
                        'url'					=>	add_query_arg(array('newsletters_method' => "newsletter", 'id' => $history_id), home_url()),
                        'html'					=>	$preview,
                        'text'					=>	$textpreview,
                    ),
                ),
            );

            echo json_encode($response);

            exit();
            die();
        }

        function ajax_previewrunner($justsave = false) {

            check_ajax_referer('previewrunner', 'security');

            if (!current_user_can('newsletters_history')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $wpdb, $Db, $Html;

            if (empty($_POST['content'])) { exit(); }
            if (empty($_POST['subject']) || $_POST['subject'] == __('Enter email subject here', 'wp-mailinglist')) { exit(); }

            ob_start();
            $history_data = array(
                'from'				=>	sanitize_text_field($_POST['from']),
                'fromname'			=>	sanitize_text_field($_POST['fromname']),
                'post_id'			=>	sanitize_text_field($_POST['post_id']),
                'subject'			=>	wp_kses_post(wp_unslash($_POST['subject'])),
                'message'			=>	wp_kses_post(wp_unslash($_POST['content'])),
                'text'				=>	((!empty($_POST['customtexton']) && !empty($_POST['customtext'])) ? sanitize_textarea_field($_POST['customtext']) : false),
                'theme_id'			=>	sanitize_text_field($_POST['theme_id']),
                'condquery'			=>	maybe_serialize(map_deep($_POST['condquery'], 'sanitize_text_field')),
                'conditions'		=>	maybe_serialize(map_deep($_POST['fields'], 'sanitize_text_field')),
                'conditionsscope'	=>	sanitize_text_field($_POST['fieldsconditionsscope']),
                'daterange'			=>	sanitize_text_field($_POST['daterange']),
                'daterangefrom'		=>	sanitize_text_field($_POST['daterangefrom']),
                'daterangeto'		=>	sanitize_text_field($_POST['daterangeto']),
                'countries'			=>	map_deep($_POST['countries'], 'sanitize_text_field'),
                'selectedcountries'	=>	maybe_serialize(map_deep($_POST['selectedcountries'], 'sanitize_text_field')),
                'mailinglists'		=>	maybe_serialize(map_deep($_POST['mailinglists'], 'sanitize_text_field')),
                'groups'			=>	maybe_serialize(map_deep($_POST['groups'], 'sanitize_text_field')),
                'roles'				=>	maybe_serialize(map_deep($_POST['roles'], 'sanitize_text_field')),
                'senddate'			=>	sanitize_text_field($_POST['senddate']),
                'scheduled'			=>	sanitize_text_field($_POST['scheduled']),
                'format'			=>	sanitize_text_field($_POST['format']),
                'grapejs_content'   =>  isset($_POST['grapejs_content']) ? $_POST['grapejs_content'] : '',
                'using_grapeJS'     =>  isset($_POST['using_grapeJS']) ? $_POST['using_grapeJS'] : ''
            );

            if (!empty($_POST['ishistory'])) {
                $history_data['id'] = $_POST['ishistory'];
                $history_curr = $this -> History() -> find(array('id' => $history_data['id']));
                $history_data['sent'] = $history_curr -> sent;
            }

            if (!empty($_POST['sendrecurring'])) {
                if (!empty($_POST['sendrecurringvalue']) && !empty($_POST['sendrecurringinterval']) && !empty($_POST['sendrecurringdate'])) {
                    $history_data['recurring'] = "Y";
                    $history_data['recurringvalue'] = sanitize_text_field($_POST['sendrecurringvalue']);
                    $history_data['recurringinterval'] = sanitize_text_field($_POST['sendrecurringinterval']);

                    /*if (!empty($history_curr) && $_POST['sendrecurringdate'] != $history_curr -> recurringdate) {
                                $history_data['recurringdate'] = date_i18n("Y-m-d H:i:s", (strtotime($_POST['sendrecurringdate'] . " +" . $_POST['sendrecurringvalue'] . " " . $_POST['sendrecurringinterval'])));
                            } else {*/
                    $history_data['recurringdate'] = sanitize_text_field($_POST['sendrecurringdate']);
                    //}

                    $history_data['recurringlimit'] = sanitize_text_field($_POST['sendrecurringlimit']);
                }
            }

            if ($this -> History() -> save($history_data, false)) {
                $history_id = $this -> History() -> insertid;
                $p_id = $this -> History() -> field('p_id', array('id' => $history_id));

                if (!empty($_POST['contentarea'])) {
                    foreach ($_POST['contentarea'] as $number => $content) {
                        $content_data = array(
                            'number'			=>	$number,
                            'history_id'		=>	$history_id,
                            'content'			=>	$content,
                        );

                        $this -> Content() -> save($content_data, true);
                    }
                }
            }

            $history_id = $this -> History() -> insertid;
            $_GET['id'] = $history_id;

            if (!empty($justsave)) {
                return $history_id;
            }

            $output = ob_get_clean();
            $preview = $this -> ajax_historyiframe(true, false, false, false);

            header("Content-Type: text/xml; charset=UTF-8");

            ?>

            <result>
                <history_id><?php echo $history_id; ?></history_id>
                <p_id><?php echo $p_id; ?></p_id>
                <previewcontent><![CDATA[<?php echo $preview; ?>]]></previewcontent>
                <textcontent><![CDATA[<?php echo $preview; ?>]]></textcontent>
                <newsletter_url><![CDATA[<?php echo $Html -> retainquery('newsletters_method=newsletter&id=' . $history_id, home_url()); ?>]]></newsletter_url>
            </result>

            <?php

            exit();
            die();
        }

        function ajax_spamscore_blockeditor() {

            check_ajax_referer('spamscore_blockeditor', 'security');

            if (!current_user_can('newsletters_history')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            $history_data = array(

            );

            global $Db, $Html, $Subscriber, $newsletters_presend, $newsletters_emailraw;
            $newsletters_presend = true;
            $subscriber_id = $Subscriber -> admin_subscriber_id();
            $subscriber = $Subscriber -> get($subscriber_id, false);
            $subject = wp_kses_post(wp_unslash($_POST['post_title']));
            //$history_id = $_POST['ishistory'];
            $content = wp_kses_post(wp_unslash($_POST['content']));
            $history_id = false;

            $message = $this -> render_email('send', array('message' => $content, 'subject' => $subject, 'subscriber' => $subscriber, 'history_id' => $history_id), false, true, true, $_POST['newsletters_theme_id']);
            $eunique = $Html -> eunique($subscriber, $history_id);
            $this -> execute_mail($subscriber, false, $subject, $message, $history -> attachments, $history_id, $eunique, false);
            $spamscore = $this -> spam_score($subscriber -> email, "long");

            if (empty($spamscore -> success) || $spamscore -> success == false) {
                $score = 0;
                $success = false;
            } else {
                $score = $spamscore -> score;
                $success = true;
                $report = $spamscore -> report;
            }

            $output = "";
            ob_start();

            ?>

            <p id="spamscore_report_link_holder" style="text-align:center; display:block;"><a href="#spamscore_report" onclick="jQuery.colorbox({inline:false, html:jQuery('#spamscore_report').html(), maxWidth:'80%', maxHeight:'80%'}); return false;"><?php _e('See Report', 'wp-mailinglist'); ?></a></p>
            <iframe width="100%" style="width:100%;" frameborder="0" scrolling="no" class="autoHeight widefat" src="<?php echo admin_url('admin-ajax.php?action=newsletters_gauge&value=' . $score . '&security=' . wp_create_nonce('gauge')); ?>"></iframe>

            <div style="display:none;">
                <div id="spamscore_report">
                    <div class="wrap newsletters">
                        <h2><?php _e('Spam Score Report', 'wp-mailinglist'); ?></h2>
                        <p><a href="" onclick="jQuery.colorbox.close(); return false;" class="button button-primary"><?php _e('Close Report', 'wp-mailinglist'); ?></a></p>

                        <p><?php echo sprintf(__('The spam score is %s out of 10 for this email', 'wp-mailinglist'), $score); ?></p>

                        <?php if (is_wp_error($spamscore)) : ?>
                            <p class="newsletters_error"><?php echo $spamscore -> get_error_message(); ?></p>
                        <?php elseif (empty($success) || $success == false) : ?>
                            <p class="newsletters_error"><?php echo $spamscore -> message; ?></p>
                        <?php else : ?>
                            <h3><?php _e('Report', 'wp-mailinglist'); ?></h3>
                            <p><pre><?php echo ($spamscore -> report); ?></pre></p>
                        <?php endif; ?>

                        <h3><?php _e('RAW Email', 'wp-mailinglist'); ?></h3>
                        <p><a href="" onclick="jQuery('#rawemail-holder').toggle(); return false;" class="button button-secondary"><?php _e('Toggle RAW Email', 'wp-mailinglist'); ?></a></p>
                        <div id="rawemail-holder" style="display:none;">
                            <p><pre><?php echo htmlspecialchars($newsletters_emailraw); ?></pre></p>
                        </div>
                        <p><a href="" onclick="jQuery.colorbox.close(); return false;" class="button button-primary"><?php _e('Close Report', 'wp-mailinglist'); ?></a></p>
                    </div>
                </div>
            </div>

            <?php

            $output = ob_get_clean();

            $data = array(
                'success'			=>	$success,
                'report'			=>	$report,
                'score'				=>	$score,
                'output'			=>	$output,
            );

            echo json_encode($data);
            exit(); die();

            global $Db, $Html, $Subscriber, $newsletters_presend, $newsletters_emailraw;
            $newsletters_presend = true;
            $subscriber_id = $Subscriber -> admin_subscriber_id();
            $subscriber = $Subscriber -> get($subscriber_id, false);
            $subject = wp_kses_post(wp_unslash($_POST['subject']));
            $content = wp_kses_post(wp_unslash($_POST['content']));
            $history_id = $_POST['ishistory'];
            $theme_id = sanitize_text_field($_POST['theme_id']);
            $message = $this -> render_email('send', array('message' => $content, 'subject' => $subject, 'subscriber' => $subscriber, 'history_id' => $history_id), false, true, true, $theme_id);
            $eunique = $Html -> eunique($subscriber, $history_id);
            $this -> execute_mail($subscriber, false, $subject, $message, $history -> attachments, $history_id, $eunique, false);
            $spamscore = $this -> spam_score($subscriber -> email, "long");

            // Save the 'spamscore'
            if (!empty($spamscore -> score)) {
                $this -> History() -> save_field('spamscore', $spamscore -> score, array('id' => $history_id));
            }

            if (empty($spamscore -> success) || $spamscore -> success == false) {
                $score = 0;
            } else {
                $score = $spamscore -> score;
            }

            $output = "";
            ob_start();

            ?>

            <p id="spamscore_report_link_holder" style="text-align:center; display:block;"><a href="#spamscore_report" onclick="jQuery.colorbox({inline:false, html:jQuery('#spamscore_report').html(), maxWidth:'80%', maxHeight:'80%'}); return false;"><?php _e('See Report', 'wp-mailinglist'); ?></a></p>
            <iframe width="100%" style="width:100%;" frameborder="0" scrolling="no" class="autoHeight widefat" src="<?php echo admin_url('admin-ajax.php?action=newsletters_gauge&value=' . $score . '&security=' . wp_create_nonce('gauge')); ?>"></iframe>

            <div style="display:none;">
                <div id="spamscore_report">
                    <div class="wrap newsletters">
                        <h2><?php _e('Spam Score Report', 'wp-mailinglist'); ?></h2>
                        <p><a href="" onclick="jQuery.colorbox.close(); return false;" class="button button-primary"><?php _e('Close Report', 'wp-mailinglist'); ?></a></p>

                        <p><?php echo sprintf(__('The spam score is %s out of 10 for this email', 'wp-mailinglist'), $score); ?></p>

                        <?php if (is_wp_error($spamscore)) : ?>
                            <p class="newsletters_error"><?php echo $spamscore -> get_error_message(); ?></p>
                        <?php elseif (empty($spamscore -> success) || $spamscore -> success == false) : ?>
                            <p class="newsletters_error"><?php echo $spamscore -> message; ?></p>
                        <?php else : ?>
                            <h3><?php _e('Report', 'wp-mailinglist'); ?></h3>
                            <p><pre><?php echo ($spamscore -> report); ?></pre></p>
                        <?php endif; ?>

                        <h3><?php _e('RAW Email', 'wp-mailinglist'); ?></h3>
                        <p><a href="" onclick="jQuery('#rawemail-holder').toggle(); return false;" class="button button-secondary"><?php _e('Toggle RAW Email', 'wp-mailinglist'); ?></a></p>
                        <div id="rawemail-holder" style="display:none;">
                            <p><pre><?php echo htmlspecialchars($newsletters_emailraw); ?></pre></p>
                        </div>
                        <p><a href="" onclick="jQuery.colorbox.close(); return false;" class="button button-primary"><?php _e('Close Report', 'wp-mailinglist'); ?></a></p>
                    </div>
                </div>
            </div>

            <?php

            $output = ob_get_clean();

            $data = array(
                'success'			=>	$spamscore -> success,
                'report'			=>	$spamscore -> report,
                'score'				=>	$score,
                'output'			=>	$output,
            );

            echo json_encode($data);
            exit(); die();

            header("Content-Type: text/xml; charset=UTF-8");

            ?>

            <result>
                <success><?php echo $spamscore -> success; ?></success>
                <report><![CDATA[<?php echo nl2br($spamscore -> report); ?>]]></report>
                <score><?php echo $score; ?></score>
                <output><![CDATA[<?php echo $output; ?>]]></output>
            </result>

            <?php

            exit();
            die();
        }

        function ajax_spamscorerunner() {

            check_ajax_referer('spamscorerunner', 'security');

            if (current_user_can('newsletters_send')) {

                global $Db, $Html, $Subscriber, $newsletters_presend, $newsletters_emailraw;
                $newsletters_presend = true;
                $subscriber_id = $Subscriber -> admin_subscriber_id();
                $subscriber = $Subscriber -> get($subscriber_id, false);
                $subject = wp_kses_post(wp_unslash($_POST['subject']));
                $content = wp_kses_post(wp_unslash($_POST['content']));
                $from = wp_kses_post(wp_unslash($_POST['from']));
                $history_id = sanitize_text_field($_POST['ishistory']);
                $message = $this -> render_email('send', array('message' => $content, 'subject' => $subject, 'subscriber' => $subscriber, 'history_id' => $history_id), false, true, true, $_POST['theme_id']);
                $eunique = $Html -> eunique($subscriber, $history_id);
                $this -> execute_mail($subscriber, false, $subject, $message, $history -> attachments, $history_id, $eunique, false);
                $spamscore = $this -> spam_score($subscriber -> email, "long");

                // Save the 'spamscore'
                if (!empty($spamscore -> score)) {
                    $this -> History() -> save_field('spamscore', $spamscore -> score, array('id' => $history_id));
                }

                if (empty($spamscore -> success) || $spamscore -> success == false) {
                    $score = 0;
                } else {
                    $score = $spamscore -> score;
                }

                $output = "";
                ob_start();

                ?>

                <p id="spamscore_report_link_holder" style="text-align:center; display:block;"><a href="#spamscore_report" onclick="jQuery.colorbox({inline:false, html:jQuery('#spamscore_report').html(), maxWidth:'80%', maxHeight:'80%'}); return false;"><?php _e('See Report', 'wp-mailinglist'); ?></a></p>
                <iframe width="100%" style="width:100%;" frameborder="0" scrolling="no" class="autoHeight widefat" src="<?php echo admin_url('admin-ajax.php?action=newsletters_gauge&value=' . $score . '&security=' . wp_create_nonce('gauge')); ?>"></iframe>

                <div style="display:none;">
                    <div id="spamscore_report">
                        <div class="wrap newsletters">
                            <h2><?php _e('Spam Score Report', 'wp-mailinglist'); ?></h2>
                            <p><a href="" onclick="jQuery.colorbox.close(); return false;" class="button button-primary"><?php _e('Close Report', 'wp-mailinglist'); ?></a></p>

                            <p><?php echo sprintf(__('The spam score is %s out of 10 for this email', 'wp-mailinglist'), $score); ?></p>

                            <?php if (is_wp_error($spamscore)) : ?>
                                <p class="newsletters_error"><?php echo $spamscore -> get_error_message(); ?></p>
                            <?php elseif (empty($spamscore -> success) || $spamscore -> success == false) : ?>
                                <p class="newsletters_error"><?php echo $spamscore -> message; ?></p>
                            <?php else : ?>
                                <h3><?php _e('Report', 'wp-mailinglist'); ?></h3>
                                <p><pre><?php echo ($spamscore -> report); ?></pre></p>
                            <?php endif; ?>

                            <h3><?php _e('RAW Email', 'wp-mailinglist'); ?></h3>
                            <p><a href="" onclick="jQuery('#rawemail-holder').toggle(); return false;" class="button button-secondary"><?php _e('Toggle RAW Email', 'wp-mailinglist'); ?></a></p>
                            <div id="rawemail-holder" style="display:none;">
                                <p><pre><?php echo htmlspecialchars($newsletters_emailraw); ?></pre></p>
                            </div>
                            <p><a href="" onclick="jQuery.colorbox.close(); return false;" class="button button-primary"><?php _e('Close Report', 'wp-mailinglist'); ?></a></p>
                        </div>
                    </div>
                </div>

                <?php

                $output = ob_get_clean();
                $success = $spamscore -> success;
            } else {
                $success = false;
                $output = __('You do not have permission', 'wp-mailinglist');
            }

            header("Content-Type: text/xml; charset=UTF-8");

            ?>

            <result>
                <success><?php echo $success; ?></success>
                <report><![CDATA[<?php echo nl2br($spamscore -> report); ?>]]></report>
                <score><?php echo $score; ?></score>
                <output><![CDATA[<?php echo $output; ?>]]></output>
            </result>

            <?php

            exit();
            die();
        }

        function spam_score($email = null, $options = "long") {
            $data = array("email" => $email, "options" => $options);
            $data_string = json_encode($data);

            $header = array(
                'Accept: application/json',
                'Content-Type: application/json',
                'Content-Length: ' . strlen($data_string),
            );

            $url = 'https://spamcheck.postmarkapp.com/filter';

            $args = array(
                'method'			=>	"POST",
                'headers'			=>	$header,
                'body'				=>	$data,
                'timeout'			=>	120,
            );

            $response = wp_remote_request($url, $args);
            if (!is_wp_error($response)) {
                return json_decode($response['body']);
            } else {
                return $response;
            }
        }

        function ajax_gauge() {

            check_ajax_referer('gauge', 'security');

            if (current_user_can('newsletters_send')) {
                $value = (empty($_REQUEST['value'])) ? 0 : sanitize_text_field($_REQUEST['value']);

                wp_enqueue_script('raphael', $this -> render_url('js/raphael.js', 'admin', false), array('jquery'), false, false);
                wp_enqueue_script('justgage', $this -> render_url('js/justgage.js', 'admin', false), array('jquery'), false, false);

                ?>

                <html>
                <head>
                    <meta charset="utf-8" />

                    <?php wp_head(); ?>
                </head>
                <body style="margin:0; padding:0;">
                <div id="gauge"></div>

                <script>
                    document.addEventListener("DOMContentLoaded", function(event) {
                        var g = new JustGage({
                            id: "gauge",
                            value: <?php echo esc_js($value); ?>,
                            min: 0,
                            max: 10,
                            title: "<?php echo ($value >= 5) ? __('This is spam!', 'wp-mailinglist') : __('This is safe!', 'wp-mailinglist'); ?>",
                            label: "<?php _e('Spam Score', 'wp-mailinglist'); ?>",
                            levelColorsGradient: false
                        });
                    });
                </script>
                </body>
                </html>

                <?php
            } else {
                echo __('You do not have permission', 'wp-mailinglist');
            }

            exit();
            die();
        }

        function ajax_history_download() {
            global $Db, $Subscriber;

            check_ajax_referer('history_download', 'security');

            if (!current_user_can('newsletters_history')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            $id = sanitize_text_field($_GET['id']);
            if (!empty($id)) {
                $email = $this -> History() -> find(array('id' => $id));

                $subscriber_id = $Subscriber -> admin_subscriber_id();
                $subscriber = $Subscriber -> get($subscriber_id);

                if (!empty($email -> post_id)) {
                    if ($thepost = get_post($email -> post_id)) {
                        global $post, $shortcode_post;
                        $post = $thepost;
                        $shortcode_post = $thepost;
                    }
                }

                $message = $email -> message;
                $content = $this -> render_email('send', array('message' => $message, 'subject' => $email -> subject, 'subscriber' => $subscriber, 'history_id' => $id), false, true, true, $email -> theme_id, true);

                $output = $content;

                $output = "";
                ob_start();
                echo do_shortcode(wp_unslash($content));
                $output = ob_get_clean();

                ob_start();
                echo $this -> process_set_variables($subscriber, null, $output, esc_html($email -> id));
                $output = ob_get_clean();

                if (!empty($email -> format) && $email -> format == "text") {
                    $output = wpautop($output);
                }

                $output = $this -> inlinestyles($output);

                if (ini_get('zlib.output_compression')) {
                    ini_set('zlib.output_compression', 'Off');
                }

                header("Pragma: public");
                header("Expires: 0");
                header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
                header("Cache-Control: public", false);
                header("Content-Description: Download Newsletter");
                header("Content-Type: text/html");
                header("Accept-Ranges: bytes");
                header("Content-Disposition: attachment; filename=\"" . __($email -> subject) . ".html\";");
                header("Content-Transfer-Encoding: binary");
                header("Content-Length: " . strlen($output));

                print($output);
                exit();
                die();
            }
        }

        function ajax_historyiframe($returnoutput = false, $text = false, $history_id = false, $ajax = true) {

            if (!empty($ajax)) {
                check_ajax_referer('historyiframe', 'security');

                if (!current_user_can('newsletters_send')) {
                    wp_die(__('You do not have permission', 'wp-mailinglist'));
                }
            }

            global $Db, $Subscriber;

            if (empty($text)) {
                if (!empty($_GET['text'])) {
                    $text = true;
                }
            }

            $id = (empty($history_id)) ? esc_html($_GET['id']) : $history_id;
            $email = $this -> History() -> find(array('id' => $id));

            $subscriber_id = $Subscriber -> admin_subscriber_id();
            $subscriber = $Subscriber -> get($subscriber_id);

            if (!empty($email -> post_id)) {
                if ($thepost = get_post($email -> post_id)) {
                    global $post, $shortcode_post;
                    $post = $thepost;
                    $shortcode_post = $thepost;
                }
            }

            $message = $email -> message;
            $content = $this -> render_email('send', array('message' => $message, 'subject' => $email -> subject, 'subscriber' => $subscriber, 'history_id' => $id), false, true, true, $email -> theme_id, true);

            $output = $content;

            $output = "";
            ob_start();
            echo do_shortcode(wp_unslash($content));
            $output = ob_get_clean();

            ob_start();
            //echo $this -> process_set_variables($subscriber, $user, $output, esc_html($email -> id));

            //below modified by Mohsen. Above commented line was original
            $user = null;
            echo $this -> process_set_variables($subscriber, $user, $output, esc_html($email -> id));
            $output = ob_get_clean();

            if (!empty($email -> format) && $email -> format == "text") {
                $output = wpautop($output);
            }

            $output = $this -> inlinestyles($output);

            // do we want the TEXT version?
            if (!empty($text)) {
                global $wpml_textmessage;
                $altbody = $wpml_textmessage;

                if (!empty($email -> text)) {
                    $altbody = $email -> text;
                    $altbody = do_shortcode($altbody);
                    $altbody = $this -> process_set_variables($subscriber, $user, urldecode(wp_unslash($altbody)), $id, $eunique);
                    $altbody = apply_filters('newsletters_execute_mail_textmessage', $altbody);
                    $wpml_textmessage = $altbody;
                }

                if (version_compare(PHP_VERSION, '5.3.2') >= 0) {
                    if (class_exists('DOMDocument')) {
                        require_once $this -> plugin_base() . DS . 'vendors' . DS . 'class.html2text.php';
                        $html2text = new Html2Text();
                        $altbody = $html2text -> convert($wpml_textmessage);
                    }
                }

                $output = nl2br($altbody);
            }

            if ($returnoutput) {
				return $this -> wpml_newsletters_conditional_sanitize_content($output);
            }

			echo $this -> wpml_newsletters_conditional_sanitize_content($output);
            exit();
            die();
        }

        function ajax_serialkey() {
            $errors = array();
            $success = false;

            check_ajax_referer('serialkey', 'security');

            if (current_user_can('newsletters_welcome')) {
                if (!empty($_GET['delete'])) {
                    $this -> delete_option('serialkey');
                    $host = sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST']));
                    $host_hash = md5($host);
                    if (!empty($host)) {
                        $time_key  = 'wpmlserial_validation_time_' . $host_hash;
						$valid_key = 'wpmlserial_valid_'           . $host_hash;

						delete_transient( $time_key );
						delete_transient( $valid_key );

						if ( is_multisite() ) {
							delete_site_transient( $time_key );
							delete_site_transient( $valid_key );
						}
                    }

                    $errors[] = __('Serial key has been deleted.', 'wp-mailinglist');
                } else {
                    if (!empty($_POST)) {
                        if (empty($_REQUEST['serialkey'])) { $errors[] = __('Please fill in a serial key.', 'wp-mailinglist'); }
                        else {
                            $this -> update_option('serialkey', esc_html($_REQUEST['serialkey']));	//update the DB option
                            $this -> delete_all_cache('all');



                            $serial_validation_status = $this->ci_serial_valid();
                            $host = sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST']));
                            $host_hash = md5($host);
                            if (!empty($host)) {
                                delete_transient("wpml" . 'serial_validation_time_' . $host_hash);
                                delete_transient("wpml" . 'serial_valid_' . $host_hash);
                            }

                            if (!is_array($serial_validation_status) && !$serial_validation_status) {
                                $errors[] = __('Serial key is invalid, please try again.', 'wp-mailinglist');
                            }
                            else if((is_array($serial_validation_status) && $serial_validation_status['disable_pro_features']) ) {
                                $errors[] = __('Serial key is expired. You can still work with it, but it is limited', 'wp-mailinglist');
                                delete_transient($this -> pre . 'update_info');
                                $success = true;
                            }
                            else if (!is_array($serial_validation_status) && $serial_validation_status)
                            {

                                delete_transient($this -> pre . 'update_info');
                                $success = true;
                            }
                        }
                    }
                }
            } else {
                $success = false;
                $errors[] = __('You do not have permission', 'wp-mailinglist');
            }

            if (empty($_POST)) { ?><div id="<?php echo $this -> pre; ?>submitserial"><?php }
            $this -> render('submitserial', array('errors' => $errors, 'success' => $success), true, 'admin');
            if (empty($_POST)) { ?></div><?php }

            exit();
            die();
        }

        function ajax_managementcustomfields() {

            check_ajax_referer('managementcustomfields', 'security');

            // No current_user_can required, this is front-end

            global $wpdb, $Db, $Subscriber, $FieldsList;

            if (!empty($_POST['subscriber_id'])) {
                $Db -> model = $Subscriber -> model;

                if ($subscriber = $Db -> find(array('id' => (int) $_POST['subscriber_id']), false, false, true, true, false)) {
                    $lists = array();
                    if (!empty($subscriber -> subscriptions)) {
                        foreach ($subscriber -> subscriptions as $subscription) {
                            $lists[] = $subscription -> mailinglist -> id;
                        }
                    }

                    $fields = $FieldsList -> fields_by_list($lists, "order", "ASC", (($this -> get_option('managementallowemailchange') == "Y") ? true : false));
                } else {
                    $errors[] = __('Subscriber could not be read.', 'wp-mailinglist');
                }
            }

            $this -> render('management' . DS . 'customfields', array('subscriber' => $subscriber, 'fields' => $fields), true, 'default');
            $this -> render('js' . DS . 'management', false, true, 'default');

            exit();
            die();
        }

        function ajax_managementsavefields() {

            check_ajax_referer('managementsavefields', 'security');

            // No current_user_can required, this is front-end

            global $wpdb, $Db, $Field, $Subscriber, $FieldsList;

            $errors = array();
            $oldpost = $_POST;
            $success = false;
            $successmessage = "";

            if (!empty($_POST)) {
                $Db -> model = $Subscriber -> model;

                if ($subscriber = $Db -> find(array('id' => $_POST['subscriber_id']), false, false, true, true, false)) {

                    do_action('newsletters_subscriber_management_savefields_before', $subscriber);

                    $lists = array();
                    if (!empty($subscriber -> subscriptions)) {
                        foreach ($subscriber -> subscriptions as $subscription) {
                            $lists[] = $subscription -> mailinglist -> id;
                        }
                    }

                    $fields = $FieldsList -> fields_by_list($lists, 'order', "ASC", (($this -> get_option('managementallowemailchange') == "Y") ? true : false));

                    $_POST = $oldpost;
                    unset($_POST['action']);
                    unset($_POST['subscriber_id']);

                    if (!empty($_POST)) {
                        $emailfield = $Field -> email_field();

                        if (!empty($_POST['email'])) {
                            if (!$Subscriber -> email_validate($_POST['email'])) { $errors['email'] = __($emailfield -> errormessage); }
                            elseif ($_POST['email'] != $subscriber -> email && $Subscriber -> email_exists($_POST['email'])) { $errors[] = __('Email address is already in use, try another.', 'wp-mailinglist'); }
                        } else {
                            $errors['email'] = __($emailfield -> errormessage);
                        }

                        $_POST['list_id'] = $lists;

                        $_POST = $data = $Field -> validate_optin($_POST, 'management');
                        if (!empty($Field -> errors)) {
                            $errors = array_merge($errors, $Field -> errors);
                        }

                        $data['password'] = false;
                        $management_password = $this -> get_option('management_password');
                        if (!empty($_POST['password1'])) {
                            if (empty($_POST['password2'])) { $errors['password'] = __('Re-enter the first password again.', 'wp-mailinglist'); }
                            elseif ($_POST['password1'] != $_POST['password2']) { $errors['password'] = __('Passwords do not match', 'wp-mailinglist'); }
                            else {
                                //password seems correct
                                $password = sanitize_text_field($_POST['password1']);
                                $password_hashed = md5($password);
                                $data['password'] = $password_hashed;

                                do_action('newsletters_subscriber_management_password', $subscriber, $password);
                            }
                        }

                        if (empty($errors)) {
                            if (!empty($_POST['email']) && $_POST['email'] != $subscriber -> email) {
                                $Db -> model = $Subscriber -> model;
                                $Db -> save_field('email', $_POST['email'], array('id' => $subscriber -> id));

                                do_action('newsletters_subscriber_management_email_change', $subscriber);
                            }

                            $data['justsubscribe'] = true;

                            if ($Subscriber -> save($data, true, false, false, true)) {
                                $success = true;
                                $successmessage = __('Profile has been saved.', 'wp-mailinglist');

                                $this -> delete_all_cache('all');
                                $Db -> model = $Subscriber -> model;
                                $subscriber = $Db -> find(array('id' => $subscriber -> id), false, false, true, true, false);
                            } else {
                                $errors[] = __('Could not be saved', 'wp-mailinglist');
                            }
                        } else {
                            $_POST[$this -> pre . 'errors'] = $errors;
                        }
                    } else {
                        $errors[] = __('No data was posted.', 'wp-mailinglist');
                    }
                } else {
                    $errors[] = __('Subscriber could not be read.', 'wp-mailinglist');
                }
            } else {
                $errors[] = __('No data was posted.', 'wp-mailinglist');
            }

            $this -> render('management' . DS . 'customfields', array('subscriber' => $subscriber, 'fields' => $fields, 'success' => $success, 'successmessage' => $successmessage, 'errors' => $errors), true, 'default');

            exit();
            die();
        }

        function ajax_managementcurrentsubscriptions() {

            check_ajax_referer('managementcurrentsubscriptions', 'security');

            global $wpdb, $Db, $Subscriber;

            if (!empty($_POST['subscriber_id'])) {
                $Db -> model = $Subscriber -> model;
                if ($subscriber = $Db -> find(array('id' => (int) $_POST['subscriber_id']), false, false, true, true, false)) {
                    $this -> render('management' . DS . 'currentsubscriptions', array('subscriber' => $subscriber), true, 'default');
                }
            }

            exit();
            die();
        }

        function ajax_managementnewsubscriptions() {

            check_ajax_referer('managementnewsubscriptions', 'security');

            global $wpdb, $Db, $Subscriber, $Mailinglist;
            $otherlists = array();

            if (!empty($_POST['subscriber_id'])) {
                $Db -> model = $Subscriber -> model;

                if ($subscriber = $Db -> find(array('id' => (int) $_POST['subscriber_id']), false, false, true, true, false)) {
                    $managementshowprivate = $this -> get_option('managementshowprivate');
                    if ($mailinglists = $Mailinglist -> select(((!empty($managementshowprivate)) ? true : false))) {
                        foreach ($mailinglists as $mkey => $mval) {
                            $otherlists[$mkey] = $mkey;
                        }

                        if (!empty($subscriber -> subscriptions)) {
                            foreach ($subscriber -> subscriptions as $subscription) {
                                if (in_array($subscription -> mailinglist -> id, $otherlists)) {
                                    unset($otherlists[$subscription -> mailinglist -> id]);
                                }
                            }
                        }

                        $this -> render('management' . DS . 'newsubscriptions', array('subscriber' => $subscriber, 'otherlists' => $otherlists), true, 'default');
                    }
                }
            }

            exit();
            die();
        }
        function ajax_subscribercountdisplay() {
            check_ajax_referer('subscribercountdisplay', 'security');

            if (!current_user_can('newsletters_subscribers')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            global $wpdb, $Subscriber;
            $subscribercount_query = get_option('newsletters_subscribercount');
            $users_tmp = get_option('newsletters_eligible_users_count_tmp');

            if (!empty($subscribercount_query) || !empty($users_tmp)) {

                $total_subscribers = (!empty($subscribercount_query)) ? (count($wpdb -> get_results($subscribercount_query))) : 0;
                $perpage = 50;
                $start = (empty($_GET['start'])) ? 0 : esc_html($_GET['start']);
                $realstart = ($start + 1);
                $end = ($start + $perpage);
                $realend = ($end > $total_subscribers) ? $total_subscribers : $end;
                $prevstart = ($start - $perpage);
                $nextstart = ($end);

                $subscribers = array();
                if( !empty($subscribercount_query)) {
                    $subscribercount_query .= " LIMIT " . esc_sql($start) . ", " . esc_sql($perpage) . "";
                    $subscribers_only = $wpdb -> get_results($subscribercount_query);
                    $subscribers = $subscribers_only;
                }



                if (!empty($users_tmp)) {

                    // Assuming $temp_user contains the serialized data from the database
                    $temp_user_data = maybe_unserialize($users_tmp);


                    ?>

                    <p><?php echo __('Users', 'wp-mailinglist'); ?></p>

                    <table class="widefat">
                        <tbody>
                        <?php
                        // Check if $temp_user_data is an array and has at least one element
                        if (is_array($temp_user_data) && !empty($temp_user_data)) {
                            // Loop through the array (in this case, it should only have one element)
                            foreach ($temp_user_data as $user_item) {
                                // Check if $user_item is an object of the class WP_User
                                if ($user_item instanceof WP_User) {
                                    // Access the properties of the WP_User object
                                    $user_id = $user_item->ID;
                                    $user_email = $user_item->user_email;
                                    ?>
                                    <tr >
                                        <td><?php
                                            // Output or use the retrieved values
                                            echo $user_email;
                                            ?>
                                        </td>
                                    </tr>
                                    <?php
                                }
                            }
                        }
                        ?>
                        </tbody>
                    </table>

                <?php }


                if (!empty($subscribers)) {

                    ?>

                    <p><?php echo sprintf(__('Showing %s - %s of %s subscribers', 'wp-mailinglist'), $realstart, $realend, $total_subscribers); ?></p>

                    <table class="widefat">
                        <tbody>
                        <?php foreach ($subscribers as $subscriber) : ?>
                            <?php $subscriber = $Subscriber -> get($subscriber -> id); ?>
                            <tr class="<?php echo $class = (empty($class)) ? 'alternate' : false; ?>">
                                <td>
                                    <?php echo $subscriber -> email; ?>
                                </td>
                            </tr>
                        <?php endforeach; ?>
                        </tbody>
                    </table>

                    <p>
                        <?php if ($start > 0) : ?>
                            <a href="" class="button button-secondary" onclick="jQuery.colorbox({width:'80%', height:'80%', title:'<?php _e('Selected Subscribers', 'wp-mailinglist'); ?>', href:'<?php echo admin_url('admin-ajax.php?action=newsletters_subscribercountdisplay&security=' . wp_create_nonce('subscribercountdisplay') . '&start=' . $prevstart); ?>'}); return false;"><i class="fa-solid fa-caret-left"></i> <?php _e('Previous Page', 'wp-mailinglist'); ?></a>
                        <?php endif; ?>
                        <?php if ($total_subscribers > $end) : ?>
                            <a href="" class="button button-secondary" onclick="jQuery.colorbox({width:'80%', height:'80%', title:'<?php _e('Selected Subscribers', 'wp-mailinglist'); ?>', href:'<?php echo admin_url('admin-ajax.php?action=newsletters_subscribercountdisplay&security=' . wp_create_nonce('subscribercountdisplay') . '&start=' . $nextstart); ?>'}); return false;"><?php _e('Next Page', 'wp-mailinglist'); ?> <i class="fa-solid fa-caret-right"></i></a>
                        <?php endif; ?>
                    </p>

                    <p><a href="" onclick="jQuery.colorbox.close(); return false;" class="button button-primary"><i class="fa-solid fa-xmark"></i> <?php _e('Close', 'wp-mailinglist'); ?></a></p>

                    <?php
                }
            }

            exit(); die();
        }

        function ajax_subscribercount($count = true) {

            check_ajax_referer('subscribercount', 'security');

            if (!current_user_can('newsletters_subscribers')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            $status = (empty($_POST['status'])) ? 'active' : sanitize_text_field($_POST['status']);

            global $wpdb, $Db, $Field, $Subscriber, $Mailinglist, $SubscribersList;
            $subscribercount = 0;

            if (!empty($_POST['groups'])) {
                foreach ($_POST['groups'] as $group_key => $group_id) {
                    $Db -> model = $Mailinglist -> model;

                    if ($lists = $Db -> find_all(array('group_id' => $group_id), array('id'))) {
                        foreach ($lists as $list) {
                            $_POST['mailinglists'][] = $list -> id;
                        }
                    }
                }
            }

            // Count the users based on roles
            $users_count = 0;
            $users_list = array();
            if (!empty($_POST['roles'])) {
                if ($count_users = count_users()) {
                    foreach ($count_users['avail_roles'] as $role => $count) {
                        if (in_array($role, $_POST['roles'])) {
                            $users_count += (int) $count;
                        }
                    }
                    $roles = $_POST['roles'];
                    foreach($roles as $role){
                        $args = array(
                            'blog_id' => 1,
                            'orderby' => 'nicename',
                            'role' => $role
                        );
                        $current_role_users = get_users($args);
                        $users_list = array_merge($current_role_users, $users_list);
                    }

                }
            }
            $query = "";
            $subscribers = array();
            if (!empty($_POST['mailinglists'])) {

                $query = "SELECT DISTINCT " . $wpdb -> prefix . $Subscriber -> table . ".id FROM " . $wpdb -> prefix . "" . $SubscribersList -> table . " LEFT JOIN
                        " . $wpdb -> prefix . "" . $Subscriber -> table . " ON
                        " . $wpdb -> prefix . "" . $SubscribersList -> table . ".subscriber_id = " . $wpdb -> prefix . "" . $Subscriber -> table . ".id LEFT JOIN
                        " . $wpdb -> prefix . $Mailinglist -> table . " ON " . $wpdb -> prefix . $SubscribersList -> table . ".list_id = " . $wpdb -> prefix . $Mailinglist -> table . ".id LEFT JOIN
                        " . $wpdb -> prefix . $this -> SubscribersOption() -> table . " ON " . $wpdb -> prefix . $Subscriber -> table . ".id = " . $wpdb -> prefix . $this -> SubscribersOption() -> table . ".subscriber_id WHERE (";

                $m = 1;

                if (!empty($_POST['mailinglists'])) {
                    foreach ($_POST['mailinglists'] as $mailinglist_id) {
                        $query .= "" . $wpdb -> prefix . $SubscribersList -> table . ".list_id = '" . esc_sql($mailinglist_id) . "'";

                        if ($m < count($_POST['mailinglists'])) {
                            $query .= " OR ";
                        }

                        $m++;
                    }
                }

                if (empty($status) || $status == "active") {
                    $query .= ") AND " . $wpdb -> prefix . $SubscribersList -> table . ".active = 'Y'";
                } elseif ($status == "inactive") {
                    $query .= ") AND " . $wpdb -> prefix . $SubscribersList -> table . ".active = 'N'";
                } elseif ($status == "all") {
                    $query .= ")";
                }

                $query .= " AND (" . $wpdb -> prefix . $SubscribersList -> table . ".paid_sent < " . $wpdb -> prefix . $Mailinglist -> table . ".maxperinterval
                        OR " . $wpdb -> prefix . $Mailinglist -> table . ".maxperinterval IS NULL OR " . $wpdb -> prefix . $Mailinglist -> table . ".maxperinterval = '')";

                // Check if "Filter by custom fields" was selected
                if (!empty($_POST['dofieldsconditions'])) {
                    $fields = array_filter($_POST['fields']);
                    $scopeall = (empty($_POST['fieldsconditionsscope']) || $_POST['fieldsconditionsscope'] == "all") ? true : false;
                    $condquery = map_deep($_POST['condquery'], 'sanitize_text_field');
                    $fieldsquery = $Subscriber -> get_segmented_query($fields, $scopeall, $condquery);
                    $query .= $fieldsquery;
                }

                if (!empty($_POST['daterange']) && $_POST['daterange'] == "Y") {
                    if (!empty($_POST['daterangefrom']) && !empty($_POST['daterangeto'])) {
                        $daterangefrom = date_i18n("Y-m-d H:i:s", strtotime(sanitize_text_field($_POST['daterangefrom'])));
                        $daterangeto = date_i18n("Y-m-d H:i:s", strtotime(sanitize_text_field($_POST['daterangeto'])));
                        $query .= " AND (" . $wpdb -> prefix . $Subscriber -> table . ".created >= '" . esc_sql($daterangefrom) . "' AND " . $wpdb -> prefix . $Subscriber -> table . ".created <= '" . esc_sql($daterangeto) . "')";
                    }
                }

                if (!empty($_POST['countries'])) {
                    if (!empty($_POST['selectedcountries']) && is_array($_POST['selectedcountries'])) {
                        $countries = implode("', '", map_deep($_POST['selectedcountries'], 'sanitize_text_field'));
                        $query .= " AND (" . $wpdb -> prefix . $Subscriber -> table . ".country IN ('" . esc_sql($countries) . "'))";
                    }
                }
            }

            $query_hash = md5($query);
            if ($ob_subscribers = $this -> get_cache($query_hash)) {
                $subscribers = $ob_subscribers;
            } else {
                if(!empty($query)) {
                    $subscribers = $wpdb -> get_results($query);
                }
                $this -> set_cache($query_hash, $subscribers);
            }

            if (!empty($subscribers)) {
                $subscribercount = count($subscribers);
            }


            if (!empty($users_count)) {
                $subscribercount += $users_count;
                update_option('newsletters_eligible_users_count_tmp', maybe_serialize($users_list));
            }
            else {
                delete_option('newsletters_eligible_users_count_tmp');
            }

            if (!empty($subscribercount)) {
                do_action('newsletters_admin_createnewsletter_subscribercount_result', $subscribercount);
                update_option('newsletters_subscribercount', $query);

                echo '<p><a href="" onclick="jQuery.colorbox({width:\'80%\', height:\'80%\', title:\'' . __('Selected Subscribers', 'wp-mailinglist') . '\', href:\'' . admin_url('admin-ajax.php?action=newsletters_subscribercountdisplay&security=' . wp_create_nonce('subscribercountdisplay')) . '\'}); return false;"><i class="fa-solid fa-eye"></i> ' . $subscribercount . ' ' . __('emails total', 'wp-mailinglist') . '</a></p>';
            } else {
                echo 0;
            }

            exit();
            die();
        }


        function is_block_editor() {
            global $post;

            if (apply_filters('replace_editor', false, $post) !== true) {
                if (function_exists('use_block_editor_for_post')) {
                    if (use_block_editor_for_post($post)) {
                        return true;
                    }
                }
            }

            return false;
        }

        function edit_form_top($post = null) {
            $custompostslug = $this -> get_option('custompostslug');
            if (!empty($post -> post_type) && $post -> post_type == $custompostslug) {
                $this -> render('edit-form-top', array('post' => $post), true, 'admin');
            }
        }

        function ajax_subscribercount_blockeditor($count = true) {

            check_ajax_referer('subscribercount_blockeditor', 'security');

            if (!current_user_can('newsletters_subscribers')) {
                wp_die(__('You do not have permission', 'wp-mailinglist'));
            }

            ob_start();
            $data = $_POST;

            $status = (empty($data['newsletters_status'])) ? 'active' : $data['newsletters_status'];

            global $wpdb, $Db, $Field, $Subscriber, $Mailinglist, $SubscribersList;
            $subscribercount = 0;

            if (!empty($data['newsletters_groups'])) {
                foreach ($data['newsletters_groups'] as $group_key => $group_id) {
                    $Db -> model = $Mailinglist -> model;

                    if ($lists = $Db -> find_all(array('group_id' => $group_id), array('id'))) {
                        foreach ($lists as $list) {
                            $data['newsletters_mailinglists'][] = $list -> id;
                        }
                    }
                }
            }

            // Count the users based on roles
            $users_count = 0;
            if (!empty($data['newsletters_roles'])) {
                if ($count_users = count_users()) {
                    foreach ($count_users['avail_roles'] as $role => $count) {
                        if (in_array($role, $data['newsletters_roles'])) {
                            $users_count += (int) $count;
                        }
                    }
                }
            }

            if (!empty($data['newsletters_mailinglists'])) {
                $query = "SELECT DISTINCT " . $wpdb -> prefix . $Subscriber -> table . ".id FROM " . $wpdb -> prefix . "" . $SubscribersList -> table . " LEFT JOIN
                        " . $wpdb -> prefix . "" . $Subscriber -> table . " ON
                        " . $wpdb -> prefix . "" . $SubscribersList -> table . ".subscriber_id = " . $wpdb -> prefix . "" . $Subscriber -> table . ".id LEFT JOIN
                        " . $wpdb -> prefix . $Mailinglist -> table . " ON " . $wpdb -> prefix . $SubscribersList -> table . ".list_id = " . $wpdb -> prefix . $Mailinglist -> table . ".id LEFT JOIN
                        " . $wpdb -> prefix . $this -> SubscribersOption() -> table . " ON " . $wpdb -> prefix . $Subscriber -> table . ".id = " . $wpdb -> prefix . $this -> SubscribersOption() -> table . ".subscriber_id WHERE (";

                $m = 1;
                foreach ($data['newsletters_mailinglists'] as $mailinglist_id) {
                    $query .= "" . $wpdb -> prefix . $SubscribersList -> table . ".list_id = '" . esc_sql($mailinglist_id) . "'";

                    if ($m < count($data['newsletters_mailinglists'])) {
                        $query .= " OR ";
                    }

                    $m++;
                }

                if (empty($status) || $status == "active") {
                    $query .= ") AND " . $wpdb -> prefix . $SubscribersList -> table . ".active = 'Y'";
                } elseif ($status == "inactive") {
                    $query .= ") AND " . $wpdb -> prefix . $SubscribersList -> table . ".active = 'N'";
                } elseif ($status == "all") {
                    $query .= ")";
                }

                $query .= " AND (" . $wpdb -> prefix . $SubscribersList -> table . ".paid_sent < " . $wpdb -> prefix . $Mailinglist -> table . ".maxperinterval
                        OR " . $wpdb -> prefix . $Mailinglist -> table . ".maxperinterval IS NULL OR " . $wpdb -> prefix . $Mailinglist -> table . ".maxperinterval = '')";

                // Check if "Filter by custom fields" was selected
                if (!empty($data['newsletters_dofieldsconditions'])) {
                    $fields = array_filter($data['newsletters_fields']);
                    $scopeall = (empty($data['newsletters_fieldsconditionsscope']) || $data['newsletters_fieldsconditionsscope'] == "all") ? true : false;
                    $condquery = $data['newsletters_condquery'];
                    $fieldsquery = $Subscriber -> get_segmented_query($fields, $scopeall, $condquery);
                    $query .= $fieldsquery;
                }

                if (!empty($data['newsletters_daterange']) && $data['newsletters_daterange'] == "Y") {
                    if (!empty($data['newsletters_daterangefrom']) && !empty($data['newsletters_daterangeto'])) {
                        $daterangefrom = date_i18n("Y-m-d H:i:s", strtotime($data['newsletters_daterangefrom']));
                        $daterangeto = date_i18n("Y-m-d H:i:s", strtotime($data['newsletters_daterangeto']));
                        $query .= " AND (" . $wpdb -> prefix . $Subscriber -> table . ".created >= '" . $daterangefrom . "' AND " . $wpdb -> prefix . $Subscriber -> table . ".created <= '" . $daterangeto . "')";
                    }
                }

                if (!empty($data['newsletters_countries'])) {
                    if (!empty($data['newsletters_selectedcountries']) && is_array($data['newsletters_selectedcountries'])) {
                        $countries = implode("', '", $data['newsletters_selectedcountries']);
                        $query .= " AND (" . $wpdb -> prefix . $Subscriber -> table . ".country IN ('" . $countries . "'))";
                    }
                }

                $query_hash = md5($query);
                if ($ob_subscribers = $this -> get_cache($query_hash)) {
                    $subscribers = $ob_subscribers;
                } else {
                    $subscribers = $wpdb -> get_results($query);
                    $this -> set_cache($query_hash, $subscribers);
                }

                if (!empty($subscribers)) {
                    $subscribercount = count($subscribers);
                }
            }

            if (!empty($users_count)) {
                $subscribercount += $users_count;
            }

            if (!empty($subscribercount)) {
                do_action('newsletters_admin_createnewsletter_subscribercount_result', $subscribercount);
                update_option('newsletters_subscribercount', $query);

                $data = array(
                    'success' 		=>	true,
                    'count'			=>	$subscribercount,
                    'message'		=>	'<p><a href="" onclick="jQuery.colorbox({width:\'80%\', height:\'80%\', title:\'' . __('Selected Subscribers', 'wp-mailinglist') . '\', href:\'' . admin_url('admin-ajax.php?action=newsletters_subscribercountdisplay&security=' . wp_create_nonce('subscribercountdisplay')) . '\'}); return false;"><i class="fa-solid fa-eye"></i> ' . $subscribercount . ' ' . __('emails total', 'wp-mailinglist') . '</a></p>',
                );
            } else {
                $data = array(
                    'success'		=>	false,
                    'count'			=>	0,
                    'message'		=>	'<p><i class="fa-solid fa-triangle-exclamation fa-fw"></i> ' . __('No subscribers to send to', 'wp-mailinglist') . '</p>',
                );
            }

            $process = ob_get_clean();
            $data['process'] = $process;
            echo json_encode($data);

            exit();
            die();
        }

        function ajax_managementsubscribe() {

            check_ajax_referer('managementsubscribe', 'security');

            global $wpdb, $Db, $Authnews, $Subscriber, $Mailinglist;

            $errors = array();
            $success = false;
            $successmessage = "";
            $otherlists = array();

            if ($mailinglists = $Mailinglist -> select()) {
                foreach ($mailinglists as $mailinglist_id => $mailinglist_title) {
                    $otherlists[] = $mailinglist_id;
                }
            }

            if (!empty($_POST['subscriber_id']) && !empty($_POST['mailinglist_id'])) {
                $Db -> model = $Subscriber -> model;

                if ($subscriber = $Db -> find(array('id' => (int) $_POST['subscriber_id']), false, false, true, true, false)) {

                    $data = (array) $subscriber;

                    $data['email'] = $subscriber -> email;
                    $data['format'] = $subscriber -> format;
                    $data['cookieauth'] = $Authnews -> read_cookie();
                    $Db -> model = $Mailinglist -> model;

                    if ($mailinglist = $Db -> find(array('id' => (int) $_POST['mailinglist_id']))) {
                        $data['mailinglists'] = $data['list_id'] = array((int) $_POST['mailinglist_id']);

                        if ($mailinglist -> paid == "Y") {
                            $data['active'] = "N";
                        } else {
                            $data['active'] = "Y";
                        }
                    }

                    do_action('newsletters_management_subscribe_before', $data);

                    if ($Subscriber -> optin($data, false, false, false, false)) {
                        $success = true;

                        do_action('newsletters_management_subscribe_success', $data);

                        $this -> delete_all_cache('all');
                        $Db -> model = $Subscriber -> model;
                        $subscriber = $Subscriber -> find(array('id' => $subscriber -> id), false, false, true, true, false);

                        if ($mailinglist -> paid == "Y") {
                            $successmessage = __('Subscription successful, please click the "Pay Now" button under current subscriptions to make a payment and activate your subscription.', 'wp-mailinglist');
                        } else {
                            $successmessage = __('Subscription successful and activated.', 'wp-mailinglist');
                        }
                    } else {
                        $errors[] = __('Subscription was not successful.', 'wp-mailinglist');
                    }

                    // Other lists…
                    $subscribedlists = $Subscriber -> mailinglists($subscriber -> id, false, false, false);
                    $managementshowprivate = $this -> get_option('managementshowprivate');
                    $alllists = $Mailinglist -> select(((!empty($managementshowprivate)) ? true : false));
                    $otherlists = array();

                    $otherlists = array();
                    if (!empty($alllists)) {
                        foreach ($alllists as $alist_id => $alist_title) {
                            if (empty($subscribedlists) || (!empty($subscribedlists) && !in_array($alist_id, $subscribedlists))) {
                                $otherlists[] = $alist_id;
                            }
                        }
                    }
                } else {
                    $errors[] = __('Subscriber cannot be read.', 'wp-mailinglist');
                }
            } else {
                $errors[] = __('No subscriber/mailing list data posted.', 'wp-mailinglist');
            }

            $this -> render('management' . DS . 'newsubscriptions', array('subscriber' => $subscriber, 'success' => $success, 'successmessage' => $successmessage, 'errors' => $errors, 'otherlists' => $otherlists), true, 'default');

            exit();
            die();
        }

        function ajax_managementactivate() {

            check_ajax_referer('managementactivate', 'security');

            $success = false;
            $successmessage = "";
            $errors = array();

            if (!empty($_POST)) {
                if (!empty($_POST['subscriber_id']) && !empty($_POST['mailinglist_id']) && !empty($_POST['activate'])) {
                    global $wpdb, $Db, $Subscriber, $SubscribersList, $Html, $Authnews, $Mailinglist, $Unsubscribe;

                    $Db -> model = $Subscriber -> model;
                    if ($subscriber = $Db -> find(array('id' => (int) $_POST['subscriber_id']), false, false, true, true, false)) {
                        if ($subscriber -> id == $_POST['subscriber_id']) {
                            $Db -> model = $Mailinglist -> model;
                            $query = "SELECT * FROM " . $wpdb -> prefix . $Mailinglist -> table . " WHERE `id` = '" . esc_sql($_POST['mailinglist_id']) . "'";
                            $mailinglist = $wpdb -> get_row($query);

                            $paid = $mailinglist -> paid;
                            $subscriber -> mailinglist_id = $mailinglist -> id;
                            $Db -> model = $SubscribersList -> model;

                            if ($_POST['activate'] == "N") {
                                if (empty($subscriber -> mandatory) || $subscriber -> mandatory != "Y") {
                                    if ($Db -> delete_all(array('subscriber_id' => $_POST['subscriber_id'], 'list_id' => $_POST['mailinglist_id']))) {
                                        $Db -> model = $Unsubscribe -> model;
                                        $unsubscribe_data = array('email' => $subscriber -> email, 'mailinglist_id' => $_POST['mailinglist_id'], 'comments' => $_POST['comments']);
                                        $_POST[$this -> pre . 'comments'] = $_POST['comments'];
                                        $Db -> save($unsubscribe_data, true);

                                        $Db -> model = $this -> Autoresponderemail() -> model;
                                        $Db -> delete_all(array('subscriber_id' => $_POST['subscriber_id'], 'list_id' => $_POST['mailinglist_id']));

                                        //send the administrator a notice
                                        $this -> admin_unsubscription_notification($subscriber, $_POST['mailinglist_id']);
                                        $this -> user_unsubscription_notification($subscriber, array($_POST['mailinglist_id']));

                                        //Should the subscriber be deleted?
                                        $deleted = false;
                                        if ($this -> get_option('unsubscribedelete') == "Y") {
                                            $subscribedlists = $Subscriber -> mailinglists($subscriber -> id);	//all subscribed mailing lists
                                            if (empty($subscribedlists) || !is_array($subscribedlists) || count($subscribedlists) <= 0) {
                                                $Db -> model = $Subscriber -> model;
                                                $Db -> delete($subscriber -> id);
                                                $deleted = true;
                                            }
                                        }

                                        $this -> delete_all_cache('all');

                                        if (!empty($deleted) || $deleted == true) {
                                            $message = __('You were deleted since no subscriptions remained but you can resubscribe at any time.', 'wp-mailinglist');

                                            $afterdeleteurl = $Html -> retainquery('updated=1&success=' . $message, $this -> get_managementpost(true));
                                            $this -> redirect($afterdeleteurl, 'success', false, true);
                                        } else {
                                            $success = true;
                                            $successmessage = __('Subscription has been removed.', 'wp-mailinglist');
                                            $subscriber = $Authnews -> logged_in($subscriber -> id);
                                        }
                                    } else {
                                        $errors[] = __('Subscription could not be removed.', 'wp-mailinglist');
                                    }
                                } else {
                                    $errors[] = __('You are a mandatory subscriber and cannot unsubscribe', 'wp-mailinglist');
                                }
                            } else {
                                if (false && $this -> get_option('requireactivate') == "Y" || $mailinglist -> paid == "Y") {
                                    $success = true;
                                    $successmessage = __('A confirmation email has been sent through to your email address.', 'wp-mailinglist');
                                    $this -> subscription_confirm($subscriber);
                                } else {
                                    $Db -> model = $SubscribersList -> model;

                                    if ($Db -> save_field('active', "Y", array('subscriber_id' => $_POST['subscriber_id'], 'list_id' => $_POST['mailinglist_id']))) {
                                        $success = true;
                                        $successmessage = __('Subscription has been activated.', 'wp-mailinglist');
                                        $this -> delete_all_cache('all');
                                        $subscriber = $Authnews -> logged_in($subscriber -> id);
                                    } else {
                                        $errors[] = __('Subscription could not be activated.', 'wp-mailinglist');
                                    }
                                }
                            }
                        } else {
                            $errors[] = __('You are logged in as a different subscriber.', 'wp-mailinglist');
                        }
                    } else {
                        $errors[] = __('You are not currently logged in.', 'wp-mailinglist');
                    }
                } else {
                    $errors[] = __('No subscriber/mailing list data posted.', 'wp-mailinglist');
                }
            } else {
                $errors[] = __('No data was posted.', 'wp-mailinglist');
            }

            $this -> render('management' . DS . 'currentsubscriptions', array('subscriber' => $subscriber, 'errors' => $errors, 'success' => $success, 'successmessage' => $successmessage), true, 'default');

            exit();
            die();
        }

        function autoresponders_form_send($subscriber = null, $form = null) {
            global $wpdb, $Db, $HistoriesAttachment, $Subscriber, $SubscribersList, $Html, $Email;

            do_action('newsletters_autoresponders_form_send', $subscriber, $form);

            if (!empty($subscriber) && !empty($form)) {
                $subscriber_id = $subscriber -> id;
                if ($autorespondersforms = $this -> AutorespondersForm() -> find_all(array('form_id' => $form -> id))) {
                    foreach ($autorespondersforms as $autorespondersform) {
                        if ($autoresponder = $this -> Autoresponder() -> find(array('id' => $autorespondersform -> autoresponder_id, 'sendauto' => 1))) {
                            if (!empty($autoresponder -> status) && $autoresponder -> status == "active") {
                                //Send the 0 delay autoresponders right now
                                if (!defined('NEWSLETTERS_IMPORTING') && (empty($autoresponder -> delay) || $autoresponder -> delay <= 0)) {
                                    $Db -> model = $SubscribersList -> model;
                                    $subscriberslist = $Db -> find(array('subscriber_id' => $subscriber -> id, 'form_id' => $form -> id));

                                    if (!empty($subscriberslist -> active) && $subscriberslist -> active == "Y") {
                                        $Db -> model = $this -> Autoresponderemail() -> model;
                                        if ((!empty($autoresponder -> alwayssend) && $autoresponder -> alwayssend == "Y") && (!$Db -> find(array('subscriber_id' => $subscriber -> id, 'autoresponder_id' => $autoresponder -> id)))) {
                                            $history = $this -> History() -> find(array('id' => $autoresponder -> history_id));
                                            $history -> attachments = array();
                                            $attachmentsquery = "SELECT id, title, filename FROM " . $wpdb -> prefix . $HistoriesAttachment -> table . " WHERE history_id = '" . $history -> id . "'";

                                            if ($attachments =  $wpdb -> get_results($attachmentsquery)) {
                                                foreach ($attachments as $attachment) {
                                                    $history -> attachments[] = array(
                                                        'id'					=>	$attachment -> id,
                                                        'title'					=>	$attachment -> title,
                                                        'filename'				=>	$attachment -> filename,
                                                    );
                                                }
                                            }

                                            $eunique = $Html -> eunique($subscriber, $history -> id);

                                            $autoresponderemail_data = array(
                                                'autoresponder_id'				=>	$autoresponder -> id,
                                                'form_id'						=>	$form -> id,
                                                'subscriber_id'					=>	$subscriber -> id,
                                                'senddate'						=>	date_i18n("Y-m-d H:i:s", strtotime($Html -> gen_date("Y-m-d H:i:s", false, false, true) . " +" . $autoresponder -> delay . " " . $autoresponder -> delayinterval)),
                                                'status'						=>	'unsent',
                                            );

                                            $this -> Autoresponderemail() -> save($autoresponderemail_data, true);
                                            global $wpdb;
                                            $ae_id = $wpdb -> insert_id;

                                            $Db -> model = $Email -> model;
                                            $message = $this -> render_email('send', array('message' => $history -> message, 'subject' => $history -> subject, 'subscriber' => $subscriber, 'history_id' => $history -> id, 'post_id' => $history -> post_id, 'eunique' => $eunique), false, $this -> htmltf($subscriber -> format), true, $history -> theme_id);

                                            if ($this -> execute_mail($subscriber, false, $history -> subject, $message, $history -> attachments, $history -> id, $eunique, true, "newsletter")) {
                                                $this -> Autoresponderemail() -> save_field('status', "sent", array('id' => $ae_id));
                                                $this -> History() -> save_field('sent', 1, array('id' => $history -> id));
                                            }
                                        }
                                    }
                                    //Save the 1+ delay autoresponders to send later
                                } else {
                                    $Db -> model = $this -> Autoresponderemail() -> model;
                                    if ((!empty($autoresponder -> alwayssend) && $autoresponder -> alwayssend == "Y") && !$Db -> find(array('subscriber_id' => $subscriber -> id, 'autoresponder_id' => $autoresponder -> id))) {
                                        if (empty($autoresponder -> delay) || empty($autoresponder -> delayinterval)) {
                                            $senddate = date_i18n("Y-m-d H:i:s");
                                        } else {
                                            //$senddate = date_i18n("Y-m-d H:i:s", strtotime($subscriber -> created . " +" . $autoresponder -> delay . " " . $autoresponder -> delayinterval));
                                            $senddate = date_i18n("Y-m-d H:i:s", strtotime($Html -> gen_date("Y-m-d H:i:s", false, false, true) . " +" . $autoresponder -> delay . " " . $autoresponder -> delayinterval));
                                        }

                                        $autoresponderemail_data = array(
                                            'autoresponder_id'				=>	$autoresponder -> id,
                                            'form_id'						=>	$form -> id,
                                            'subscriber_id'					=>	$subscriber -> id,
                                            'status'						=>	'unsent',
                                            'senddate'						=>	$senddate,
                                        );

                                        $this -> Autoresponderemail() -> save($autoresponderemail_data, true);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        function autoresponders_send($subscriber = null, $mailinglist = null) {
            global $wpdb, $Db, $HistoriesAttachment, $Subscriber, $SubscribersList, $Html, $Email;

            do_action('newsletters_autoresponders_send', $subscriber, $mailinglist);

            if (!empty($subscriber) && !empty($mailinglist)) {
                $subscriber_id = $subscriber -> id;
                if ($autoresponserslists = $this -> AutorespondersList() -> find_all(array('list_id' => $mailinglist -> id))) {
                    foreach ($autoresponserslists as $al) {
                        $Db -> model = $this -> Autoresponder() -> model;
                        if ($autoresponder = $Db -> find(array('id' => $al -> autoresponder_id, 'sendauto' => 1))) {
                            if (!empty($autoresponder -> status) && $autoresponder -> status == "active") {
                                //Send the 0 delay autoresponders right now
                                if (!defined('NEWSLETTERS_IMPORTING') && (empty($autoresponder -> delay) || $autoresponder -> delay <= 0)) {
                                    $Db -> model = $SubscribersList -> model;
                                    $subscriberslist = $Db -> find(array('subscriber_id' => $subscriber -> id, 'list_id' => $mailinglist -> id));
                                    if (!empty($subscriberslist -> active) && $subscriberslist -> active == "Y") {
                                        $Db -> model = $this -> Autoresponderemail() -> model;
                                        if ((!empty($autoresponder -> alwayssend) && $autoresponder -> alwayssend == "Y") && (!$Db -> find(array('subscriber_id' => $subscriber -> id, 'autoresponder_id' => $autoresponder -> id)))) {
                                            $history = $this -> History() -> find(array('id' => $autoresponder -> history_id));
                                            $history -> attachments = array();
                                            $attachmentsquery = "SELECT id, title, filename FROM " . $wpdb -> prefix . $HistoriesAttachment -> table . " WHERE history_id = '" . $history -> id . "'";

                                            if ($attachments =  $wpdb -> get_results($attachmentsquery)) {
                                                foreach ($attachments as $attachment) {
                                                    $history -> attachments[] = array(
                                                        'id'					=>	$attachment -> id,
                                                        'title'					=>	$attachment -> title,
                                                        'filename'				=>	$attachment -> filename,
                                                    );
                                                }
                                            }

                                            $subscriber -> mailinglist_id = $mailinglist -> id;
                                            $eunique = $Html -> eunique($subscriber, $history -> id);

                                            $autoresponderemail_data = array(
                                                'autoresponder_id'				=>	$autoresponder -> id,
                                                'list_id'						=>	$mailinglist -> id,
                                                'subscriber_id'					=>	$subscriber -> id,
                                                'senddate'						=>	date_i18n("Y-m-d H:i:s", strtotime($Html -> gen_date("Y-m-d H:i:s", false, false, true) . " +" . $autoresponder -> delay . " " . $autoresponder -> delayinterval)),
                                                'status'						=>	'unsent',
                                            );

                                            $this -> Autoresponderemail() -> save($autoresponderemail_data, true);
                                            global $wpdb;
                                            $ae_id = $wpdb -> insert_id;

                                            $Db -> model = $Email -> model;
                                            $message = $this -> render_email('send', array('message' => $history -> message, 'subject' => $history -> subject, 'subscriber' => $subscriber, 'history_id' => $history -> id, 'post_id' => $history -> post_id, 'eunique' => $eunique), false, $this -> htmltf($subscriber -> format), true, $history -> theme_id);

                                            if ($this -> execute_mail($subscriber, false, $history -> subject, $message, $history -> attachments, $history -> id, $eunique, true, "newsletter")) {
                                                $this -> Autoresponderemail() -> save_field('status', "sent", array('id' => $ae_id));
                                                $this -> History() -> save_field('sent', 1, array('id' => $history -> id));
                                            }
                                        }
                                    }
                                    //Save the 1+ delay autoresponders to send later
                                } else {
                                    $Db -> model = $SubscribersList -> model;
                                    $subscriberslist = $Db -> find(array('subscriber_id' => $subscriber -> id, 'list_id' => $mailinglist -> id));
                                    if (!empty($subscriberslist -> active) && $subscriberslist -> active == "Y") {
                                        $Db -> model = $this -> Autoresponderemail() -> model;
                                        if ((!empty($autoresponder -> alwayssend) && $autoresponder -> alwayssend == "Y") && !$Db -> find(array('subscriber_id' => $subscriber -> id, 'autoresponder_id' => $autoresponder -> id))) {
                                            if (empty($autoresponder -> delay) || empty($autoresponder -> delayinterval)) {
                                                $senddate = date_i18n("Y-m-d H:i:s");
                                            } else {
                                                $created_date = (!empty($subscriber -> created) && $subscriber -> created != "0000-00-00 00:00:00") ? $subscriber -> created : false;

                                                $senddate = date_i18n("Y-m-d H:i:s", strtotime($Html -> gen_date("Y-m-d H:i:s", false, false, true) . " +" . $autoresponder -> delay . " " . $autoresponder -> delayinterval));
                                                //$senddate = date_i18n("Y-m-d H:i:s", strtotime($created_date . " +" . $autoresponder -> delay . " " . $autoresponder -> delayinterval));
                                            }

                                            $autoresponderemail_data = array(
                                                'autoresponder_id'				=>	$autoresponder -> id,
                                                'list_id'						=>	$mailinglist -> id,
                                                'subscriber_id'					=>	$subscriber -> id,
                                                'status'						=>	'unsent',
                                                'senddate'						=>	$senddate,
                                            );

                                            $this -> Autoresponderemail() -> save($autoresponderemail_data, true);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }


        function paidsubscription_form($subscriber = null, $mailinglist = null, $autosubmit = true, $target = "_self", $extend = false, $pmethod = "paypal") {
            global $Html;

            if (!empty($subscriber) && !empty($mailinglist)) {
                if ($pmethod == "2co") {
                    $checkoutdata = array(
                        'sid'					=>	$this -> get_option('tcovendorid'),
                        'cart_order_id'			=>	$subscriber -> id . $mailinglist -> id,
                        'total'					=>	$mailinglist -> price,
                        'id_type'				=>	1,
                        'c_prod'				=>	$mailinglist -> id . ',1',
                        'c_name'				=>	__($mailinglist -> title),
                        'c_description'			=>	__($mailinglist -> title),
                        'c_price'				=>	$mailinglist -> price,
                        'quantity'				=>	1,
                        'return_url'			=>	home_url() . '/?' . $this -> pre . 'method=twocheckout',
                        'x_receipt_link_url'	=>	home_url() . '/?' . $this -> pre . 'method=twocheckout',
                        $this -> pre . 'method'	=>	'twocheckout',
                        'subscriber_id'			=>	$subscriber -> id,
                        'subscriber_email'		=>	$subscriber -> email,
                        'mailinglist_id'		=>	$mailinglist -> id,
                        'fixed'					=>	'Y',
                        'demo'					=>	$this -> get_option('tcodemo'),
                        'currency_code'			=>	$this -> get_option('currency'),
                        'email'					=>	$subscriber -> email,
                    );

                    if (!empty($extend)) {
                        $checkoutdata['subscription_extend'] = 1;
                    }

                    $formid = '2co_paidsubscriptionform' . $mailinglist -> id;
                    $this -> render('twocheckout-form', array('checkoutdata' => $checkoutdata, 'extend' => $extend, 'autosubmit' => $autosubmit, 'formid' => $formid, 'target' => $target));
                } elseif ($pmethod == "paypal") {
                    $pp_return = ($this -> get_option('paypalsubscriptions') == "Y" && $mailinglist -> interval != "once") ?
                        $Html -> retainquery('method=paidsubscriptionsuccess', $this -> get_managementpost(true)) :
                        $Html -> retainquery('method=paidsubscriptionsuccess', $this -> get_managementpost(true));

                    $checkoutdata = array(
                        'charset'							=>	get_option('blog_charset'),
                        'return'							=>	$pp_return,
                        'rm'								=>	2,
                        'notify_url'						=>	home_url() . '/?' . $this -> pre . 'method=paypal',
                        'cbt'								=>	__('Click here to complete your order', 'wp-mailinglist'),
                        'currency_code'						=>	$this -> get_option('currency'),
                        'business'							=>	$this -> get_option('paypalemail'),
                        'item_name'							=>	__($mailinglist -> title),
                        'item_number'						=>	$mailinglist -> id,
                        'custom'							=>	array(
                            'subscriber_id'			=>	$subscriber -> id,
                            'mailinglist_id'		=>	$mailinglist -> id,
                        ),
                        'no_shipping'						=>	1,
                        'no_note'							=>	1,
                        'bn'								=>	"TribulantSoftware_SP",
                    );

                    if (!empty($extend)) {
                        $checkoutdata['custom']['subscription_extend'] = 1;
                    }

                    //$checkoutdata['custom'] = urlencode(maybe_serialize($checkoutdata['custom']));
                    $checkoutdata['custom'] = urlencode(json_encode($checkoutdata['custom']));

                    if ($this -> get_option('paypalsubscriptions') == "Y" && $mailinglist -> interval != "once" && $extend == false) {
                        $checkoutdata['cmd'] = "_xclick-subscriptions";
                        $checkoutdata['a3'] = number_format($mailinglist -> price, 2, '.', '');
                        $checkoutdata['p3'] = $Html -> getpptd($mailinglist -> interval);
                        $checkoutdata['t3'] = $Html -> getppt($mailinglist -> interval);
                        $checkoutdata['src'] = 1;
                        $checkoutdata['sra'] = 1;
                    } else {
                        $checkoutdata['cmd'] = "_xclick";
                        $checkoutdata['amount'] = $mailinglist -> price;
                        $checkoutdata['quantity'] = 1;
                    }

                    $formid = 'paypal_paidsubscriptionform' . $mailinglist -> id;
                    $this -> render('paypal-form', array('checkoutdata' => $checkoutdata, 'extend' => $extend, 'autosubmit' => $autosubmit, 'formid' => $formid, 'target' => $target));
                }
            }
        }

        function process_unsubscribe($subscriber = null, $mailinglists = null, $history_id = null) {
            global $wpdb, $Db, $Mailinglist, $Subscriber, $SubscribersList, $Authnews, $Unsubscribe,
                   $newsletters_errors, $Field, $Html;

            $unsubscribeemails = $this -> get_option('unsubscribeemails');

            if (empty($mailinglists)) {
                $subscribedlists = $Subscriber -> mailinglists($subscriber -> id, false, false, false);	//all subscribed mailing lists
            } else {
                $subscribedlists = $Subscriber -> mailinglists($subscriber -> id, $mailinglists, false, false);
            }

            $this -> user_unsubscription_notification($subscriber, $mailinglists);

            foreach ($subscribedlists as $ukey => $unsubscribelist_id) {
                $Db -> model = $Mailinglist -> model;
                $mailinglist = $Db -> find(array('id' => $unsubscribelist_id));
                $subscriber -> mailinglist_id = $unsubscribelist_id;

                if (!empty($unsubscribeemails) && $unsubscribeemails == "multiple") {
                    $this -> admin_unsubscription_notification($subscriber, $unsubscribelist_id);
                }

                if (!empty($subscriber -> id) && !empty($unsubscribelist_id)) {
                    $SubscribersList -> delete_all(array('subscriber_id' => $subscriber -> id, 'list_id' => $unsubscribelist_id));
                    $Db -> model = $this -> Autoresponderemail() -> model;
                    $Db -> delete_all(array('subscriber_id' => $subscriber -> id, 'list_id' => $unsubscribelist_id));

                    unset($subscribedlists[$ukey]);

                    $Db -> model = $Unsubscribe -> model;
                    $unsubscribe_data = array('email' => $subscriber -> email, 'mailinglist_id' => $unsubscribelist_id, 'history_id' => $history_id);
                    $Db -> save($unsubscribe_data, true);
                }
            }

            if (!empty($unsubscribeemails) && $unsubscribeemails == "single") {
                $this -> admin_unsubscription_notification($subscriber, $unsubscribelists);
            }

            do_action('newsletters_subscriber_unsubscribe', $subscriber -> id, $data['unsubscribelists']);

            if ($this -> get_option('unsubscriberemoveallsubscriptions') == "Y") {
                foreach ($subscribedlists as $ukey => $subscribedlist_id) {
                    if (!empty($subscriber -> id) && !empty($subscribedlist_id)) {
                        $SubscribersList -> delete_all(array('subscriber_id' => $subscriber -> id, 'list_id' => $subscribedlist_id));

                        unset($subscribedlists[$ukey]);
                    }
                }
            }

            //Should the subscriber be deleted?
            if ($this -> get_option('unsubscribedelete') == "Y") {
                if (empty($subscribedlists)) {
                    $Db -> model = $Subscriber -> model;
                    $Db -> delete($subscriber -> id);
                    $deleted = true;
                }
            }


            //Should the WP User deleted on unsubscribe?
            if ($this -> get_option('unsubscribewpuserdeletebyuser') == "Y") {
                $useridfrommail = get_user_by( 'email', $subscriber -> email );
                $wpuserid = $useridfrommail->ID;
                require_once(ABSPATH.'wp-admin/includes/user.php' );
                if (!user_can( $wpuserid, 'manage_options' ) ) {
		            // User is an administrator, so avoid the next operation.
		            wp_delete_user($wpuserid);
	            }
            }


            return true;
        }

        function sc_management($atts = array(), $content = null) {
            global $wpdb, $Db, $Mailinglist, $Subscriber, $SubscribersList, $Authnews, $Unsubscribe,
                   $newsletters_errors, $Field, $Html;

            if (!defined('NEWSLETTERS_IS_MANAGEMENT')) {
                define('NEWSLETTERS_IS_MANAGEMENT', true);
            }

            $errors = array();

            $output = "";
            $defaults = array();
            extract(shortcode_atts($defaults, $atts));
            $emailfield = $Field -> email_field();

            ob_start();

            $method = sanitize_text_field(isset($_GET['method']) ? $_GET['method'] : "");
            $method = (!empty($method)) ? $method : false;

            switch ($method) {
                case 'paidsubscription'			:
                    $subscriber_id = sanitize_text_field($_REQUEST['subscriber_id']);
                    $list_id = sanitize_text_field($_REQUEST['list_id']);
                    $extend = sanitize_text_field($_REQUEST['extend']);

                    if (!empty($subscriber_id)) {
                        if (!empty($list_id)) {

                            $subscriber = $Subscriber -> get($subscriber_id);
                            $data = (array) $subscriber;
                            $data['list_id'] = $list_id;
                            $mailinglist = $Mailinglist -> get($list_id);
                            $extend = (empty($extend)) ? false : true;

                            $Field -> validate_optin($data, 'management');

                            if (empty($Field -> errors)) {
                                $this -> render('management' . DS . 'paidsubscription', array('subscriber' => $subscriber, 'mailinglist' => $mailinglist, 'extend' => $extend), true, 'default');
                            } else {
                                $url = $Html -> retainquery('updated=1&error=' . __('Some profile fields are required, please complete them.', 'wp-mailinglist') . '#profile', $this -> get_managementpost(true));
                                $this -> redirect($url);
                            }
                        } else {
                            $errors[] = __('No mailing list was specified', 'wp-mailinglist');
                        }
                    } else {
                        $errors[] = __('No subscriber was specified', 'wp-mailinglist');
                    }

                    break;
                case 'paidsubscriptionsuccess'	:
                    $message = __('Thank you for your payment! Please allow a moment for the subscription to be activated.', 'wp-mailinglist');
                    $this -> redirect($this -> get_managementpost(true), "success", $message);
                    break;
                case 'subscribe'			:

                    $errors = false;
                    $success = false;
                    $id = (int) sanitize_text_field($_GET['id']);

                    if (!empty($id)) {
                        if (!empty($_GET['mailinglists'])) {
                            $Db -> model = $Subscriber -> model;
                            if ($subscriber = $Db -> find(array('id' => $id))) {

                                $subscriber -> mailinglists = explode(",", esc_html($_GET['mailinglists']));
                                $subscriber -> active = "Y";

                                if ($Subscriber -> optin($subscriber, false, false, false)) {
                                    $success = true;

                                    $Authnews -> set_emailcookie($subscriber -> email, "+30 days");
                                    if (empty($subscriber -> cookieauth)) {
                                        $subscriberauth = $Authnews -> gen_subscriberauth();
                                        $Db -> model = $Subscriber -> model;
                                        $Db -> save_field('cookieauth', $subscriberauth, array('id' => $subscriber -> id));
                                    } else {
                                        $subscriberauth = $subscriber -> cookieauth;
                                    }

                                    $Authnews -> set_cookie($subscriberauth, "+30 days", true);
                                } else {
                                    $errors = $Subscriber -> errors;
                                }
                            } else {
                                $errors[] = __('Subscriber cannot be read', 'wp-mailinglist');
                            }
                        } else {
                            $errors[] = __('No list was specified', 'wp-mailinglist');
                        }
                    } else {
                        $errors[] = __('No subscriber was specified', 'wp-mailinglist');
                    }

                    $this -> render('management' . DS . 'subscribe', array('subscriber' => $subscriber, 'errors' => $errors, 'success' => $success), true, 'default');
                    break;
                case 'resubscribe'			:
                    $errors = false;
                    $success = false;

                    if (!empty($_GET['email']) && (!empty($_GET['mailinglists']))) {

                        $Db -> model = $Subscriber -> model;
                        if (!$subscriber = $Db -> find(array('email' => $_GET['email']))) {
                            $subscriber = array();
                        }

                        $subscriber = (array) $subscriber;

                        $subscriber['email'] = esc_html($_GET['email']);
                        $subscriber['mailinglists'] = explode(",", esc_html($_GET['mailinglists']));
                        $subscriber['active'] = "Y";

                        if ($Subscriber -> optin($subscriber, false, false, false)) {
                            $success = true;

                            $Authnews -> set_emailcookie($subscriber -> email, "+30 days");
                            if (empty($subscriber -> cookieauth)) {
                                $subscriberauth = $Authnews -> gen_subscriberauth();
                                $Db -> model = $Subscriber -> model;
                                $Db -> save_field('cookieauth', $subscriberauth, array('id' => $subscriber -> id));
                            } else {
                                $subscriberauth = $subscriber -> cookieauth;
                            }

                            $Authnews -> set_cookie($subscriberauth, "+30 days", true);
                        } else {
                            $errors = $Subscriber -> errors;
                        }
                    } else {
                        $errors[] = __('Some data is missing, please try again', 'wp-mailinglist');
                    }

                    $this -> render('resubscribe', array('subscriber' => $subscriber, 'errors' => $errors, 'success' => $success), true, 'default');
                    break;
                case 'unsubscribe'			:
                    global $wpdb, $Html, $Authnews, $Db, $Subscriber, $Mailinglist, $SubscribersList;

                    $data = $_REQUEST;
                    $dorender = true;
                    $error = false;
                    $success = false;
                    $deleted = false;
                    $userfile = "-success";

                    $history_id = $data[$this -> pre . 'history_id'];
                    $history = $this -> History() -> find(array('id' => $history_id));
                    $subscriber_id = $data[$this -> pre . 'subscriber_id'];

                    if (!empty($subscriber_id) || !empty($data['user_id'])) {
                        if (($mailinglists = explode(",", $data[$this -> pre . 'mailinglist_id'])) !== false) {
                            //do nothing, it's good...
                            $includeonly = (empty($mailinglists)) ? $history -> mailinglists : $mailinglists;
                            $mailinglists = $Subscriber -> mailinglists($subscriber_id, $includeonly, false, false);
                        } else {
                            $mailinglists = false;
                        }

                        if (!empty($data[$this -> pre . 'subscriber_id'])) {
                            $subscriber_query = "SELECT * FROM " . $wpdb -> prefix . $Subscriber -> table . " WHERE id = '" . $data[$this -> pre . 'subscriber_id'] . "'";

                            $subscriber = $wpdb -> get_row($subscriber_query);

                            if (!empty($subscriber)) {
                                if ($subscriber -> authkey == $_GET['authkey']) {
                                    if (empty($subscriber -> mandatory) || $subscriber -> mandatory == "N") {
                                        /* Management Auth */
                                        if (empty($data['cookieauth'])) {
                                            $Authnews -> set_emailcookie($subscriber -> email);
                                            $subscriberauth = $Authnews -> gen_subscriberauth();
                                            $Db -> model = $Subscriber -> model;
                                            $Db -> save_field('cookieauth', $subscriberauth, array('id' => $subscriber -> id));
                                            $Authnews -> set_cookie($subscriberauth);
                                        }

                                        $subscriber -> mailinglists = $mailinglists;

                                        if (empty($subscriber -> mailinglists)) {
                                            $errors[] = __('This email was not sent to any lists.', 'wp-mailinglist');
                                        }
                                    } else {
                                        $dorender = false;
                                        $errors[] = __('You are a mandatory subscriber and cannot unsubscribe', 'wp-mailinglist');
                                    }
                                } else {
                                    $dorender = false;
                                    $errors[] = __('You are not authorised to use this link', 'wp-mailinglist');
                                }
                            } else {
                                $errors[] = __('Your subscriber record cannot be read, please try again.', 'wp-mailinglist');
                            }
                        } elseif (!empty($data['user_id'])) {
                            if ($user = $this -> userdata($data['user_id'])) {
                                // all good
                                $userfile = "-user";
                            } else {
                                $errors[] = __('User cannot be read', 'wp-mailinglist');
                            }
                        } else {
                            $errors[] = __('No subscriber or user was specified', 'wp-mailinglist');
                        }
                    } else {
                        $errors[] = __('No subscriber ID was specified, please try again.', 'wp-mailinglist');
                    }

                    $clicktrack = $this -> get_option('clicktrack');
                    if (!empty($clicktrack) && $clicktrack == "Y") {
                        $click_data = array(
                            'referer'			=>	"unsubscribe",
                            'history_id'		=>	$_GET[$this -> pre . 'history_id'],
                            'user_id'			=>	$_GET[$this -> pre . 'user_id'],
                            'subscriber_id'		=>	$_GET[$this -> pre . 'subscriber_id'],
                            'device'			=>	$this -> get_device()
                        );

                        $this -> Click() -> save($click_data, true);
                    }

                    if (!empty($data['confirm']) || $this -> get_option('unsubscribeconfirmation') == "N") {
                        $unsubscribeemails = $this -> get_option('unsubscribeemails');
                        $unsubscribelists = $data['unsubscribelists'];

                        if (!empty($data[$this -> pre . 'subscriber_id'])) {
                            if ($this -> get_option('unsubscribeconfirmation') == "N") {
                                $data['unsubscribelists'] = $mailinglists;
                            }

                            if (!empty($data['unsubscribelists'])) {
                                $this -> user_unsubscription_notification($subscriber, $mailinglists);

                                $subscribedlists = $Subscriber -> mailinglists($subscriber -> id);	//all subscribed mailing lists

                                foreach ($data['unsubscribelists'] as $unsubscribelist_id) {
                                    $Db -> model = $Mailinglist -> model;
                                    $mailinglist = $Db -> find(array('id' => $unsubscribelist_id));
                                    $subscriber -> mailinglist_id = $unsubscribelist_id;

                                    if (!empty($unsubscribeemails) && $unsubscribeemails == "multiple") {
                                        $this -> admin_unsubscription_notification($subscriber, $unsubscribelist_id);
                                    }

                                    if (!empty($subscriber -> id) && !empty($unsubscribelist_id)) {
                                        $subscribedlists = array_diff($subscribedlists, array($unsubscribelist_id));
                                        $SubscribersList -> delete_all(array('subscriber_id' => $subscriber -> id, 'list_id' => $unsubscribelist_id));
                                        $Db -> model = $this -> Autoresponderemail() -> model;
                                        $Db -> delete_all(array('subscriber_id' => $subscriber -> id, 'list_id' => $unsubscribelist_id));

                                        $Db -> model = $Unsubscribe -> model;
                                        $unsubscribe_data = array('email' => $subscriber -> email, 'mailinglist_id' => $unsubscribelist_id, 'history_id' => $data[$this -> pre . 'history_id'], 'comments' => $data[$this -> pre . 'comments']);
                                        $Db -> save($unsubscribe_data, true);
                                    }
                                }

                                if (!empty($unsubscribeemails) && $unsubscribeemails == "single") {
                                    $this -> admin_unsubscription_notification($subscriber, $unsubscribelists);
                                }

                                do_action('newsletters_subscriber_unsubscribe', $subscriber -> id, $data['unsubscribelists']);

                                if ($this -> get_option('unsubscriberemoveallsubscriptions') == "Y") {
                                    foreach ($subscribedlists as $subscribedlist_id) {
                                        if (!empty($subscriber -> id) && !empty($subscribedlist_id)) {
                                            $SubscribersList -> delete_all(array('subscriber_id' => $subscriber -> id, 'list_id' => $subscribedlist_id));
                                        }
                                    }
                                }

                                //Should the subscriber be deleted?
                                if ($this -> get_option('unsubscribedelete') == "Y") {
                                    if (empty($subscribedlists) || !is_array($subscribedlists) || count($subscribedlists) <= 0) {
                                        $Db -> model = $Subscriber -> model;
                                        $Db -> delete($subscriber -> id);
                                        $deleted = true;
                                    }
                                }

                                //Should the WP User deleted on unsubscribe?
                                if ($this -> get_option('unsubscribewpuserdeletebyuser') == "Y") {
                                    $useridfrommail = get_user_by( 'email', $subscriber -> email );
                                    $wpuserid = $useridfrommail->ID;
                                    require_once(ABSPATH.'wp-admin/includes/user.php' );
                                    if (!user_can( $wpuserid, 'manage_options' ) ) {
                                        // User is an administrator, so avoid the next operation.
                                        wp_delete_user($wpuserid);
                                    }
                                }

                                $success = true;
                            } else {
                                $errors[] = __('You did not select any list(s) to unsubscribe from.', 'wp-mailinglist');
                                $success = false;
                            }
                        } elseif (!empty($data['user_id'])) {
                            $Db -> model = $Unsubscribe -> model;
                            $unsubscribe_data = array('user_id' => $user -> ID, 'email' => $user -> user_email, 'mailinglist_id' => false, 'history_id' => $data[$this -> pre . 'history_id'], 'comments' => $data[$this -> pre . 'comments']);
                            $Db -> save($unsubscribe_data, true);
                            $success = true;
                            $errors = false;
                        } else {
                            $errors[] = __('No subscriber or user was specified', 'wp-mailinglist');
                        }
                    }

                    // Is the unsubscribe successful?
                    if (!empty($success)) {
                        $unsubscribe_redirect = $this -> get_option('unsubscribe_redirect');
                        if (!empty($unsubscribe_redirect)) {
                            $unsubscribe_redirect_url = $this -> get_option('unsubscribe_redirect_url');
                            if (!empty($unsubscribe_redirect_url)) {
                                $this -> redirect($unsubscribe_redirect_url);
                            }
                        }
                    }

                    $this -> render('unsubscribe' . $userfile, array('subscriber' => $subscriber, 'history' => $history, 'dorender' => $dorender, 'user' => $user, 'data' => $data, 'errors' => $errors, 'success' => $success, 'deleted' => $deleted), true, 'default');
                    break;
                case 'delete'				:

                    global $Authnews, $Db, $Subscriber;

                    $subscriber = $Authnews -> logged_in();
                    $Db -> model = $Subscriber -> model;
                    $Db -> delete($subscriber -> id);
                    $this -> delete_all_cache();

                    $this -> render('management' . DS . 'delete', false, true, 'default');

                    break;
                case 'logout'				:
                    global $wpmljavascript;
                    $subscriberemailauth = $Authnews -> read_emailcookie();
                    $subscriberauth = $Authnews -> read_cookie();

                    $managementauthtype = $this -> get_option('managementauthtype');
                    switch ($managementauthtype) {
                        case 1					:
                            $Authnews -> delete_cookie($Authnews -> cookiename, $subscriberauth);
                            $Authnews -> delete_cookie($Authnews -> emailcookiename, $subscriberemailauth);
                            break;
                        case 2					:
                            $this -> end_session();
                            break;
                        case 3					:
                        default 				:
                            $Authnews -> delete_cookie($Authnews -> cookiename, $subscriberauth);
                            $Authnews -> delete_cookie($Authnews -> emailcookiename, $subscriberemailauth);
                            $this -> end_session();
                            break;
                    }

                    if(! empty($wpmljavascript)){
                        wp_add_inline_script( 'jquery', $wpmljavascript );
                    }
                    $this -> render('management' . DS . 'logout-auth', false, true, 'default');
                    break;
                case 'loginauth'			:
                    if (empty($_GET['email'])) {
                        $subscriberemailauth = $_POST['email'] = $Authnews -> read_emailcookie();
                    } else {
                        $subscriberemailauth = sanitize_text_field($_GET['email']);
                    }

                    $subscriberauth = sanitize_text_field($_GET['subscriberauth']);

                    if (!empty($subscriberemailauth)) {
                        if (!empty($subscriberauth)) {
                            $Db -> model = $Subscriber -> model;
                            if ($subscriber = $Db -> find(array('email' => $subscriberemailauth, 'cookieauth' => $subscriberauth))) {
                                global $wpmljavascript;
                                $Authnews -> set_cookie($subscriber -> cookieauth);
                                $Authnews -> set_emailcookie($subscriberemailauth);
                            } else {
                                $errors[] = __('Authentication failed, please try again.', 'wp-mailinglist');
                            }
                        } else {
                            $errors[] = __('No authentication string passed, please click the link again.', 'wp-mailinglist');
                        }
                    } else {
                        $errors[] = __('No email saved, please try again.', 'wp-mailinglist');
                    }

                    if (empty($errors)) {
                        $this -> render('management' . DS . 'login-auth', array('subscriberauth' => $subscriberauth, 'subscriberemailauth' => $subscriberemailauth), true, 'default');
                    } else {
                        $this -> render('management' . DS . 'login', array('errors' => $errors), true, 'default');
                    }
                    break;
                case 'login'				:
                    $errors = array_merge($errors, $newsletters_errors);
                    $this -> render('management' . DS . 'login', array('errors' => $errors), true, 'default');
                    break;
                default						:
                    if (!empty($_GET['subscriberauth'])) {
                        $_COOKIE['subscriberauth'] = esc_html($_GET['subscriberauth']);
                    }

                    if ($subscriber = $Authnews -> logged_in()) {
                        if ($this -> get_option('subscriptions') == "Y") {
                            $SubscribersList -> check_expirations(false, false, true, $subscriber -> id);
                        }

                        $subscriber = $Authnews -> logged_in();
                        $this -> render('management' . DS . 'index', array('subscriber' => $subscriber), true, 'default');
                    } else {
                        $this -> render('management' . DS . 'login', false, true, 'default');
                    }
                    break;
            }

            global $wpmljavascript;
            if (!empty($wpmljavascript)) {
                echo $wpmljavascript;
            }

            $output = ob_get_clean();
            global $Html;
            $output = $Html -> fragment_cache($output, 'this', 'sc_management', false);
            return $output;
        }

        function is_plugin_screen($screen = null) {
            if (!empty($_GET['page'])) {
                if (!empty($screen)) {
                    if (in_array($_GET['page'], (array) $this -> sections -> {$screen})) {
                        return true;
                    }
                } else {
                    if (in_array($_GET['page'], (array) $this -> sections)) {
                        return true;
                    }
                }
            }

            return false;
        }

        function get_menu_names($dofilter = true) {
            $menunames = array(
                'newsletters'					=>	__('Overview', 'wp-mailinglist'),
                'newsletters-settings'			=>	__('Configuration', 'wp-mailinglist'),
                'newsletters-forms'				=>	__('Subscribe Forms', 'wp-mailinglist'),
                'newsletters-send'				=>	__('Create Newsletter', 'wp-mailinglist'),
                'newsletters-history'			=>	__('Sent & Draft Emails', 'wp-mailinglist'),
                'newsletters-links'				=>	__('Links & Clicks', 'wp-mailinglist'),
                'newsletters-autoresponders'	=>	__('Autoresponders', 'wp-mailinglist'),
                'newsletters-lists'				=>	__('Mailing Lists', 'wp-mailinglist'),
                'newsletters-groups'			=>	__('Groups', 'wp-mailinglist'),
                'newsletters-subscribers'		=>	__('Subscribers', 'wp-mailinglist'),
                'newsletters-import'			=>	__('Import/Export Subscribers', 'wp-mailinglist'),
                'newsletters-fields'			=>	__('Custom Fields', 'wp-mailinglist'),
                'newsletters-themes'			=>	__('Themes/Templates', 'wp-mailinglist'),
                'newsletters-templates'			=>	__('Email Snippets', 'wp-mailinglist'),
                'newsletters-queue'				=>	__('Email Queue', 'wp-mailinglist'),
                'newsletters-orders'			=>	__('Subscription Orders', 'wp-mailinglist'),
                'newsletters-extensions'		=>	__('Extensions', 'wp-mailinglist'),
                'newsletters-updates'			=>	__('Updates', 'wp-mailinglist'),
                'newsletters-support'			=>	__('Support & Help', 'wp-mailinglist'),
                'newsletters-submitserial'		=>	__('Submit Serial', 'wp-mailinglist'),
                'newsletters-gdpr'				=>	__('GDPR Compliance', 'wp-mailinglist'),
            );

            if (!empty($dofilter)) {
                $menunames = apply_filters('newsletters_menu_names', $menunames);
            }

            return $menunames;
        }

        function plugins_loaded() {
            $this -> name = apply_filters('newsletters_plugin_name', $this -> name);

            $this -> initialize_classes();
            $this -> ci_initialize();
            $this -> theme_folder_functions();

            return;
        }

        function manage_users_columns($columns = array()) {
            $columns['newsletters'] = __($this -> name, 'wp-mailinglist');
            return $columns;
        }

        function manage_users_custom_column($value = null, $column_name = null, $user_id = null) {
            switch ($column_name) {
                case 'newsletters'				:
                    global $Db, $Email;

                    $newsletters = 0;

                    if (!empty($user_id)) {
                        $Db -> model = $Email -> model;
                        if ($emails_count = $Db -> count(array('user_id' => $user_id))) {
                            $newsletters = $emails_count;
                        }
                    }

                    return $newsletters;
                    break;
            }

            return $value;
        }

        function language_useordefault($content) {
            $text = $content;

            if (!empty($text)) {
                $current_language = $this -> language_current();
                $language = (empty($current_language) || $current_language == "all") ? $this -> language_default() : $current_language;
                $text = $this -> language_use($language, $content, false);
            }

            return $text;
        }

        function language_use($lang = null, $text = null, $show_available = false) {

            if (!$this -> language_isenabled($lang)) {
                return $text;
            }

            if (is_array($text) || is_object($text)) {
                // handle arrays recursively
                if (is_array($text)) {
                    foreach($text as $key => $t) {
                        $text[$key] = $this -> language_use($lang, $text[$key], $show_available);
                    }
                } elseif (is_object($text)) {
                    foreach($text as $key => $t) {
                        $text -> {$key} = $this -> language_use($lang, $text -> {$key}, $show_available);
                    }
                }

                return $text;
            }

            if(is_object($text) && get_class($text) == '__PHP_Incomplete_Class') {
                foreach(get_object_vars($text) as $key => $t) {
                    $text->$key = $this -> language_use($lang,$text -> $key,$show_available);
                }
                return $text;
            }

            // prevent filtering weird data types and save some resources
            if(!is_string($text) || $text == '') {
                return $text;
            }

            // get content
            $content = $this -> language_split($text);

            if (!is_array($content)) {
                return $content;
            }

            // find available languages
            $available_languages = array();
            foreach($content as $language => $lang_text) {
                $lang_text = trim($lang_text);
                if(!empty($lang_text)) $available_languages[] = $language;
            }

            // if no languages available show full text
            if(sizeof($available_languages)==0) return $text;
            // if content is available show the content in the requested language
            if(!empty($content[$lang])) {
                return $content[$lang];
            }
            // content not available in requested language (bad!!) what now?
            if(!$show_available){
                // check if content is available in default language, if not return first language found. (prevent empty result)
                if($lang != $this -> language_default()) {
                    $str = $this -> language_use($this -> language_default(), $text, $show_available);

                    if ($q_config['show_displayed_language_prefix'])
                        $str = "(". $this -> language_name($this -> language_default()) .") " . $str;
                    return $str;
                }
                foreach($content as $language => $lang_text) {
                    $lang_text = trim($lang_text);
                    if (!empty($lang_text)) {
                        $str = $lang_text;
                        if ($q_config['show_displayed_language_prefix'])
                            $str = "(". $this -> language_name($language) .") " . $str;
                        return $str;
                    }
                }
            }
            // display selection for available languages
            $available_languages = array_unique($available_languages);
            $language_list = "";
            if(preg_match('/%LANG:([^:]*):([^%]*)%/',$q_config['not_available'][$lang],$match)) {
                $normal_seperator = $match[1];
                $end_seperator = $match[2];
                // build available languages string backward
                $i = 0;
                foreach($available_languages as $language) {
                    if($i==1) $language_list  = $end_seperator.$language_list;
                    if($i>1) $language_list  = $normal_seperator.$language_list;
                    $language_list = "<a href=\"". $this -> language_converturl('', $language)."\">". $this -> language_name($language) ."</a>".$language_list;
                    $i++;
                }
            }
            return "<p>".preg_replace('/%LANG:([^:]*):([^%]*)%/', $language_list, $q_config['not_available'][$lang])."</p>";
        }

        function language_converturl($url = null, $language = null) {
            global $newsletters_languageplugin;

            if (!empty($url) && !empty($language)) {
                switch ($newsletters_languageplugin) {
                    case 'qtranslate'				:
                        $url = qtrans_convertURL($url, $language);
                        break;
                    case 'qtranslate-x'				:
                        $url = qtranxf_convertURL($url, $language);
                        break;
                    case 'polylang'					:
                        $url = add_query_arg(array('lang' => $language), $url);
                        break;
                    case 'wpglobus'					:
                        if (class_exists('WPGlobus_Utils')) {
                            $url = WPGlobus_Utils::localize_url($url, $language);
                        }
                        break;
                    case 'wpml'						:
                        $url = apply_filters('wpml_permalink', $url, $language);
                        break;
                }
            }

            return $url;
        }

        function language_default() {
            global $newsletters_languageplugin, $newsletters_languagedefault;
            $default = false;

            if (!empty($newsletters_languagedefault)) {
                return $newsletters_languagedefault;
            }

            switch ($newsletters_languageplugin) {
                case 'qtranslate'				:
                case 'qtranslate-x'				:
                    global $q_config;
                    $default = $q_config['default_language'];
                    break;
                case 'polylang'					:
                    if (function_exists('pll_default_language')) {
                        $default = pll_default_language();
                    }
                    break;
                case 'wpglobus'					:
                    if (class_exists('WPGlobus')) {
                        $default = WPGlobus::Config() -> default_language;
                    }
                    break;
                case 'wpml'						:
                    global $sitepress;
                    if (method_exists($sitepress, 'get_default_language')) {
                        $default = $sitepress -> get_default_language();
                    }
                    break;
            }

            $newsletters_languagedefault = $default;
            return $default;
        }

        function language_name($language = null) {
            $name = false;

            if (!empty($language)) {
                global $newsletters_languageplugin, ${'newsletters_languagename_' . $language};

                if (!empty(${'newsletters_languagename_' . $language})) {
                    return ${'newsletters_languagename_' . $language};
                }

                switch ($newsletters_languageplugin) {
                    case 'qtranslate'				:
                    case 'qtranslate-x'				:
                        global $q_config;
                        $name = $q_config['language_name'][$language];
                        break;
                    case 'polylang'					:
                        global $polylang;
                        if ($pll_language = $polylang -> model -> get_language($language)) {
                            $name = $pll_language -> name;
                        }
                        break;
                    case 'wpglobus'					:
                        if (class_exists('WPGlobus')) {
                            $name = WPGlobus::Config() -> language_name[$language];
                        }
                        break;
                    case 'wpml'						:
                        if (function_exists('icl_get_languages')) {
                            $languages = icl_get_languages();
                            if (!empty($languages[$language]['translated_name'])) {
                                $name = $languages[$language]['translated_name'];
                            }
                        }
                        break;
                }
            }

            ${'newsletters_languagename_' . $language} = $name;
            return $name;
        }

        function language_do() {
            global $newsletters_languageplugin;

            $result = false;

            if (empty($newsletters_languageplugin)) {
                if ($this -> is_plugin_active('qtranslate')) {
                    $newsletters_languageplugin = "qtranslate";
                    $result = true;
                } elseif ($this -> is_plugin_active('qtranslate-x')) {
                    $newsletters_languageplugin = 'qtranslate-x';
                    $result = true;
                } elseif ($this -> is_plugin_active('wpml')) {
                    $newsletters_languageplugin = "wpml";

                    if (!empty($_GET['lang']) && $_GET['lang'] == "all") {
                        $result = false;
                    }

                    $result = true;
                } elseif ($this -> is_plugin_active('polylang')) {
                    $newsletters_languageplugin = "polylang";
                    $result = true;
                } elseif ($this -> is_plugin_active('wpglobus')) {
                    $newsletters_languageplugin = "wpglobus";
                    $result = true;
                }
            } else {
                $result = true;
            }

            return apply_filters('newsletters_language_do', $result, $newsletters_languageplugin);
        }

        function language_set($language = null) {
            global $newsletters_languageplugin, $newsletters_languagecurrent;
            $this -> language_do();

            do_action('newsletters_language_set_before', $language, $newsletters_languageplugin);

            if (!empty($language) && !empty($newsletters_languageplugin)) {
                $newsletters_languagecurrent = $language;

                switch ($newsletters_languageplugin) {
                    case 'qtranslate'					:
                    case 'qtranslate-x'					:
                        if (function_exists('qtranxf_set_language_cookie')) {
                            qtranxf_set_language_cookie($language);
                        }
                        break;
                    case 'polylang'						:
                        global $polylang;
                        if ($pll_language = $polylang -> model -> get_language($language)) {
                            $polylang -> curlang = $pll_language;
                        }
                        break;
                    case 'wpglobus'						:
                        if (class_exists('WPGlobus')) {
                            WPGlobus::Config() -> set_language($language);
                        }
                        break;
                    case 'wpml'							:
                        global $sitepress;
                        if (method_exists($sitepress, 'switch_lang')) {
                            $sitepress -> switch_lang($language, true);
                        }
                        break;
                }

                do_action('newsletters_language_set_success', $language, $newsletters_languageplugin);

                return true;
            }

            do_action('newsletters_language_set_failed', $language, $newsletters_languageplugin);

            return false;
        }

        function language_current() {
            global $newsletters_languageplugin, $newsletters_languagecurrent;
            $current = false;

            if (!empty($newsletters_languagecurrent)) {
                return $newsletters_languagecurrent;
            }

            switch ($newsletters_languageplugin) {
                case 'qtranslate'			:
                    if (function_exists('qtrans_getLanguage')) {
                        $current = qtrans_getLanguage();
                    }
                    break;
                case 'qtranslate-x'			:
                    if (function_exists('qtranxf_getLanguage')) {
                        $current = qtranxf_getLanguage();
                    }
                    break;
                case 'polylang'				:
                    if (function_exists('pll_current_language') && function_exists('pll_default_language')) {
                        $current = pll_current_language();

                        if (empty($current)) {
                            $current = pll_default_language();
                        }
                    }
                    break;
                case 'wpglobus'				:
                    if (class_exists('WPGlobus')) {
                        $current = WPGlobus::Config() -> language;
                    }
                    break;
                case 'wpml'					:
                    //$current = ICL_LANGUAGE_CODE;
                    global $sitepress;
                    $current = $sitepress -> get_current_language();
                    break;
            }

            if (empty($current)) {
                $current = $this -> language_default();
            }

            $newsletters_languagecurrent = $current;
            return $current;
        }

        function language_flag($language = null) {
            global $newsletters_languageplugin, ${'newsletters_languageflag_' . $language};
            $flag = false;

            if (!empty(${'newsletters_languageflag_' . $language})) {
                return ${'newsletters_languageflag_' . $language};
            }

            switch ($newsletters_languageplugin) {
                case 'qtranslate'			:
                case 'qtranslate-x'			:
                    global $q_config;
                    $flag = '<img src="' . content_url() . '/' . $q_config['flag_location'] . '/' . $q_config['flag'][$language] . '" alt="' . $language . '" />';
                    break;
                case 'polylang'				:
                    global $polylang;
                    if ( $lng = $polylang->model->get_language( $language ) ) {
						// Polylang ≥ 3.0
						if ( ! empty( $lng->flag_url ) ) {
							return sprintf(
								'<img src="%s" alt="%s" width="16" height="11" />',
								esc_url( $lng->flag_url ),
								esc_attr( $lng->name )
							);
						}
						// fallback for very old Polylang builds
						if ( ! empty( $lng->flag ) ) {
							return $lng->flag;          // may still be a data‑URI
						}
					}
                    break;
                case 'wpglobus'				:
                    if (class_exists('WPGlobus')) {
                        $flag = '<img src="' . WPGlobus::Config() -> flags_url . WPGlobus::Config() -> flag[$language] . '" alt="' . $language . '" />';
                    }
                    break;
                case 'wpml'					:
                    if (function_exists('icl_get_languages')) {
                        $languages = icl_get_languages();
                        $flag = '<img src="' . $languages[$language]['country_flag_url'] . '" alt="' . $language . '" />';
                    }
                    break;
            }

            ${'newsletters_languageflag_' . $language} = $flag;
            return $flag;
        }

        function language_isenabled($language = null) {
            $enabled = false;

            if (!empty($language)) {
                global $newsletters_languageplugin, ${'newsletters_languageenabled_' . $language};

                if (!empty(${'newsletters_languageenabled_' . $language})) {
                    return ${'newsletters_languageenabled_' . $language};
                }

                switch ($newsletters_languageplugin) {
                    case 'qtranslate'				:
                        $enabled = qtrans_isEnabled($language);
                        break;
                    case 'qtranslate-x'				:
                        $enabled = qtranxf_isEnabled($language);
                        break;
                    case 'polylang'					:
                        global $polylang;
                        if ($pll_language = $polylang -> model -> get_language($language)) {
                            if (empty($pll_language -> active) || $pll_language -> active == true) {
                                $enabled = true;
                            }
                        }
                        break;
                    case 'wpglobus'					:
                        if (class_exists('WPGlobus_Utils')) {
                            if (WPGlobus_Utils::is_enabled($language)) {
                                $enabled = true;
                            }
                        }
                        break;
                    case 'wpml'						:
                        if (function_exists('icl_get_languages')) {
                            $languages = icl_get_languages();
                            if (!empty($languages[$language])) {
                                $enabled = true;
                            }
                        }
                        break;
                }
            }

            ${'newsletters_languageenabled_' . $language} = $enabled;
            return $enabled;
        }

        function language_join($texts = array(), $tagTypeMap = array(), $strip_tags = false) {
            if(!is_array($texts)) $texts = $this -> language_split($texts, false);
            $split_regex = "#<!--more-->#ism";
            $max = 0;
            $text = "";
            $languages = $this -> language_getlanguages();

            foreach ($languages as $language) {
                $tagTypeMap[$language] = true;
            }

            foreach($languages as $language) {
                if (!empty($texts[$language])) {
                    $texts[$language] = preg_split($split_regex, $texts[$language]);
                    if(sizeof($texts[$language]) > $max) $max = sizeof($texts[$language]);
                }
            }

            for ($i = 0; $i < $max; $i++) {
                if($i>=1) {
                    $text .= '<!--more-->';
                }
                foreach($languages as $language) {
                    if (isset($texts[$language][$i]) && $texts[$language][$i] !== '') {
                        if ($strip_tags) {
                            $texts[$language][$i] = strip_tags($texts[$language][$i]);
                        }

                        if (empty($tagTypeMap[$language]))
                            $text .= '<!--:'.$language.'-->'.$texts[$language][$i].'<!--:-->';
                        else
                            $text .= "[:{$language}]{$texts[$language][$i]}";
                    }
                }
            }

            return $text;
        }

        function language_split($text, $quicktags = true, ?array $languageMap = NULL) {
            $array = false;

            if (!empty($text)) {
                //init vars
                $split_regex = "#(<!--[^-]*-->|\[:[a-z-]{2,10}\])#ism";
                $current_language = "";
                $result = array();

                $languages = $this -> language_getlanguages();
                foreach ($languages as $language) {
                    $result[$language] = "";
                }

                if(is_array($text))
                {
                    return $result;
                }

                // split text at all xml comments
                $blocks = preg_split($split_regex, $text, -1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);

                foreach($blocks as $block) {
                    # detect language tags
                    if(preg_match("#^<!--:([a-z-]{2,10})-->$#ism", $block, $matches)) {
                        if($this -> language_isenabled($matches[1])) {
                            $current_language = $matches[1];
                            $languageMap[$current_language] = false;
                        } else {
                            $current_language = "invalid";
                        }
                        continue;
                        // detect quicktags
                    } elseif($quicktags && preg_match("#^\[:([a-z-]{2,10})\]$#ism", $block, $matches)) {
                        if($this -> language_isenabled($matches[1])) {
                            $current_language = $matches[1];
                            $languageMap[$current_language] = true;
                        } else {
                            $current_language = "invalid";
                        }

                        continue;
                    } elseif(preg_match("#^<!--:-->$#ism", $block, $matches)) {
                        $current_language = "";
                        continue;
                    } elseif(preg_match("#^<!--more-->$#ism", $block, $matches)) {
                        foreach($languages as $language) {
                            $result[$language] .= $block;
                        }

                        continue;
                    }

                    if($current_language == "") {
                        foreach($languages as $language) {
                            $result[$language] .= $block;
                        }
                    } elseif($current_language != "invalid") {
                        $result[$current_language] .= $block;
                    }
                }

                foreach($result as $lang => $lang_content) {
                    $result[$lang] = str_replace('[:]', '', preg_replace("#(<!--more-->|<!--nextpage-->)+$#ism", "", $lang_content));
                }

                return $result;
            }

            return $array;
        }

        function language_getlanguages() {
            global $newsletters_languageplugin, $newsletters_languagelanguages;
            $languages = array();

            if (!empty($newsletters_languagelanguages)) {
                return $newsletters_languagelanguages;
            }

            switch ($newsletters_languageplugin) {
                case 'qtranslate'					:
                    if (function_exists('qtrans_getSortedLanguages')) {
                        $languages = qtrans_getSortedLanguages();
                    }
                    break;
                case 'qtranslate-x'					:
                    if (function_exists('qtranxf_getSortedLanguages')) {
                        $languages = qtranxf_getSortedLanguages();
                    }
                    break;
                case 'polylang'						:
                    if (function_exists('pll_languages_list')) {
						$languages = pll_languages_list(array(
							'fields'        => 'slug',
							'hide_empty'    => 0,
						));
					}
                    break;
                case 'wpglobus'						:
                    if (class_exists('WPGlobus')) {
                        $languages = WPGlobus::Config() -> enabled_languages;
                    }
                    break;
                case 'wpml'							:
                    if (function_exists('icl_get_languages')) {
                        $icl_languages = icl_get_languages('skip_missing=0&orderby=code');
                        $languages = array();

                        if (!empty($icl_languages) && is_array($icl_languages)) {
                            foreach ($icl_languages as $lang => $icl_language) {
                                $languages[] = $lang;
                            }
                        }
                    }
                    break;
            }

            $languages = apply_filters('newsletters_language_getlanguages', $languages);

            $newsletters_languagelanguages = $languages;
            return $languages;
        }

        function wp_cron_file_exists() {
            $result = false;
            $wp_cron = ABSPATH . 'wp-cron.php';

            if (file_exists($wp_cron)) {
                $result = true;
            } else {
                $this -> log_error(__('The wp-cron.php file does not exist, please check if it is deleted or renamed.', 'wp-mailinglist'));
            }

            return apply_filters('newsletters_wp_cron_file_exists', $result);
        }

        function paginate($model = null, $fields = '*', $sub = null, $conditions = false, $searchterm = null, $perpage = 10, $order = array('modified', "DESC"), $conditions_and = null) {
            global $wpdb, $Db, $Subscriber, $SubscribersList, $Mailinglist,
                   ${$model}, $Mailinglist, $Unsubscribe, $Bounce;

            $object = (!is_object(${$model})) ? $this -> {$model}() : ${$model};
            $conditions = apply_filters('newsletters_admin_paginate_' . strtolower($object -> model) . '_conditions', $conditions);
            $conditions_and = apply_filters('newsletters_admin_paginate_' . strtolower($object -> model) . '_conditions_and', $conditions_and);

            if (!empty($model)) {
                global $paginate;
                $paginate = $this -> vendor('paginate');
                $paginate -> plugin_name = $this -> plugin_name;
                $paginate -> model = $model;
                $paginate -> table = $wpdb -> prefix . $this -> pre . $object -> controller;
                $paginate -> sub = (empty($sub)) ? $object -> controller : $sub;
                $paginate -> fields = (empty($fields)) ? '*' : $fields;
                $paginate -> where = (empty($conditions)) ? false : $conditions;
                $paginate -> where_and = (empty($conditions_and)) ? false : $conditions_and;
                $paginate -> searchterm = (empty($searchterm)) ? false : $searchterm;
                $paginate -> perpage = $perpage;
                $paginate -> order = $order;

                $page = (empty($_GET[$this -> pre . 'page'])) ? 1 : esc_html($_GET[$this -> pre . 'page']);
                $data = $paginate -> start_paging($page);

                if (!empty($data)) {
                    $newdata = array();
                    $n = 0;

                    foreach ($data as $record) {
                        //$newdata[$n] = $this -> init_class($model, $record);
                        $newdata[$n] = $record;

                        switch ($model) {
                            case 'Bounce'						:
                            case 'Unsubscribe'					:
                                $newdata[$n] = $this -> init_class($model, $record);
                                break;
                            case 'History'						:
                                $newdata[$n] = $this -> init_class($this -> History() -> model, $record);
                                break;
                            case 'Subscriber'					:
                                $Db -> model = $SubscribersList -> model;
                                if ($subscriberslists = $Db -> find_all(array('subscriber_id' => $record -> id))) {
                                    foreach ($subscriberslists as $sl) {
                                        $listquery = "SELECT * FROM " . $wpdb -> prefix . $Mailinglist -> table . " WHERE id = '" . $sl -> list_id . "' LIMIT 1";
                                        $list = $wpdb -> get_row($listquery);
                                        $newdata[$n] -> Mailinglist[] = $list;
                                    }
                                }
                                break;
                            case 'SubscribersList'				:
                                $Db -> model = $Subscriber -> model;

                                if ($subscriber = $Db -> find(array('id' => $record -> subscriber_id))) {
                                    $newdata[$n] = $subscriber;

                                    foreach ($record as $rkey => $rval) {
                                        $newdata[$n] -> {$rkey} = $rval;
                                    }
                                }
                                break;
                            case 'Autoresponder'				:
                                /* Pending Emails */
                                //$newdata[$n] -> pending = $this -> Autoresponderemail() -> count(array('autoresponder_id' => $record -> id, 'status' => "unsent"));

                                /* Mailing Lists */
                                $newdata[$n] -> mailinglists = array();

                                if ($autoresponderslists = $this -> AutorespondersList() -> find_all(array('autoresponder_id' => $record -> id))) {
                                    foreach ($autoresponderslists as $autoresponderslist) {
                                        $Db -> model = $Mailinglist -> model;
                                        $newdata[$n] -> lists[] = $autoresponderslist -> list_id;
                                        $newdata[$n] -> mailinglists[] = $Db -> find(array('id' => $autoresponderslist -> list_id));
                                    }
                                }
                                break;
                            case 'Autoresponderemail'			:
                                /* Autoresponder */
                                $Db -> model = $this -> Autoresponder() -> model;
                                $newdata[$n] -> autoresponder = $Db -> find(array('id' => $record -> autoresponder_id), false, false, false, false);

                                /* Subscriber */
                                $Db -> model = $Subscriber -> model;
                                $newdata[$n] -> subscriber = $Db -> find(array('id' => $record -> subscriber_id), false, false, false, false);
                                break;
                        }

                        $n++;
                    }

                    $data = array();
                    $data[$model] = (object) $newdata;
                    $data['Paginate'] = $paginate;
                }
                return $data;
            }

            return false;
        }

        function admin_pointers() {
            if ($this -> custom_admin_pointers_check()) {
                $this -> add_action('admin_print_footer_scripts', 'custom_admin_pointers_footer');

                wp_enqueue_script('wp-pointer');
                wp_enqueue_style('wp-pointer');
            }
        }

        function custom_admin_pointers_check() {
            $admin_pointers = $this -> custom_admin_pointers();

            foreach ($admin_pointers as $pointer => $array) {
                if (!empty($array['active'])) {
                    return true;
                }
            }
        }

        function custom_admin_pointers_footer() {
            $admin_pointers = $this -> custom_admin_pointers();

            ?>
            <script type="text/javascript">
                (function($) {
                    <?php

                    foreach ($admin_pointers as $pointer => $array) {
                    if (!empty($array['active'])) {

                    ?>

                    $('<?php echo $array['anchor_id']; ?>').pointer( {
                        content: '<?php echo $array['content']; ?>',
                        position: {
                            edge: '<?php echo $array['edge']; ?>',
                            align: '<?php echo $array['align']; ?>'
                        },
                        close: function() {
                            $.post( ajaxurl, {
                                pointer: '<?php echo $pointer; ?>',
                                action: 'dismiss-wp-pointer'
                            });
                        }
                    }).pointer('open');

                    <?php
                    }
                    }

                    ?>
                })(jQuery);
            </script>
            <?php
        }

        function custom_admin_pointers() {
            $dismissed = explode(',', (string) get_user_meta(get_current_user_id(), 'dismissed_wp_pointers', true));
            $prefix = 'newsletters_admin_pointers_';

            $admin_pointers = array();

            $gdpr_pointer_content = '';
            $gdpr_pointer_content .= '<h3>' . __('Newsletters: GDPR', 'wp-mailinglist') . '</h3>';
            $gdpr_pointer_content .= '<p>' . sprintf(__('Newsletters: Are you GDPR compliant? Check the %s to make sure you comply.', 'wp-mailinglist'), '<a href="' . admin_url('admin.php?page=' . $this -> sections -> gdpr) . '">' . __('GDPR Requirements', 'wp-mailinglist') . '</a>') . '</p>';

            $admin_pointers[$prefix . 'gdpr'] = array(
                'content'				=>	$gdpr_pointer_content,
                'anchor_id'				=>	'#toplevel_page_newsletters',
                'edge'					=>	'left',
                'align'					=>	'middle',
                'active'				=>	(!in_array($prefix . 'gdpr', $dismissed)),
            );

            return $admin_pointers;

        }

        function ci_print_styles() {
            wp_enqueue_style('newsletters', $this -> render_url('css/wp-mailinglist.css', 'admin', false), null, $this -> version, "all");
            wp_enqueue_style('colorbox', plugins_url() . '/' . $this -> plugin_name . '/css/colorbox.css', false, $this -> version, "all");
        }

        function ci_print_scripts() {
            wp_enqueue_script($this -> plugin_name, plugins_url() . '/' . $this -> plugin_name . '/js/wp-mailinglist.js', array('jquery'), '1.0', true);
            wp_enqueue_script('colorbox', plugins_url() . '/' . $this -> plugin_name . '/js/colorbox.js', array('jquery'), false, true);
        }

        function print_scripts() {
            $this -> enqueue_scripts();
        }

        function print_styles() {
            $this -> enqueue_styles();
        }

        function enqueue_scripts() {
            global $wp_locale, $wp_scripts, $Html, $Db;
            $custompostslug = $this -> get_option('custompostslug');
            $page = sanitize_text_field(isset($_GET['page']) ? $_GET['page'] : "");

            //enqueue jQuery JS Library
            if (apply_filters('newsletters_enqueuescript_jquery', true)) { wp_enqueue_script('jquery'); }
            wp_dequeue_script( 'newsletters-turnstile' );

            if (is_admin() && !defined('DOING_AJAX')) {
                $donotloadpages = array(
                    'codestyling-localization/codestyling-localization.php'
                );

                if (!empty($_GET['page']) && in_array($_GET['page'], $donotloadpages)) {
                    return;
                }

                if (apply_filters('newsletters_enqueuescript_jqueryuicore', true)) { wp_enqueue_script('jquery-ui-core'); }
                if (apply_filters('newsletters_enqueuescript_jqueryuiwidget', true)) { wp_enqueue_script('jquery-ui-widget'); }

                $screen = get_current_screen();

                // Charts
                if ($screen -> id == "dashboard" || preg_match("/(index.php)/si", $_SERVER['REQUEST_URI']) ||
                    (!empty($_GET['page']) && ($_GET['page'] == $this -> sections -> welcome || $_GET['page'] == $this -> sections -> history))) {
                    wp_enqueue_script('chartjs', 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.4.1/chart.min.js', array('jquery'), '3.4.1', false);
                }

                // Tooltips
                if (preg_match("/(index\.php|widgets\.php|post\.php|post\-new\.php)/", $_SERVER['REQUEST_URI'], $matches)) {
                    wp_enqueue_script('jquery-ui-tooltip', false, array('jquery'), false, true);
                }

                if ((!empty($_GET['page']) && in_array($_GET['page'], (array) $this -> sections)) || preg_match("/(post\.php|post\-new\.php)/", $_SERVER['REQUEST_URI'], $matches)) {

                    // Select 2
                    if (in_array($_GET['page'], (array) $this -> sections)) {
                        wp_deregister_script('select2');
                        wp_deregister_script('wc-enhanced-select');
                        wp_enqueue_script('select2', $this -> render_url('js/select2.js', 'admin', false), array('jquery'), '4.0.0', false);
                    }

                    // CKEditor
                    // Let's not load the CKEditor on post editing screens
                    if (empty($matches)) {
                        wp_enqueue_script('ckeditor', $this -> render_url('js/ckeditor/ckeditor.js', 'admin', false), array('jquery'), '4.4.7', false);
                        wp_enqueue_script('ckeditor-jquery', $this -> render_url('vendors/ckeditor/adapters/jquery.js', 'admin', false), array('ckeditor', 'jquery'), "4.4.7", false);
                    }

                    // Color Picker
                    wp_enqueue_script('iris', admin_url('js/iris.min.js'), array( 'jquery-ui-draggable', 'jquery-ui-slider', 'jquery-touch-punch' ), false, 1);
                    wp_enqueue_script('wp-color-picker', admin_url('js/color-picker.min.js'), array( 'iris' ), false, 1);
                    wp_enqueue_script('jquery-ui-tooltip', false, array('jquery'), false, true);
                    //wp_enqueue_script('jquery-ui-button', false, array('jquery'), false, true);
                }

                if (!empty($_GET['page']) && in_array($_GET['page'], (array) $this -> sections) || (get_post_type() == $custompostslug)) {
                    wp_enqueue_media();

                    wp_enqueue_script('jquery-serialize-object', $this -> render_url('js/jquery.serialize-object.js', 'admin', false), array('jquery'), false, true);
                    wp_enqueue_script('jquery-serialize-json', $this -> render_url('js/jquery.serialize-json.js', 'admin', false), array('jquery'), false, true);

                    wp_enqueue_script('jquery-autoheight', plugins_url() . '/' . $this -> plugin_name . '/js/jquery.autoheight.js', array('jquery'), false, true);
                    wp_enqueue_script('jquery-form', false, array('jquery'), false, true);

                    // Ace editor
                    if (!empty($_GET['page']) && ($_GET['page'] == $this -> sections -> settings || $page == $this -> sections -> settings_api || ($_GET['page'] == $this -> sections -> forms))) {
                        wp_enqueue_script('ace', $this -> render_url('js/ace/ace.js', 'admin', false), array('jquery'), false, true);
                    }

                    // List
                    if (!empty($page) && $page == $this -> sections -> extensions) {
                        wp_enqueue_script('jslist', $this -> render_url('js/list.js', 'admin', false), array('jquery'), false, true);
                    }

                    //countdown script
                    if (!empty($_GET['page']) && $_GET['page'] == $this -> sections -> queue) {
                        wp_enqueue_script('jquery-countdown', plugins_url() . '/' . $this -> plugin_name . '/js/jquery.countdown.js', array('jquery'), false, true);
                    }

                    //sortables
                    $method = sanitize_text_field(isset($_GET['method']) ? $_GET['method'] : "");
                    if ($_GET['page'] == $this -> sections -> fields && $method == "order") {
                        wp_enqueue_script('jquery-ui-sortable', false, false, false, true);
                    }

                    wp_enqueue_script('clipboard');


                    // GrapesJS
                    if (isset($_GET['page']) && ($_GET['page'] == $this -> sections -> themes ||
                            $_GET['page'] == $this -> sections -> send)) {
                        $grapesjs = plugins_url() . '/' . $this -> plugin_name . '/vendors/grapesjs/grapes.min.js';
                        wp_enqueue_script('grapesjs', $grapesjs, array('jquery'), false, false);

                        $grapesjs_preset_newsletter = plugins_url() . '/' . $this -> plugin_name . '/vendors/grapesjs/grapesjs-preset-newsletter.min.js';
                        wp_enqueue_script('grapesjs-preset-newsletter', $grapesjs_preset_newsletter, array('jquery', 'grapesjs'), false, false);

                        $grapesjs_plugin_wordpress = plugins_url() . '/' . $this -> plugin_name . '/vendors/grapesjs/grapesjs-plugin-wordpress.js';
                        wp_enqueue_script('grapesjs-plugin-wordpress', $grapesjs_plugin_wordpress, array('jquery', 'grapesjs'), false, false);


                        wp_deregister_script('jetpack-gallery-settings');
                        wp_dequeue_script('jetpack-gallery-settings');



                        $grapesjs = plugins_url() . '/' . $this -> plugin_name . '/vendors/grapesjs/css/grapes.min.css';
                        wp_enqueue_style('grapesjs', $grapesjs, false, false, 'all');

                        $grapesjs_preset_newsletter = plugins_url() . '/' . $this -> plugin_name . '/vendors/grapesjs/css/grapesjs-preset-newsletter.css';
                        wp_enqueue_style('grapesjs-preset-newsletter', $grapesjs_preset_newsletter, false, false, 'all');




                    }

                    /* Progress Bar */
                    if ($_GET['page'] == $this -> sections -> importexport ||
                        $_GET['page'] == $this -> sections -> send) {
                        wp_enqueue_script('jquery-ui-progressbar', false, array('jquery-ui-core', 'jquery-ui-widget'));

                        $datejs = $this -> render_url('js/date.js', 'admin', false);
                        wp_enqueue_script('datejs', $datejs, array('jquery'), false, false);
                    }

                    if ($_GET['page'] == $this -> sections -> welcome ||
                        $_GET['page'] == $this -> sections -> send ||
                        $_GET['page'] == $this -> sections -> forms ||
                        $_GET['page'] == $this -> sections -> autoresponders ||
                        $_GET['page'] == $this -> sections -> templates_save ||
                        $_GET['page'] == $this -> sections -> themes ||
                        $_GET['page'] == $this -> sections -> settings ||
                        $_GET['page'] == $this -> sections -> settings_templates ||
                        $_GET['page'] == $this -> sections -> settings_subscribers ||
                        $_GET['page'] == $this -> sections -> settings_system ||
                        $_GET['page'] == $this -> sections -> extensions_settings) {
                        //meta boxes
                        wp_enqueue_script('common', false, false, false, true);
                        wp_enqueue_script('wp-lists', false, false, false, true);
                        wp_enqueue_script('postbox', false, false, false, true);
                        wp_enqueue_script('plugin-install');
                        wp_enqueue_script('updates');

                        //editor
                        wp_enqueue_script('editor', false, false, false, true);
                        wp_enqueue_script('quicktags', false, false, false, true);
                        wp_enqueue_script('wplink', false, false, false, true);
                        wp_enqueue_script('wpdialogs-popup', false, false, false, true);
                        wp_enqueue_style('wp-jquery-ui-dialog', false, false, false, true);
                        wp_enqueue_script('word-count', false, false, false, true);
                        wp_enqueue_script('media-upload', false, false, false, true);
                        wp_admin_css();
                        wp_enqueue_script('utils', false, false, false, true);

                        //editors files
                        if ($_GET['page'] == $this -> sections -> welcome) { wp_enqueue_script('welcome-editor', plugins_url() . '/' . $this -> plugin_name . '/js/editors/welcome-editor.js', array('jquery'), false, true); }
                        if ($_GET['page'] == $this -> sections -> send) { wp_enqueue_script('send-editor', plugins_url() . '/' . $this -> plugin_name . '/js/editors/send-editor.js', array('jquery'), false, true); }
                        if ($_GET['page'] == $this -> sections -> forms) { wp_enqueue_script('forms-editor', plugins_url() . '/' . $this -> plugin_name . '/js/editors/forms-editor.js', array('jquery'), false, true); }
                        if ($_GET['page'] == $this -> sections -> templates_save) { wp_enqueue_script('templates-editor', plugins_url() . '/' . $this -> plugin_name . '/js/editors/templates-editor.js', array('jquery'), false, true); }
                        if ($_GET['page'] == $this -> sections -> themes) { wp_enqueue_script('themes-editor', plugins_url() . '/' . $this -> plugin_name . '/js/editors/themes-editor.js', array('jquery'), false, true); }
                        if ($_GET['page'] == $this -> sections -> settings) { wp_enqueue_script('settings-editor', plugins_url() . '/' . $this -> plugin_name . '/js/editors/settings-editor.js', array('jquery'), false, true); }
                        if ($_GET['page'] == $this -> sections -> settings_templates) { wp_enqueue_script('settings-editor-templates', plugins_url() . '/' . $this -> plugin_name . '/js/editors/settings-editor-templates.js', array('jquery'), false, true); }
                        if ($_GET['page'] == $this -> sections -> settings_subscribers) { wp_enqueue_script('settings-editor-subscribers', plugins_url() . '/' . $this -> plugin_name . '/js/editors/settings-editor-subscribers.js', array('jquery'), false, true); }
                        if ($_GET['page'] == $this -> sections -> settings_system) { wp_enqueue_script('settings-editor-system', plugins_url() . '/' . $this -> plugin_name . '/js/editors/settings-editor-system.js', array('jquery'), false, true); }
                        if ($_GET['page'] == $this -> sections -> extensions_settings) { wp_enqueue_script('settings-editor-extensions-settings', plugins_url() . '/' . $this -> plugin_name . '/js/editors/settings-editor-extensions-settings.js', array('jquery'), false, true); }
                    }
                }

                add_thickbox();

                wp_register_script('wp-mailinglist', $this -> render_url('js/wp-mailinglist.js', 'admin', false), array('jquery'), '1.0', true);

                $params = array(
                    'ajaxnonce'			=>	array(
                        'get_country'			=>	wp_create_nonce('get_country'),
                        'serialkey'				=>	wp_create_nonce('serialkey'),
                        'refreshfields'			=>	wp_create_nonce('refreshfields'),
                        'dismissed_notice'		=>	wp_create_nonce('dismissed_notice'),
                    )
                );
                // Apply the filter and get the result
                $execute = apply_filters( 'wpmlloadscripts', true );

                // Check the value of $execute and execute the code only if it's true
                if ( $execute ) {
                    wp_localize_script('wp-mailinglist', 'newslettersmain', $params);
                    wp_enqueue_script('wp-mailinglist');
                }

                wp_enqueue_script('jquery-ui-tabs');
                wp_enqueue_script('jquery-shiftclick', plugins_url() . '/' . $this -> plugin_name . '/js/jquery.shiftclick.js', array('jquery'));
                wp_enqueue_script('jquery-ui-droppable');
                wp_enqueue_script('jquery-ui-datepicker');
                wp_enqueue_script('colorbox', plugins_url() . '/' . $this -> plugin_name . '/js/colorbox.js', array('jquery'), false, false);

                //add our instantiator js
                wp_register_script('datepicker-i18n', $this -> render_url('js/datepicker-i18n.js', 'admin', false), array('jquery-ui-datepicker'));

                $isRTL = (empty($wp_locale -> is_rtl)) ? false : true;

                //localize our js
                $aryArgs = array(
                    'closeText'         => __('Done', 'wp-mailinglist'),
                    'currentText'       => __('Today', 'wp-mailinglist'),
                    'monthNames'        => $Html -> strip_array_indices($wp_locale -> month),
                    'monthNamesShort'   => $Html -> strip_array_indices($wp_locale -> month_abbrev),
                    'monthStatus'       => __('Show a different month', 'wp-mailinglist'),
                    'dayNames'          => $Html -> strip_array_indices($wp_locale -> weekday),
                    'dayNamesShort'     => $Html -> strip_array_indices($wp_locale -> weekday_abbrev),
                    'dayNamesMin'       => $Html -> strip_array_indices($wp_locale -> weekday_initial),
                    'dateFormat'        => $Html -> dateformat_PHP_to_jQueryUI(get_option('date_format')),
                    'firstDay'          => get_option('start_of_week'),
                    'isRTL'             => $isRTL,
                );

                // Pass the localized array to the enqueued JS
                wp_localize_script('datepicker-i18n', 'objectL10n', $aryArgs);
                wp_enqueue_script('datepicker-i18n');

                /* Front-End Scripts */
            } else {
                $functions_variables = array();

                $loadscripts = $this -> get_option('loadscripts');
                $loadscripts_handles = $this -> get_option('loadscripts_handles');
                $loadscripts_pages = $this -> get_option('loadscripts_pages');

                $loadrecaptcha = false;
                include($this -> plugin_base() . DS . 'includes' . DS . 'variables.php');

                if (!empty($defaultscripts)) {
                    // Deregister WooCommerce Select2 on Manage Subscriptions
                    if (wpml_is_management()) {
                        wp_deregister_script('select2');
                        wp_deregister_script('wc-enhanced-select');
                    }

                    foreach ($defaultscripts as $handle => $script) {
                        $custom_handle = (empty($loadscripts_handles[$handle])) ? $handle : $loadscripts_handles[$handle];
                        $custom_pages = (empty($loadscripts_pages[$handle])) ? false : explode(",", $loadscripts_pages[$handle]);

                        if ((!empty($loadscripts) && in_array($handle, $loadscripts)) || wpml_is_management()) {
                            if (empty($custom_pages) || (!empty($custom_pages) && (is_single($custom_pages) || is_page($custom_pages)))) {
                                if (apply_filters('newsletters_enqueuescript_' . $handle, true)) {
                                    switch ($handle) {
                                        case 'recaptcha'				:
                                            $loadrecaptcha = true;
                                            break;
                                        case 'turnstile':
                                            $turnstile_public = $this->get_option( 'turnstile_sitekey' );
                                            wp_enqueue_script(
                                                'newsletters-turnstile',
                                                'https://challenges.cloudflare.com/turnstile/v0/api.js?render=' . esc_attr( $turnstile_public ),
                                                array( 'jquery' ),
                                                null,
                                                false
                                            );
                                            break;
                                        default 						:
                                            wp_enqueue_script($custom_handle, $script['url'], $script['deps'], $script['version'], $script['footer']);
                                            break;
                                    }

                                    do_action('newsletters_enqueuescript_after', $handle, $script);
                                }
                            }
                        }
                    }
                }

                if (apply_filters('newsletters_enqueuescript_' . $this -> plugin_name, true)) {
                    wp_register_script('wp-mailinglist', $this -> render_url('js/wp-mailinglist.js', 'admin', false), array('jquery'), '1.0', true);

                    $params = array(
                        'ajaxnonce'			=>	array(
                            'get_country'			=>	wp_create_nonce('get_country'),
                            'serialkey'				=>	wp_create_nonce('serialkey'),
                            'refreshfields'			=>	wp_create_nonce('refreshfields'),
                            'dismissed_notice'		=>	wp_create_nonce('dismissed_notice'),
                        )
                    );
                    // Apply the filter and get the result
                    $execute = apply_filters( 'wpmlloadscripts', true );

                    // Check the value of $execute and execute the code only if it's true
                    if ( $execute ) {
                        wp_localize_script('wp-mailinglist', 'newslettersmain', $params);
                        wp_enqueue_script('wp-mailinglist');
                    }
                }

                if ( $captcha_type = $this->use_captcha() ) {

					$functions_variables['has_captcha'] = true;

					if ( $captcha_type === 'recaptcha' && ! empty( $loadrecaptcha ) ) {

						$functions_variables['captcha'] = 'recaptcha';

						$sitekey   = $this->get_option( 'recaptcha_publickey' );
						$secret    = $this->get_option( 'recaptcha_privatekey' );
						$type_opt  = $this->get_option( 'recaptcha_type' );      // robot | invisible
						$language  = $this->get_option( 'recaptcha_language' ) ?: 'en';
						$theme     = $this->get_option( 'recaptcha_theme' ) ?: 'light';

						/* Multilingual override */
						if ( $this->language_do() && ( $lang = $this->language_current() ) ) {
							$language = $lang;
						}

						$functions_variables += array(
							'recaptcha_sitekey'   => $sitekey,
							'recaptcha_secretkey' => $secret,
							'recaptcha_type'      => ( $type_opt === 'invisible' ? 'invisible' : 'robot' ),
							'recaptcha_language'  => $language,
							'recaptcha_theme'     => $theme,
						);

						/* ----- Visible (checkbox) -------------------------- */
						if ( $type_opt !== 'invisible' ) {

							wp_enqueue_script(
								'newsletters-recaptcha',
								'https://www.google.com/recaptcha/api.js?hl=' . esc_attr( $language ),
								array(),
								null,
								true
							);

						/* ----- Invisible ― FIXED badge bottom-right -------- */
						} else {

							if ( ! wp_script_is( 'newsletters-recaptcha', 'enqueued' ) ) {

								wp_enqueue_script(
									'newsletters-recaptcha',
									'https://www.google.com/recaptcha/api.js?render=explicit&hl=' .
									esc_attr( $language ) .
									'&onload=newsletterRecaptchaInit',
									array(),
									null,
									true
								);

								/* Render every placeholder once, badge bottom-right */
								wp_add_inline_script(
									'newsletters-recaptcha',
									sprintf(
										'
										function newsletterRecaptchaInit() {
											document.querySelectorAll(".newsletters-recaptcha-challenge").forEach(function(el){
												if ( el.dataset.grecaptchaWidgetId !== undefined ) { return; }
												var id = grecaptcha.render(el,{
													sitekey:"%1$s",
													size:"invisible",
													badge:"bottomright"
												});
												el.dataset.grecaptchaWidgetId = id;
												
												var badge = el.querySelector(".grecaptcha-badge");
												if (badge && !badge.dataset.movedToBody){
													document.body.appendChild(badge);
													badge.dataset.movedToBody = "1";
												}
											});
										}
										',
										esc_js( $sitekey )
									)
								);
							}
						}

					} elseif ( $captcha_type === 'recaptcha3' ) {

						$functions_variables['captcha'] = 'recaptcha3';

						$sitekey   = $this->get_option( 'recaptcha3_publickey' );
						$secret    = $this->get_option( 'recaptcha3_privatekey' );
						$language  = $this->get_option( 'recaptcha3_language' ) ?: 'en';
						$score     = $this->get_option( 'recaptcha3_score' )    ?: '0.5';

						if ( $this->language_do() && ( $lang = $this->language_current() ) ) {
							$language = $lang;
						}

						$functions_variables += array(
							'recaptcha3_sitekey'   => $sitekey,
							'recaptcha3_secretkey' => $secret,
							'recaptcha3_language'  => $language,
							'recaptcha3_score'     => $score,
						);

						wp_enqueue_script(
							'newsletters-recaptcha3',
							'https://www.google.com/recaptcha/api.js?render=' .
							esc_attr( $sitekey ) .
							'&hl=' . esc_attr( $language ),
							array(),
							null,
							true
						);

					} elseif ( $captcha_type === 'rsc' ) {

						$functions_variables['captcha'] = 'rsc';

					} elseif ( $captcha_type === 'turnstile' ) {

						$functions_variables['captcha']           = 'turnstile';
						$functions_variables['turnstile_sitekey'] = $this->get_option( 'turnstile_sitekey' );
					}
				}

                $functions_variables['ajax_error'] = esc_js(__('An Ajax error occurred, please submit again.', 'wp-mailinglist'));

                $functions_variables['ajaxnonce'] = array(
                    'subscribe'						=>	wp_create_nonce('subscribe'),
                );

                wp_register_script('newsletters-functions', $this -> render_url('js/functions.js', 'default', false), array('jquery'), false, true);

                // Apply the filter and get the result
                $execute = apply_filters( 'wpmlloadscripts', true );

                // Check the value of $execute and execute the code only if it's true
                if ( $execute ) {
                    wp_localize_script('newsletters-functions', 'newsletters', $functions_variables);
                    wp_enqueue_script('newsletters-functions');
                }
            }

            return true;
        }

        function enqueue_styles() {
            global $wp_styles;

            $load = false;
            $theme_folder = $this -> get_option('theme_folder');

            // Admin dashboard
            if (is_admin() && !defined('DOING_AJAX')) {
                wp_enqueue_style('wp-color-picker');
                wp_enqueue_style('colorbox', $this -> render_url('css/colorbox.css', 'admin', false), false, $this -> version, "all");
                wp_enqueue_style('fontawesome', $this -> render_url('css/fontawesome.css', 'admin', false), false, '7.1.0', "all");
                wp_enqueue_style('fontawesome-v4-shims', $this -> render_url('css/v4-shims.css', 'admin', false), array('fontawesome'), '7.1.0', "all");

                if ((preg_match("/(widgets\.php)/", $_SERVER['REQUEST_URI'], $matches)) || (!empty($_GET['page']) && in_array($_GET['page'], (array) $this -> sections)) || (get_post_type() == "newsletter")) {
                    $uisrc = $this -> render_url('css/jquery-ui.css', 'admin', false);
                    wp_enqueue_style('jquery-ui', $uisrc, false, '1.0', "all");
                    wp_enqueue_style('bootstrap', $this -> render_url('css/bootstrap.css', 'admin', false), false, false, "all");
                    wp_deregister_style('select2');
                    wp_enqueue_style('select2', $this -> render_url('css/select2.css', 'admin', false), false, false, "all");
                }

                // Count Down
                if (!empty($_GET['page']) && $_GET['page'] == $this -> sections -> queue) {
                    wp_enqueue_style('jquery-countdown', $this -> render_url('css/jquery-countdown.css', 'admin', false), false, false, "all");
                }

                wp_enqueue_style('wp-mailinglist', $this -> render_url('css/wp-mailinglist.css', 'admin', false), false, $this -> version, "screen");

                // Front-end
            } else {
                $loadstyles = $this -> get_option('loadstyles');
                $loadstyles_handles = $this -> get_option('loadstyles_handles');
                $loadstyles_pages = $this -> get_option('loadstyles_pages');

                include($this -> plugin_base() . DS . 'includes' . DS . 'variables.php');

                if (!empty($defaultstyles)) {
                    foreach ($defaultstyles as $handle => $style) {
                        $custom_handle = (empty($loadstyles_handles[$handle])) ? $handle : $loadstyles_handles[$handle];
                        $custom_pages = (empty($loadstyles_pages[$handle])) ? false : explode(",", $loadstyles_pages[$handle]);

                        if ((!empty($loadstyles) && in_array($handle, $loadstyles)) || wpml_is_management()) {
                            if (empty($custom_pages) || (!empty($custom_pages) && (is_single($custom_pages) || is_page($custom_pages)))) {
                                if (apply_filters('newsletters_enqueuestyle_' . $handle, true)) {
                                    wp_enqueue_style($custom_handle, $style['url'], $style['deps'], $style['version'], $style['media']);
                                    do_action('newsletters_enqueuestyle_after', $handle, $style);
                                }
                            }
                        }
                    }
                }
            }

            return true;
        }

        function delete_default_themes() {
            global $wpdb, $Theme;

            $themes = array(
                'blueretro'			=>	array('title' => __('Blue Retro', 'wp-mailinglist'), 'name' => "blueretro"),
                'getaway'			=>	array('title' => __('Getaway', 'wp-mailinglist'), 'name' => "getaway"),
                'nightlife'			=>	array('title' => __('Night Life', 'wp-mailinglist'), 'name' => "nightlife"),
                'paperphase'		=>	array('title' => __('Paper Phase', 'wp-mailinglist'), 'name' => "paperphase"),
                'redray'			=>	array('title' => __('Red Ray', 'wp-mailinglist'), 'name' => "redray"),
                'simplyelegant'		=>	array('title' => __('Simply Elegant', 'wp-mailinglist'), 'name' => "simplyelegant"),
                'snazzy'			=>	array('title' => __('Snazzy', 'wp-mailinglist'), 'name' => "snazzy"),
                'pronews'			=>	array('title' => __('Pro News', 'wp-mailinglist'), 'name' => "pronews"),
                'lagoon'			=>	array('title' => __('Lagoon', 'wp-mailinglist'), 'name' => "lagoon"),
                'themailer'			=>	array('title' => __('The Mailer', 'wp-mailinglist'), 'name' => "themailer"),
            );

            foreach ($themes as $theme) {
                $query = "DELETE FROM `" . $wpdb -> prefix . $Theme -> table . "` WHERE `name` = '" . esc_sql($theme['name']) . "'";
                $wpdb -> $query($query);
            }

            return true;
        }

        function initialize_default_themes() {
            if (!is_admin() && !defined('DOING_AJAX')) return;

            $premade_include = $this -> plugin_base() . DS . 'includes' . DS . 'themes' . DS . 'premade.php';
            include($premade_include);

            return true;
        }

        function set_timezone() {
            $timezone_set = $this -> get_option('timezone_set');
            if (!empty($timezone_set)) {
                $timezone_format = _x('Y-m-d G:i:s', 'timezone date format');
                $current_offset = get_option('gmt_offset');
                $tzstring = wp_timezone_string(); //get_option('timezone_string');
                $check_zone_info = true;
                if (false !== strpos($tzstring,'Etc/GMT')) { $tzstring = ''; }

                if (empty($tzstring)) {
                    $check_zone_info = false;
                    if (0 == $current_offset) {
                        $tzstring = 'UTC+0';
                    } elseif ($current_offset < 0) {
                        $tzstring = 'UTC' . $current_offset;
                    } else {
                        $tzstring = 'UTC+' . $current_offset;
                    }
                }

                @putenv("TZ=" . $tzstring);
                @ini_set('date.timezone', $tzstring);

                $timezone = new DateTimeZone( $tzstring );
                wp_date($timezone_format, null, $timezone );

                /* if (function_exists('date_default_timezone_set')) {
                            @date_default_timezone_set($tzstring);
                        } */
            }

            return true;
        }

        function init_class($name = null, $params = array()) {
            if (!empty($name)) {
                $name = (!preg_match("/" . $this -> pre . "/si", $name)) ? $this -> pre . $name : $name;
                if (class_exists($name)) {
                    if ($class = new $name($params)) {
                        if (!empty($this -> plugin_name)) {
                            $class -> plugin_name = $this -> plugin_name;
                        }
                        return $class;
                    }
                }
            }

            return false;
        }

        function register_external_model($model = null) {
            if (!empty($model)) {
                if ($this -> {$model}()) {
                    $this -> tablenames[$this -> pre . $this -> {$model}() -> controller] = $wpdb -> prefix . $this -> {$model}() -> table;
                    $this -> tables[$this -> pre . $this -> {$model}() -> controller] = (empty($this -> {$model}() -> table_fields)) ? $this -> {$model}() -> fields : $this -> {$model}() -> table_fields;
                    $this -> tables_tv[$this -> pre . $this -> {$model}() -> controller] = (empty($this -> {$model}() -> tv_fields)) ? false : $this -> {$model}() -> tv_fields;
                    $this -> indexes[$this -> pre . $this -> {$model}() -> controller] = (!empty($this -> {$model}() -> indexes)) ? $this -> {$model}() -> indexes : false;

                    return true;
                }
            }

            return false;
        }

        function initialize_classes() {
            global $wpdb;

            if (!empty($this -> helpers)) {
                foreach ($this -> helpers as $helper) {
                    global ${$helper};

                    $helpername = $this -> pre . $helper . 'Helper';
                    if (!is_object(${$helper})) {
                        ${$helper} = $this -> init_class($helpername);
                    }
                }
            }

            if (!empty($this -> models)) {
                foreach ($this -> models as $model) {
                    //global ${$model};
                    //$newmethod = $this -> {$model}();
                    //${$model} = $newmethod;
                    //$this -> {$model} = $newmethod;
                    $this -> {$model}();
                }
            }

            //make sure that we have some classes defined.
            if (!empty($this -> classes)) {
                //loop our classes
                foreach ($this -> classes as $class) {
                    global ${$class};

                    if (!is_object(${$class})) {
                        switch ($class) {
                            //case 'wpmlGroup'		:
                            //case 'wpmlOrder'		:
                            case 'wpmlCountry'		:
                                ${$class} = $this -> init_class($class);
                                break;
                            default					:
                                ${$class} = $this -> init_class($this -> pre . $class);
                                break;
                        }

                        if (!empty(${$class} -> table_fields)) {
                            ${$class} -> table_fields = apply_filters('newsletters_db_table_fields', ${$class} -> table_fields, $class);
                        } elseif (!empty(${$class} -> fields)) {
                            ${$class} -> fields = apply_filters('newsletters_db_table_fields', ${$class} -> fields, $class);
                        }

                        $this -> tablenames[$this -> pre . ${$class} -> controller] = $wpdb -> prefix . ${$class} -> table;
                        $this -> tables[$this -> pre . ${$class} -> controller] = (empty(${$class} -> table_fields)) ? ${$class} -> fields : ${$class} -> table_fields;
                        $this -> tables_tv[$this -> pre . ${$class} -> controller] = (empty(${$class} -> tv_fields)) ? false : ${$class} -> tv_fields;
                        $this -> indexes[$this -> pre . ${$class} -> controller] = (!empty(${$class} -> indexes)) ? ${$class} -> indexes : false;
                    }

                    if (empty($this -> {$class}) || !is_object($this -> {$class})) {
                        $this -> {$class} = ${$class};
                    }
                }
            }

            $this -> tables = apply_filters('newsletters_db_tables', $this -> tables);

            do_action('newsletters_initialize_classes_done', $this -> tables);

            return true;
        }

        function activateaction_scheduling() {
            $activateaction = $this -> get_option('activateaction');

            if (!empty($activateaction) && $activateaction != "none") {
                $timestamp = time();

                if (!wp_next_scheduled($this -> pre . '_activateaction')) {
                    wp_schedule_event($timestamp, "hourly", $this -> pre . '_activateaction');
                }
            }

            return true;
        }

        function latestposts_scheduling($interval = null, $startdate = null, $args = null) {
            if (!empty($interval) && !empty($args[0])) {
                wp_clear_scheduled_hook('newsletters_latestposts', $args);
                $schedules = wp_get_schedules();

                if (empty($startdate) || strtotime($startdate) < current_time('timestamp')) {
                    $new_timestamp = time();
                } else {
                    $new_timestamp = strtotime(get_gmt_from_date($startdate));
                }

                if (!wp_next_scheduled('newsletters_latestposts', $args)) {
                    wp_schedule_event($new_timestamp, $interval, 'newsletters_latestposts', $args);
                }
            }

            return true;
        }

        function pop_scheduling() {
            wp_clear_scheduled_hook($this -> pre . '_pophook');
            if ($this -> get_option('bouncemethod') == "pop") {
                $schedules = wp_get_schedules();
                $interval = $this -> get_option('bouncepop_interval');
                $new_timestamp = time() + $schedules[$interval]['interval'];

                if (!wp_next_scheduled($this -> pre . '_pophook')) {
                    wp_schedule_event($new_timestamp, $interval, $this -> pre . '_pophook');
                }
            }

            return;
        }

        function importusers_scheduling() {
            wp_clear_scheduled_hook($this -> pre . '_importusers');
            if ($this -> get_option('importusers') == "Y") {
                $schedules = wp_get_schedules();
                $interval = $this -> get_option('importusersscheduling');
                $interval = (empty($interval)) ? "hourly" : $interval;

                $new_timestamp = time() + $schedules[$interval]['interval'];

                if (!wp_next_scheduled($this -> pre . '_importusers')) {
                    wp_schedule_event($new_timestamp, $interval, $this -> pre . '_importusers');
                }
            }
        }

        function autoresponder_scheduling() {
            $schedules = wp_get_schedules();
            $interval = $this -> get_option('autoresponderscheduling');
            $new_timestamp = time() + $schedules[$interval]['interval'];

            if (!wp_next_scheduled($this -> pre . '_autoresponders')) {
                wp_schedule_event($new_timestamp, $interval, $this -> pre . '_autoresponders');
            }

            return true;
        }

        function captchacleanup_scheduling() {
            wp_clear_scheduled_hook($this -> pre . '_captchacleanup');
            $schedules = wp_get_schedules();
            $interval = $this -> get_option('captchainterval');
            $new_timestamp = time() + $schedules[$interval]['interval'];

            if (!wp_next_scheduled($this -> pre . '_captchacleanup')) {
                wp_schedule_event($new_timestamp, $interval, $this -> pre . '_captchacleanup');
            }

            return true;
        }

        function scheduling($increase = false) {
            wp_clear_scheduled_hook($this -> pre . '_cronhook');

            $schedules = wp_get_schedules();
            $interval = $this -> get_option('croninterval');
            $interval = (empty($interval)) ? 'hourly' : $interval;
            $new_timestamp = time() + $schedules[$interval]['interval'];
            if ($increase == true) { $new_timestamp += 300; }

            if (!wp_next_scheduled($this -> pre . '_cronhook')) {
                wp_schedule_event($new_timestamp, $interval, $this -> pre . '_cronhook');
            }
        }

        function countries_scheduling() {
            if (!wp_next_scheduled('newsletters_countrieshook')) {
                wp_schedule_event(time(), 'hourly', 'newsletters_countrieshook');
            }
        }

        function optimize_scheduling() {
            if (!wp_next_scheduled('newsletters_optimizehook')) {
                wp_schedule_event(time(), 'daily', 'newsletters_optimizehook');
            }
        }

        function emailarchive_scheduling() {
            if (!wp_next_scheduled('newsletters_emailarchivehook')) {
                wp_schedule_event(time(), 'daily', 'newsletters_emailarchivehook');
            }
        }

        function get_custom_post_types($removedefaults = true) {
            if ($post_types = get_post_types(null, 'objects')) {
                $default_types = array( 'page', 'attachment', 'revision', 'nav_menu_item');

                if ($removedefaults) {
                    foreach ($default_types as $dpt) {
                        unset($post_types[$dpt]);
                    }
                }

                return $post_types;
            }

            return false;
        }

        function check_tables() {
            global $wpdb;
            $this -> initialize_classes();

            if (!empty($this -> models)) {
                foreach ($this -> models as $model) {
                    if (!empty($this -> {$model}() -> table_fields)) {
                        $this -> {$model}() -> table_fields = apply_filters('newsletters_db_table_fields', $this -> {$model}() -> table_fields, $model);
                    }
                    if( isset($this -> {$model}()->fields) && !is_array($this -> {$model}()->fields) && property_exists(get_class($this -> {$model}()),$this -> {$model}() -> fields)) {
                        $this->{$model}()->fields = apply_filters('newsletters_db_table_fields_new', $this->{$model}()->fields, $model);
                    }
                    $this -> tablenames[$this -> pre . $this -> {$model}() -> controller] = $wpdb -> prefix . $this -> {$model}() -> table;
                    $this -> tables[$this -> pre . $this -> {$model}() -> controller] = (!empty($this -> {$model}() -> table_fields)) ? $this -> {$model}() -> table_fields : $this -> {$model}() -> fields;
                    $this -> tables_tv[$this -> pre . $this -> {$model}() -> controller] = (!empty($this -> {$model}() -> tv_fields)) ? $this -> {$model}() -> tv_fields : false;
                    $this -> indexes[$this -> pre . $this -> {$model}() -> controller] = (!empty($this -> {$model}() -> indexes)) ? $this -> {$model}() -> indexes : false;
                }
            }

            if (!empty($this -> tablenames)) {
                foreach ($this -> tablenames as $controller => $tablename) {
                    $this -> check_table($controller);
                }
            }
        }

        function check_table($name = null) {
            //global WP variables
            global $wpdb;
            if (!is_admin() && !defined('DOING_AJAX')) return;

            //ensure that a "name" was passed
            if (!empty($name)) {
                //add the WP prefix to the table name
                $oldname = $name;
                $name = $wpdb -> prefix . $name;

                //make sure that the table fields are available
                if (!empty($this -> tables[$oldname])) {
                    //check if the table exists. boolean value returns
                    $query = "SHOW TABLES LIKE '" . esc_sql($name) . "'";
                    if (!$wpdb -> get_var($query)) {

                        //let's start the query for a new table!
                        $query = "CREATE TABLE `" . $name . "` (";
                        $c = 1;

                        //loop the table fields.
                        foreach ($this -> tables[$oldname] as $field => $attributes) {
                            //we might need to use a KEY declaration
                            //in case not "key", continue with normal attributes set.
                            if ($field != "key") {
                                //append the field name and attributes
                                $query .= "`" . $field . "` " . $attributes . "";
                            } else {
                                //this is a "key" field. declare it
                                $query .= "" . $attributes . "";
                            }

                            //the last query doesn't get a comma at the end.
                            //ensure that it is not the last query section.
                            if ($c < count($this -> tables[$oldname])) {
                                //append a comma "," to the query
                                $query .= ",";
                            }

                            $c++;
                        }

                        // Commented... do not add another `id` index to the database table, it is redundant
                        /*if (array_key_exists('id', $this -> tables[$oldname])) {
                                    $query .= ", INDEX (`id`)";
                                }*/

                        //end the query!
                        //$query .= ") ENGINE=MyISAM AUTO_INCREMENT=1 CHARSET=UTF8 COLLATE=utf8_general_ci;";
                        //change to utf8mb4 and utf8mb4_unicode_ci if possible
                        $charset = (empty($wpdb -> charset)) ? 'utf8' : $wpdb -> charset;
                        $collate = (empty($wpdb -> collate)) ? 'utf8_general_ci' : $wpdb -> collate;
                        $query .= ") ENGINE=MyISAM AUTO_INCREMENT=1 CHARSET=" . $charset . " COLLATE=" . $collate . ";";

                        if (!empty($query)) {
                            $this -> table_query[$name] = $query;
                        }
                    } else {
                        //get the current fields for this table.
                        $field_array = $this -> get_fields($oldname);

                        //loop the fields of the table
                        foreach ($this -> tables[$oldname] as $field => $attributes) {
                            //make sure that its not a KEY value.
                            if ($field != "key") {
                                //add the database table field.
                                $this -> add_field($oldname, $field, $attributes);
                            }
                        }

                        $subscriberTable = ! empty($Subscriber -> table) ? $Subscriber -> table : '';

                        global $wpdb, $Db, $Field, $Subscriber;
                        switch ($oldname) {
                            case $subscriberTable			:
                                $Db -> model = $Field -> model;
                                if ($fields = $Db -> find_all()) {
                                    foreach ($fields as $field) {
                                        $this -> add_field($oldname, $field -> slug);
                                    }
                                }
                                break;
                        }

                        if (!empty($this -> indexes[$oldname])) {
                            $indexes = $this -> indexes[$oldname];

                            // drop any redundant `id` index
                            if ($wpdb -> get_var("SHOW INDEX FROM `" . $name . "` WHERE `Key_name` = 'id'")) {
                                $query = "ALTER TABLE `" . $name . "` DROP INDEX `id`";
                                $wpdb -> query($query);
                            }

                            foreach ($indexes as $index) {
                                if (is_array($index)) {
                                    $indexname = implode("_", $index);
                                    if (!empty($indexname)) {
                                        $query = "SHOW INDEX FROM `" . $name . "` WHERE `Key_name` = '" . $indexname . "'";
                                        if (!$wpdb -> get_row($query)) {
                                            $query = "ALTER TABLE `" . $name . "` ADD UNIQUE INDEX " . $indexname . " (" . implode(", ", $index) . ");";
                                            $wpdb -> query($query);
                                        }
                                    }
                                } else {
                                    $query = "SHOW INDEX FROM `" . $name . "` WHERE `Key_name` = '" . $index . "'";
                                    if (!$wpdb -> get_row($query)) {
                                        $query = "ALTER TABLE `" . $name . "` ADD INDEX(`" . $index . "`);";
                                        $wpdb -> query($query);
                                    }
                                }
                            }
                        }
                    }

                    //make sure that the query is not empty.
                    foreach ($this -> table_query as $tableName => $query) {
                        $wpdb -> query($query);
                        unset($this -> table_query[$tableName]);
                    }
                }
            } else {
                return false;
            }
        }

        /**
         * Retrieves all the fields for a specific database table
         * @param $table STRING The name of the table to check.
         * @return $field_array ARRAY An array of fields for the specific table.
         *
         **/
        function get_fields($table = null) {
            global $wpdb;

            //make sure the table nae is available
            if (!empty($table)) {
                $fullname = $wpdb -> prefix . $table;

                $field_array = array();
                if ($fields = $wpdb -> get_results("SHOW COLUMNS FROM " . $fullname)) {
                    foreach ($fields as $field) {
                        $field_array[] = $field -> Field;
                    }
                }

                return $field_array;
            }

            return false;
        }

        function delete_field($table = null, $field = null) {
            global $wpdb;

            if (!empty($table)) {
                if (!empty($field)) {
                    $query = "ALTER TABLE `" . $wpdb -> prefix . $table . "` DROP `" . $field . "`";

                    if ($wpdb -> query($query)) {
                        return true;
                    }
                }
            }

            return false;
        }

        function change_field($table = null, $field = null, $newfield = null, $attributes = "TEXT NOT NULL") {
            global $wpdb;

            if (!empty($table)) {
                if (!empty($field)) {
                    if (!empty($newfield)) {
                        $query = "ALTER TABLE `" . $wpdb -> prefix . $table . "` CHANGE `" . $field . "` `" . $newfield . "` " . $attributes . "";

                        if ($wpdb -> query($query)) {
                            return true;
                        }
                    }
                }
            }

            return false;
        }

        function add_field($table = null, $field = null, $attributes = "TEXT NOT NULL") {
            global $wpdb;

            if (!empty($table)) {
                if (!empty($field)) {
                    $field_array = $this -> get_fields($table);

                    if (!empty($field_array)) {
                        if (!in_array($field, $field_array)) {
                            $query = "ALTER TABLE `" . $wpdb -> prefix . $table . "` ADD `" . $field . "` " . $attributes . "";
                            if ($field == "id") { $query .= ", ADD PRIMARY KEY (id)"; }

                            if ($wpdb -> query($query)) {
                                return true;
                            }
                        }
                    }
                }
            }

            return false;
        }

        function add_user_option($user_id = null, $option = null, $value = null) {
            $user_id = (empty($user_id)) ? get_current_user_id() : $user_id;

            if (!empty($user_id) && !empty($option)) {
                if (add_user_meta($user_id, 'newsletters_' . $option, $value, false)) {
                    return true;
                }
            }

            return false;
        }

        function update_user_option($user_id = null, $option = null, $value = null) {
            $user_id = (empty($user_id)) ? get_current_user_id() : $user_id;

            if (!empty($user_id) && !empty($option)) {
                $option = sanitize_text_field($option);

                if (update_user_meta($user_id, 'newsletters_' . $option, $value)) {
                    return true;
                }
            }

            return false;
        }

        function get_user_option($user_id = null, $option = null, $single = true) {
            $user_id = (empty($user_id)) ? get_current_user_id() : $user_id;

            if (!empty($user_id) && !empty($option)) {
                if ($value = get_user_meta($user_id, 'newsletters_' . $option, $single)) {
                    return $value;
                }
            }

            return false;
        }

        function delete_user_option($user_id = null, $option = null) {
            $user_id = (empty($user_id)) ? get_current_user_id() : $user_id;

            if (!empty($user_id) && !empty($option)) {
                if (delete_user_meta($user_id, 'newsletters_' . $option)) {
                    return true;
                }
            }

            return false;
        }

        function userdata($user_id = null) {
            if (!empty($user_id)) {
                if ($user = get_userdata($user_id)) {
                    return $user;
                }
            }

            return false;
        }

        function user_role($user_id = null, $user = null) {
            if (!empty($user_id)) {
                if (!empty($user) || $user = $this -> userdata($user_id)) {
                    $user_roles = $user -> roles;
                    $user_role = array_shift($user_roles);

                    return $user_role;
                }
            }

            return false;
        }

        function vendor($name = null, $pre = 'class', $classit = true) {
            if (!empty($name)) {
                $filename = $pre . '.' . strtolower($name) . '.php';
                $filepath = rtrim(NEWSLETTERS_DIR, DS) . DS . 'vendors' . DS;
                $filefull = $filepath . $filename;

                if (file_exists($filefull)) {
                    require_once($filefull);

                    if ($classit == true) {
                        $class = $this -> pre . $name;

                        if (${$name} = new $class) {
                            return ${$name};
                        }
                    } else {
                        return true;
                    }
                }
            }

            return false;
        }

        function render_field($field_id = null, $fieldset = true, $optinid = null, $showcaption = true, $watermark = true, $instance = null, $offsite = false, $errors = array(), $form_id = null, $form_field = null) {
        global $Html, $Field, $wpmltabindex, $Mailinglist, $Subscriber,
               ${'newsletters_fields_count_' . $optinid}, $newsletters_is_management;

        if (empty(${'newsletters_fields_count_' . $optinid})) {
            ${'newsletters_fields_count_' . $optinid} = 1;
        }

        if (!empty($field_id)) {
        if ($field = $Field -> get($field_id)) {
        $Subscriber -> data = (array) $Subscriber -> data;

        $col = '';

        if (!empty($form_id) && !empty($form_field)) {
            $form = $this -> Subscribeform() -> find(array('id' => $form_id));
            $form_styling = maybe_unserialize($form -> styling);

            if ($this -> language_do()) {
                $settings = $this -> language_use($this -> language_current(), $form_field -> settings);
                $settings = maybe_unserialize($settings);
            } else {
                $settings = maybe_unserialize($form_field -> settings);
            }

            $list = false;
            if ($field -> slug == "list") {
                if (empty($settings['listchoice']) || $settings['listchoice'] == "user") {
                    if (empty($settings['listchoice_user_type']) || $settings['listchoice_user_type'] == "checkboxes") {
                        $list = "checkboxes";
                        $listsselectall = '<div class="checkbox"><input onclick="jqCheckAll(this, false, \'list_id\');" type="checkbox" name="listsselectall" value="1" id="listsselectall" /></div>';
                    } else {
                        $list = "select";
                    }

                    $includelists = (!empty($settings['includelists'])) ? $settings['includelists'] : false;
                } elseif ($settings['listchoice'] == "admin") {
                    $list = "admin";
                    $adminlists = $settings['adminlists'];
                }
            }

            $visible = true;
            if ($field -> type == "hidden" || ($field -> type == "special" && $field -> slug == "list" && !empty($list) && (is_numeric($list) || $list == "all" || $list == "admin")) || (!empty($newsletters_is_management) && $field -> slug == "list")) {
                $visible = false;
                $newsletters_is_management = false;
            }

            if (!empty($fieldset) && $fieldset == true) {
                echo '<div class="form-group' . ((!empty($Subscriber -> errors[$field -> slug])) ? ' has-error' : '') . ' newsletters-fieldholder ' . ((empty($visible) && (!is_admin() || defined('DOING_AJAX'))) ? 'newsletters-fieldholder-hidden hidden' : 'newsletters-fieldholder-visible') . '" ' . ((empty($visible) && (!is_admin() || defined('DOING_AJAX'))) ? 'hidden' : '') . '>';
            }

            if (!empty($offsite) && $offsite == true) {
                echo '<p>' . "\r\n";
            }

            if (!empty($form_styling['fieldshowlabel'])) {
                $label_text = ((empty($form_field -> label)) ? __($field -> title) : __($form_field -> label)) ;
                if ( $this->language_do() ) {

                    $label_text = $this->language_useordefault(  $label_text  ) ;
                }

                echo '<label for="' . ((!empty($list) && $list == "checkboxes") ? '' : ( '' . $this -> pre . '-' . $optinid . $field -> slug . '' )) . '" class="control-label' . ((!empty($list) && $list == "checkboxes") ? ' form-inline' : '') . ' ' . $this -> pre . 'customfield ' . $this -> pre . 'customfield' . $field_id . '">'  . ( $label_text ) . ((empty($form_field -> required)) ? ' <small class="small text-muted">' . __('(optional)', 'wp-mailinglist') . '</small>' : '') . '</label> ';


                if (!empty($offsite)) {
                    echo '<br/>';
                }


                $show_select_all = true;
                if (!empty($field) && !empty($field->type) && $field->type === "special")
                {
                    if (!empty($list) && $list === 'checkboxes' )
                    {

                        if (!empty($includelists)) {
                            $lists_temp = $Mailinglist -> select(true, $includelists);
                        } else {
                            $lists_temp = $Mailinglist -> select(false);
                        }

                        if(is_array($lists_temp) && count($lists_temp ) < 2)
                        {
                            $show_select_all = false;
                        }

                    }

                }


                //Seperate the Select All from the label. Put it below the List Label
                if( !empty($list) && $list == "checkboxes" && $show_select_all) {
                    echo '<label for="' . ((!empty($list) && $list == "checkboxes") ? 'listsselectall' : ( '' . $this -> pre . '-' . $optinid . $field -> slug . '' )) . '" class="control-label' . ((!empty($list) && $list == "checkboxes") ? ' form-inline' : '') . ' ' . $this -> pre . 'customfield ' . $this -> pre . 'customfield' . $field_id . '">' . ((!empty($list) && $list == "checkboxes") ? $listsselectall . ' ' : '') . '&nbsp;' . __('Select All', 'wp-mailinglist')   . '</label> ';
                }
            }


            $watermark = (empty($form_field -> placeholder)) ? ((empty($field -> watermark)) ? false : __($field -> watermark)) : __($form_field -> placeholder);
            if ( $this->language_do() ) {

                $watermark = $this->language_useordefault(  $watermark  ) ;
            }

            if (!empty($watermark)) {
                $placeholder = ' placeholder="' . $watermark . '"';
            }

            $required = (!empty($form_field -> required)) ? true : false;
        } else {
        // Determine the list(s) to use
        $list = (empty($instance['list'])) ? ((!empty($Subscriber -> data['list_id'])) ? __($Subscriber -> data['list_id'][0]) : false) : __($instance['list']);
        if ($this -> language_do() && !empty($instance['lang'])) {
            $list = $this -> language_use($instance['lang'], $list, false);
        }

        $visible = true;
        if ($field -> type == "hidden" || ($field -> type == "special" && $field -> slug == "list" && !empty($list) && (is_numeric($list) || $list == "all")) || (!empty($newsletters_is_management) && $field -> slug == "list")) {
            $visible = false;
            $newsletters_is_management = false;
        }

        $watermark = ((!empty($field -> watermark) && $watermark == true && empty($offsite)) ? esc_attr(wp_unslash(__($field -> watermark))) : '');

        if ( $this->language_do() ) {

            $watermark = $this->language_useordefault(  $watermark  ) ;
        }

        $placeholder =  ' placeholder="' . $watermark . '"';


        if (!empty($fieldset) && $fieldset == true) {
            echo '<div id="newsletters-' . $optinid . $field -> slug . '-holder" class="form-group ' . $col . ' newsletters-fieldholder' . ((!empty($Subscriber -> errors[$field -> slug])) ? ' has-error' : '') . ' ' . ((empty($visible) && (!is_admin() || defined('DOING_AJAX'))) ? 'newsletters-fieldholder-hidden hidden' : 'newsletters-fieldholder-visible') . ' ' . $field -> slug . '">';
        }

        if (!empty($offsite) && $offsite == true) {
            echo '<p>' . "\r\n";
        }

        if ($fieldset == true && $field -> type != "special" && $field -> type != "hidden") {
            if ($field->type == "file") {
                echo '<label for="file_upload_' . $field->id . $optinid . '" class="control-label ' . $this->pre . 'customfield' . $this->pre . 'customfield' . $field_id . '">';
            } else {
                echo '<label for="' . $this->pre . '-' . $optinid . $field->slug . '" class="control-label ' . $this->pre . 'customfield ' . $this->pre . 'customfield' . $field_id . '">';
            }

            $title = $field->title;
            if ( $this->language_do() && !empty($title)) {

                $watermark = $this->language_useordefault(  $title  ) ;
            }

            _e($title);
            if (empty($field->required) || $field->required == "N") {
                echo ' <small class="small text-muted">' . __('(optional)', 'wp-mailinglist') . '</small>';
            };
            echo '</label><br/>';
        }

            $required = (!empty($field -> required)) ? true : false;
            }

            $fieldname = $field -> slug;
            $method = sanitize_text_field(isset($_GET['method']) ? $_GET['method'] : "");
            if (is_admin() && !defined('DOING_AJAX') && $field -> type != "file"
                && ($_GET['page'] != $this -> sections -> forms)
                && (empty($method) || $method != "offsitewizard")) {
                $fieldname = 'Subscriber[' . $field -> slug . ']';
            }

            // Either subscriber data or a GET/POST value
            $fieldvalue = false;
            $fieldvalue_from_request = false;
            if (!empty($Subscriber -> data[$field -> slug])) {
                $fieldvalue = $Subscriber -> data[$field -> slug];
            } elseif (array_key_exists($field -> slug, $_REQUEST)) {
                $fieldvalue = wp_unslash($_REQUEST[$field -> slug]);
                $fieldvalue_from_request = true;

                if (is_array($fieldvalue)) {
                    $fieldvalue = array_map('sanitize_text_field', $fieldvalue);
                } else {
                    $fieldvalue = sanitize_text_field($fieldvalue);
                }
            }

            switch ($field -> type) {
                case 'hidden'			:
                    if (empty($Subscriber -> data[$field -> slug])) {
                        switch ($field -> hidden_type) {
                            case 'post'					:
                                $hidden_value = $_REQUEST[$field -> hidden_value];
                                break;
                            case 'predefined'			:
                                $hidden_value = $field -> hidden_value;
                                break;
                            case 'custom'				:
                            default  					:
                                $hidden_value = $Subscriber -> data[$field -> slug];
                                break;
                            case 'get'					:
                                $hidden_value = esc_html($_GET[$field -> hidden_value]);
                                break;
                            case 'global'				:
                                $hidden_value = $GLOBALS[$field -> hidden_value];
                                break;
                            case 'cookie'				:
                                $hidden_value = $_COOKIE[$field -> hidden_value];
                                break;
                            case 'session'				:
                                $hidden_value = $_SESSION[$field -> hidden_value];
                                break;
                            case 'server'				:
                                $hidden_value = $_SERVER[$field -> hidden_value];
                                break;
                        }
                    } else {
                        $hidden_value = $Subscriber -> data[$field -> slug];
                    }

                    //parse any shortcodes in the hidden field value
                    $hidden_value = ! empty($hidden_value) ? wp_unslash(do_shortcode($hidden_value)) : '';
                    $method = sanitize_text_field(isset($_GET['method']) ? $_GET['method'] : "");

                    if (!is_admin() || defined('DOING_AJAX') || (!empty($method) && $method == "offsitewizard")) {
                        echo '<input type="hidden" name="' . $fieldname . '" value="' . esc_attr(wp_unslash($hidden_value)) . '" />';
                    } else {
                        echo '<input type="text" class="" name="' . $fieldname . '" value="' . esc_attr(wp_unslash($hidden_value)) . '" />';
                    }
                    break;
                case 'text'				:
                    $placeholder = isset($placeholder) ? $placeholder : '';
                    $tabindex = $field -> slug === 'email' ? '' : $Html -> tabindex($optinid);
                    echo '<input' . $placeholder . ' class="form-control ' . $this -> pre . ' ' . $this -> pre . 'text' . ((!empty($Subscriber -> errors[$field -> slug])) ? ' newsletters_fielderror' : '') . '" id="' . $this -> pre . '-' . $optinid . '' . $field -> slug . '" ' . $tabindex . ' type="text" name="' . $fieldname . '" value="' . esc_attr(wp_unslash($fieldvalue)) . '" />';
                    break;
                case 'special'			:
                    switch ($field -> slug) {
                        case 'list'				:
                        default 				:
                            // Form
                            if (!empty($form_id) && !empty($form_field)) {
                                if (!empty($list)) {
                                    switch ($list) {
                                        case 'admin'			:
                                            $lists = $Mailinglist -> select(true, $adminlists);
                                            if (!empty($lists)) {
                                                foreach ($lists as $list_id => $list_title) {
                                                    echo '<input type="hidden" name="list_id[]" value="' . $list_id . '" />';
                                                }
                                            }
                                            break;
                                        case 'select'			:
                                            if (!empty($includelists)) {
                                                $lists = $Mailinglist -> select(true, $includelists);
                                            } else {
                                                $lists = $Mailinglist -> select(false);
                                            }

                                            if (!empty($lists)) {
                                                echo '<select ' . $Html -> tabindex($optinid) . ' class="' . ((!empty($Subscriber -> errors['list_id'])) ? ' newsletters_fielderror ' : '') . $this -> pre . ' autowidth ' . $this -> pre . 'select newsletters-list-select" id="' . $optinid . $field -> slug . '-list-select" name="list_id[]">';
                                                echo '<option value="">' . __('- Select -', 'wp-mailinglist') . '</option>';

                                                foreach ($lists as $list_id => $list_title) {

                                                    if ( $this->language_do() && !empty($list_title)) {

                                                        $list_title = $this->language_useordefault(  $list_title  ) ;
                                                    }

                                                    echo '<option' . ((!empty($Subscriber -> data['list_id']) && $Subscriber -> data['list_id'][0] == $list_id) ? ' selected="selected"' : '') . ' value="' . $list_id . '">' . __($list_title) . '</option>';
                                                }

                                                echo '</select>';
                                            }
                                            break;
                                        case 'checkboxes'		:
                                            if (!empty($includelists)) {
                                                $lists = $Mailinglist -> select(true, $includelists);
                                            } else {
                                                $lists = $Mailinglist -> select(false);
                                            }

                                            if (!empty($lists)) {
                                                foreach ($lists as $list_id => $list_title) {
                                                    if ( $this->language_do() && !empty($list_title)) {

                                                        $list_title = $this->language_useordefault(  $list_title  ) ;
                                                    }
                                                    echo '<div class="checkbox">';
                                                    echo '<label class="wpmlcheckboxlabel ' . $this -> pre . '">';
                                                    echo '<input' . ((!empty($Subscriber -> data['list_id']) && in_array($list_id, $Subscriber -> data['list_id'])) ? ' checked="checked"' : '') . ' type="checkbox" name="list_id[]" value="' . $list_id . '" class="newsletters-list-checkbox" id="' . $optinid . $field -> slug . '-list-checkbox" /> ';
                                                    echo wp_unslash(__($list_title)) . '</label>';
                                                    echo '</div>';
                                                }
                                            }
                                            break;
                                    }
                                }
                                // Not Form
                            } else {
                                if (!empty($errors['list_id'])) {
                                    $errors['list'] = $errors['list_id'];
                                }

                                $optinid_string = (isset($optinid) && $optinid !== null) ? (string) $optinid : '';
                                preg_match("/[0-9]/si", $optinid_string, $matches);
                                $number = isset($matches[0]) ? $matches[0] : 0;

                                if (!empty($list)) {
                                    if (is_numeric($list)) {
                                        echo '<input type="hidden" name="list_id[]" value="' . $list . '" />';
                                    } else {
                                        if (empty($form_id) && (empty($list) || $list != "all")) {
                                            echo '<label class="' . $this -> pre . 'customfield ' . $this -> pre . 'customfield' . $field_id . '">';
                                            $title = $field -> title;
                                            if ( $this->language_do() && !empty($title)) {

                                                $title = $this->language_useordefault(  $title  ) ;
                                            }
                                            _e($title);
                                            if (empty($field -> required) || $field -> required == "N") { echo ' <small class="small text-muted">' . __('(optional)', 'wp-mailinglist') . '</small>'; };
                                            echo '</label>';
                                        }

                                        $instance['lists'] = array_filter(explode(",", $instance['lists']));
                                        $lists = (empty($instance['lists'])) ? $Mailinglist -> select(false) : $Mailinglist -> select(true, $instance['lists']);

                                        if ($list == "checkboxes") {
                                            foreach ($lists as $list_id => $list_title) {
                                                if ( $this->language_do() && !empty($list_title)) {
                                                    $list_title = $this->language_useordefault(  $list_title  ) ;
                                                }
                                                echo '<div class="checkbox">';
                                                echo '<label class="wpmlcheckboxlabel ' . $this -> pre . '">';
                                                echo '<input' . ((!empty($Subscriber -> data['list_id']) && in_array($list_id, $Subscriber -> data['list_id'])) ? ' checked="checked"' : '') . ' type="checkbox" name="list_id[]" value="' . $list_id . '" class="newsletters-list-checkbox" id="' . $optinid . $field -> slug . '-list-checkbox" /> ';
                                                echo __($list_title) . '</label>';
                                                echo '</div>';
                                            }
                                        } elseif ($list == "all") {
                                            echo '<input type="hidden" name="list_id[]" value="all" />';
                                        } else {
                                            echo '<select ' . $Html -> tabindex($optinid) . ' class="' . ((!empty($Subscriber -> errors['list_id'])) ? ' newsletters_fielderror ' : '') . $this -> pre . ' autowidth ' . $this -> pre . 'select newsletters-list-select" id="' . $optinid . $field -> slug . '-list-select" name="list_id[]">';
                                            echo '<option value="">' . __('- Select -', 'wp-mailinglist') . '</option>';

                                            foreach ($lists as $list_id => $list_title) {
                                                if ( $this->language_do() && !empty($list_title)) {

                                                    $list_title = $this->language_useordefault(  $list_title  ) ;
                                                }
                                                echo '<option' . ((!empty($Subscriber -> data['list_id']) && $Subscriber -> data['list_id'][0] == $list_id) ? ' selected="selected"' : '') . ' value="' . $list_id . '">' . __($list_title) . '</option>';
                                            }

                                            echo '</select>';
                                        }

                                        if (!empty($field -> caption) && $showcaption == true && $field -> type != "special") {
                                            echo '<span class="' . $this -> pre . 'customfieldcaption">' . __(wp_unslash($field -> caption)) . '</span>';
                                        }
                                    }
                                }
                            }
                            break;
                    }
                    break;
                case 'textarea'			:
                    echo '<textarea' . $placeholder . ' class="form-control ' . $this -> pre . ' ' . $this -> pre . 'textarea' . ((!empty($Subscriber -> errors[$field -> slug])) ? ' newsletters_fielderror' : '') . '" id="' . $this -> pre . '-' . $optinid . '' . $field -> slug . '" ' . $Html -> tabindex($optinid) . ' rows="4" name="' . $fieldname . '">' . strip_tags($fieldvalue) . '</textarea>';
                    break;
                case 'select'			:
                    echo '<select' . $placeholder . ' class="form-control ' . $this -> pre . ' ' . $this -> pre . 'select' . ((!empty($Subscriber -> errors[$field -> slug])) ? ' newsletters_fielderror' : '') . '" style="width:auto;" id="' . $this -> pre . '-' . $optinid . '' . $field -> slug . '" ' . $Html -> tabindex($optinid) . ' name="' . $fieldname . '">';
                    echo '<option value="">' . __('- Select -', 'wp-mailinglist') . '</option>';

                    if (!empty($field -> newfieldoptions)) {
                        foreach ($field -> newfieldoptions as $option_id => $option_value) {
                            if ( $this->language_do() && !empty($option_value)) {

                                $option_value = $this->language_useordefault(  $option_value  ) ;
                            }
                            $select = (!empty($fieldvalue) && ($fieldvalue == $option_id || $fieldvalue == __($option_value))) ? 'selected="selected"' : '';
                            echo '<option ' . $select . ' value="' . $option_id . '">' . __($option_value) . '</option>';
                        }
                    }

                    echo '</select>';
                    break;
                case 'radio'			:
                    if (!empty($field -> newfieldoptions)) {
                        foreach ($field -> newfieldoptions as $option_id => $option_value) {
                            $checked = ($fieldvalue == $option_id || (!empty($fieldvalue) && $fieldvalue == __($value))) ? 'checked="checked"' : '';
                            echo '<div class="radio">';
                            echo '<label class="control-label wpmlradiolabel ' . $this -> pre . '">';
                            echo '<input class="' . $this -> pre . 'radio' . ((!empty($Subscriber -> errors[$field -> slug])) ? ' newsletters_fielderror' : '') . '" ' . $Html -> tabindex($optinid) . ' type="radio" ' . $checked . ' name="' . $fieldname . '" value="' . $option_id . '" /> ' . __($option_value);
                            echo '</label>';
                            echo '</div>';
                        }
                    }
                    break;
                case 'checkbox'			:
                    $subscribercheckboxes = false;
                    if (!empty($fieldvalue) || $fieldvalue === "0" || $fieldvalue === 0) {
                        if ($fieldvalue_from_request) {
                            $subscribercheckboxes = is_array($fieldvalue) ? $fieldvalue : array($fieldvalue);
                        } else {
                            $subscribercheckboxes = $fieldvalue;

                            if (is_string($fieldvalue) && function_exists('is_serialized') && is_serialized($fieldvalue)) {
                                $maybe_unserialized = @unserialize($fieldvalue, array('allowed_classes' => false));

                                if ($maybe_unserialized !== false || $fieldvalue === 'b:0;') {
                                    $subscribercheckboxes = $maybe_unserialized;
                                }
                            }
                        }

                        if (!is_array($subscribercheckboxes) && $subscribercheckboxes !== false && $subscribercheckboxes !== null && $subscribercheckboxes !== '') {
                            $subscribercheckboxes = array($subscribercheckboxes);
                        }
                    }

                    if (!empty($field -> newfieldoptions)) {
                        foreach ($field -> newfieldoptions as $option_id => $option_value) {
                            if ( $this->language_do() && !empty($option_value)) {

                                $option_value = $this->language_useordefault(  $option_value  ) ;
                            }
                            $checked = (!empty($subscribercheckboxes) && (is_array($subscribercheckboxes) && in_array($option_id, $subscribercheckboxes))) ? 'checked="checked"' : '';
                            echo '<div class="checkbox">';
                            echo '<label class="control-label wpmlcheckboxlabel ' . $this -> pre . '">';
                            echo '<input class="' . $this -> pre . 'checkbox' . ((!empty($Subscriber -> errors[$field -> slug])) ? ' newsletters_fielderror' : '') . '" ' . $Html -> tabindex($optinid) . ' type="checkbox" ' . $checked . ' name="' . $fieldname . '[]" value="' . $option_id . '" /> ' . __($option_value);
                            echo '</label>';
                            echo '</div>';
                        }
                    }
                    break;
            case 'file'				:
                $filetypes = false;
                if (!empty($field -> filetypes)) {
                    if (($types = @explode(",", $field -> filetypes)) !== false) {
                        if (is_array($types)) {
                            $f = 1;
                            foreach ($types as $type) {
                                $filetypes .= '*' . $type;
                                if ($f < count($types)) { $filetypes .= "; "; }
                                $f++;
                            }
                        }
                    }
                }

                ?>

                <div class="clearfix"></div>
                <label class="btn btn-secondary btn-file">
                    <?php _e('Browse...', 'wp-mailinglist'); ?> <input onchange="jQuery('#file_upload_<?php echo $field -> id; ?>_info').html(jQuery(this).val().replace('C:\\fakepath\\', ''));" type="file" <?php echo $Html -> tabindex($optinid); ?> name="<?php echo esc_attr(wp_unslash($fieldname)); ?>" id="file_upload_<?php echo $field -> id; ?>" />
                </label>
                <span class="label label-info" id="file_upload_<?php echo $field -> id; ?>_info"></span>

            <?php
            break;
            case 'pre_country'		:
            global $Db, $Form;

            if ($countries = $this -> Country() -> select()) {

            $saveipaddress = $this -> get_option('saveipaddress');
            if (!empty($saveipaddress)) {
                $ipaddress = $this -> get_ip_address();
                if ($ipcountry = $this -> get_country_by_ip($ipaddress)) {
                    if ($country_id = $this -> Country() -> field('id', array('code' => $ipcountry))) {
                        if (empty($fieldvalue)) {
                            $Subscriber -> data[$field -> slug] = $country_id;
                        }
                    }
                }
            }

            ?>

                <select class="<?php echo $this -> pre; ?>country <?php echo $this -> pre; ?> <?php echo $this -> pre; ?>precountry<?php echo ((!empty($Subscriber -> errors[$field -> slug])) ? ' newsletters_fielderror' : ''); ?>" id="<?php echo $this -> pre; ?>-<?php echo $optinid . $field -> slug; ?>" <?php echo $Html -> tabindex($optinid); ?> name="<?php echo $fieldname; ?>">
                    <option value=""><?php _e('- Select Country -', 'wp-mailinglist'); ?></option>
                    <?php foreach ($countries as $id => $value) : ?>
                        <option <?php echo (!empty($fieldvalue) && $fieldvalue == $id) ? 'selected="selected"' : ''; ?> value="<?php echo esc_attr($id); ?>"><?php echo $value; ?></option>
                    <?php endforeach; ?>
                </select>

            <?php
            }
            break;
            case 'pre_date'			:
            ob_start();

            $field_value = false;
            if (!empty($fieldvalue)) {
                $field_value = maybe_unserialize($fieldvalue);
            }

            $currentDate = "";
            if (!empty($field_value) && $field_value != "0000-00-00") {
                if (is_array($field_value)) {
                    $currentDate = date_i18n(get_option('date_format'), strtotime($field_value['d'] . '/' . $field_value['m'] . '/' . $field_value['y']));
                } else {
                    $currentDate = date_i18n(get_option('date_format'), strtotime($field_value));
                }
            }

            if (!empty($currentDate)) {
                $defaultDate = 'new Date(' . date_i18n("Y", strtotime($currentDate)) . ', ' . date_i18n("m", strtotime($currentDate)) . ', ' . date_i18n("d", strtotime($currentDate)) . ')';
            } else {
                $defaultDate = 'new Date(' . date_i18n("Y") . ', ' . date_i18n("m") . ', ' . date_i18n("d") . ')';
            }

            ?>

            <input type="text" class="<?php echo $this -> pre; ?>predate <?php echo $this -> pre; ?>text <?php echo $this -> pre; ?> <?php echo $this -> pre; ?>predate<?php echo ((!empty($Subscriber -> errors[$field -> slug])) ? ' newsletters_fielderror' : ''); ?>" value="<?php echo esc_attr(wp_unslash($currentDate)); ?>" name="<?php echo $fieldname; ?>" id="<?php echo $this -> pre; ?>-<?php echo $optinid . $field -> slug; ?>" />

            <?php if (empty($offsite)) : ?>
                <script type="text/javascript">
                    jQuery(document).ready(function() {
                        jQuery('#<?php echo $this -> pre; ?>-<?php echo $optinid . $field -> slug; ?>').datepicker({
                            changeMonth: true,
                            changeYear: true,
                            yearRange: "<?php echo esc_js(date_i18n("Y", strtotime($Html -> gen_date("Y-m-d H:i:s", false, false, true) . " -100 years")) . ':' . date_i18n("Y", strtotime($Html -> gen_date("Y-m-d H:i:s", false, false, true) . " +100 years"))); ?>",
                            dateFormat: "<?php echo esc_js($Html -> dateformat_PHP_to_jQueryUI(get_option('date_format'))); ?>",
                            defaultDate: <?php echo esc_js($defaultDate); ?>,
                            showOn: "both"
                        });
                    });
                </script>
            <?php endif; ?>

            <?php

            $datepicker_output = ob_get_clean();
            echo apply_filters('newsletters_datepicker_output', $datepicker_output, $optinid, $field);
            break;
            case 'pre_gender'		:
            ?>

                <select<?php echo $placeholder; ?> class="<?php echo $this -> pre; ?> <?php echo $this -> pre; ?>pregender<?php echo ((!empty($Subscriber -> errors[$field -> slug])) ? ' newsletters_fielderror' : ''); ?>" style="width:auto;" id="<?php echo $this -> pre; ?>-<?php echo $optinid; ?><?php echo $field -> slug; ?>" <?php echo $Html -> tabindex($optinid); ?> name="<?php echo $fieldname; ?>">
                    <option value=""><?php _e('- Select Gender -', 'wp-mailinglist'); ?></option>
                    <option <?php echo (!empty($fieldvalue) && $fieldvalue == "male") ? 'selected="selected"' : ''; ?> value="male"><?php _e('Male', 'wp-mailinglist'); ?></option>
                    <option <?php echo (!empty($fieldvalue) && $fieldvalue == "female") ? 'selected="selected"' : ''; ?> value="female"><?php _e('Female', 'wp-mailinglist'); ?></option>
                </select>

                <?php
                break;
            }

            if (!empty($form_id) && !empty($form_field)) {
                $caption = (empty($form_field -> caption)) ? ((empty($field -> caption)) ? false : __($field -> caption)) : __($form_field -> caption);
                if (!empty($caption) && !empty($form_styling['fieldcaptions'])) {
                    if ( $this->language_do() && !empty($caption)) {

                        $caption = $this->language_useordefault(  $caption  ) ;
                    }
                    echo '<p class="help-block">' . wp_unslash($caption) . '</p>';
                }
            } else {
                $docaption = false;
                if (!empty($field -> caption) && $showcaption == true && $field -> type != "special" && $field -> type != "hidden") {
                    $caption = $field -> caption;
                    if ( $this->language_do() && !empty($caption)) {

                        $caption = $this->language_useordefault(  $caption  ) ;
                    }
                    echo '<p class="help-block ' . $this -> pre . 'customfieldcaption">' . __(wp_unslash($caption)) . '</p>';
                    $docaption = true;
                }
            }

            if (!empty($errors[$field -> slug])) {
                if (empty($form) || (!empty($form) && !empty($form_styling['fielderrors']))) {
                    ?>

                    <div id="newsletters-<?php echo $optinid; ?>-<?php echo $field -> slug; ?>-error" class="newsletters-field-error alert alert-danger my-1 ui-state-error ui-corner-all">
                        <i class="fa-solid fa-triangle-exclamation"></i> <?php echo wp_unslash($errors[$field -> slug]); ?>
                    </div>

                    <?php
                }
            }

            if (!empty($field -> type) && $field -> type == "file") {
                if (!empty($field -> filesizelimit)) { echo '<small>' . sprintf(__('Maximum file size of <strong>%s</strong>', 'wp-mailinglist'), $field -> filesizelimit) . '</small><br/>'; }
                if (!empty($filetypes)) { echo '<small>' . sprintf(__('Allowed file types are <strong>%s</strong>', 'wp-mailinglist'), $filetypes) . '</small><br/>'; }

                if (!empty($fieldvalue)) {
                    echo $Html -> file_custom_field($fieldvalue, $field -> filesizelimit, $filetypes, $field, true);
                    echo '<input id="newsletters_oldfile_' . $field -> id . '" type="hidden" name="oldfiles[' . $field -> slug . ']" value="' . esc_attr(wp_unslash($fieldvalue)) . '" />';
                }
            }

            if (!empty($offsite) && $offsite == true) {
                echo '</p>' . "\r\n";
            }

            if (!empty($fieldset) && $fieldset == true) {
                echo '</div>' . "\r\n";
            }

            /*if (!empty($visible) && $visible == true) {
                                if (${'newsletters_fields_count_' . $optinid}%2 == 0) {
                                    if (empty($form_id) || (!empty($form_id) && $form_styling['formlayout'] == "normal")) {
                                        ?><div class="clearfix"></div><?php
                                    }
                                }

                                ${'newsletters_fields_count_' . $optinid}++;
                            }*/
                }
                }

            return true;
                }

            function get_ip_address()
            {
                if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
                    return $_SERVER['HTTP_CLIENT_IP'];
                } else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                    return $_SERVER['HTTP_X_FORWARDED_FOR'];
                }

                return $_SERVER['REMOTE_ADDR'];
            }

            function output_custom_fields($subscriber = null) {
                global $Db, $Html, $Field;
                $customfields = "";
                ob_start();

                if (!empty($subscriber)) {
                    $fields = $Field -> get_all();

                    if (!empty($fields)) {
                        $class = "alternate";

                        ?><table><tbody><?php

                        foreach ($fields as $field) {
                            if (!empty($subscriber -> {$field -> slug})) {

                                $fieldoptions = $field -> newfieldoptions;

                                ?>

                                <tr class="<?php echo $class = (empty($class)) ? 'alternate' : ''; ?>">
                                    <th><?php _e($field -> title); ?></th>
                                    <td>
                                        <?php if ($field -> type == "radio" || $field -> type == "select") : ?>
                                            <?php echo __($fieldoptions[$subscriber -> {$field -> slug}]); ?>
                                        <?php elseif ($field -> type == "checkbox") : ?>
                                            <?php $supoptions = maybe_unserialize($subscriber -> {$field -> slug}); ?>
                                            <?php if (!empty($supoptions) && is_array($supoptions)) : ?>
                                                <?php foreach ($supoptions as $supopt) : ?>
                                                    &raquo;&nbsp;<?php echo __($fieldoptions[$supopt]); ?><br/>
                                                <?php endforeach; ?>
                                            <?php else : ?>
                                                <?php _e('none', 'wp-mailinglist'); ?>
                                            <?php endif; ?>
                                        <?php elseif ($field -> type == "file") : ?>
                                            <?php echo $Html -> file_custom_field($subscriber -> {$field -> slug}); ?>
                                        <?php elseif ($field -> type == "pre_country") : ?>
                                            <?php echo $this -> Country() -> field('value', array('id' => $subscriber -> {$field -> slug})); ?>
                                        <?php elseif ($field -> type == "pre_date") : ?>
                                            <?php if (is_serialized($subscriber -> {$field -> slug})) : ?>
                                                <?php $date = @unserialize($subscriber -> {$field -> slug}); ?>
                                                <?php if (!empty($date) && is_array($date)) : ?>
                                                    <?php echo $date['y']; ?>-<?php echo $date['m']; ?>-<?php echo $date['d']; ?>
                                                <?php endif; ?>
                                            <?php else : ?>
                                                <?php echo date_i18n(get_option('date_format'), strtotime($subscriber -> {$field -> slug})); ?>
                                            <?php endif; ?>
                                        <?php else : ?>
                                            <?php echo $subscriber -> {$field -> slug}; ?>
                                        <?php endif; ?>
                                    </td>
                                </tr>

                                <?php
                            }
                        }

                        ?></tbody></table><?php
                    }
                }

                $customfields = ob_get_clean();
                return $customfields;
            }

            function gen_auth($subscriber_id = null, $mailinglist_id = null) {
                $mailinglist_id = false;

                if (!empty($subscriber_id)) {
                    global $Db, $Subscriber, $SubscribersList;
                    $Db -> model = $Subscriber -> model;
                    $subscriber = $Db -> find(array('id' => $subscriber_id));
                    $authkey = (empty($subscriber -> authkey)) ? md5($subscriber_id) : $subscriber -> authkey;

                    if (!empty($mailinglist_id)) {
                        $Db -> model = $SubscribersList -> model;
                        if ($subscriberslist = $Db -> find(array('subscriber_id' => $subscriber_id, 'list_id' => $mailinglist_id))) {
                            if ($subscriberslist -> authinprog == "Y" && !empty($subscriberslist -> authkey) && $subscriberslist -> authkey == $authkey) {
                                $authkey = $subscriberslist -> authkey;
                            } else {
                                $Db -> model = $SubscribersList -> model;
                                $Db -> save_field('authkey', $authkey, array('list_id' => $mailinglist_id, 'subscriber_id' => $subscriber_id));
                                $Db -> model = $SubscribersList -> model;
                                $Db -> save_field('authinprog', "Y", array('list_id' => $mailinglist_id, 'subscriber_id' => $subscriber_id));
                            }
                        }
                    } else {
                        if (!empty($subscriber)) {
                            if ($subscriber -> authinprog == "Y" && !empty($subscriber -> authkey)) {
                                $authkey = $subscriber -> authkey;
                            } else {
                                $Db -> model = $Subscriber -> model;
                                $Db -> save_field('authkey', $authkey, array('id' => $subscriber_id));
                                $Db -> model = $Subscriber -> model;
                                $Db -> save_field('cookieauth', $authkey, array('id' => $subscriber_id));
                                $Db -> model = $Subscriber -> model;
                                $Db -> save_field('authinprog', "Y", array('id' => $subscriber_id));
                            }
                        }
                    }
                }

                return $authkey;
            }

            function htmltf($format = 'html') {
                switch ($format) {
                    case 'html'			:
                        return true;
                        break;
                    case 'text'			:
                        return false;
                        break;
                }

                return true;
            }

            function gen_subscribe_url($subscriber = null, $mailinglists = null) {
                global $Html;
                $url = "";

                try {
                    if (!empty($subscriber)) {
                        if (!empty($mailinglists) && is_array($mailinglists)) {
                            $mailinglists = is_array($mailinglists) ? implode(",", $mailinglists) : $mailinglists;
                        }

                        $querystring = 'method=subscribe&id=' . $subscriber -> id . '&mailinglists=' . $mailinglists;
                        $url = $Html -> retainquery($querystring, $this -> get_managementpost(true));
                    }
                }
                catch (Exception $ex) {
                    error_log( 'Caught exception: ',  $ex->getMessage(), "\n");
                }

                return $url;

            }

            function gen_resubscribe_link($subscriber = null, $urlonly = false) {
                global $Html;
                $link = "";

                try {
                    if (!empty($subscriber)) {
                        $querystring = 'method=resubscribe&email=' . $subscriber->email . '&mailinglists=' . (is_array($subscriber->mailinglists) ? implode(",", $subscriber->mailinglists) : $subscriber->mailinglists);
                        $url = $Html->retainquery($querystring, $this->get_managementpost(true));

                        if (!empty($urlonly)) {
                            $link = $url;
                        } else {
                            $link = '<a class="newsletters_resubscribe newsletters_link" href="' . $url . '">' . __($this->get_option('resubscribetext')) . '</a>';
                        }
                    }
                }
                catch (Exception $ex) {
                    error_log( 'Caught exception: ',  $ex->getMessage(), "\n");
                }

                return $link;
            }

            function gen_unsubscribe_link($subscriber = null, $user = null, $theme_id = null, $history_id = null, $alllists = false, $urlonly = false) {
                global $Db, $Html, $Subscriber, $HistoriesList;

                try {
                    if (!empty($subscriber) || !empty($user)) {
                        $linktext = __($this -> get_option('unsubscribetext'));
                        $auth_id = (empty($subscriber)) ? $user -> ID : $subscriber -> id;
                        $auth_string = (empty($subscriber)) ? $user -> roles[0] : ((!empty($subscriber -> mailinglist_id)) ? $subscriber -> mailinglist_id : false);
                        $authkey = $this -> gen_auth($auth_id, $auth_string);

                        if (!empty($theme_id)) {
                            global $wpdb, $Theme;

                            $acolorquery = "SELECT `acolor` FROM `" . $wpdb -> prefix . $Theme -> table . "` WHERE `id` = '" . esc_sql($theme_id) . "' LIMIT 1";

                            $query_hash = md5($acolorquery);
                            if ($ob_acolor = $this -> get_cache($query_hash)) {
                                $acolor = $ob_acolor;
                            } else {
                                $acolor = $wpdb -> get_var($acolorquery);
                                $this -> set_cache($query_hash, $acolor);
                            }

                            $style = "color:" . $acolor . ";";
                        }

                        if (!empty($subscriber)) {
                            $mailinglists = "";
                            if (!empty($alllists) && $alllists == true) {
                                $slists = $Subscriber -> mailinglists($subscriber -> id);
                                $mailinglists = is_array($slists) ? implode(",", $slists) : $slists ;
                                $linktext = __($this -> get_option('unsubscribealltext'));
                            } else {

                                $history = $this -> History() -> find(array('id' => $history_id));
                                $history_lists = is_object($history) ? maybe_unserialize($history -> mailinglists) : null;
                                $includeonly = (empty($history_lists)) ? (isset($subscriber -> mailinglists) ? $subscriber -> mailinglists : '') : $history_lists;
                                $subscriber_lists = maybe_unserialize($Subscriber -> mailinglists($subscriber -> id, $includeonly, false, false));
                                $mailinglists = (empty($subscriber_lists)) ? $history_lists : $subscriber_lists;
                            }

                            if (!empty($mailinglists) && is_array($mailinglists)) {
                                $mailinglists = implode(",", $mailinglists);
                            }

                            $querystring = 'method=unsubscribe&' . $this -> pre . 'history_id=' . $history_id . '&' . $this -> pre . 'subscriber_id=' . $subscriber -> id . '&' . $this -> pre . 'mailinglist_id=' . $mailinglists . '&authkey=' . $authkey;
                        } elseif (!empty($user)) {
                            $querystring = 'method=unsubscribe&' . $this -> pre . 'history_id=' . $history_id . '&user_id=' . $user -> ID . '&authkey=' . $authkey;
                        }

                        $url = $Html -> retainquery($querystring, $this -> get_managementpost(true));
                        if (empty($urlonly) || $urlonly == false) {
                            $style = isset($style) ? $style : '';
                            $unsubscribelink = '<a class="newsletters_unsubscribe newsletters_link" href="' . $url . '" title="' . $linktext . '" style="' . $style . '">' . $linktext . '</a>';
                        } else {
                            $unsubscribelink = $url;
                        }

                        return $unsubscribelink;
                    }
                }
                catch (Exception $ex) {
                    error_log( 'Caught exception: ',  $ex->getMessage(), "\n");
                }


                return false;
            }

            function gen_manage_link($subscriber = array(), $theme_id = null, $history_id = null) {
                global $Db, $Subscriber, $Html, $Authnews;
                try {
                    if (!empty($subscriber)) {
                        $linktext = __($this -> get_option('managelinktext'));

                        if (empty($subscriber -> cookieauth)) {
                            $subscriberauth = $Authnews -> gen_subscriberauth();
                            $Db -> model = $Subscriber -> model;
                            $Db -> save_field('cookieauth', $subscriberauth, array('id' => $subscriber -> id));
                        } else {
                            $subscriberauth = $subscriber -> cookieauth;
                        }

                        $url = $Html -> retainquery('method=loginauth&email=' . $subscriber -> email . '&subscriberauth=' . $subscriberauth, $this -> get_managementpost(true));

                        if (!empty($theme_id)) {
                            global $wpdb, $Theme;

                            $acolorquery = "SELECT `acolor` FROM `" . $wpdb -> prefix . $Theme -> table . "` WHERE `id` = '" . esc_sql($theme_id) . "' LIMIT 1";

                            $query_hash = md5($acolorquery);
                            if ($ob_acolor = $this -> get_cache($query_hash)) {
                                $acolor = $ob_acolor;
                            } else {
                                $acolor = $wpdb -> get_var($acolorquery);
                                $this -> set_cache($query_hash, $acolor);
                            }

                            $style = "color:" . $acolor . ";";
                        }

                        if (empty($subscriber -> format) || $subscriber -> format == "html") {
                            $style = isset($style) ? $style : '';
                            $managelink = '<a class="newsletters_manage newsletters_link" href="' . $url . '" title="' . $linktext . '" style="' . $style . '">' . $linktext . '</a>';
                        } else {
                            $managelink = $url;
                        }

                        return $managelink;
                    }
                }
                catch (Exception $ex) {
                    error_log( 'Caught exception: ',  $ex->getMessage(), "\n");
                }

                return false;
            }

            function gen_online_link($subscriber = null, $user = null, $history_id = null, $onlyurl = false, $theme_id = null, $print = false) {
                if (!empty($history_id)) {
                    global $Db, $Html;
                    if ($email = $this -> History() -> find(array('id' => $history_id))) {
                        $auth_id = (empty($subscriber)) ? ((isset($user) && !empty($user)) ? $user -> ID : 0) : $subscriber -> id;
                        $authkey = !empty($auth_id) ? $this -> gen_auth($auth_id) : '';

                        if (!empty($subscriber)) {
                            $querystring = 'newsletters_method=newsletter&id=' . esc_html($email -> id) . '&mailinglist_id=' . ((!empty($subscriber -> mailinglist_id)) ? $subscriber -> mailinglist_id : false)  . '&subscriber_id=' . $subscriber -> id . '&authkey=' . $authkey;
                            $url = $Html -> retainquery($querystring, home_url());
                        } else {
                            $querystring = 'newsletters_method=newsletter&id=' . esc_html($email -> id) . '&user_id=' . ((isset($user) && !empty($user)) ? $user -> ID : 0) . '&authkey=' . $authkey;
                            $url = $Html -> retainquery($querystring, home_url());
                        }

                        if (!empty($print) && $print == true) {
                            $url = $Html -> retainquery('print=1', $url);
                        }
                        $style = "";
                        if (!empty($theme_id)) {
                            global $wpdb, $Theme;

                            $acolorquery = "SELECT `acolor` FROM `" . $wpdb -> prefix . $Theme -> table . "` WHERE `id` = '" . esc_sql($theme_id) . "' LIMIT 1";

                            $query_hash = md5($acolorquery);
                            if ($ob_acolor = $this -> get_cache($query_hash)) {
                                $acolor = $ob_acolor;
                            } else {
                                $acolor = $wpdb -> get_var($acolorquery);
                                $this -> set_cache($query_hash, $acolor);
                            }

                            $style = "color:" . $acolor . ";";
                        }

                        if (!empty($print)) {
                            $url = 'https://www.printfriendly.com/print?url=' . urlencode($url);
                        }

                        if (!empty($onlyurl) && $onlyurl == true) {
                            return $url;
                        } else {
                            if (empty($subscriber -> format) || $subscriber -> format == "html") {
                                $text = (empty($print)) ? __($this -> get_option('onlinelinktext')) : __($this -> get_option('printlinktext'));
                                $onlinelink = '<a class="newsletters_online newsletters_link" href="' . $url . '" style="' . $style . '">' . $text . '</a>';
                            } else {
                                $onlinelink = $url;
                            }
                        }

                        return $onlinelink;
                    }
                }

                return false;
            }

            function gen_tracking_link($eunique = null) {
                $tracking = "";

                if (!empty($eunique)) {
                    if ($this -> get_option('tracking') == "Y") {

                        $track_alt = '';
                        $tracking_image_alt = $this -> get_option('tracking_image_alt');
                        if (!empty($tracking_image_alt)) {
                            $track_alt = esc_html($tracking_image_alt);
                        }

                        $tracking = '<img alt="' . esc_attr($track_alt) . '" class="newsletters-tracking" src="' . html_entity_decode(add_query_arg(array($this -> pre . 'method' => "track", 'id' => $eunique), home_url())) . '" />';
                    }
                }

                return $this->apply_filters_safe('newsletters_tracking_image', array($tracking, $eunique));
            }

            protected function describe_callable_safe( $callable ) {
                if (is_string($callable)) {
                    return $callable;
                }

                if (is_array($callable)) {
                    $parts = array();

                    if (isset($callable[0])) {
                        if (is_object($callable[0])) {
                            $parts[] = get_class($callable[0]);
                        } else {
                            $parts[] = (string) $callable[0];
                        }
                    }

                    if (isset($callable[1])) {
                        $parts[] = (string) $callable[1];
                    }

                    return implode('::', $parts);
                }

                if ($callable instanceof Closure) {
                    return 'Closure';
                }

                if (is_object($callable)) {
                    return get_class($callable);
                }

                return gettype($callable);
            }

            protected function apply_filters_safe($hook, $args = array(), $stage_logger = null) {
                global $wp_filter;

                if (!is_array($args)) {
                    $args = array($args);
                }

                if (empty($args)) {
                    $args = array(null);
                }

                $original_value = isset($args[0]) ? $args[0] : null;

                if (!is_callable($stage_logger)) {
                    $stage_logger = static function() {
                        return;
                    };
                }

                if (isset($wp_filter[$hook])) {
                    $callbacks_source = $wp_filter[$hook];

                    if ($callbacks_source instanceof WP_Hook) {
                        $callback_sets = $callbacks_source->callbacks;
                    } else {
                        $callback_sets = $callbacks_source;
                    }

                    if (!empty($callback_sets) && is_array($callback_sets)) {
                        foreach ($callback_sets as $priority => $callbacks) {
                            foreach ($callbacks as $callback) {
                                $function = (is_array($callback) && isset($callback['function'])) ? $callback['function'] : (is_callable($callback) ? $callback : null);

                                if (!is_callable($function)) {
                                    $stage_logger(
                                        'filter_handler_missing',
                                        array(
                                            'hook'     => $hook,
                                            'priority' => (int) $priority,
                                            'callback' => $this->describe_callable_safe($function),
                                            'action'   => 'removed',
                                        )
                                    );

                                    remove_filter($hook, $function, (int) $priority);
                                }
                            }
                        }
                    }
                }

                try {
                    return apply_filters_ref_array($hook, $args);
                } catch (Throwable $e) {
                    $stage_logger(
                        'filter_apply_exception',
                        array(
                            'hook'    => $hook,
                            'message' => $e->getMessage(),
                            'file'    => $e->getFile(),
                            'line'    => $e->getLine(),
                            'trace'   => wp_debug_backtrace_summary(),
                        )
                    );

                    return $original_value;
                }
            }

            function strip_set_variables($message = null) {
                if (!empty($message)) {
                    $newpatterns = array(
                        "/\[(" . $this -> pre . "|news|newsletters_)email\]/",
                        "/\[(" . $this -> pre . "|news|newsletters_)unsubscribe\]/",
                        "/\[(" . $this -> pre . "|news|newsletters_)blogname\]/",
                        "/\[(" . $this -> pre . "|news|newsletters_)siteurl\]/",
                        "/\[(" . $this -> pre . "|news|newsletters_)activate\]/",
                        "/\[(" . $this -> pre . "|news|newsletters_)manage\]/",
                        "/\[(" . $this -> pre . "|news|newsletters_)online\]/",
                        "/\[(" . $this -> pre . "|news|newsletters_)track\]/",
                        "/\[(" . $this -> pre . "|news|newsletters_)mailinglist\]/",
                        "/\[(" . $this -> pre . "|news|newsletters_)subject\]/",
                        "/\[(" . $this -> pre . "|news|newsletters_)historyid\]/",
                        "/\[(" . $this -> pre . "|news|newsletters_)unsubscribecomments\]/",
                        "/\[(" . $this -> pre . "|news|newsletters_)bouncecount\]/",
                        "/\[(" . $this -> pre . "|news|newsletters_)customfields\]/",
                        "/\[(" . $this -> pre . "|news|newsletters_)date\]/",
                    );

                    $message = preg_replace($newpatterns, "", $message);

                    $pattern = get_shortcode_regex(array("wpmlfield", "newsfield", "newsletters_field"));
                    $message = preg_replace("/" . $pattern . "/si", "", $message);

                    $message = $this->apply_filters_safe('newsletters_strip_set_variables', array($message));
                    return $message;
                }

                return false;
            }

            function gen_role_names($user = null) {
                $role_names = "";

                if (!empty($user -> roles) && is_array($user -> roles)) {
                    global $wp_roles;
                    $role_names = array();

                    foreach ($user -> roles as $role_key) {
                        $role_names[] = $wp_roles -> role_names[$role_key];
                    }

                    $role_names = implode(", ", $role_names);
                }

                return $role_names;
            }

            function gen_mailinglist_names($subscriber = null) {
                global $wpdb, $Mailinglist;
                $mailinglist_names = "";
                $titles = array();

                if (is_null($subscriber)) {
                    return $mailinglist_names;
                }

                if (empty($subscriber -> mailinglists)) {
                    if (!empty($_POST['mailinglists'])) {
                        $subscriber -> mailinglists = map_deep($_POST['mailinglists'], 'sanitize_text_field');
                    } else {
                        if (!is_bool($subscriber)) {
                            $subscriber -> mailinglists = isset($subscriber -> mailinglist_id) ? array($subscriber -> mailinglist_id) : [0];
                        }
                    }
                }

                if (!empty($subscriber -> mailinglists)) {
                    foreach ($subscriber -> mailinglists as $list_id) {
                        if ($title = $Mailinglist -> get_title_by_id($list_id)) {
                            $titles[] = __($title);
                        }
                    }

                    $mailinglist_names = implode(", ", $titles);
                }

                return $mailinglist_names;
            }

            function process_set_variables($subscriber = null, $user = null, $message = null, $history_id = null, $eunique = null, $issubject = false, $execute_mail_stage = null) {
                global $wpdb, $Db, $Mailinglist, $Subscriber, $Html, $Theme;

                if (!is_callable($execute_mail_stage)) {
                    $execute_mail_stage = static function () {
                        // noop stage logger when advanced profiling is unavailable.
                    };
                }

                if (!empty($issubject) && $issubject == true) {
                    $subject = $message;
                }

                if (!empty($message)) {
                    // Process shortcodes from subscriber
                    if (!empty($subscriber) || empty($user)) {
                        global $current_subscriber;
                        $current_subscriber = $subscriber;

                        if (!empty($history_id)) {

                            global $current_history_id, $current_theme_id;
                            $current_history_id = $history_id;

                            $history = $this -> History -> find(array('id' => $history_id));
                            $subject = $this -> History() -> field('subject', array('id' => $history_id));
                            $post_id = $this -> History() -> field('post_id', array('id' => $history_id));
                            if (!empty($post_id) && $getpost = get_post($post_id)) {
                                global $post, $shortcode_post;
                                $post = $getpost;
                                $shortcode_post = $getpost;
                            }

                            $themeidquery = "SELECT `theme_id` FROM `" . $wpdb -> prefix . $this -> History() -> table . "` WHERE `id` = '" . esc_sql($history_id) . "' LIMIT 1";

                            $query_hash = md5($themeidquery);
                            if ($ob_theme_id = $this -> get_cache($query_hash)) {
                                $theme_id = $ob_theme_id;
                            } else {
                                $theme_id = $wpdb -> get_var($themeidquery);
                                $this -> set_cache($query_hash, $theme_id);
                            }

                            $current_theme_id = $theme_id;
                        } else {
                            $themeidquery = "SELECT `id` FROM `" . $wpdb -> prefix . $Theme -> table . "` WHERE `def` = 'Y' LIMIT 1";

                            $query_hash = md5($themeidquery);
                            if ($ob_theme_id = $this -> get_cache($query_hash)) {
                                $theme_id = $ob_theme_id;
                            } else {
                                $theme_id = $wpdb -> get_var($themeidquery);
                                $this -> set_cache($query_hash, $theme_id);
                            }
                        }

                        $newsearch = array(
                            "/\[(" . $this -> pre . "|news|newsletters_)email\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)unsubscribe\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)unsubscribeurl\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)unsubscribeall\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)blogname\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)siteurl\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)manage\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)print\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)online\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)online_url\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)track\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)mailinglist\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)subject\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)historyid\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)unsubscribecomments\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)bouncecount\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)customfields\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)resubscribe\]/",
                        );

                        $newsearch = $this->apply_filters_safe('newsletters_processvariables_search', array($newsearch, $subscriber), $execute_mail_stage);

                        $subject = isset($subject) ? $subject : '';

                        $newreplace = array(
                            isset($subscriber -> email) ? $subscriber -> email : '',
                            $this -> gen_unsubscribe_link($subscriber, false, $theme_id, $history_id, false),
                            $this -> gen_unsubscribe_link($subscriber, false, $theme_id, $history_id, false, true),
                            $this -> gen_unsubscribe_link($subscriber, false, $theme_id, $history_id, true),
                            get_bloginfo('name'),
                            home_url(),
                            $this -> gen_manage_link($subscriber, $theme_id, $history_id),
                            $this -> gen_online_link($subscriber, false, $history_id, false, $theme_id, true),
                            $this -> gen_online_link($subscriber, false, $history_id, false, $theme_id, false),
                            $this -> gen_online_link($subscriber, false, $history_id, true, $theme_id, false),
                            $this -> gen_tracking_link($eunique),
                            $this -> gen_mailinglist_names(((empty($history)) ? $subscriber : $history)),
                            (preg_replace('/\$(\d)/', '\\\$$1', wp_unslash($subject))),
                            $history_id,
                            $this -> gen_unsubscribe_comments(),
                            isset($subscriber -> bouncecount) ? $subscriber -> bouncecount : 0,
                            $this -> output_custom_fields($subscriber),
                            $this -> gen_resubscribe_link($subscriber),
                        );

                        $newreplace = $this->apply_filters_safe('newsletters_processvariables_replace', array($newreplace, $subscriber), $execute_mail_stage);

                        // Default subscriber fields
                        if (!empty($Subscriber -> table_fields)) {
                            foreach ($Subscriber -> table_fields as $field => $attributes) {
                                $newsearch[$field] = '/\[(' . $this -> pre . '|news|newsletters_)field name="' . $field . '"\]/';
                                $newreplace[$field] = isset($subscriber -> {$field}) ? $subscriber -> {$field} : '';
                            }
                        }

                        $subject = preg_replace($newsearch, $newreplace, wp_unslash($subject));
                        $subject = $this->apply_filters_safe('newsletters_process_set_variables_subscriber_subject', array($subject, $subscriber), $execute_mail_stage);
                        $message = preg_replace($newsearch, $newreplace, (wp_unslash($message)));
                        $message = $this->apply_filters_safe('newsletters_process_set_variables_subscriber_message', array($message, $subscriber), $execute_mail_stage);

                        $this -> replace_subscriber = $subscriber;
                        // get regular expression on [wpmlfield...] and [newsletters_field...]
                        $pattern = get_shortcode_regex(array("wpmlfield", "newsfield", "newsletters_field"));

                        $message = preg_replace_callback("/" . $pattern . "/si", array($this, "replace_custom_field"), $message);
                        $message = htmlspecialchars_decode($message, ENT_NOQUOTES);
                        $subject = preg_replace_callback("/" . $pattern . "/si", array($this, "replace_custom_field"), $subject);
                        $subject = htmlspecialchars_decode($subject, ENT_NOQUOTES);

                        $this -> replace_subscriber = false;
                        // Process shortcodes from user
                    } elseif (!empty($user)) {
                        global $current_user;
                        $current_user = $user;

                        if (!empty($history_id)) {
                            $subject = $this -> History() -> field('subject', array('id' => $history_id));
                            $post_id = $this -> History() -> field('post_id', array('id' => $history_id));
                            if (!empty($post_id) && $getpost = get_post($post_id)) {
                                global $post, $shortcode_post;
                                $post = $getpost;
                                $shortcode_post = $getpost;
                            }

                            $themeidquery = "SELECT `theme_id` FROM `" . $wpdb -> prefix . $this -> History() -> table . "` WHERE `id` = '" . esc_sql($history_id) . "' LIMIT 1";

                            $query_hash = md5($themeidquery);
                            if ($ob_theme_id = $this -> get_cache($query_hash)) {
                                $theme_id = $ob_theme_id;
                            } else {
                                $theme_id = $wpdb -> get_var($themeidquery);
                                $this -> set_cache($query_hash, $theme_id);
                            }
                        } else {
                            $themeidquery = "SELECT `id` FROM `" . $wpdb -> prefix . $Theme -> table . "` WHERE `def` = 'Y' LIMIT 1";

                            $query_hash = md5($themeidquery);
                            if ($ob_theme_id = $this -> get_cache($query_hash)) {
                                $theme_id = $ob_theme_id;
                            } else {
                                $theme_id = $wpdb -> get_var($themeidquery);
                                $this -> set_cache($query_hash, $theme_id);
                            }
                        }

                        $newsearch = array(
                            "/\[(" . $this -> pre . "|news|newsletters_)email\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)unsubscribe\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)unsubscribeurl\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)unsubscribeall\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)blogname\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)siteurl\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)activate\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)manage\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)online\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)track\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)mailinglist\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)subject\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)historyid\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)unsubscribecomments\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)bouncecount\]/",
                            "/\[(" . $this -> pre . "|news|newsletters_)customfields\]/",
                        );

                        $newreplace = array(
                            $user -> user_email,
                            $this -> gen_unsubscribe_link(false, $user, $theme_id, $history_id, false),
                            $this -> gen_unsubscribe_link(false, $user, $theme_id, $history_id, false, true),
                            $this -> gen_unsubscribe_link(false, $user, $theme_id, $history_id, true),
                            get_bloginfo('name'),
                            home_url(),
                            "",
                            get_edit_user_link($user -> ID),
                            $this -> gen_online_link(false, $user, $history_id, false, $theme_id),
                            $this -> gen_tracking_link($eunique),
                            $this -> gen_role_names($user),
                            wp_unslash($subject),
                            $history_id,
                            $this -> gen_unsubscribe_comments(),
                            $subscriber -> bouncecount,
                            "",
                        );

                        $subject = preg_replace($newsearch, $newreplace, wp_unslash($subject));
                        $subject = $this->apply_filters_safe('newsletters_process_set_variables_user_subject', array($subject, $user), $execute_mail_stage);
                        $message = preg_replace($newsearch, $newreplace, (wp_unslash($message)));
                        $message = $this->apply_filters_safe('newsletters_process_set_variables_user_message', array($message, $user), $execute_mail_stage);

                        $this -> replace_user = $user;
                        $pattern = get_shortcode_regex(array("wpmlfield", "newsfield", "newsletters_field"));
                        $message = preg_replace_callback("/" . $pattern . "/si", array($this, "replace_custom_field"), $message);
                        $message = htmlspecialchars_decode($message, ENT_NOQUOTES);
                        $subject = preg_replace_callback("/" . $pattern . "/si", array($this, "replace_custom_field"), $subject);
                        $subject = htmlspecialchars_decode($subject, ENT_NOQUOTES);

                        $this -> replace_user = false;
                    }
                }

                $sanitize_shortcodes = function($content, $context) use ($execute_mail_stage) {
                    global $shortcode_tags;

                    if (empty($content) || empty($shortcode_tags) || !is_array($shortcode_tags)) {
                        return $content;
                    }

                    $pattern = get_shortcode_regex();

                    return preg_replace_callback(
                        '/' . $pattern . '/s',
                        function($matches) use ($shortcode_tags, $execute_mail_stage, $context) {
                            $tag = $matches[2];

                            if (isset($shortcode_tags[$tag]) && !is_callable($shortcode_tags[$tag])) {
                                $execute_mail_stage(
                                    'shortcode_handler_missing',
                                    array(
                                        'tag'     => $tag,
                                        'context' => $context,
                                        'handler' => $this->describe_callable_safe($shortcode_tags[$tag]),
                                    )
                                );

                                return '';
                            }

                            return $matches[0];
                        },
                        $content
                    );
                };

                $purge_invalid_shortcodes = function() use ($execute_mail_stage) {
                    global $shortcode_tags;

                    if (empty($shortcode_tags) || !is_array($shortcode_tags)) {
                        return;
                    }

                    foreach ($shortcode_tags as $tag => $handler) {
                        if (!is_callable($handler)) {
                            $execute_mail_stage(
                                'shortcode_handler_removed',
                                array(
                                    'tag'     => $tag,
                                    'handler' => $this->describe_callable_safe($handler),
                                )
                            );
                            remove_shortcode($tag);
                        }
                    }
                };

                if (!empty($issubject) && $issubject == true) {
                    $purge_invalid_shortcodes();
                    $subject = $sanitize_shortcodes($subject, 'subject');
                    try {
                        $subject = do_shortcode($subject);
                        $execute_mail_stage('subject_do_shortcode');
                    } catch (Throwable $e) {
                        $execute_mail_stage(
                            'subject_do_shortcode_exception',
                            array(
                                'message' => $e->getMessage(),
                                'file'    => $e->getFile(),
                                'line'    => $e->getLine(),
                                'trace'   => wp_debug_backtrace_summary(),
                            )
                        );
                        $subject = wp_strip_all_tags($subject);
                    }
                    $return = $subject;
                } else {
                    $purge_invalid_shortcodes();
                    $message = $sanitize_shortcodes($message, 'message');
                    try {
                        $message = do_shortcode($message);
                    } catch (Throwable $e) {
                        $execute_mail_stage(
                            'message_do_shortcode_exception',
                            array(
                                'message' => $e->getMessage(),
                                'file'    => $e->getFile(),
                                'line'    => $e->getLine(),
                                'trace'   => wp_debug_backtrace_summary(),
                            )
                        );
                        $message = wp_strip_all_tags($message);
                    }
                    $return = $message;
                }

                //** Bitly and Click tracking
                $pattern = '/<a[^>]*?href=[\'"](.*?)[\'"][^>]*?>(.*?)<\/a>/si';
                if (preg_match_all($pattern, $return, $regs)) {
                    $return = $this->apply_filters_safe('newsletters_emailbody_links', array($return, $history_id, $regs), $execute_mail_stage);
                    preg_match_all($pattern, $return, $regs);

                    $shortlinks = $this -> get_option('shortlinks');

                    /* Bitly if shortlinks are enabled */
                    if (!empty($shortlinks) && $shortlinks == "Y") {
                        if (!empty($regs[1])) {
                            $results = $regs[1];
                            foreach($results as $k => $v) {
                                $decision = $this->apply_filters_safe('wpml_bitlink_loop', array(true, $v, $regs), $execute_mail_stage);
                                if ($decision) {
                                    $bitlink = $this -> make_bitly_url($v);
                                    if (!empty($bitlink)) {
                                        $pattern = '/[\'"](' . preg_quote($v, '/') . ')[\'"]/si';
                                        $return = preg_replace($pattern, '"' . $bitlink . '"', $return);
                                        $regs[1][$k] = $bitlink;
                                    }
                                }
                            }
                        }
                    }

                    /* Click Tracking */
                    $clicktrack = $this -> get_option('clicktrack');
                    if ($clicktrack == "Y") {
                        if (!empty($regs[1])) {
                            $results = $regs[1];
                            foreach ($results as $rkey => $result) {
                                $decision = $this->apply_filters_safe('wpml_hashlink_loop', array(true, $result, $regs), $execute_mail_stage);
                                if ($decision) {
                                    $user_id = is_object($user) ? $user->ID : 0;
                                    $hashlink = $this -> hashlink($result, $history_id, ((isset($subscriber) && !empty($subscriber)) ? $subscriber -> id : 0), $user_id);
                                    $pattern = '/[\'"](' . preg_quote($result, '/') . ')[\'"]/si';
                                    $return = preg_replace($pattern, '"' . $hashlink . '"', $return);
                                }
                            }
                        }
                    }
                }

                // Replace video URLs
                $videoembed = $this -> get_option('videoembed');
                if (!empty($videoembed)) {
                    require_once(ABSPATH . WPINC . DS . 'class-wp-oembed.php');
                    $embed = new WP_oEmbed();

                    $patterns = array();
                    if (!empty($embed -> providers)) {
                        foreach ($embed -> providers as $regex => $data) {
                            if (empty($data[1])) {
                                $regex = '#' . str_replace( '___wildcard___', '(.+)', preg_quote(str_replace('*', '___wildcard___', $regex), '#')) . '#i';
                                $regex = preg_replace('|^#http\\\://|', '#https?\://', $regex);
                            }

                            $patterns[] = $regex;
                        }
                    }

                    $return = preg_replace_callback($patterns, array($this, 'autoembed_callback'), $return);
                }

                return $return;
            }

            function autoembed_callback($match = null, $width = false, $height = false) {
                if (!empty($match) && is_array($match)) {
                    $url = trim(strip_tags($match[0]));
                } else {
                    $url = $match;
                }

                if (!empty($url)) {

                    // See if this video was cached
                    if ($oc_output = $this -> get_cache(md5($url), 'video')) {
                        return $oc_output;
                    }

                    require_once(ABSPATH . WPINC . DS . 'class-wp-oembed.php');
                    $embed = new WP_oEmbed();
                    if ($provider = $embed -> get_provider($url)) {
                        if ($response = $embed -> fetch($provider, $url)) {
                            if ($response !== false) {
                                $play_icon = $this -> render_url('img/play.png', 'default');

                                $imagesize = getimagesize($response -> thumbnail_url);
                                $width = (empty($width)) ? $imagesize[0] : $width;
                                $height = (empty($height)) ? $imagesize[1] : $height;

                                $output .= '<table border="0" style="width:' . $width . 'px;" width="' . $width . '" cellspacing="0" cellpadding="0">
                                        <tbody>
                                            <tr>
                                                <td background="' . $response -> thumbnail_url . '" style="padding:0 !important; border:0; background-image: url(\'' . $response -> thumbnail_url . '\'); background-repeat:no-repeat; text-align:center; vertical-align:middle;" align="center" valign="middle" bgcolor="#FFFFFF" width="100%" height="' . $height . '">
                                                    <!--[if gte mso 9]>
                                                        <v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="width:' . $width . 'px; height:' . $height . 'px;" strokecolor="none">
                                                        <v:fill type="tile" color="#ffffff" src="' . $response -> thumbnail_url . '" /></v:fill>
                                                    <![endif]-->
                                                        <table width="' . $width . '" border="0" cellspacing="0" cellpadding="0">
                                                            <tbody>
                                                                <tr>
                                                                    <td style="padding:0 !important; border:0; text-align:center; vertical-align:middle;" width="100%" height="' . $height . '"" valign="middle" align="center">
                                                                        <a href="' . $url . '"><img src="' . $play_icon . '" /></a>
                                                                    </td>
                                                                </tr>
                                                            </tbody>
                                                        </table>
                                                    <!--[if gte mso 9]>
                                                        </v:rect>
                                                    <![endif]-->
                                                </td>
                                            </tr>
                                        </tbody>
                                    </table>';

                                // Cache the video output so it doesn't have to be fetched each time
                                $this -> set_cache(md5($url), $output, 'video');

                                return $output;
                            } else {
                                $error = sprintf(__('Could not auto embed URL %s because of error code %s and error message %s', 'wp-mailinglist'), $url, $response -> errorCode, $response -> errorMessage);
                                $this -> log_error($error);
                            }
                        } else {
                            $error = sprintf(__('%s No response received from the video provider, please check that the video has embedding enabled.', 'wp-mailinglist'), $url);
                            $this -> log_error($error);
                        }
                    } else {
                        $error = sprintf(__('%s No provider found for this video, the video provider may not be supported.', 'wp-mailinglist'), $url);
                        $this -> log_error($error);
                    }
                }

                return $match[0];
            }

            function replace_custom_field($matches = null) {
                global $Db, $Field, $Html;
        
                //  $user  = $subscriber = array();
                //  print_r(get_class($this));
                // print_r($this);
                // if(property_exists(get_class($this), 'replace_subscriber')) {
                $subscriber = $this->replace_subscriber;
                // }
                //  $user  = $subscriber = array();
                //	if(property_exists(get_class($this), 'replace_user')) {
                $user = $this->replace_user;
                //    }
        
                if (!empty($matches)) {
                    $atts = shortcode_parse_atts($matches['3']);
        
                    if (!empty($atts['name'])) {
        
                        $namesplit = explode("|", $atts['name']);
        
        
                        $prefix = "";
        
                        if(!empty($atts['prefix'])) {
                            $prefix = esc_html($atts['prefix']);
                        }
        
                        $atts['name'] = (is_array($namesplit) && count($namesplit) >= 1) ? $namesplit[0] : $namesplit;
                        $defaultvalue = (is_array($namesplit) && count($namesplit) > 1) ? $namesplit[1] : (is_array($namesplit) ? $namesplit[0] : $namesplit);
        
                        $Db -> model = $Field -> model;
                        if ($field = $Db -> find(array('slug' => (is_array($atts['name']) ? implode(',',  $atts['name']) : $atts['name']) ))) {
                            $fieldoptions = $field -> newfieldoptions;
        
                            if (!empty($subscriber)) {
                                switch ($field -> type) {
                                    case 'pre_country'		:
                                        $shortcode_replace = $this -> Country() -> field('value', array('id' => $subscriber -> {$field -> slug}));
                                        break;
                                    case 'pre_date'			:
                                        $date = @unserialize($subscriber -> {$field -> slug});
                                        if (!empty($date) && is_array($date)) {
                                            $shortcode_replace = $date['y'] . '-' . $date['m'] . '-' . $date['d'];
                                        } else {
                                            $shortcode_replace = date_i18n(get_option('date_format'), strtotime($subscriber -> {$field -> slug}));
                                        }
                                        break;
                                    case 'pre_gender'		:
                                        $shortcode_replace = $Html -> gender($subscriber -> {$field -> slug});
                                        break;
                                    case 'checkbox'			:
                                        $supoptions = maybe_unserialize($subscriber -> {$field -> slug});
                                        if (!empty($supoptions) && is_array($supoptions)) {
                                            $replace = "";
                                            foreach ($supoptions as $supopt) {
                                                $replace .= '&raquo; ' . __($fieldoptions[$supopt]) . "\r\n";
                                            }
                                            $shortcode_replace = $replace;
                                        } else {
                                            $shortcode_replace = __('none', 'wp-mailinglist');
                                        }
                                        break;
                                    case 'radio'			:
                                    case 'select'			:
                                        $value = $subscriber -> {$field -> slug};
                                        $shortcode_replace = __($fieldoptions[$value]);
                                        break;
                                    case 'special'			:
                                        switch ($field -> slug) {
                                            case 'list'			:
                                                $shortcode_replace = $this -> gen_mailinglist_names($subscriber);
                                                break;
                                        }
                                        break;
                                    default					:
                                        $value = $subscriber -> {$field -> slug};
                                        if (!empty($value)) {
                                            if (($varray = @unserialize($value)) !== false) {
                                                $subscriber -> {$field -> slug} = '';
                                                $newline = (empty($subscriber -> format) || $subscriber -> format == "html") ? "<br/>" : "\r\n";
        
                                                foreach ($varray as $vkey => $vval) {
                                                    $subscriber -> {$field -> slug} .= '&raquo; ' . __($vval) . $newline;
                                                }
                                            } else {
                                                if (!empty($field -> type) && $field -> type == "textarea") {
                                                    $subscriber -> {$field -> slug} = wpautop($subscriber -> {$field -> slug});
                                                }
                                            }
                                        }
        
                                        $shortcode_replace = $subscriber -> {$field -> slug};
                                        break;
                                }
        
                                if ($shortcode_replace == $field -> slug)
                                {
                                    $shortcode_replace = "";
                                }
        
                                if (empty($shortcode_replace) && !empty($defaultvalue)) {
                                    return trim($prefix . $defaultvalue);
                                }
        
                                if ($prefix . $shortcode_replace === $prefix) {
                                    return trim($prefix . $shortcode_replace);
                                }
                                return  $prefix . $shortcode_replace;
                            } elseif (!empty($user)) {
                                switch ($field -> type) {
                                    case 'email'				:
                                        $shortcode_replace = $user -> user_email;
                                        break;
                                    case 'special'				:
                                        switch ($field -> slug) {
                                            case 'list'			:
                                                global $wp_roles;
                                                $role = $user -> roles[0];
                                                $shortcode_replace = $wp_roles -> role_names[$role];
                                                break;
                                        }
                                        break;
                                    default 					:
                                        $importusersfields = $this -> get_option('importusersfields');
                                        $importusersfieldspre = $this -> get_option('importusersfieldspre');
        
                                        if (!empty($importusersfieldspre[$field -> id])) {
                                            if (!empty($user -> {$importusersfieldspre[$field -> id]})) {
                                                $shortcode_replace = $user -> {$importusersfieldspre[$field -> id]};
                                            }
                                        } elseif (!empty($importusersfields[$field -> id])) {
                                            if (!empty($user -> {$importusersfields[$field -> id]})) {
                                                $shortcode_replace = $user -> {$importusersfields[$field -> id]};
                                            }
                                        }
                                        break;
                                }
        
                                if (empty($shortcode_replace) && !empty($defaultvalue)) {
                                    return trim($prefix . $defaultvalue);
                                }
        
                                if ($prefix . $shortcode_replace === $prefix) {
                                    return trim($prefix . $shortcode_replace);
                                }
        
                                return $prefix . $shortcode_replace;
                            }
                        } else {
                            if (isset($subscriber) && !empty($subscriber -> {$atts['name']})) {
                                return $prefix . wp_unslash($subscriber -> {$atts['name']});
                            } elseif (isset($defaultvalue) &&  !empty($defaultvalue)) {
                                return trim($prefix . $defaultvalue) ;
                            }
                        }
                    }
                }
        
                return false;
            }

            function gen_unsubscribe_comments() {
                /* Unsubscribe Comments */
                $unsubscribecomments = __('No feedback was provided by the subscriber.', 'wp-mailinglist');
                if (!empty($_POST[$this -> pre . 'comments'])) {
                    $unsubscribecomments = "";
                    $unsubscribecomments .= __('Comments:', 'wp-mailinglist') . "\r\n";
                    $unsubscribecomments .= "------------------------------------" . "\r\n";
                    $unsubscribecomments .= esc_html(wp_unslash($_POST[$this -> pre . 'comments'])) . "\r\n";
                    $unsubscribecomments .= "------------------------------------" . "\r\n";
                }

                return wpautop($unsubscribecomments);
            }

            function subscription_confirm($subscriber = array()) {
                global $wpdb, $Db, $Html, $Subscriber, $Mailinglist, $SubscribersList;

                if (!empty($subscriber)) {
                    if (!empty($_POST['list_id'])) {
                        $subscriber -> mailinglists = map_deep($_POST['list_id'], 'sanitize_text_field');
                    } elseif (!empty($subscriber -> mailinglists)) {
                        //do nothing, it's ready
                    } else {
                        $subscriber -> mailinglists = $Subscriber -> mailinglists($subscriber -> id, false, false, "N");
                    }

                    if ($this -> get_option('requireactivate') == "Y" || $mailinglist -> paid == "Y") {
                        if ($this -> get_option('activationemails') == "multiple") {
                            foreach ($subscriber -> mailinglists as $list_id) {
                                $isactive = $SubscribersList -> field('active', array('subscriber_id' => $subscriber -> id, 'list_id' => $list_id));
                                $subscriber -> mailinglist_id = $list_id;
                                $subscriber -> mailinglists = array($list_id);
                                $mailinglist = $Mailinglist -> get($list_id, false);

                                if ($isactive == "N") {
                                    if (empty($mailinglist -> doubleopt) || $mailinglist -> doubleopt == "Y") {
                                        if ($this -> get_option('requireactivate') == "Y" || $mailinglist -> paid == "Y") {

                                            $subject = wp_unslash($this -> et_subject('confirm'));
                                            $fullbody = $this -> et_message('confirm', $subscriber);

                                            $form_id = esc_html($_POST['form_id']);
                                            if (!empty($form_id)) {
                                                if ($etsubject = $this -> et_subject('confirm_form_' . $form_id, $subscriber)) {
                                                    $subject = $etsubject;
                                                }

                                                if ($etmessage = $this -> et_message('confirm_form_' . $form_id, $subscriber)) {
                                                    $fullbody = $etmessage;
                                                }
                                            }

                                            $message = $this -> render_email(false, array('subscriber' => $subscriber, 'mailinglist' => $mailinglist), false, $this -> htmltf($subscriber -> format), true, $this -> et_template('confirm'), false, $fullbody);
                                            $eunique = $Html -> eunique($subscriber, false, "confirmation");
                                            $this -> execute_mail($subscriber, false, $subject, $message, false, false, $eunique, false, "confirmation");
                                        }
                                    } else {
                                        $Db -> model = $SubscribersList -> model;
                                        $Db -> save_field('active', "Y", array('subscriber_id' => $subscriber -> id, 'list_id' => $list_id));
                                    }
                                }
                            }
                        } else {
                            foreach ($subscriber -> mailinglists as $lkey => $list_id) {
                                $mailinglist = $Mailinglist -> get($list_id, false);
                                if (!empty($mailinglist -> doubleopt) && $mailinglist -> doubleopt == "N") {
                                    unset($subscriber -> mailinglists[$lkey]);
                                    $Db -> model = $SubscribersList -> model;
                                    $Db -> save_field('active', "Y", array('subscriber_id' => $subscriber -> id, 'list_id' => $list_id));
                                }
                            }

                            if (!empty($subscriber -> mailinglists)) {
                                $subject = wp_unslash($this -> et_subject('confirm'));
                                $fullbody = $this -> et_message('confirm', $subscriber);

                                $form_id = sanitize_text_field($_POST['form_id']);
                                if (!empty($form_id)) {
                                    if ($etsubject = $this -> et_subject('confirm_form_' . $form_id, $subscriber)) {
                                        $subject = $etsubject;
                                    }

                                    if ($etmessage = $this -> et_message('confirm_form_' . $form_id, $subscriber)) {
                                        $fullbody = $etmessage;
                                    }
                                }

                                $message = $this -> render_email(false, array('subscriber' => $subscriber), false, $this -> htmltf($subscriber -> format), true, $this -> et_template('confirm'), false, $fullbody);
                                $eunique = $Html -> eunique($subscriber, false, "confirmation");
                                $this -> execute_mail($subscriber, false, $subject, $message, false, false, $eunique, false, "confirmation");
                            }
                        }

                        return true;
                    }
                }

                return false;
            }

            function admin_notification_import_complete() {
                global $Html, $Subscriber;

                $import_notification = $this -> get_option('import_notification');
                if (!empty($import_notification)) {
                    $adminemail = $this -> get_option('adminemail');
                    $subject = wp_unslash($this -> et_subject('import_complete'));
                    $fullbody = $this -> et_message('import_complete');
                    $message = $this -> render_email(false, false, false, true, true, $this -> et_template('import_complete'), false, $fullbody);

                    if (strpos($adminemail, ",") !== false) {
                        $adminemails = explode(",", $adminemail);
                        foreach ($adminemails as $adminemail) {
                            if (empty($emailsused) || !in_array($adminemail, $emailsused)) {
                                $subscriber = $Subscriber -> get_by_email($adminemail);
                                $eunique = $Html -> eunique($subscriber, false, "importcomplete");
                                $this -> execute_mail($subscriber, false, $subject, $message, false, false, $eunique, false, "importcomplete");
                                $emailsused[] = $adminemail;
                            }
                        }
                    } else {
                        $subscriber = $Subscriber -> get_by_email($adminemail);
                        $eunique = $Html -> eunique($subscriber, false, "importcomplete");
                        $this -> execute_mail($subscriber, false, $subject, $message, false, false, $eunique, false, "importcomplete");
                    }
                }
            }

            function admin_notification_queue_complete() {
                global $Html, $Subscriber;

                //<!-- Changing from 3 notifications for the 3 queues to 1 notification at the end of queue. Needs work. -->
                $newsletters_queue_count = get_transient('newsletters_queue_count');
                // if(!empty($newsletters_queue_count) )
                // {
                $notifyqueuecomplete = $this -> get_option('notifyqueuecomplete');
                if (!empty($notifyqueuecomplete)) {
                    $adminemail = $this -> get_option('adminemail');
                    $subject = wp_unslash($this -> et_subject('queue_complete'));
                    $fullbody = $this -> et_message('queue_complete');
                    $message = $this -> render_email(false, false, false, true, true, $this -> et_template('queue_complete'), false, $fullbody);

                    if (strpos($adminemail, ",") !== false) {
                        $adminemails = explode(",", $adminemail);
                        foreach ($adminemails as $adminemail) {
                            if (empty($emailsused) || !in_array($adminemail, $emailsused)) {
                                $subscriber = $Subscriber -> get_by_email($adminemail);
                                $eunique = $Html -> eunique($subscriber, false, "queuecomplete");
                                $this -> execute_mail($subscriber, false, $subject, $message, false, false, $eunique, false, "queuecomplete");
                                $emailsused[] = $adminemail;
                            }
                        }
                    } else {
                        $subscriber = $Subscriber -> get_by_email($adminemail);
                        $eunique = $Html -> eunique($subscriber, false, "queuecomplete");
                        $this -> execute_mail($subscriber, false, $subject, $message, false, false, $eunique, false, "queuecomplete");
                    }
                }
                //}
            }

            function admin_subscription_notification($subscriber = array()) {
                global $wpdb, $Mailinglist, $Html;

                if (!empty($subscriber)) {
                    if ($this -> get_option('adminemailonsubscription') == "Y") {

                        $emailsused = array();

                        $adminemail = $this -> get_option('adminemail');	// main administrator email
                        $to = (object) array('email' => $adminemail);
                        $subject = wp_unslash($this -> et_subject('subscribe', $subscriber));
                        $fullbody = $this -> et_message('subscribe', $subscriber);
                        $message = $this -> render_email(false, array('subscriber' => $subscriber, 'mailinglist' => $mailinglist), false, $this -> htmltf($subscriber -> format), true, $this -> et_template('subscribe'), false, $fullbody);

                        if (strpos($adminemail, ",") !== false) {
                            $adminemails = explode(",", $adminemail);
                            foreach ($adminemails as $adminemail) {
                                if (empty($emailsused) || !in_array($adminemail, $emailsused)) {
                                    $to -> email = $adminemail;
                                    $eunique = $Html -> eunique($to, false, "subscription");
                                    $this -> execute_mail($to, false, $subject, $message, false, false, $eunique, false, "subscription");
                                    $emailsused[] = $adminemail;
                                }
                            }
                        } else {
                            $to -> email = $adminemail;
                            $this -> execute_mail($to, false, $subject, $message, false, false, false, false, "subscription");
                        }

                        if (!empty($subscriber -> mailinglists)) {
                            foreach ($subscriber -> mailinglists as $mailinglist_id) {
                                $adminemailquery = "SELECT `adminemail` FROM `" . $wpdb -> prefix . $Mailinglist -> table . "` WHERE `id` = '" . $mailinglist_id . "'";
                                if ($email = $wpdb -> get_var($adminemailquery)) {
                                    if (!empty($email) && $email != $adminemail) {
                                        if (empty($emailsused) || !in_array($email, $emailsused)) {
                                            $to = (object) array('email' => $email);
                                            $subject = wp_unslash($this -> et_subject('subscribe', $subscriber));
                                            $fullbody = $this -> et_message('subscribe', $subscriber);
                                            $message = $this -> render_email(false, array('subscriber' => $subscriber, 'mailinglist' => $mailinglist), false, $this -> htmltf($subscriber -> format), true, $this -> et_template('subscribe'), false, $fullbody);
                                            $eunique = $Html -> eunique($to, false, "subscription");
                                            $this -> execute_mail($to, false, $subject, $message, false, false, $eunique, false, "subscription");
                                            $emailsused[] = $email;
                                        }
                                    }
                                }
                            }
                        }

                        return true;
                    }
                }

                return false;
            }

            function user_unsubscription_notification($subscriber = null, $mailinglists = null) {
                global $wpdb, $Mailinglist, $Subscriber, $Html;
                $unsubscribe_usernotification = $this -> get_option('unsubscribe_usernotification');

                if (!empty($subscriber) && !empty($mailinglists)) {
                    if (!empty($unsubscribe_usernotification)) {
                        $subject = wp_unslash($this -> et_subject('unsubscribeuser', $subscriber));
                        $fullbody = $this -> et_message('unsubscribeuser', $subscriber);
                        $message = $this -> render_email(false, array('subscriber' => $subscriber, 'mailinglists' => $mailinglists), false, $this -> htmltf($subscriber -> format), true, $this -> et_template('unsubscribeuser'), false, $fullbody);
                        $eunique = $Html -> eunique($subscriber, false, "unsubscription");

                        if ($this -> execute_mail($subscriber, false, $subject, $message, false, false, $eunique, false, "unsubscription")) {
                            return true;
                        }
                    }
                }

                return false;
            }

            function admin_unsubscription_notification($subscriber = array(), $mailinglist = array()) {
                global $wpdb, $Mailinglist, $Subscriber, $Html;

                if (!empty($subscriber) && !empty($mailinglist)) {
                    if ($this -> get_option('adminemailonunsubscription') == "Y") {
                        $emailsused = array();
                        $adminemail = $this -> get_option('adminemail');	// main administrator email

                        if (!empty($subscriber -> mailinglists)) {
                            foreach ($subscriber -> mailinglists as $mailinglist_id) {
                                $adminemailquery = "SELECT `adminemail` FROM `" . $wpdb -> prefix . $Mailinglist -> table . "` WHERE `id` = '" . $mailinglist_id . "'";
                                if ($email = $wpdb -> get_var($adminemailquery)) {
                                    if (!empty($email) && $email != $adminemail) {
                                        if (empty($emailsused) || !in_array($email, $emailsused)) {
                                            $to = (object) array('email' => $email);
                                            $subject = wp_unslash($this -> et_subject('unsubscribe', $subscriber));
                                            $fullbody = $this -> et_message('unsubscribe', $subscriber);
                                            $message = $this -> render_email(false, array('subscriber' => $subscriber, 'mailinglist' => $mailinglist), false, $this -> htmltf($subscriber -> format), true, $this -> et_template('subscribe'), false, $fullbody);
                                            $eunique = $Html -> eunique($to, false, "unsubscription");
                                            $this -> execute_mail($to, false, $subject, $message, false, false, $eunique, false, "unsubscription");
                                            $emailsused[] = $email;
                                        }
                                    }
                                }
                            }
                        }

                        if (is_array($mailinglist)) {
                            $subscriber -> mailinglists = $mailinglist;
                        } else {
                            $subscriber -> mailinglists = array($mailinglist);
                        }

                        $to = new stdClass();
                        $to -> id = $Subscriber -> admin_subscriber_id();
                        $to -> email = $adminemail;
                        $subject = wp_unslash($this -> et_subject('unsubscribe', $subscriber));
                        $fullbody = $this -> et_message('unsubscribe', $subscriber);
                        $message = $this -> render_email(false, array('subscriber' => $subscriber, 'mailinglist' => $mailinglist), false, $this -> htmltf($subscriber -> format), true, $this -> et_template('unsubscribe'), false, $fullbody);

                        if (strpos($adminemail, ",") !== false) {
                            $adminemails = explode(",", $adminemail);
                            foreach ($adminemails as $adminemail) {
                                if (empty($emailsused) || !in_array($adminemail, $emailsused)) {
                                    $to -> email = $adminemail;
                                    $this -> execute_mail($to, false, $subject, $message, false, false, false, false, "unsubscription");
                                    $emailsused[] = $adminemail;
                                }
                            }

                            return true;
                        } else {
                            $to -> email = $adminemail;
                            $this -> execute_mail($to, false, $subject, $message, false, false, false, false, "unsubscription");

                            return true;
                        }
                    }
                }

                return false;
            }

            function admin_bounce_notification($subscriber = null) {
                if ($this->get_option('adminemailonbounce') == "Y") {
                    // Ensure $subscriber is a valid object with required properties
                    if (is_object($subscriber) && !empty($subscriber->email)) {
                        $emailsused = array();
                        $adminemail = $this->get_option('adminemail');
                        $subject = wp_unslash($this->et_subject('bounce', $subscriber));
                        $fullbody = $this->et_message('bounce', $subscriber);
                        $message = $this->render_email(
                            false,
                            array('subscriber' => $subscriber, 'mailinglist' => null),
                            false,
                            $this->htmltf(isset($subscriber->format) ? $subscriber->format : 'html'),
                            true,
                            $this->et_template('bounce'),
                            false,
                            $fullbody
                        );
            
                        // Initialize $to as a stdClass object
                        $to = new stdClass();
            
                        if (strpos($adminemail, ",") !== false) {
                            $adminemails = explode(",", $adminemail);
                            foreach ($adminemails as $adminemail) {
                                $adminemail = trim($adminemail);
                                if (!empty($adminemail) && (empty($emailsused) || !in_array($adminemail, $emailsused))) {
                                    $to->email = $adminemail;
                                    $this->execute_mail($to, false, $subject, $message, false, false, false, false, "bounce");
                                    $emailsused[] = $adminemail;
                                }
                            }
                        } else {
                            $to->email = $adminemail;
                            $this->execute_mail($to, false, $subject, $message, false, false, false, false, "bounce");
                        }
            
                        return true;
                    } else {
                        error_log('admin_bounce_notification: Invalid subscriber object');
                        return false;
                    }
                }
            
                return false;
            }

            function strip_title($title = null) {
                global $Html;
                return $Html -> sanitize($title, "_");

                return false;
            }

            function replace_history($match = array()) {
                if (!empty($match)) {
                    global $Db, $Html;

                    if ($emails = $this -> History() -> find_all(array('sent' => "> 0"), false, array('modified', "DESC"))) {
                        $content = '';

                        foreach ($emails as $email) {
                            ob_start();

                            ?>

                            <h3><a href="<?php echo $Html -> retainquery('newsletters_method=newsletter&id=' . esc_html($email -> id), home_url()); ?>" title="<?php echo $email -> subject; ?>"><?php echo $email -> subject; ?></a></h3>
                            <div><small><?php _e('Sent on', 'wp-mailinglist'); ?> : <?php echo $email -> modified; ?></small></div>
                            <?php echo $this -> strip_set_variables($email -> message); ?>

                            <?php

                            $content .= ob_get_clean();
                        }

                        $content = wpautop($content);
                        return $content;
                    }
                }

                return false;
            }

            function replace_meta($matches = array()) {
                if (!empty($matches[0])) {
                    if (preg_match("/" . $this -> pre . "meta\_([0-9]*)/i", $matches[0], $matches2)) {
                        if (!empty($matches2[1])) {
                            global $post_ID;
                            $oldpostid = $post_ID;
                            $post_ID = $matches2[1];

                            ob_start();
                            the_meta();
                            $meta = ob_get_clean();

                            $post_ID = $oldpostid;
                            return $meta;
                        }
                    }
                }

                return false;
            }

            function remove_server_limits() {
                @set_time_limit(0);
                @ini_set('memory_limit', -1);
                @ini_set('upload_max_filesize', '128M');
                @ini_set('post_max_size', '1024M');
                @ini_set('max_execution_time', 3000);
                @ini_set('max_input_time', 3000);
                return true;
            }

            function set_time_limit($time = 0) {
                if (ini_get('max_execution_time')) {
                    ini_set('max_execution_time', 0);
                }

                //check if "set_time_limit" is available
                if (ini_get('set_time_limit')) {
                    //set the "max_execution_time" to unlimited
                    set_time_limit(0);
                }
            }

            function phpmailer_messageid() {
                $messageid = "<";
                $messageid .= md5(uniqid(current_time('timestamp')));
                $messageid .= "@";
                $messageid .= $_SERVER['SERVER_NAME'];
                $messageid .= ">";
                return $messageid;
            }

            function inlinestyles($html = null) {
                global $newsletters_plaintext;

                if (!empty($newsletters_plaintext) || !class_exists('DOMDocument')) {
                    return $html;
                }

                $inlinestyles = $this -> get_option('inlinestyles');

                if (!empty($inlinestyles)) {

                    require_once($this -> plugin_base() . DS . 'vendor' . DS . 'autoload.php');

                    $html = Pelago\Emogrifier\CssInliner::fromHtml($html)->inlineCss()->render();

                    return apply_filters('newsletters_inlinestyles_html', $html);
                }

                return apply_filters('newsletters_inlinestyles_html', $html);
            }


            //Added by Mohsen to prevent duplicated emails
            function has_been_sent_already($subscriber = null, $user = null, $history_id = null, $eunique = null )
            {
                global $wpdb, $Db, $Html, $Email, $phpmailer, $Mailinglist, $Subscriber,
                       $SubscribersList, $orig_message, $wpml_message, $wpml_textmessage, $fromwpml, $newsletters_plaintext;

                $email_table = $wpdb -> prefix . $Email -> table;

                if (empty($history_id)){
                    return false;
                }
                $subscriber_or_user_id = "subscriber_id";
                $identifier_of_either_user_or_subscriber = $subscriber;
                if (empty($subscriber) && !empty($user))
                {
                    $subscriber_or_user_id = "user_id";
                    $identifier_of_either_user_or_subscriber = $user->ID;
                }
                else
                {
                    $identifier_of_either_user_or_subscriber = $subscriber -> id;
                }
                $query =  "SELECT count(id) FROM `" . $email_table . "` WHERE ". $subscriber_or_user_id . " = " . $identifier_of_either_user_or_subscriber . " and history_id = " . esc_sql($history_id) . "   and eunique = '" . esc_sql($eunique) . "' ;";
                $count = $wpdb -> get_var($query);

                if($count > 0)
                {
                    return true;
                }
                else {
                    return false;
                }
            }

            function is_using_grapeJS ($history_id = null) {
                global $wpdb;

                $history_table = $wpdb -> prefix . $this -> History() -> table;

                if (empty($history_id)){
                    return false;
                }

                $query =  "SELECT using_grapeJS FROM `" . $history_table . "` WHERE id = " . $history_id . ";";
                $result = $wpdb -> get_var($query);
                return $result;

            }

            function get_grapeJS_content ($history_id = null) {
                global $wpdb;

                $history_table = $wpdb -> prefix . $this -> History() -> table;

                if (empty($history_id)){
                    return false;
                }

                $query =  "SELECT grapejs_content FROM `" . $history_table . "` WHERE id = " . $history_id . ";";
                $result = $wpdb -> get_var($query);
                return $result;

            }

            function sanitize_content( $content ) {
                $allowed_tags = array(
                    // Document metadata
                    'html'      => array(),
                    'head'      => array(),
                    'title'     => array(),
                    'base'      => array( 'href' => true, 'target' => true ),
                    'link'      => array( 'href' => true, 'rel' => true, 'type' => true ),
                    'meta'      => array( 'name' => true, 'content' => true, 'charset' => true ),
                    'style'     => array( 'type' => true, 'media' => true ),

                    // Body and structural layout
                    'body'      => array(
                        'class'       => true,
                        'id'          => true,
                        'style'       => true,
                        'leftmargin'  => true,
                        'marginwidth' => true,
                        'topmargin'   => true,
                        'marginheight'=> true,
                        'offset'      => true,
                    ),
                    'center'    => array(),
                    'section'   => array( 'class' => true, 'id' => true, 'style' => true ),
                    'nav'       => array( 'class' => true, 'id' => true, 'style' => true ),
                    'article'   => array( 'class' => true, 'id' => true, 'style' => true ),
                    'aside'     => array( 'class' => true, 'id' => true, 'style' => true ),
                    'header'    => array( 'class' => true, 'id' => true, 'style' => true ),
                    'footer'    => array( 'class' => true, 'id' => true, 'style' => true ),
                    'address'   => array( 'class' => true, 'id' => true, 'style' => true ),
                    'main'      => array( 'class' => true, 'id' => true, 'style' => true ),

                    // Text content and inline elements
                    'p'         => array( 'class' => true, 'id' => true, 'style' => true, 'align' => true ),
                    'hr'        => array( 'class' => true, 'id' => true, 'style' => true ),
                    'pre'       => array( 'class' => true, 'id' => true, 'style' => true ),
                    'blockquote'=> array( 'cite' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'ol'        => array( 'class' => true, 'id' => true, 'style' => true, 'start' => true, 'type' => true ),
                    'ul'        => array( 'class' => true, 'id' => true, 'style' => true ),
                    'li'        => array( 'class' => true, 'id' => true, 'style' => true, 'value' => true ),
                    'dl'        => array( 'class' => true, 'id' => true, 'style' => true ),
                    'dt'        => array( 'class' => true, 'id' => true, 'style' => true ),
                    'dd'        => array( 'class' => true, 'id' => true, 'style' => true ),
                    'figure'    => array( 'class' => true, 'id' => true, 'style' => true ),
                    'figcaption'=> array( 'class' => true, 'id' => true, 'style' => true ),
                    'div'       => array( 'class' => true, 'id' => true, 'style' => true ),
                    'a'         => array( 'href' => true, 'title' => true, 'target' => true, 'rel' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'em'        => array( 'class' => true, 'id' => true, 'style' => true ),
                    'strong'    => array( 'class' => true, 'id' => true, 'style' => true ),
                    'small'     => array( 'class' => true, 'id' => true, 'style' => true ),
                    's'         => array( 'class' => true, 'id' => true, 'style' => true ),
                    'cite'      => array( 'class' => true, 'id' => true, 'style' => true ),
                    'q'         => array( 'cite' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'dfn'       => array( 'class' => true, 'id' => true, 'style' => true ),
                    'abbr'      => array( 'title' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'data'      => array( 'value' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'time'      => array( 'datetime' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'code'      => array( 'class' => true, 'id' => true, 'style' => true ),
                    'var'       => array( 'class' => true, 'id' => true, 'style' => true ),
                    'samp'      => array( 'class' => true, 'id' => true, 'style' => true ),
                    'kbd'       => array( 'class' => true, 'id' => true, 'style' => true ),
                    'sub'       => array( 'class' => true, 'id' => true, 'style' => true ),
                    'sup'       => array( 'class' => true, 'id' => true, 'style' => true ),
                    'i'         => array( 'class' => true, 'id' => true, 'style' => true ),
                    'b'         => array( 'class' => true, 'id' => true, 'style' => true ),
                    'u'         => array( 'class' => true, 'id' => true, 'style' => true ),
                    'mark'      => array( 'class' => true, 'id' => true, 'style' => true ),
                    'ruby'      => array( 'class' => true, 'id' => true, 'style' => true ),
                    'rt'        => array( 'class' => true, 'id' => true, 'style' => true ),
                    'rp'        => array( 'class' => true, 'id' => true, 'style' => true ),
                    'bdi'       => array( 'class' => true, 'id' => true, 'style' => true ),
                    'bdo'       => array( 'dir' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'span'      => array( 'class' => true, 'id' => true, 'style' => true ),
                    'br'        => array( 'class' => true, 'id' => true, 'style' => true ),
                    'wbr'       => array( 'class' => true, 'id' => true, 'style' => true ),

                    // Heading tags (h1 to h6)
                    'h1'        => array( 'class' => true, 'id' => true, 'style' => true, 'align' => true ),
                    'h2'        => array( 'class' => true, 'id' => true, 'style' => true, 'align' => true ),
                    'h3'        => array( 'class' => true, 'id' => true, 'style' => true, 'align' => true ),
                    'h4'        => array( 'class' => true, 'id' => true, 'style' => true, 'align' => true ),
                    'h5'        => array( 'class' => true, 'id' => true, 'style' => true, 'align' => true ),
                    'h6'        => array( 'class' => true, 'id' => true, 'style' => true, 'align' => true ),

                    // Multimedia elements
                    'img'       => array( 'src' => true, 'alt' => true, 'width' => true, 'height' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'iframe'    => array( 'src' => true, 'width' => true, 'height' => true, 'frameborder' => true, 'allowfullscreen' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'embed'     => array( 'src' => true, 'type' => true, 'width' => true, 'height' => true, 'allowfullscreen' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'object'    => array( 'data' => true, 'type' => true, 'width' => true, 'height' => true, 'classid' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'param'     => array( 'name' => true, 'value' => true ),
                    'video'     => array( 'src' => true, 'controls' => true, 'width' => true, 'height' => true, 'poster' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'audio'     => array( 'src' => true, 'controls' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'source'    => array( 'src' => true, 'type' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'track'     => array( 'kind' => true, 'src' => true, 'srclang' => true, 'label' => true ),
                    'canvas'    => array( 'width' => true, 'height' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'svg'       => array( 'width' => true, 'height' => true, 'viewBox' => true, 'xmlns' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'math'      => array( 'class' => true, 'id' => true, 'style' => true ),

                    // Forms and interactive content
                    'form'      => array( 'action' => true, 'method' => true, 'class' => true, 'id' => true, 'style' => true, 'enctype' => true, 'accept-charset' => true, 'name' => true ),
                    'fieldset' => array( 'disabled' => true, 'form' => true, 'name' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'legend'    => array( 'class' => true, 'id' => true, 'style' => true ),
                    'label'     => array( 'for' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'input'     => array(
                        'type'        => true,
                        'name'        => true,
                        'value'       => true,
                        'placeholder' => true,
                        'checked'     => true,
                        'disabled'    => true,
                        'readonly'    => true,
                        'size'        => true,
                        'maxlength'   => true,
                        'min'         => true,
                        'max'         => true,
                        'step'        => true,
                        'class'       => true,
                        'id'          => true,
                        'style'       => true,
                    ),
                    'button'    => array(
                        'type'     => true,
                        'name'     => true,
                        'value'    => true,
                        'disabled' => true,
                        'class'    => true,
                        'id'       => true,
                        'style'    => true,
                    ),
                    'select'    => array( 'name' => true, 'multiple' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'datalist'  => array( 'class' => true, 'id' => true, 'style' => true ),
                    'optgroup'  => array( 'label' => true, 'disabled' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'option'    => array( 'value' => true, 'selected' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'textarea'  => array( 'name' => true, 'rows' => true, 'cols' => true, 'placeholder' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'output'    => array( 'for' => true, 'form' => true, 'name' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'progress'  => array( 'max' => true, 'value' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'meter'     => array( 'min' => true, 'max' => true, 'value' => true, 'low' => true, 'high' => true, 'optimum' => true, 'class' => true, 'id' => true, 'style' => true ),

                    // Table elements
                    'table'     => array( 'class' => true, 'id' => true, 'style' => true, 'border' => true, 'cellpadding' => true, 'cellspacing' => true, 'width' => true, 'height' => true, 'align' => true ),
                    'caption'   => array( 'class' => true, 'id' => true, 'style' => true ),
                    'colgroup'  => array( 'span' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'col'       => array( 'span' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'thead'     => array( 'class' => true, 'id' => true, 'style' => true, 'width' => true, 'height' => true ),
                    'tbody'     => array( 'class' => true, 'id' => true, 'style' => true, 'width' => true, 'height' => true ),
                    'tfoot'     => array( 'class' => true, 'id' => true, 'style' => true, 'width' => true, 'height' => true ),
                    'tr'        => array( 'class' => true, 'id' => true, 'style' => true, 'valign' => true, 'width' => true, 'height' => true ),
                    'td'        => array( 'colspan' => true, 'rowspan' => true, 'headers' => true, 'class' => true, 'id' => true, 'style' => true, 'align' => true, 'valign' => true, 'width' => true, 'height' => true ),
                    'th'        => array( 'colspan' => true, 'rowspan' => true, 'headers' => true, 'scope' => true, 'class' => true, 'id' => true, 'style' => true, 'width' => true, 'height' => true ),

                    // Interactive and additional elements
                    'details'   => array( 'open' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'summary'   => array( 'class' => true, 'id' => true, 'style' => true ),
                    'dialog'    => array( 'open' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'menu'      => array( 'class' => true, 'id' => true, 'style' => true ),
                    'menuitem'  => array( 'label' => true, 'icon' => true, 'class' => true, 'id' => true, 'style' => true ),
                    'template'  => array( 'class' => true, 'id' => true, 'style' => true ),
                );

                // Add width and height attributes to specific table-related tags
                $table_tags = array('table', 'tr', 'td', 'th', 'tfoot', 'tbody');
                foreach( $table_tags as $tag ) {
                    if ( isset($allowed_tags[$tag]) ) {
                        $allowed_tags[$tag]['width']  = true;
                        $allowed_tags[$tag]['height'] = true;
                    }
                }

                if ( ! function_exists( 'wp_kses' ) ) {
                    return $content;
                }

                try {
                    $sanitized_content = wp_kses( $content, $allowed_tags );
                    return $sanitized_content;
                } catch ( Exception $e ) {
                    error_log( 'Sanitization error: ' . $e->getMessage() );
                    return $content;
                }
            }



            function wpml_newsletters_conditional_sanitize_content( $content ) {
                // Allow unfiltered HTML for users who have the capability.
                if ( current_user_can( 'unfiltered_html' ) ) {
                    //return $content;
                }
                if($this -> get_option('sanitize_content'))
                {
                    $content = $this -> sanitize_content($content);
                }
                // Otherwise, sanitize using wp_kses_post.
                return  $content ;
            }


            // Filter callback for user messages.
            function newsletters_sanitize_user_message( $message, $user ) {
                $message = $this -> wpml_newsletters_conditional_sanitize_content( $message );
                return $message;
            }
            // Filter callback for subscriber messages.
            function newsletters_sanitize_subscriber_message( $message, $subscriber ) {
                $message = $this -> wpml_newsletters_conditional_sanitize_content( $message );
                return $message;
            }

            function execute_mail($subscriber = null, $user = null, $subject = null, $message = null, $attachments = null, $history_id = null, $eunique = null, $shortlinks = true, $emailtype = "newsletter") {
                global $wpdb, $Db, $Html, $Email, $phpmailer, $Mailinglist, $Subscriber,
                       $SubscribersList, $orig_message, $wpml_message, $wpml_textmessage, $fromwpml, $newsletters_plaintext;

                $sent = false;
                $fromwpml = true;

                $execute_mail_stage = static function($stage = null, $context = array()) {
                    return;
                };

                $execute_mail_stage('start', array(
                    'subscriber_id' => (is_object($subscriber) && isset($subscriber -> id)) ? $subscriber -> id : null,
                    'user_id'       => (is_object($user) && isset($user -> ID)) ? $user -> ID : (is_array($user) && isset($user['ID']) ? $user['ID'] : null),
                    'history_id'    => $history_id,
                    'email_type'    => $emailtype,
                ));

                if (!empty($history_id)) {
                    $is_using_grapeJS = $this -> is_using_grapeJS($history_id);
                    if ($is_using_grapeJS) {
                        $message = $this -> get_grapeJS_content($history_id);
                    }
                }

                if (empty($subscriber) && empty($user)) { $error[] = __("No subscriber specified", 'wp-mailinglist'); }
                if (empty($subject)) { $error[] = __('No subject specified', 'wp-mailinglist'); }
                if (empty($message)) { $error[] = __('No message specified', 'wp-mailinglist'); }

                global $wpdb;
                if (!empty($history_id)) {
                    $query = "SELECT `id`, `from`, `fromname`, `text`, `mailinglists`, `user_id` FROM `" . $wpdb -> prefix . $this -> History() -> table . "` WHERE `id` = '" . esc_sql($history_id) . "'";
                    $his = $wpdb -> get_row($query);
                    $history = stripslashes_deep($his);
                }

                $found_duplicate = false;
                if(!empty($history_id) && ($emailtype == 'newsletter') && $this -> has_been_sent_already($subscriber, $user , $history_id, $eunique) )
                {
                    //$error[] = __('Duplicated Email (already sent)', 'wp-mailinglist');
                    $found_duplicate = true;
                    $execute_mail_stage('duplicate_detected', array(
                        'history_id'    => $history_id,
                        'subscriber_id' => (is_object($subscriber) && isset($subscriber -> id)) ? $subscriber -> id : null,
                        'user_id'       => (is_object($user) && isset($user -> ID)) ? $user -> ID : (is_array($user) && isset($user['ID']) ? $user['ID'] : null),
                    ));
                }

                $smtpfrom = (empty($history -> from)) ? __($this -> get_option('smtpfrom')) : $history -> from;
                $smtpfromname = (empty($history -> fromname)) ? __($this -> get_option('smtpfromname')) : $history -> fromname;

                $validationdata = array('subscriber' => $subscriber, 'user' => $user, 'subject' => $subject, 'message' => $message, 'history_id' => $history_id);
                $error = isset($error) ? $error : [];
                $error = apply_filters($this -> pre . '_sendmail_validation', $error, $validationdata);

                if (!empty($attachments) && $attachments != false) {
                    $attachments = maybe_unserialize($attachments);
                }

                $attachments = apply_filters('newsletters_execute_mail_attachments', $attachments, $subscriber, $user, $history_id);
                $execute_mail_stage('attachments_prepared', array(
                    'attachments_count' => (is_array($attachments) ? count($attachments) : (empty($attachments) ? 0 : 1)),
                ));

                if (empty($error)) {
                    $execute_mail_stage('validation_passed');
                    $Db -> model = $Email -> model;

                    $message = str_replace("[wpmlsubject]", $subject, $message);
                    $message = str_replace("[newsletters_subject]", $subject, $message);

                    $subject = do_shortcode($subject);

                    //TOD: ADD LOGIC TO EXCHANGE $messasge WITH DRAG AND DROP BUILDER IN CASE OF AVAILABILITY

                    $message = do_shortcode($message);
                    $wpml_textmessage = do_shortcode($wpml_textmessage);
                    $execute_mail_stage('message_do_shortcode', array(
                        'message_length' => is_string($message) ? strlen($message) : 0,
                    ));

                    $subject = $this -> process_set_variables($subscriber, $user, wp_unslash($subject), $history_id, $eunique, true, $execute_mail_stage);
                    $message = $this -> process_set_variables($subscriber, $user, (wp_unslash($message)), $history_id, $eunique, false, $execute_mail_stage);
                    $message = apply_filters('newsletters_execute_mail_message', $message);
                    $wpml_textmessage = $this -> process_set_variables($subscriber, $user, urldecode(wp_unslash($wpml_textmessage)), $history_id, $eunique, false, $execute_mail_stage);
                    $wpml_textmessage = apply_filters('newsletters_execute_mail_textmessage', $wpml_textmessage);
                    $execute_mail_stage('variables_processed', array(
                        'message_length' => is_string($message) ? strlen($message) : 0,
                    ));

                    if (!empty($subscriber -> id)) {
                        $Subscriber -> inc_sent($subscriber -> id);
                    }

                    if (!empty($subscriber -> mailinglists)) {
                        foreach ($subscriber -> mailinglists as $mailinglist_id) {
                            $query = "SELECT `paid` FROM `" . $wpdb -> prefix . $Mailinglist -> table . "` WHERE `id` = '" . esc_sql($mailinglist_id) . "' LIMIT 1";
                            $paid = $wpdb -> get_var($query);

                            if (!empty($paid) && $paid == "Y") {
                                $query = "UPDATE `" . $wpdb -> prefix . $SubscribersList -> table . "` SET `paid_sent` = (`paid_sent` + 1) WHERE `subscriber_id` = '" . esc_sql($subscriber -> id) . "' AND `list_id` = '" . esc_sql($mailinglist_id) . "' LIMIT 1";
                                $wpdb -> query($query);
                            }
                        }
                    }

                    $multimime = $this -> get_option('multimime');

                    // Should an AltBody be generated?
                    // This is used with multi-mime emails are turned on
                    $altbody = false;
                    if (!empty($history -> text)) {
                        $altbody = $history -> text;
                        $altbody = do_shortcode($altbody);
                        $altbody = $this -> process_set_variables($subscriber, $user, urldecode(wp_unslash($altbody)), $history_id, $eunique, false, $execute_mail_stage);
                        $altbody = apply_filters('newsletters_execute_mail_textmessage', $altbody);
                        $wpml_textmessage = $altbody;
                    }
                    $execute_mail_stage('altbody_prepared', array(
                        'has_altbody' => !empty($altbody),
                        'multimime'   => ($multimime == "Y"),
                    ));
                    if (version_compare(PHP_VERSION, '5.3.2') >= 0) {
                        if (class_exists('DOMDocument')) {
                            require_once $this -> plugin_base() . DS . 'vendors' . DS . 'class.html2text.php';
                            $html2text = new Html2Text();

                            if (!empty($wpml_textmessage)) {
                                $altbody = $html2text -> convert($wpml_textmessage);
                            }
                        }
                    }

                    $to = false;
                    if (!empty($subscriber)) {
                        $to = $subscriber -> email;
                    } elseif (!empty($user)) {
                        $to = $user -> user_email;
                    }

                    $mailtype = $this -> get_option('mailtype');
                    $mailpriority = $this -> get_option('mailpriority');

                    global $newsletters_presend, $newsletters_emailraw, $mailerrors, $messageid;

                    $mailapi = $this -> get_option('mailapi');

                    $data = array(
                        'mailtype'		=>	$mailtype,
                        'mailapi'		=>	$mailapi,
                        'to'			=>	$to,
                        'smtpfrom'		=>	$smtpfrom,
                        'smtpfromname'	=>	$smtpfromname,
                        'smtpreply'		=>	isset($smtpreply) ? $smtpreply : '',
                        'subject'		=>	$subject,
                        'message'		=>	$message,
                        'altbody'		=>	$altbody,
                        'attachments'	=>	$attachments,
                        'mailpriority'	=>	$mailpriority,
                    );

                    $sent = apply_filters('newsletters_execute_mail', false, $data);
                    $execute_mail_stage('pre_send_filters', array('sent_via_filters' => (bool) $sent));

                    if (!apply_filters('newsletters_execute_mail_override', false) || (!empty($emailtype)  && $emailtype === "spam_check")) {
                        if ($mailtype == "smtp" || $mailtype == "gmail" || (!empty($newsletters_presend) && $newsletters_presend == true) || (!empty($emailtype)  && $emailtype === "spam_check")) {


                            if (!is_object($phpmailer)) {

                                /**
                                 * Since 4.7
                                 * PHPMailer update - support for phpMailer 6.0 (WP 5.5+)
                                 */


                                if ( version_compare( get_bloginfo( 'version' ), '5.5-alpha', '<' ) ) {
                                    require_once(ABSPATH . WPINC . DS . 'class-phpmailer.php');
                                    $phpmailer = new PHPMailer(true);

                                } else {

                                    if ( ! class_exists( '\PHPMailer\PHPMailer\PHPMailer', false ) ) {
                                        require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
                                    }

                                    if ( ! class_exists( '\PHPMailer\PHPMailer\Exception', false ) ) {
                                        require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
                                    }

                                    if ( ! class_exists( '\PHPMailer\PHPMailer\SMTP', false ) ) {
                                        require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
                                    }

                                    $phpmailer = new \PHPMailer\PHPMailer\PHPMailer(true);
                                }

                            }

                            try {
                                //clear all recipients
                                $phpmailer -> ClearAddresses();
                                $phpmailer -> ClearAllRecipients();
                                $phpmailer -> ClearCCs();
                                $phpmailer -> ClearBCCs();
                                $phpmailer -> ClearAttachments();
                                $phpmailer -> ClearReplyTos();
                                $phpmailer -> ClearCustomHeaders();

                                //set the language
                                $phpmailer_language = $this -> plugin_base() . DS . 'vendors' . DS . 'phpmailer-language';
                                $phpmailer -> SetLanguage('en', $phpmailer_language);

                                $phpmailer -> IsSMTP();
                                $phpmailer -> Host = $this -> get_option('smtphost');
                                $phpmailer -> Port = $this -> get_option('smtpport');
                                $phpmailer -> SMTPKeepAlive = true;

                                $smtpsecure = $this -> get_option('smtpsecure');
                                if (!empty($smtpsecure) && $smtpsecure != "N") {
                                    $phpmailer -> SMTPSecure = $smtpsecure;
                                }

                                $phpmailer -> SMTPAutoTLS = false;

                                if ($this -> debugging) {
                                    $phpmailer -> SMTPDebug = 1;
                                    $phpmailer -> Debugoutput = 'html';
                                }

                                if ($this -> get_option('smtpauth') == "Y") {
                                    $phpmailer -> SMTPAuth = true;
                                    $phpmailer -> Username = $this -> get_option('smtpuser');
                                    $phpmailer -> Password = html_entity_decode($this -> get_option('smtppass'));
                                }

                                //DKIM-Signature (DomainKeys Identified Mail)
                                if ($this -> get_option('dkim') == "Y") {
                                    $phpmailer -> DKIM_identity = $smtpfrom;
                                    $phpmailer -> DKIM_private_string = $this -> get_option('dkim_private');
                                    $phpmailer -> DKIM_domain = $this -> get_option('dkim_domain');
                                    $phpmailer -> DKIM_selector = $this -> get_option('dkim_selector');
                                }

                                if (!empty($attachments) && $attachments != false) {
                                    if (is_array($attachments)) {
                                        foreach ($attachments as $attachment) {
                                            if (empty($attachment['data'])) {
                                                $phpmailer -> AddAttachment($attachment['filename'], $attachment['title']);
                                            } else {
                                                $phpmailer -> addStringAttachment($attachment['data'], $attachment['filename']);
                                            }
                                        }
                                    } else {
                                        if (empty($attachments['data'])) {
                                            $phpmailer -> AddAttachment($attachments['filename'], $attachments['title']);
                                        } else {
                                            $phpmailer -> addStringAttachment($attachments['data'], $attachments['filename']);
                                        }
                                    }
                                }

                                //set the Charset to that of Wordpress
                                $phpmailer -> CharSet = get_option('blog_charset');
                                $phpmailer -> SetFrom($smtpfrom, $smtpfromname);

                                $phpmailer -> Sender = $this -> get_option('bounceemail');

                                if (!empty($subscriber)) {
                                    $to = $subscriber -> email;
                                } elseif (!empty($user)) {
                                    $to = $user -> user_email;
                                }

                                $phpmailer -> AddCustomHeader('Precedence', "bulk");
                                $phpmailer -> AddCustomHeader('List-Unsubscribe', $this -> gen_unsubscribe_link($subscriber, $user, $theme_id, $history_id, false, true));

                                $phpmailer -> AddAddress($to);
                                $phpmailer -> AddReplyTo($smtpfrom, $smtpfromname);

                                // Should the Reply-To header be different?
                                $replytodifferent = $this -> get_option('replytodifferent');
                                if (!empty($replytodifferent)) {
                                    $smtpreply = $this -> get_option('smtpreply');
                                    $phpmailer -> AddReplyTo($smtpreply, $smtpfromname);
                                }

                                $bccemails = $this -> get_option('bccemails');
                                if (!empty($bccemails)) {
                                    $bccemails_address = $this -> get_option('bccemails_address');
                                    if (!empty($bccemails_address) && $Subscriber -> email_validate($bccemails_address)) {
                                        $phpmailer -> addBCC($bccemails_address);
                                    }
                                }

                                if (!empty($altbody) && $multimime == "Y") {
                                    $phpmailer -> AltBody = $altbody;
                                }

                                if (!empty($newsletters_plaintext)) {
                                    $phpmailer -> ContentType = "text/plain";
                                    $phpmailer -> IsHTML(false);
                                    $message = strip_tags($message);
                                    $phpmailer -> AltBody = false;
                                } else {
                                    $phpmailer -> ContentType = "text/html";
                                    $phpmailer -> IsHTML(true);
                                }

                                $phpmailer -> Subject = wp_unslash($subject);
                                $phpmailer -> Body = $this -> inlinestyles(apply_filters($this -> pre . '_send_body', wp_unslash($message), $phpmailer, $history_id));

                                if (!empty($mailpriority) && $mailpriority != 3) {
                                    $phpmailer -> Priority = $mailpriority; //set the email priority
                                }
                                $phpmailer -> WordWrap = 0;
                                $phpmailer -> Encoding = $this -> get_option('emailencoding');
                                $phpmailer -> MessageID = $this -> phpmailer_messageid();

                                global $newsletters_presend, $newsletters_emailraw;

                                if  (!empty($emailtype)  && $emailtype === "spam_check")
                                {
                                    return $phpmailer;
                                    die();
                                }
                                if (!empty($newsletters_presend) && $newsletters_presend == true) {
                                    $yourmailexchange = gethostname() ;
                                    $yourmailexchange = $_SERVER['HTTP_HOST'];
                                    $yourmailexchangeip_response = wp_remote_get("http://ipecho.net/plain");
                                    $yourmailexchangeip = wp_remote_retrieve_body($yourmailexchangeip_response);
                                    $receivermailexchange = $_SERVER['HTTP_HOST'];
                                    $receiveddate = date_i18n('D, d M Y H:i:s O');
                                    $receivermailexchange = 'gmail.com';
                                    $phpmailer -> AddCustomHeader('Received', 'from ' . $yourmailexchange . ' (' . $yourmailexchange . ' [' . $yourmailexchangeip . ']) by ' . $receivermailexchange . ' with SMTP; ' . $receiveddate);
                                    $phpmailer -> PreSend();
                                    $emailraw = $phpmailer -> getSentMIMEMessage();
                                    $newsletters_emailraw = $emailraw;
                                    return $emailraw;
                                }

                                $phpmailer = apply_filters($this->pre . '_phpmailer_before_send', $phpmailer);

                                $execute_mail_stage('smtp_send_attempt');
                                $result = $phpmailer -> Send();
                                $execute_mail_stage('smtp_send_result', array('result' => (bool) $result));

                                if ($result) {
                                    $sent = true;
                                    $messageid = $phpmailer -> MessageID;
                                } else {
                                    global $mailerrors;
                                    $mailerrors = $phpmailer -> ErrorInfo;
                                    return false;
                                }

                                // Since 4.7 - catch exception for phpMailer 6.0
                            } catch (PHPMailer\PHPMailer\Exception $e) {
                                $mailerrors = $e -> errorMessage(); //Pretty error messages from PHPMailer 6.0
                                $execute_mail_stage('smtp_exception', array('error' => $mailerrors));
                            } catch (phpmailerException $e) {
                                $mailerrors = $e -> errorMessage(); //Pretty error messages from PHPMailer < 6.0
                                $execute_mail_stage('smtp_exception', array('error' => $mailerrors));
                            } catch (Exception $e) {
                                $mailerrors = $e -> getMessage(); //Boring error messages from anything else!
                                $execute_mail_stage('smtp_exception', array('error' => $mailerrors));
                            }
                        } elseif ($mailtype == "api") {
                            $mailapi = $this -> get_option('mailapi');

                            $data = array(
                                'api'			=>	$mailapi,
                                'to'			=>	$to,
                                'from'			=>	$smtpfrom,
                                'fromname'		=>	$smtpfromname,
                                'replyto'		=>	$smtpreply,
                                'subject'		=>	$subject,
                                'html'			=>	$message,
                                'text'			=>	$altbody,
                                'attachments'	=>	$attachments,
                                'mailpriority'	=>	$mailpriority,
                            );

                            do_action('newsletters_sendmail_api', $data);

                            switch ($mailapi) {
                                case 'sparkpost'					:
                                    require($this -> plugin_base() . DS . 'vendor' . DS . 'autoload.php');

                                    $sparkpost_apikey = $this -> get_option('mailapi_sparkpost_apikey');

                                    $client = new GuzzleHttp\Client();
                                    $httpClient = new Http\Adapter\Guzzle6\Client($client);
                                    $sparky = new SparkPost\SparkPost($httpClient, array('key' => $sparkpost_apikey));

                                    try {
                                        $replytodifferent = $this -> get_option('replytodifferent');
                                        if (!empty($replytodifferent)) {
                                            $smtpreply = $this -> get_option('smtpreply');
                                        } else {
                                            $smtpreply = $smtpfrom;
                                        }

                                        $headers = array();
                                        $headers['Precedence'] = "bulk";
                                        $headers['List-Unsubscribe'] = $this -> gen_unsubscribe_link($subscriber, $user, $theme_id, $history_id, false, true);

                                        $sparkpost_data = array(
                                            'content'				=>	array(
                                                'from'					=>	array(
                                                    'name'					=>	$smtpfromname,
                                                    'email'					=>	$smtpfrom,
                                                ),
                                                'reply_to'				=> 	$smtpreply,
                                                'headers'				=>	$headers,
                                                'subject'				=>	wp_unslash($subject),
                                                'html'					=>	((empty($newsletters_plaintext)) ? $this -> inlinestyles(apply_filters($this -> pre . '_send_body', wp_unslash($message), $phpmailer, $history_id, 'sparkpost', false)) : null),
                                                //'text'					=>	$altbody,
                                            ),
                                            'recipients'			=>	array(
                                                array(
                                                    'address'			=>	array(
                                                        'email'				=>	$to,
                                                    ),
                                                )
                                            ),
                                        );

                                        $bccemails = $this -> get_option('bccemails');
                                        if (!empty($bccemails)) {
                                            $bccemails_address = $this -> get_option('bccemails_address');
                                            if (!empty($bccemails_address) && $Subscriber -> email_validate($bccemails_address)) {
                                                $sparkpost_data['recipients'][0]['address']['email'] = $bccemails_address;
                                                $sparkpost_data['recipients'][0]['address']['header_to'] = $to;
                                            }
                                        }

                                        if (!empty($altbody)) {
                                            $sparkpost_data['content']['text'] = $altbody;
                                        }

                                        if (!empty($attachments)) {
                                            $sparkpost_data['content']['attachments'] = array();
                                            foreach ($attachments as $attachment) {
                                                $filetype = wp_check_filetype($attachment['filename']);
                                                $data = file_get_contents($attachment['filename']);

                                                $sparkpost_data['content']['attachments'][] = array(
                                                    'type'			=>	$filetype['type'],
                                                    'name'			=>	$attachment['title'],
                                                    'data'			=>	base64_encode($data),
                                                );
                                            }
                                        }

                                        $messageid = $this -> phpmailer_messageid();

                                        $sparkpost_data['metadata'] = array(
                                            'messageid'				=>	$messageid,
                                        );

                                        $sparkpost_data = apply_filters('newsletters_mailapi_sparkpost_data', $sparkpost_data);

                                        $promise = $sparky -> transmissions -> post($sparkpost_data);

                                        $response = $promise -> wait();
                                        $statuscode = $response -> getStatusCode();

                                        if (!empty($statuscode) && $statuscode < 400) {
                                            $responsebody = $response -> getBody();

                                            $sent = true;
                                        } else {
                                            global $mailerrors;
                                            $mailerrors = sprintf(__('%s status code received', 'wp-mailinglist'), $statuscode);
                                            return false;
                                        }
                                    } catch (Exception $e) {
                                        global $mailerrors;
                                        $errors = $e -> getMessage();
                                        $errors = json_decode($errors);
                                        $error = $errors -> errors[0];
                                        $mailerrors = $error -> code . ': ' . $error -> message . ' (' . $error -> description . ')';
                                        $this -> log_error($mailerrors);
                                        return false;
                                    }
                                    break;
                                case 'mailgun'						:
                                    $mailgun_apikey = $this -> get_option('mailapi_mailgun_apikey');
                                    $mailgun_domain = $this -> get_option('mailapi_mailgun_domain');
                                    $mailgun_region = $this -> get_option('mailapi_mailgun_region');
                                    $region = (empty($mailgun_region) || $mailgun_region == "US") ? 'https://api.mailgun.net' : 'https://api.eu.mailgun.net';


                                    require($this -> plugin_base() . DS . 'vendor' . DS . 'autoload.php');
                                    //$mailgun = new Mailgun\Mailgun($mailgun_apikey);
                                    //$mailgun = new Mailgun\Mailgun::create($mailgun_apikey);
                                    //$mg = $mailgun -> create($mailgun_apikey, $region);
                                    //$mg = Mailgun\Mailgun::create($mailgun_apikey, $region);
                                    $mg = Mailgun\Mailgun::create($mailgun_apikey, $region);


                                    try {

                                        $data = array(
                                            'from'				=>	$smtpfromname . '<' . $smtpfrom . '>',
                                            'to'				=>	$to,
                                            'subject'			=>	wp_unslash($subject),
                                            'text'				=>	$altbody,
                                            'html'				=>	((empty($newsletters_plaintext)) ? $this -> inlinestyles(apply_filters($this -> pre . '_send_body', wp_unslash($message), $phpmailer, $history_id, 'mailgun', $mg)) : null),
                                            'attachment'		=>	array(),
                                        );

                                        $bccemails = $this -> get_option('bccemails');
                                        if (!empty($bccemails)) {
                                            $bccemails_address = $this -> get_option('bccemails_address');
                                            if (!empty($bccemails_address) && $Subscriber -> email_validate($bccemails_address)) {
                                                $data['bcc'] = $bccemails_address;
                                            }
                                        }

                                        $data['h:Precedence'] = "bulk";
                                        $data['h:List-Unsubscribe'] = $this -> gen_unsubscribe_link($subscriber, $user, $theme_id, $history_id, false, true);

                                        $files = array();

                                        if (!empty($attachments) && $attachments != false) {
                                            if (is_array($attachments)) {
                                                foreach ($attachments as $attachment) {
                                                    $files['attachment'][] = $attachment['filename'];
                                                }
                                            } else {
                                                $files['attachment'][] = $attachment['filename'];
                                            }
                                        }

                                        $messageid = $this -> phpmailer_messageid();
                                        $data['v:my-custom-data'] = json_encode(array('MessageID' => $messageid));

                                        $data = apply_filters('newsletters_mailapi_mailgun_data', $data);
                                        $files = apply_filters('newsletters_mailapi_mailgun_files', $files);

                                        $result = $mg -> messages() -> send($mailgun_domain, $data, $files);

                                        $sent = true;
                                    } catch (Exception $e) {
                                        global $mailerrors;
                                        $mailerrors = $e -> getMessage();
                                        return false;
                                    }
                                    break;
                                case 'mailjet'						:

                                    break;
                                case 'amazonses'					:

                                    $mailapi_amazonses_key = $this -> get_option('mailapi_amazonses_key');
                                    $mailapi_amazonses_secret = $this -> get_option('mailapi_amazonses_secret');
                                    $mailapi_amazonses_region = $this -> get_option('mailapi_amazonses_region');

                                    require($this -> plugin_base() . DS . 'vendor' . DS . 'autoload.php');

                                    global $sesmessage, $ses;
                                    $sesmessage = new SimpleEmailServiceMessage();
                                    $sesmessage -> addTo($to);
                                    $sesmessage -> setFrom($smtpfromname . '<' . $smtpfrom . '>');
                                    $sesmessage -> setSubject(wp_unslash($subject));
                                    $htmlbody = ((empty($newsletters_plaintext)) ? $this -> inlinestyles(apply_filters($this -> pre . '_send_body', wp_unslash($message), $phpmailer, $history_id, 'amazonses', $sesmessage)) : null);
                                    $sesmessage -> setMessageFromString($altbody, $htmlbody);

                                    if (!empty($attachments) && $attachments != false) {
                                        if (is_array($attachments)) {
                                            foreach ($attachments as $attachment) {
                                                $sesmessage -> addAttachmentFromFile($attachment['title'], $attachment['filename']);
                                            }
                                        } else {
                                            $sesmessage -> addAttachmentFromFile($attachment['title'], $attachment['filename']);
                                        }
                                    }

                                    $bccemails = $this -> get_option('bccemails');
                                    if (!empty($bccemails)) {
                                        $bccemails_address = $this -> get_option('bccemails_address');
                                        if (!empty($bccemails_address) && $Subscriber -> email_validate($bccemails_address)) {
                                            $sesmessage -> addBCC($bccemails_address);
                                        }
                                    }

                                    $sesmessage -> addCustomHeader("Precedence: bulk");
                                    $sesmessage -> addCustomHeader("List-Unsubscribe: " . $this -> gen_unsubscribe_link($subscriber, $user, $theme_id, $history_id, false, true));

                                    do_action('newsletters_mailapi_amazonses_beforesend', $sesmessage);

                                    if (empty($ses)) {
                                        $signature_version = SimpleEmailService::REQUEST_SIGNATURE_V4;
                                        $ses = new SimpleEmailService($mailapi_amazonses_key, $mailapi_amazonses_secret, 'email.' . $mailapi_amazonses_region . '.amazonaws.com', false, $signature_version);
                                        $ses -> setBulkMode(true);
                                    }

                                    $result = $ses -> sendEmail($sesmessage, false, false);

                                    if (!empty($result) && empty($result -> error)) {
                                        $messageid = $result['MessageId'];
                                        $sent = true;
                                    } else {
                                        global $mailerrors;
                                        $error = $result -> error['Error']['Message'];
                                        $this -> log_error($error);
                                        $mailerrors = $error;
                                        return false;
                                    }

                                    break;
                                case 'sendgrid'						:
                                    $sendgrid_apikey = $this -> get_option('mailapi_sendgrid_apikey');

                                    require($this -> plugin_base() . DS . 'vendor' . DS . 'autoload.php');
                                    $sendgrid = new \SendGrid($sendgrid_apikey);

                                    global $sendgridemail;
                                    $sendgridemail = new \SendGrid\Mail\Mail();

                                    $sendgridemail -> addTo($to);
                                    $sendgridemail -> setFrom($smtpfrom, $smtpfromname);
                                    $sendgridemail -> setSubject(wp_unslash($subject));

                                    if (empty($newsletters_plaintext)) {
                                        $sendgridemail -> addContent("text/plain", $altbody . " ");
                                        $html = $this -> inlinestyles(apply_filters($this -> pre . '_send_body', wp_unslash($message), $phpmailer, $history_id, 'sendgrid', $sendgridemail));
                                        $sendgridemail -> addContent("text/html", $html . " ");
                                    } else {
                                        $sendgridemail -> addContent("text/plain", $altbody . " ");
                                    }

                                    if (!empty($attachments) && $attachments != false) {
                                        if (is_array($attachments)) {
                                            foreach ($attachments as $attachment) {
                                                $attachment_data = file_get_contents($attachment['filename']);
                                                $file_encoded = base64_encode($attachment_data);
                                                $sendgridemail -> addAttachment($file_encoded, null, basename($attachment['filename']));
                                            }
                                        } else {
                                            $attachment_data = file_get_contents($attachment['filename']);
                                            $file_encoded = base64_encode($attachment_data);
                                            $sendgridemail -> addAttachment($file_encoded, null, basename($attachment['filename']));
                                        }
                                    }

                                    do_action('newsletters_mailapi_sendgrid_beforesend', $sendgridemail);

                                    $replytodifferent = $this -> get_option('replytodifferent');
                                    if (!empty($replytodifferent)) {
                                        $smtpreply = $this -> get_option('smtpreply');
                                        $sendgridemail -> setReplyTo($smtpreply);
                                    }

                                    $bccemails = $this -> get_option('bccemails');
                                    if (!empty($bccemails)) {
                                        $bccemails_address = $this -> get_option('bccemails_address');
                                        if (!empty($bccemails_address) && $Subscriber -> email_validate($bccemails_address)) {
                                            $sendgridemail -> addBcc($bccemails_address);
                                        }
                                    }

                                    $messageid = $this -> phpmailer_messageid();

                                    $sendgridemail -> addHeader('Precedence', "bulk");
                                    $sendgridemail -> addHeader('List-Unsubscribe', $this -> gen_unsubscribe_link($subscriber, $user, $theme_id, $history_id, false, true));
                                    $sendgridemail -> addCustomArg('MessageID', $messageid);

                                    try {
                                        $result = $sendgrid -> send($sendgridemail);
                                        $body = json_decode($result -> body());

                                        if (!empty($this -> debugging)) {
                                            echo '<p>' . sprintf(__('Status Code: %s', 'wp-mailinglist'), $result -> statusCode()) . '</p>';
                                            echo implode("<br/>", $result -> headers());
                                        }

                                        if (empty($body -> errors)) {
                                            $sent = true;
                                        } else {
                                            global $mailerrors;
                                            foreach ($body -> errors as $error) {
                                                $this -> log_error($error -> message);
                                                $mailerrors = $error -> message;
                                            }

                                            return false;
                                        }
                                    } catch (Exception $e) {
                                        global $mailerrors;
                                        $this -> log_error($e -> getMessage());
                                        $mailerrors = $e -> getMessage();
                                        return false;
                                    }
                                    break;
                                case 'mandrill'						:

                                    $headers['Precedence'] = "bulk";
                                    $headers['List-Unsubscribe'] = $this -> gen_unsubscribe_link($subscriber, $user, $theme_id, $history_id, false, true);

                                    $mailpriority = $this -> get_option('mailpriority');

                                    try {
                                        require_once($this -> plugin_base() . DS . 'vendors' . DS . 'mailapis' . DS . 'mandrill' . DS . 'Mandrill.php');
                                        $mailapi_mandrill_key = $this -> get_option('mailapi_mandrill_key');
                                        $mandrill = new Mandrill($mailapi_mandrill_key);

                                        global $mandrillmessage;

                                        $mandrillmessage = array(
                                            'html' => ((empty($newsletters_plaintext)) ? $this -> inlinestyles(apply_filters($this -> pre . '_send_body', wp_unslash($message), $phpmailer, $history_id, 'mandrill', $mandrill)) : null),
                                            'text' => $altbody,
                                            'subject' => wp_unslash($subject),
                                            'from_email' => $smtpfrom,
                                            'from_name' => $smtpfromname,
                                            'to' => array(
                                                array(
                                                    'email' => $to,
                                                    //'name' => 'Recipient Name',
                                                    'type' => 'to'
                                                )
                                            ),
                                            'headers' => $headers,
                                            'important' => ((!empty($mailpriority) && $mailpriority == 1) ? true : false),
                                            'track_opens' => null,
                                            'track_clicks' => null,
                                            'auto_text' => null,
                                            'auto_html' => null,
                                            'inline_css' => null,
                                            'url_strip_qs' => null,
                                            'preserve_recipients' => null,
                                            'view_content_link' => null,
                                            //'bcc_address' => 'message.bcc_address@example.com',
                                            'tracking_domain' => null,
                                            'signing_domain' => null,
                                            'return_path_domain' => null,
                                            //'merge' => true,
                                            //'merge_language' => 'mailchimp',
                                            /*'global_merge_vars' => array(
                                                    array(
                                                        'name' => 'merge1',
                                                        'content' => 'merge1 content'
                                                    )
                                                ),
                                                'merge_vars' => array(
                                                    array(
                                                        'rcpt' => 'recipient.email@example.com',
                                                        'vars' => array(
                                                            array(
                                                                'name' => 'merge2',
                                                                'content' => 'merge2 content'
                                                            )
                                                        )
                                                    )
                                                ),
                                                'tags' => array('password-resets'),*/
                                            //'subaccount' => ,
                                            /*'google_analytics_domains' => array('example.com'),
                                                'google_analytics_campaign' => 'message.from_email@example.com',
                                                'metadata' => array('website' => 'www.example.com'),
                                                'recipient_metadata' => array(
                                                    array(
                                                        'rcpt' => 'recipient.email@example.com',
                                                        'values' => array('user_id' => 123456)
                                                    )
                                                ),
                                                'attachments' => array(
                                                    array(
                                                        'type' => 'text/plain',
                                                        'name' => 'myfile.txt',
                                                        'content' => 'ZXhhbXBsZSBmaWxl'
                                                    )
                                                ),
                                                'images' => array(
                                                    array(
                                                        'type' => 'image/png',
                                                        'name' => 'IMAGECID',
                                                        'content' => 'ZXhhbXBsZSBmaWxl'
                                                    )
                                                )*/
                                        );

                                        $bccemails = $this -> get_option('bccemails');
                                        if (!empty($bccemails)) {
                                            $bccemails_address = $this -> get_option('bccemails_address');
                                            if (!empty($bccemails_address) && $Subscriber -> email_validate($bccemails_address)) {
                                                $mandrillmessage['to'][] = array(
                                                    'email'					=>	$bccemails_address,
                                                    'type'					=>	'bcc',
                                                );
                                            }
                                        }

                                        $mandrillmessage = apply_filters('newsletters_mailapi_mandrill_messagearray', $mandrillmessage);

                                        $subaccount = $this -> get_option('mailapi_mandrill_subaccount');
                                        if (!empty($subaccount)) {
                                            $mandrillmessage['subaccount'] = $subaccount;
                                        }

                                        if (!empty($attachments) && $attachments != false) {
                                            $mandrillmessage['attachments'] = array();

                                            if (is_array($attachments)) {
                                                foreach ($attachments as $attachment) {
                                                    $filetype = wp_check_filetype($attachment['filename']);
                                                    $attachment_data = file_get_contents($attachment['filename']);

                                                    $mandrillmessage['attachments'][] = array(
                                                        'type'				=>	$filetype['type'],
                                                        'name'				=>	$attachment['title'],
                                                        'content'			=>	base64_encode($attachment_data),
                                                    );
                                                }
                                            } else {
                                                $filetype = wp_check_filetype($attachment['filename']);
                                                $attachment_data = file_get_contents($attachment['filename']);

                                                $mandrillmessage['attachments'][] = array(
                                                    'type'				=>	$filetype['type'],
                                                    'name'				=>	$attachment['title'],
                                                    'content'			=>	base64_encode($attachment_data),
                                                );
                                            }
                                        }

                                        /*$mandrillmessage['headers'] = array(
                                                'Content-Type'				=>	"text/plain",
                                            );*/

                                        $async = true;
                                        //$ip_pool = 'Main Pool';
                                        $ip_pool = $this -> get_option('mailapi_mandrill_ippool');
                                        //$send_at = 'example send_at';
                                        $send_at = null;
                                        $result = $mandrill -> messages -> send($mandrillmessage, $async, $ip_pool, $send_at);


                                        if (!empty($result[0]['status']) && ($result[0]['status'] == "sent" || $result[0]['status'] == "queued")) {
                                            $sent = true;
                                        }

                                        /*
                                            Array
                                            (
                                                [0] => Array
                                                    (
                                                        [email] => recipient.email@example.com
                                                        [status] => sent
                                                        [reject_reason] => hard-bounce
                                                        [_id] => abc123abc123abc123abc123abc123
                                                    )

                                            )
                                            */
                                    } catch(Mandrill_Error $e) {
                                        // Mandrill errors are thrown as exceptions
                                        //echo 'A mandrill error occurred: ' . get_class($e) . ' - ' . $e->getMessage();
                                        // A mandrill error occurred: Mandrill_Unknown_Subaccount - No subaccount exists with the id 'customer-123'
                                        //throw $e;

                                        global $mailerrors;
                                        $mailerrors = $e -> getMessage();
                                        return false;
                                    }
                                    break;
                            }
                        } else {
                            if (!empty($subscriber)) {
                                $to = $subscriber -> email;
                            } elseif (!empty($user)) {
                                $to = $user -> user_email;
                            }

                            $content_type = (!empty($newsletters_plaintext)) ? 'text/plain' : 'text/html';

                            $subject = wp_unslash($subject);
                            $message = wp_unslash($message);
                            $headers = '';
                            $headers .= 'Content-Type: ' . $content_type . '; charset="UTF-8"' . "\r\n";
                            $headers .= 'From: ' . $smtpfromname . ' <' . $smtpfrom . '>' . "\r\n";

                            $atts = array();
                            if (!empty($attachments) && is_array($attachments)) {
                                foreach ($attachments as $attachment) {
                                    $atts[] = $attachment['filename'];
                                }
                            }

                            global $wpml_message, $wpmlhistory_id;
                            $wpml_message = $message;
                            $wpmlhistory_id = $history_id;

                            if ( true ) { //!$found_duplicate ) {
                                $execute_mail_stage('wp_mail_attempt', array('mailtype' => $mailtype));
                                if ($result = wp_mail($to, $subject, $message, $headers, $atts)) {
                                    $sent = true;
                                    $messageid = $phpmailer -> MessageID;
                                    $execute_mail_stage('wp_mail_success');
                                } else {
                                    global $mailerrors, $phpmailer;
                                    $mailerrors = $phpmailer -> ErrorInfo;
                                    $execute_mail_stage('wp_mail_failed');
                                    return false;
                                }
                            }
                            else {
                                global $mailerrors, $phpmailer;
                                $mailerrors = $phpmailer -> ErrorInfo;
                                return false;
                            }
                        }
                    }

                    if (!empty($sent) && $sent == true) {
                        $execute_mail_stage('post_send_processing', array('messageid' => isset($messageid) ? $messageid : null));
                        global $phpmailer;
                        $this -> delete_all_cache('all');

                        $history_lists = isset($history) ? maybe_unserialize($history -> mailinglists) : null;
                        $includeonly = (empty($history_lists)) ? $subscriber -> mailinglists : $history_lists;
                        $subscriber_lists = maybe_unserialize($Subscriber -> mailinglists($subscriber -> id, $includeonly, false, false));
                        $e_mailinglists = (empty($subscriber_lists)) ? $history_lists : $subscriber_lists;

                        $owner_id = 0;
                        $owner_role = '';
                        if (!empty($history -> user_id) && $current_user = get_userdata($history -> user_id)) {
                            $owner_id = $current_user -> ID;
                            $owner_role = $current_user -> roles[0];
                        }

                        if (!empty($eunique)) {
                            $e_data = array(
                                'eunique'				=>	$eunique,
                                'subscriber_id'			=>	(!empty($subscriber) ? $subscriber -> id : 0),
                                'user_id'				=>	(!empty($user) ? $user -> ID : 0),
                                'mailinglist_id'		=>	(!empty($subscriber -> mailinglist_id) ? $subscriber -> mailinglist_id : ''),
                                'mailinglists'			=>	maybe_serialize($e_mailinglists),
                                'history_id'			=>	$history_id,
                                'owner_id'				=>	$owner_id,
                                'owner_role'			=>	$owner_role,
                                'type'					=>	$emailtype,
                                'read'					=>	"N",
                                'status'				=>	"sent",
                                'messageid'				=>	$messageid,
                            );

                            $Db -> model = $Email -> model;

                            if (!$Db -> save($e_data, true)) {
                                $this -> log_error('Email could not be saved: ' . implode("; ", $Email -> errors));
                            }
                        }
                    }
                } else {
                    $execute_mail_stage('validation_failed', array('errors' => $error));
                    $sent = false;
                }

                $execute_mail_stage('end', array('sent' => (bool) $sent));

                $execute_mail_stage('teardown_start');

                if (isset($phpmailer) && is_object($phpmailer)) {
                    try {
                        if (method_exists($phpmailer, 'ClearAllRecipients')) {
                            $phpmailer->ClearAllRecipients();
                        }
                        if (method_exists($phpmailer, 'ClearAttachments')) {
                            $phpmailer->ClearAttachments();
                        }
                        if (method_exists($phpmailer, 'ClearReplyTos')) {
                            $phpmailer->ClearReplyTos();
                        }
                        if (method_exists($phpmailer, 'ClearCustomHeaders')) {
                            $phpmailer->ClearCustomHeaders();
                        }
                        if (method_exists($phpmailer, 'clearAddresses')) {
                            $phpmailer->clearAddresses();
                        }
                    } catch (Throwable $e) {
                        $execute_mail_stage('teardown_warning', array('error' => $e->getMessage()));
                    }
                }

                if (isset($altbody)) {
                    $altbody = null;
                }

                if (isset($newsletters_plaintext)) {
                    $newsletters_plaintext = null;
                }

                if (isset($orig_message)) {
                    $orig_message = null;
                }

                if (isset($wpml_message)) {
                    $wpml_message = null;
                }

                if (isset($wpml_textmessage)) {
                    $wpml_textmessage = null;
                }

                if (isset($message)) {
                    $message = null;
                }

                if (isset($attachments)) {
                    $attachments = null;
                }

                if (isset($subscriber)) {
                    $subscriber = null;
                }

                if (isset($user)) {
                    $user = null;
                }

                if (function_exists('gc_collect_cycles')) {
                    gc_collect_cycles();
                }

                $execute_mail_stage('teardown_complete');

                return $sent;
            }

            function log_error($error = null) {
                $debugging = get_option('tridebugging');
                $this->debugging = (empty($debugging)) ? $this->debugging : true;
    
                if (!empty($error)) {
                    // Recursively sanitize the input to handle arrays/objects
                    if (is_array($error) || is_object($error)) {
                        $error = $this->sanitize_recursive($error);
                        $error = '<pre>' . print_r($error, true) . '</pre>';
                    } else {
                        $error = sanitize_text_field($error); // Sanitize scalar values
                    }
    
                    error_log(date_i18n('[Y-m-d H:i:s] ') . $error . PHP_EOL, 3, NEWSLETTERS_LOG_FILE);
    
                    return true;
                }
    
                return false;
            }
    
            // Helper function to recursively sanitize arrays/objects
            private function sanitize_recursive($data) {
                if (is_array($data)) {
                    return array_map([$this, 'sanitize_recursive'], $data);
                } elseif (is_object($data)) {
                    foreach ($data as $key => $value) {
                        $data->$key = $this->sanitize_recursive($value);
                    }
                    return $data;
                } else {
                    return sanitize_text_field($data);
                }
            }

            /**
             * Prints a variable or an array encapsulated in PRE tags
             * Creates an easy to read hierarchy/structure
             *
             * @param ARRAY/STRING
             * @return BOOLEAN
             */
            function debug($var = array(), $output = true, $specialchars = false) {
                if ($output == false) { ob_start(); }
                $debugging = get_option('tridebugging');
                $this -> debugging = (empty($debugging)) ? $this -> debugging : true;

                if ($this -> debugging == true) {
                    if (!empty($specialchars) && $specialchars == true) {
                        echo '<pre>' . print_r(htmlspecialchars($var), true) . '</pre>';
                    } else {
                        echo '<pre>' . print_r($var, true) . '</pre>';
                    }
                }

                if ($output == false) {
                    $debug = ob_get_clean();
                    ob_end_clean();
                    return $debug;
                }

                return true;
            }

            function debug_trace($var = null) {
                $this -> debug($var);
                $this -> debug(array_reverse(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)));
            }

            function add_option($name = null, $value = null) {
                global $wpml_add_option_count;
                $value = apply_filters('newsletters_add_option', $value, $name);
                if (add_option($this -> pre . $name, $value)) {
                    $wpml_add_option_count++;
                    return true;
                }

                return false;
            }

            function update_option($name = null, $value = null) {
                $name = sanitize_text_field($name);
                $value = map_deep($value, 'wp_kses_post');

                $value = apply_filters('newsletters_update_option', $value, $name);
                if (update_option($this -> pre . $name, $value)) {
                    return true;
                }

                return false;
            }

            function get_managementpost($permalink = false, $autocreate = false, $language = null) {
                global $wpdb, $wp_rewrite, $newsletters_managementpost_error;
                $user_id = get_current_user_id();
                require_once(ABSPATH . WPINC . DS . 'rewrite.php');
                if (!is_object($wp_rewrite)) { $wp_rewrite = new WP_Rewrite(); }

                $language = (empty($language)) ? $this -> language_default() : $language;
                $managementpost = $this -> language_use($language, $this -> get_option('managementpost'));
                $managementpost = apply_filters('wpml_object_id', (int) $managementpost, 'page', true);

                $query = "SELECT `ID` FROM `" . $wpdb -> posts . "` WHERE `ID` = '" . esc_sql($managementpost) . "' AND `post_status` = 'publish'";

                $query_hash = md5($query);
                if ($ob_post = $this -> get_cache($query_hash)) {
                    $post = $ob_post;
                } else {
                    $post = $wpdb -> get_row($query);
                    $this -> set_cache($query_hash, $post);
                }

                if (empty($managementpost) || !$post || !get_post($managementpost)) {
                    if ($autocreate == true) {
                        $postdata = array(
                            'post_title'			=>	__('Manage Subscriptions', 'wp-mailinglist'),
                            'post_content'			=>	__('[newsletters_management]', 'wp-mailinglist'),
                            'post_type'				=>	"page",
                            'post_status'			=>	"publish",
                            'post_author'			=>	$user_id,
                            'comment_status'		=>	"closed",
                            'ping_status'			=>	"closed",
                        );

                        $post_id = wp_insert_post($postdata);
                        update_option($this -> pre . 'managementpost', $post_id);

                        if ($permalink == true) {
                            return get_permalink($post_id);
                        } else {
                            return $post_id;
                        }
                    } else {
                        if (is_admin() && !defined('DOING_AJAX')) {
                            if (!$newsletters_managementpost_error) {
                                $error = sprintf(__('Newsletter plugin subscriber management post/page does not exist %s', 'wp-mailinglist'), '<a href="' . wp_nonce_url(admin_url('admin.php?page=' . $this -> sections -> settings . '&method=managementpost'), $this -> sections -> settings . '_managementpost') . '" class="button button-secondary">' . __('please create it now', 'wp-mailinglist') . '</a>');
                                $this -> render_warning($error);
                                $newsletters_managementpost_error = true;
                            }
                        }
                    }
                } else {
                    if ($permalink == true) {
                        return get_permalink($post -> ID);
                    } else {
                        return $post -> ID;
                    }
                }

                return false;
            }

            function get_imagespost() {
                global $wpdb;
                $user_id = get_current_user_id();

                $imagespost = get_option($this -> pre . 'imagespost');
                $query = "SELECT `ID` FROM `" . $wpdb -> posts . "` WHERE `ID` = '" . esc_sql($imagespost) . "'";

                $query_hash = md5($query);
                if ($ob_post = $this -> get_cache($query_hash)) {
                    $post = $ob_post;
                } else {
                    $post = $wpdb -> get_row($query);
                    $this -> set_cache($query_hash, $post);
                }

                if (empty($imagespost) || !$post) {
                    $postdata = array(
                        'post_title'			=>	__('Newsletter Images (do not remove)', 'wp-mailinglist'),
                        'post_content'			=>	__('This is a placeholder for the Newsletter plugin images. You may edit and reuse this post but do not remove it.', 'wp-mailinglist'),
                        'post_type'				=>	"post",
                        'post_status'			=>	"draft",
                        'post_author'			=>	$user_id,
                    );

                    $post_id = wp_insert_post($postdata);
                    update_option($this -> pre . 'imagespost', $post_id);
                    return $post_id;
                } else {
                    return $post -> ID;
                }

                return false;
            }

            function get_option($name = null, $stripslashes = true) {
                switch ($name) {
                    case 'imagespost'			:
                        if ($imagespost = $this -> get_imagespost()) {
                            $this -> update_option('imagespost', $imagespost);
                        }
                        break;
                }

                /* if ($option = $this -> get_cache($name, 'option')) {
                        return $option;
                    } */

                if ($option = get_option($this -> pre . $name)) {
                    if (maybe_unserialize($option) !== false) {
                        $option = maybe_unserialize($option);
                    }

                    if ($stripslashes == true) {
                        $option = stripslashes_deep($option);
                    }

                    ${'newsletters_option_' . $name} = $option;
                    $option = apply_filters('newsletters_get_option', $option, $name);
                    $this -> set_cache($name, $option, 'option');
                    return $option;
                }

                return false;
            }

            function delete_option($name = null) {
                if (!empty($name)) {
                    if (delete_option($this -> pre . $name)) {
                        return true;
                    }
                }

                return false;
            }

            function ajax_latestposts_settings() {

                check_ajax_referer('latestposts_settings', 'security');

                if (current_user_can('newsletters_settings')) {
                    $this -> render('metaboxes' . DS . 'settings-latestposts', false, true, 'admin');
                } else {
                    echo __('You do not have permission', 'wp-mailinglist');
                }

                exit();
                die();
            }

            function ajax_latestposts_delete() {

                check_ajax_referer('latestposts_delete', 'security');

                if (current_user_can('newsletters_settings')) {
                    $id = sanitize_text_field($_GET['id']);
                    if (!empty($id)) {
                        if ($this -> Latestpostssubscription() -> delete($id)) {
                            echo 'success';
                        }
                    }
                }

                exit();
                die();
            }

            function ajax_latestposts_clearhistory() {

                check_ajax_referer('latestposts_clearhistory', 'security');

                $success = false;

                if (current_user_can('newsletters_settings')) {
                    $id = sanitize_text_field($_POST['id']);
                    if (!empty($id)) {
                        if ($this -> Latestpost() -> delete_all(array('lps_id' => $id))) {
                            $success = true;
                        } else {
                            $success = false;
                        }
                    } else {
                        $success = false;
                    }
                }

                echo json_encode(array('success' => $success));

                exit();
                die();
            }

            function ajax_load_new_editor() {
                define('DOING_AJAX', true);

                wp_enqueue_script('jquery');
                //meta boxes
                wp_enqueue_script('common', false, false, false, true);
                wp_enqueue_script('wp-lists', false, false, false, true);
                wp_enqueue_script('postbox', false, false, false, true);
                //editor
                wp_enqueue_script('editor', false, false, false, true);
                wp_enqueue_script('quicktags', false, false, false, true);
                wp_enqueue_script('wplink', false, false, false, true);
                wp_enqueue_script('wpdialogs-popup', false, false, false, true);
                wp_enqueue_style('wp-jquery-ui-dialog', false, false, false, true);
                wp_enqueue_script('word-count', false, false, false, true);
                wp_enqueue_script('media-upload', false, false, false, true);
                wp_admin_css();
                wp_enqueue_script('utils', false, false, false, true);

                ?>

                <div class="postbox" id="contentareabox<?php echo esc_attr($_REQUEST['contentarea']); ?>">
                    <div class="handlediv" title="Click to toggle"><br></div>
                    <h3 class="hndle"><span><?php echo __('Content Area', 'wp-mailinglist'); ?> <?php echo esc_html($_REQUEST['contentarea']); ?></span></h3>
                    <div class="inside">

                        <?php

                        wp_editor("", 'contentarea' . esc_attr($_REQUEST['contentarea']), array(
                            'textarea_name'				=>	'contentarea[' . esc_attr($_REQUEST['contentarea']) . ']',
                        ));

                        ?>

                        <table id="post-status-info" cellpadding="0" cellspacing="0">
                            <tbody>
                            <tr>
                                <td id="wp-word-count">
                                    <span id="word-count"><code>[newsletters_content id="<?php echo esc_attr($_REQUEST['contentarea']); ?>"]</code></span>
                                </td>
                                <td class="autosave-info">
                                    <span id="autosave" style="display:none;"></span>
                                </td>
                            </tr>
                            </tbody>
                        </table>
                        <p><a href="" onclick="if (confirm('<?php echo esc_js(__('Are you sure you want to remove this content area?', 'wp-mailinglist')); ?>')) { deletecontentarea('<?php echo esc_attr($_REQUEST['contentarea']); ?>', ''); } return false;" class="button button-secondary"><?php _e('Delete', 'wp-mailinglist'); ?></a></p>
                    </div>
                </div>

                <?php

                exit();
                die();
            }

            function ajax_latestposts_changestatus() {

                check_ajax_referer('latestposts_changestatus', 'security');

                $success = false;

                if (current_user_can('newsletters_settings')) {
                    if (!empty($_POST['id']) && !empty($_POST['status'])) {
                        $status = sanitize_text_field($_POST['status']);
                        $id = sanitize_text_field($_POST['id']);
                        if ($this -> Latestpostssubscription() -> save_field('status', $status, array('id' => $id))) {
                            $success = __('Status has been changed', 'wp-mailinglist');
                        }
                    }
                }

                $this -> render('metaboxes' . DS . 'settings-latestposts', array('success' => $success), true, 'admin');

                exit();
                die();
            }

            function ajax_latestposts_save() {
                $ajax = false;
                $success = false;

                if (!empty($_POST)) {
                    check_ajax_referer('newsletters_latestposts_save');
                    $ajax = true;

                    if (current_user_can('newsletters_settings')) {
                        foreach ($_POST as $pkey => $pval) {
                            if (!empty($pval) && is_array($pval)) {
                                $_POST[$pkey] = maybe_serialize($pval);
                            }
                        }

                        if ($this -> Latestpostssubscription() -> save($_POST)) {
                            $success = true;
                        } else {
                            $success = false;
                        }

                        $latestpostssubscription = $this -> Latestpostssubscription() -> data;
                    } else {
                        $success = false;
                    }
                } else {
                    $id = sanitize_text_field($_GET['id']);
                    if (!empty($id)) {
                        $latestpostssubscription = $this -> Latestpostssubscription() -> find(array('id' => $id));
                    }
                }

                $this -> render('latestposts-save', array('latestpostssubscription' => $latestpostssubscription, 'errors' => $this -> Latestpostssubscription() -> errors, 'success' => $success, 'ajax' => $ajax), true, 'admin');

                exit();
                die();
            }

            function ajax_latestposts_preview() {

                check_ajax_referer('latestposts_preview', 'security');

                if (current_user_can('newsletters_settings')) {
                    $id = sanitize_text_field($_GET['id']);
                    if ($content = $this -> latestposts_hook($id, true)) {
                        echo $content;
                    } else {
                        echo __('Latest posts preview could not load', 'wp-mailinglist');
                    }
                } else {
                    echo __('You do not have permission', 'wp-mailinglist');
                }

                exit(); die();
            }

            function ajax_lpsposts() {

                check_ajax_referer('lpsposts', 'security');

                if (!current_user_can('newsletters_settings')) {
                    wp_die(__('You do not have permission', 'wp-mailinglist'));
                }

                global $Db;

                $conditions = array();
                $id = (int) sanitize_text_field($_GET['id']);

                if (!empty($id)) {
                    $conditions['lps_id'] = $id;
                    $latestpostssubscription = $this -> Latestpostssubscription() -> find(array('id' => $id));
                }

                $posts = $this -> Latestpost() -> find_all($conditions, null, array('created', "DESC"));

                $this -> render('posts', array('posts' => $posts, 'latestpostssubscription' => $latestpostssubscription), true, 'admin');

                exit(); die();
            }

            function ajax_delete_lps_post() {

                check_ajax_referer('delete_lps_post', 'security');

                if (!current_user_can('newsletters_settings')) {
                    wp_die(__('You do not have permission', 'wp-mailinglist'));
                }

                global $Db;

                if (!empty($_POST['id'])) {
                    $this -> Latestpost() -> delete(sanitize_text_field($_POST['id']));
                }

                exit(); die();
            }

            function get_latestposts_used($latestpostssubscription = null) {
                global $wpdb, $Db;

                if (!empty($latestpostssubscription)) {
                    $count = $this -> Latestpost() -> count(array('lps_id' => $latestpostssubscription -> id));
                    return $count;
                }

                return 0;
            }

            function latestposts_normalize_categories($categories = array()) {
                if ($categories === 'all') {
                    return 'all';
                }

                if (!is_array($categories)) {
                    $categories = maybe_unserialize($categories);
                }

                if (!is_array($categories)) {
                    return array();
                }

                $language_categories = array();
                $flat_categories = array();
                $has_language_keys = false;

                foreach ($categories as $key => $value) {
                    $values = array_filter(array_map('absint', (array) $value));
                    if (empty($values)) {
                        continue;
                    }

                    if (is_string($key)) {
                        $has_language_keys = true;
                        $language_categories[sanitize_key($key)] = array_values($values);
                    } else {
                        $flat_categories = array_merge($flat_categories, $values);
                    }
                }

                if ($has_language_keys) {
                    return $language_categories;
                }

                return array_values($flat_categories);
            }

            function latestposts_categories_for_language($categories = array(), $language = '') {
                if ($categories === 'all') {
                    return 'all';
                }

                $normalized = $this -> latestposts_normalize_categories($categories);

                if (!is_array($normalized) || empty($normalized)) {
                    return array();
                }

                $has_language_keys = false;
                foreach ($normalized as $key => $value) {
                    if (is_string($key)) {
                        $has_language_keys = true;
                        break;
                    }
                }

                if ($has_language_keys) {
                    if (!empty($language) && !empty($normalized[$language])) {
                        return $normalized[$language];
                    }

                    return array();
                }

                return $normalized;
            }

            function get_latestposts($latestpostssubscription = null) {
                global $wpdb, $post, $Db, $Html, $Mailinglist, $Subscriber, $SubscribersList;
                $post_criteria = false;

                if (!empty($latestpostssubscription)) {
                    $exclude = array();
                    if (!empty($latestpostssubscription -> exclude)) {
                        if (($exclude = @explode(",", $latestpostssubscription -> exclude)) !== false) {
                            //exclude array exists…
                            foreach ($exclude as $exkey => $exval) {
                                $exclude[$exkey] = trim($exval);
                            }
                        }
                    }

                    $order = (!empty($latestpostssubscription -> order)) ? $latestpostssubscription -> order : "DESC";
                    $orderby = (!empty($latestpostssubscription -> orderby)) ? $latestpostssubscription -> orderby : "date";

                    $post_criteria = array(
                        'numberposts'			=>	$latestpostssubscription -> number,
                        'orderby'				=>	$orderby,
                        'order'					=>	$order,
                        'exclude'				=>	$exclude,
                        'post_type'				=>	"post",
                        'post_status'			=>	"publish",
                    );

                    if (!empty($latestpostssubscription -> categories) && $latestpostssubscription -> categories != "all") {
                        $language_categories = $this -> latestposts_categories_for_language($latestpostssubscription -> categories, $latestpostssubscription -> language);

                        if (!empty($language_categories) && is_array($language_categories)) {
                            $post_criteria['category'] = @implode(",", $language_categories);
                        }
                    }

                    if (!empty($latestpostssubscription -> takefrom)) {
                        if ($latestpostssubscription -> takefrom == "posttypes") {
                            $post_criteria['category'] = 0;
                            $post_criteria['post_type'] = maybe_unserialize($latestpostssubscription -> posttypes);
                        } elseif ($latestpostssubscription -> takefrom == "pages") {
                            $post_criteria['post_type'] = "page";
                        }
                    }

                    $latestpostsquery = "SELECT id, post_id FROM " . $wpdb -> prefix . $this -> Latestpost() -> table . " WHERE `lps_id` = '" . $latestpostssubscription -> id . "'";
                    $latestposts = $wpdb -> get_results($latestpostsquery);

                    if (!empty($latestposts)) {
                        foreach ($latestposts as $latestpost) {
                            if (!empty($post_criteria['exclude'])) {
                                $post_criteria['exclude'][] = $latestpost -> post_id;
                            } else {
                                $post_criteria['exclude'][] = $latestpost -> post_id;
                            }
                        }
                    }

                    $olderthanquery = "SELECT ID FROM " . $wpdb -> posts . " WHERE post_date < '" . date_i18n("Y-m-d H:i:s", strtotime($latestpostssubscription -> olderthan)) . "'";
                    $olderthan = $wpdb -> get_results($olderthanquery);

                    if (!empty($olderthan)) {
                        foreach ($olderthan as $olderthanpost) {
                            $post_criteria['exclude'][] = $olderthanpost -> ID;
                        }
                    }

                    $post_criteria['suppress_filters'] = 0;
                }

                return apply_filters('newsletters_latest_posts_criteria', $post_criteria);
            }

            function updating_plugin() {
                if (!is_admin() && !defined('DOING_AJAX')) return;

                if (defined('NEWSLETTERS_UPDATING')) {
                    return;
                }

                define('NEWSLETTERS_UPDATING', true);

                $dbversion = $this -> get_option('dbversion');
                if (empty($dbversion)) {
                    $this -> add_option('dbversion', $this -> dbversion);
                }

                if (!$this -> get_option('version')) {
                    $this -> add_option('version', $this -> version);
                    $this -> update_options();
                    return;
                }

                $cur_dbversion = $this -> get_option('dbversion');
                if (version_compare($cur_dbversion, $this -> dbversion) < 0) {
                    $this -> update_option('showmessage_dbupdate', true);
                }

                $cur_version = $this -> get_option('version');
                $version = $this -> version;

                if (version_compare($this -> version, $cur_version) === 1) {
                    if (version_compare("3.8.4", $cur_version) === 1) {
                        if (!empty($this -> classes)) {
                            global $wpdb;
                            $this -> update_options();
                            $this -> initialize_classes();

                            foreach ($this -> classes as $class_name) {
                                global ${$class_name};

                                $query = "ALTER TABLE `" . $wpdb -> prefix . "" . $this -> pre . "" . ${$class_name} -> controller . "` ENGINE=MyISAM AUTO_INCREMENT=1 CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
                                $wpdb -> query($query);

                                if (!empty(${$class_name} -> tv_fields)) {
                                    foreach (${$class_name} -> tv_fields as $table_field_name => $table_field_attributes) {
                                        if (!empty($table_field_name) && $table_field_name != "key") {
                                            if (!preg_match("/(INT|DATETIME)/si", $table_field_attributes[0])) {
                                                $query = "ALTER TABLE `" . $wpdb -> prefix . "" . $this -> pre . "" . ${$class_name} -> controller . "` CHANGE `" . $table_field_name . "` `" . $table_field_name . "` " . $table_field_attributes[0] . " CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci " . $table_field_attributes[1] . ";";
                                                $wpdb -> query($query);
                                            }
                                        }
                                    }
                                }
                            }

                            global $wpdb, $Theme;
                            $wpdb -> flush();

                            $db_queries = array(
                                "ALTER TABLE `" . $wpdb -> prefix . "" . $this -> History() -> table . "` CHANGE `message` `message` LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL",
                                "ALTER TABLE `" . $wpdb -> prefix . "" . $this -> Template() -> table . "` CHANGE `content` `content` LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL",
                                "ALTER TABLE `" . $wpdb -> prefix . "" . $Theme -> table . "` CHANGE `content` `content` LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL",
                            );

                            foreach ($db_queries as $db_query) {
                                $wpdb -> query($db_query);
                            }
                        }

                        $version = "3.8.4";
                    } elseif (version_compare("3.8.4.1", $cur_version) === 1) {
                        $this -> update_options();
                        $version = "3.8.4.1";
                    } elseif (version_compare("3.8.5.1", $cur_version) === 1) {
                        $this -> update_options();
                        $version = "3.8.5.1";
                    } elseif (version_compare("3.8.6", $cur_version) === 1) {
                        $this -> update_options();

                        /* Currencies */
                        global $currencies;
                        require_once $this -> plugin_base() . DS . 'includes' . DS . 'currencies.php';
                        $this -> update_option('currencies', $currencies);

                        /* Permissions */
                        $permissions = maybe_unserialize($this -> get_option('permissions'));
                        $permissions['autoresponders'] = 10;
                        $this -> update_option('permissions', $permissions);

                        $this -> update_option('sendnewsletteronsubscribe', "N");
                        $version = "3.8.6";
                    } elseif (version_compare("3.8.7", $cur_version) === 1) {
                        $this -> update_options();

                        $permissions = maybe_unserialize($this -> get_option('permissions'));
                        $permissions['groups'] = "10";
                        $this -> update_option('permissions', $permissions);
                        $this -> get_managementpost();

                        global $wpdb, $Theme;
                        $wpdb -> flush();

                        $db_queries = array(
                            "ALTER TABLE `" . $wpdb -> prefix . "" . $this -> History() -> table . "` CHANGE `message` `message` LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL",
                            "ALTER TABLE `" . $wpdb -> prefix . "" . $this -> Template() -> table . "` CHANGE `content` `content` LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL",
                            "ALTER TABLE `" . $wpdb -> prefix . "" . $Theme -> table . "` CHANGE `content` `content` LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL",
                            "ALTER TABLE `" . $wpdb -> prefix . $this -> Autoresponderemail() -> table . "` ADD UNIQUE INDEX (subscriber_id, autoresponder_id)",
                        );

                        foreach ($db_queries as $db_query) {
                            $wpdb -> query($db_query);
                        }

                        $version = '3.8.7';
                    } elseif (version_compare("3.8.7.2", $cur_version) === 1) {
                        $this -> update_options();
                        $version = '3.8.7.2';
                    }

                    if (version_compare($cur_version, "3.8.9.2") < 0) {
                        $this -> update_options();
                        $this -> initialize_default_themes();

                        global $wpdb, $Db, $Theme;
                        $themesquery = "SELECT * FROM " . $wpdb -> prefix . $Theme -> table . "";
                        if ($themes = $wpdb -> get_results($themesquery)) {
                            foreach ($themes as $theme) {
                                $newcontent = "";
                                ob_start();
                                echo do_shortcode(wp_unslash($theme -> content));
                                $newcontent = ob_get_clean();

                                $themequery = "UPDATE `" . $wpdb -> prefix . $Theme -> table . "` SET `content` = '" . esc_sql($newcontent) . "' WHERE `id` = '" . $theme -> id . "'";
                                $wpdb -> query($themequery);
                            }
                        }

                        $version = "3.8.9.2";
                    }

                    if (version_compare($cur_version, "3.8.9.4") < 0) {
                        global $wpdb, $Mailinglist;
                        $this -> update_options();

                        $intervals = array(
                            'daily'			=>	__('Daily', 'wp-mailinglist'),
                            'weekly'		=>	__('Weekly', 'wp-mailinglist'),
                            'monthly'		=>	__('Monthly', 'wp-mailinglist'),
                            '2months'		=>	__('Every Two Months', 'wp-mailinglist'),
                            '3months'		=>	__('Every Three Months', 'wp-mailinglist'),
                            'biannually'	=>	__('Twice Yearly (Six Months)', 'wp-mailinglist'),
                            '9months'		=>	__('Every Nine Months', 'wp-mailinglist'),
                            'yearly'		=>	__('Yearly', 'wp-mailinglist'),
                            'once'			=>	__('Once Off', 'wp-mailinglist'),
                        );

                        $this -> update_option('intervals', $intervals);

                        $query = "ALTER TABLE `" . $wpdb -> prefix . $Mailinglist -> table . "` CHANGE `interval` `interval` ENUM('daily', 'weekly', 'monthly', '2months', '3months', 'biannually', '9months', 'yearly', 'once') NOT NULL DEFAULT 'monthly';";
                        $wpdb -> query($query);

                        $version = "3.8.9.4";
                    }

                    if (version_compare($cur_version, "3.9") < 0) {
                        $this -> update_options();
                        $this -> initialize_default_themes();

                        global $wpdb, $Db, $Theme;
                        $themesquery = "SELECT * FROM " . $wpdb -> prefix . $Theme -> table . "";
                        if ($themes = $wpdb -> get_results($themesquery)) {
                            foreach ($themes as $theme) {
                                $newcontent = "";
                                ob_start();
                                $newcontent = ob_get_clean();
                                $themequery = "UPDATE `" . $wpdb -> prefix . $Theme -> table . "` SET `content` = '" . esc_sql($newcontent) . "' WHERE `id` = '" . $theme -> id . "'";
                                //$wpdb -> query($themequery);
                            }
                        }

                        $version = "3.9";
                    }

                    if (version_compare($cur_version, "3.9.4") < 0) {
                        global $wpdb;
                        $this -> update_options();

                        /* convert database tables to MyISAM */
                        if (!empty($this -> tablenames)) {
                            foreach ($this -> tablenames as $tablename) {
                                $query = "ALTER TABLE `" . $tablename . "` ENGINE=MyISAM;";
                                $wpdb -> query($query);
                            }
                        }

                        /* Auto import WordPress users */
                        if ($importuserslist = $this -> get_option('importuserslist')) {
                            $this -> update_option('importuserslists', array($importuserslist));
                        }

                        $version = "3.9.4";
                    }

                    if (version_compare($cur_version, "3.9.9") < 0) {
                        global $wpdb, $Field;
                        $this -> update_options();
                        $wpdb -> query("ALTER TABLE `" . $wpdb -> prefix . $Field -> table . "` CHANGE `type` `type` VARCHAR(255) NOT NULL DEFAULT 'text'");
                        $version = "3.9.9";
                    }

                    if (version_compare($cur_version, "4.4.4") < 0) {
                        $this -> update_options();

                        $latestposts = $this -> get_option('latestposts');
                        if (!empty($latestposts) && $latestposts == "Y") {
                            $latestpostssubscription = array(
                                'subject'				=>	$this -> get_option('latestposts_subject'),
                                'number'				=>	$this -> get_option('latestposts_number'),
                                'language'				=>	$this -> get_option('latestposts_language'),
                                'takefrom'				=>	$this -> get_option('latestposts_takefrom'),
                                'posttypes'				=>	maybe_serialize($this -> get_option('latestposts_posttypes')),
                                'categories'			=>	maybe_serialize($this -> get_option('latestposts_categories')),
                                'groupbycategory'		=>	$this -> get_option('latestposts_groupbycategory'),
                                'exclude'				=>	$this -> get_option('latestposts_exclude'),
                                'order'					=>	$this -> get_option('latestposts_order'),
                                'orderby'				=>	$this -> get_option('latestposts_orderby'),
                                'olderthan'				=>	$this -> get_option('latestposts_olderthan'),
                                'lists'					=>	maybe_serialize($this -> get_option('latestposts_lists')),
                                'startdate'				=>	$this -> get_option('latestposts_startdate'),
                                'interval'				=>	$this -> get_option('latestposts_interval'),
                                'theme_id'				=>	$this -> get_option('latestposts_theme'),
                            );

                            $this -> Latestpostssubscription() -> save($latestpostssubscription);
                            $this -> latestposts_scheduling($latestpostssubscription['interval'], $latestpostssubscription['startdate'], array((int) $this -> Latestpostssubscription() -> insertid));
                        }

                        // Set the 'rel_id' field on fieldslists table as AUTO_INCREMENT
                        global $wpdb, $Db, $FieldsList;
                        $query = "ALTER TABLE " . $wpdb -> prefix . $this -> Latestpost() -> table . " CHANGE `post_id` `post_id` INT(11) NOT NULL DEFAULT '0'";
                        $wpdb -> query($query);
                        $query = "ALTER TABLE " . $wpdb -> prefix . $FieldsList -> table . " CHANGE `rel_id` `rel_id` INT(11) NOT NULL AUTO_INCREMENT";
                        $wpdb -> query($query);

                        $version = '4.4.4';
                    }

                    if (version_compare($cur_version, "4.4.6.1") < 0) {
                        global $wpdb, $Db;

                        $this -> update_options();

                        $query = "ALTER TABLE `" . $wpdb -> prefix . $this -> Latestpost() -> table . "` DROP INDEX `post_id`";
                        $wpdb -> query($query);

                        $version = '4.4.6.1';
                    }

                    if (version_compare($cur_version, "4.5.4.2") < 0) {
                        global $wpdb;
                        $this -> update_options();

                        //update the theme folder to default
                        $this -> update_option('theme_folder', "default");
                        $this -> theme_folder_functions();
                        include($this -> plugin_base() . DS . 'includes' . DS . 'variables.php');
                        $stylesdone = false;
                        $scriptsdone = false;

                        if (!empty($defaultstyles)) {
                            $loadstyles = array();
                            foreach ($defaultstyles as $handle => $style) {
                                $loadstyles[] = $handle;
                            }
                            $this -> update_option('loadstyles', $loadstyles);
                            $stylesdone = true;
                        }
                        if (!empty($defaultscripts)) {
                            $loadscripts = array();
                            foreach ($defaultscripts as $handle => $script) {
                                $loadscripts[] = $handle;
                            }
                            $this -> update_option('loadscripts', $loadscripts);
                            $scriptsdone = true;
                        }

                        if (!empty($stylesdone) && !empty($scriptsdone)) {
                            // all done, update the version
                            $version = '4.5.4.2';
                        }
                    }

                    if (version_compare($cur_version, "4.5.5.4.4") < 0) {
                        global $wpdb, $Subscriber, $SubscribersList;
                        $this -> update_options();

                        // Change of 'bootstrap' to 'newsletters-bootstrap' handle
                        $this -> theme_folder_functions();
                        include($this -> plugin_base() . DS . 'includes' . DS . 'variables.php');
                        $loadstyles = $this -> get_option('loadstyles');
                        if (!empty($loadstyles) && in_array('bootstrap', $loadstyles)) {
                            $loadstyles[] = 'newsletters-bootstrap';
                            $this -> update_option('loadstyles', $loadstyles);
                        }

                        /* Unique 'email' column stuff */
                        $subscribers_table = $wpdb -> prefix . $Subscriber -> table;
                        $subscriberslists_table = $wpdb -> prefix . $SubscribersList -> table;
                        // Delete duplicate subscribers and only keep the one with the smallest ID value
                        $query = "DELETE n1 FROM `" . $subscribers_table . "` n1, `" . $subscribers_table . "` n2 WHERE n1.id > n2.id AND n1.email = n2.email";
                        $wpdb -> query($query);
                        // Remove empty associations
                        $query = "DELETE FROM `" . $subscriberslists_table . "` WHERE `subscriber_id` NOT IN (SELECT `id` FROM `" . $subscribers_table . "`)";
                        $wpdb -> query($query);
                        // Make the 'email' column a unique index/key to prevent duplicates
                        $query = "ALTER TABLE  `" . $subscribers_table . "` ADD UNIQUE KEY `email_unique` (`email`)";
                        $wpdb -> query($query);

                        $version = '4.5.5.4.4';
                    }

                    if (version_compare($cur_version, "4.5.5.9") < 0) {
                        $this -> update_options();

                        $loadscripts = $this -> get_option('loadscripts');
                        $loadscripts[] = 'jquery-form';
                        $this -> update_option('loadscripts', $loadscripts);

                        $version = "4.5.5.9";
                    }

                    if (version_compare($cur_version, "4.6.3") < 0) {
                        $this -> update_options();

                        $paymentmethod = $this -> get_option('paymentmethod');
                        $this -> update_option('paymentmethod', array($paymentmethod));

                        // Update the "Posts" and "Latest Posts" templates
                        include($this -> plugin_base() . DS . 'includes' . DS . 'email-templates.php');

                        $current_posts = $this -> get_option('etmessage_posts');
                        if (!preg_match("/(newsletters_post_anchor)/si", $current_posts)) {
                            $this -> update_option('etmessage_posts_backup', $current_posts);
                            $this -> update_option('etmessage_posts', $email_templates['posts']['message']);
                        }

                        $current_latestposts = $this -> get_option('etmessage_latestposts');
                        if (!preg_match("/(newsletters_post_anchor)/si", $current_latestposts)) {
                            $this -> update_option('etmessage_latestposts_backup', $current_latestposts);
                            $this -> update_option('etmessage_latestposts', $email_templates['latestposts']['message']);
                        }

                        $version = "4.6.3";
                    }

                    if (version_compare($cur_version, "4.6.4") < 0) {

                        global $wpdb, $Email, $Subscriber;

                        $this -> update_options();
                        $this -> predefined_templates();

                        $queries = array();

                        // Update the read_date column of emails with the modified date where empty
                        $queries[] = "UPDATE `" . $wpdb -> prefix . $Email -> table . "` SET `read_date` = `modified` WHERE `read_date` IS NULL;";

                        // Update messageid database field on emails table to VARCHAR for indexing
                        $this -> change_field($Email -> table, 'messageid', 'messageid', "VARCHAR(255) NOT NULL DEFAULT ''");

                        // Change all tables and their fields to utf8mb4_unicode_ci collation
                        if (!empty($this -> tables_tv)) {
                            foreach ($this -> tables_tv as $tablename => $tablefields) {
                                $queries[] = "ALTER TABLE `" . $wpdb -> prefix . $tablename . "` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;";

                                foreach ($tablefields as $field => $attributes) {
                                    if (!empty($field) && $field != "key") {
                                        if (!preg_match("/(INT|DATETIME|FLOAT)/si", $attributes[0])) {
                                            $queries[] = "ALTER TABLE `" . $wpdb -> prefix . $tablename . "` CHANGE `" . $field . "` `" . $field . "` " . $attributes[0] . " CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci " . $attributes[1] . ";";
                                        }
                                    }
                                }
                            }
                        }

                        if (!empty($queries)) {
                            foreach ($queries as $query) {
                                $this -> dbupdate_process -> push_to_queue($query);
                            }

                            $this -> dbupdate_process -> save();
                            $this -> dbupdate_process -> dispatch();
                        }

                        $version = '4.6.4';
                    }

                    if (version_compare($cur_version, "4.6.6.1") < 0) {
                        $this -> update_options();
                        $this -> initialize_default_themes();

                        // Update the default styling settings on all forms
                        if ($forms = $this -> Subscribeform() -> find_all()) {
                            foreach ($forms as $form) {
                                $formstyling = maybe_unserialize($form -> styling);
                                $defaults = $this -> Subscribeform() -> defaults();
                                $defaultstyling = $defaults['styling'];

                                if (empty($formstyling)) {
                                    $this -> Subscribeform() -> save_field('styling', maybe_serialize($defaultstyling), array('id' => $form -> id));
                                } else {
                                    foreach ($defaultstyling as $stylekey => $stylevalue) {
                                        if (!isset($formstyling[$stylekey])) {
                                            $formstyling[$stylekey] = $stylevalue;
                                        }
                                    }
                                    $this -> Subscribeform() -> save_field('styling', maybe_serialize($formstyling), array('id' => $form -> id));
                                }
                            }
                        }

                        $version = '4.6.6.1';
                    }

                    if (version_compare($cur_version, "4.6.6.2") < 0) {
                        $this -> update_options();

                        $loadscripts = $this -> get_option('loadscripts');
                        $loadscripts[] = 'recaptcha';
                        $this -> update_option('loadscripts', $loadscripts);

                        global $wpdb, $Theme;
                        $query = "ALTER TABLE `" . $wpdb -> prefix . $Theme -> table . "` CHANGE `type` `type` ENUM('upload','paste','builder') NOT NULL DEFAULT 'paste';";
                        $wpdb -> query($query);

                        $version = '4.6.6.2';
                    }

                    if (version_compare($cur_version, "4.6.22") < 0) {
                        $this -> update_options();
                        $this -> check_tables();
                        $this -> initialize_default_themes();

                        // Insert mailing list slugs
                        global $Mailinglist, $Db, $Html;
                        if ($mailinglists = $Mailinglist -> select()) {
                            foreach ($mailinglists as $list_id => $list_title) {
                                $slug = $Html -> sanitize($list_title);
                                $Db -> model = $Mailinglist -> model;
                                $Db -> save_field('slug', $slug, array('id' => $list_id));
                            }
                        }

                        // Reload the countries with country codes
                        global $wpdb;
                        $query = "TRUNCATE TABLE `" . $wpdb -> prefix . $this -> Country() -> table . "`";
                        $wpdb -> query($query);
                        include($this -> plugin_base() . DS . 'vendors' . DS . 'sql.countries.php');
                        $wpdb -> query($countriesquery);

                        $version = '4.7.1';
                    }

                    if (version_compare($cur_version, "4.7.9.2") < 0) {

                        if (empty(get_option('unsubscribewpuserdelete'))) {
                            $this -> add_option('unsubscribewpuserdelete', 'N');
                        }

                        $version = '4.7.9.2';
                    }


                    if (version_compare($cur_version, "4.7.9.7") < 0) {

                        if (empty(get_option('unsubscribewpuserdeletebyuser'))) {
                            $this -> add_option('unsubscribewpuserdeletebyuser', 'N');
                        }

                        $version = '4.7.9.7';
                    }

                    if (version_compare($cur_version, "4.8.1") < 0) {
                        global $wpdb;

                        $query = "ALTER TABLE `" . $wpdb -> prefix . $this -> History() -> table . "`
                                    ADD COLUMN builderon LONGTEXT NULL AFTER modified ";
                        $wpdb -> query($query);
                        $query = "ALTER TABLE `" . $wpdb -> prefix . $this -> History() -> table . "`
                                    ADD COLUMN grapejs_content LONGTEXT NULL ";
                        $wpdb -> query($query);
                        $query = "ALTER TABLE `" . $wpdb -> prefix . $this -> History() -> table . "`
                                ADD COLUMN using_grapeJS INT(1) NOT NULL DEFAULT '0'";
                        $wpdb -> query($query);


                        $version = '4.8.1';
                    }


                    if (version_compare($cur_version, "4.8.2") < 0) {
                        global $wpdb;
                        $query = "Delete from  `" . $wpdb -> prefix .  "options` where `option_name` like '_transient_%process_lock'";
                        $wpdb -> query($query);

                        $query = "Delete from  `" . $wpdb -> prefix .  "options` where `option_name` like '_transient_%newsletter%'";
                        $wpdb -> query($query);

                        $version = '4.8.2';
                    }


                    if (version_compare($cur_version, "4.9.7") < 0) {
                        global $wpdb, $Subscriber;

                        $query = "ALTER TABLE `" . $wpdb -> prefix . $Subscriber -> table  . "`
                                    ADD COLUMN is_active ENUM('Y','N') NOT NULL DEFAULT 'N' AFTER referer ";
                        $wpdb -> query($query);

                        $version = '4.9.7';
                    }


                    if (version_compare($cur_version, $this->version) < 0) {
                        $version = $this->version;
                    }

                    //the current version is older.
                    //let's update the database
                    $this -> update_option('version', $version);
                }
            }

            function update_options() {
                if (!is_admin() && !defined('DOING_AJAX')) return;
                $this -> check_tables();
                $this -> get_managementpost(false, true);

                global $wpml_add_option_count, $wpdb, $Field, $Theme;
                $wpml_add_option_count = 0;

                $options = array();
                $options['defaulttemplate'] = true;
                $options['old_folder_name'] = "newsletters-lite";
                $options['screenoptions_subscribers_custom'] = array('gravatars', 'device');

                // Import settings
                $options['import_notification'] = true;
                $options['import_createfieldoptions'] = true;

                $options['managementloginsubject'] = __('Authenticate Subscriber Account', 'wp-mailinglist');
                $options['authenticatelinktext'] = __('Authenticate now', 'wp-mailinglist');
                $options['managementauthtype'] = 3;
                $options['managementallowemailchange'] = "Y";
                $options['managementformatchange'] = "Y";
                $options['managementallownewsubscribes'] = "Y";
                $options['managementshowsubscriptions'] = "Y";
                $options['managementdelete'] = true;
                $options['managementcustomfields'] = "Y";
                $options['cookieformat'] = "D, j M Y H:i:s";
                $options['defaultlistcreated'] = "N";
                $options['subscriptionmessage'] = __('Subscription Successful', 'wp-mailinglist');
                $options['sendingprogress'] = "N";
                $options['createpreview'] = "Y";
                $options['createspamscore'] = "Y";
                $options['emailencoding'] = "8bit";
                $options['clicktrack'] = "Y";
                $options['shortlinks'] = "N";
                $options['theme_folder'] = "default2";
                $options['theme_usestyle'] = "Y";
                $options['customcss'] = "N";
                $options['multimime'] = "N"; //should multi mime (text/html) emails be sent?
                $options['videoembed'] = true;
                $options['mailtype'] = 'mail';
                $options['smtphost'] = 'mail.example.com';
                $options['smtpport'] = 25;
                $options['smtpsecure'] = "N";
                $options['smtpauth'] = 'N';
                $options['smtpuser'] = __('username', 'wp-mailinglist');
                $options['smtppass'] = __('password', 'wp-mailinglist');
                $options['adminemail'] = get_option('admin_email');
                $options['smtpfrom'] = get_option('admin_email');
                $options['smtpreply'] = get_option('admin_email');
                $options['smtpfromname'] = get_option('blogname');
                $options['dkim'] = "N";
                $options['dkim_domain'] = "example.com";
                $options['dkim_selector'] = "newsletters";
                $options['tracking'] = "Y";
                $options['tracking_image'] = "invisible";
                $options['tracking_image_alt'] = "track";
                $options['servertype'] = 'cpanel';
                $options['mailpriority'] = 3; //set the mail priority to "Normal"
                $options['unsubscribeondelete'] = 'N';
                $options['unsubscribeemails'] = "single";
                $options['unsubscribeconfirmation'] = "Y";
                $options['unsubscribecomments'] = "Y";
                $options['registercheckbox'] = 'Y';
                $options['registerformlabel'] = __('Receive news updates via email from this site', 'wp-mailinglist');
                $options['checkboxon'] = 'N';
                $options['autosubscribelist'] = array(1);
                $options['sendonpublish'] = 'Y';
                $options['sendonpublishef'] = 'ep';
                $options['postswpautop'] = true;
                $options['sendonpublishexcerptlength'] = 250;
                $options['resubscribe'] = 1;
                $options['resubscribetext'] = __('Resubscribe', 'wp-mailinglist');
                $options['unsubscribetext'] = __('Unsubscribe from this newsletter', 'wp-mailinglist');
                $options['unsubscribealltext'] = __('Unsubscribe from all emails', 'wp-mailinglist');
                $options['unsubscribedelete'] = "N";
                $options['unsubscribewpuserdelete'] = "N";
                $options['unsubscribewpuserdeletebyuser'] = "N";
                $options['saveipaddress'] = true;
                $options['adminemailonsubscription'] = 'Y';
                $options['adminemailonunsubscription'] = 'Y';
                $options['activationlinktext'] = __('Confirm Subscription', 'wp-mailinglist');
                $options['customactivateredirect'] = "N";
                $options['activateredirecturl'] = home_url();
                $options['managelinktext'] = __('Manage Subscriptions', 'wp-mailinglist');
                $options['onlinelinktext'] = __('View in your browser', 'wp-mailinglist');
                $options['printlinktext'] = __('Print Email', 'wp-mailinglist');
                $options['autoresponderscheduling'] = "hourly";
                $options['tinymcebtn'] = "Y";
                $options['sendasnewsletterbox'] = "Y";
                $options['subscriberegister'] = "N";
                $options['custompostslug'] = "newsletter";
                $options['importusers'] = "N";
                $options['importusersscheduling'] = "hourly";
                $options['importuserslists'] = array(1);
                $options['importusersrequireactivate'] = "N";
                $options['subscriptions'] = "Y";
                $options['paidsubscriptionredirect'] = "Y";
                $options['rssfeed'] = "N";
                $options['language_location'] = 'langdir';
                $options['deleteonbounce'] = 'Y';
                $options['bouncecount'] = 3;
                $options['adminemailonbounce'] = 'Y';
                $options['bounceemail'] = get_option('admin_email');
                $options['bouncemethod'] = "off";
                $options['bouncepop_interval'] = "3600";
                $options['bouncepop_type'] = "imap";
                $options['bouncepop_host'] = "localhost";
                $options['bouncepop_user'] = "bounce@example.com";
                $options['bouncepop_pass'] = "mailboxpassword";
                $options['bouncepop_port'] = "110";
                $options['bouncepop_prot'] = "normal";
                $options['subscriberexistsredirect'] = "management";
                $options['subscriberexistsmessage'] = __('You are already subscribed, redirecting to the management page...', 'wp-mailinglist');
                $options['subscriberexistsredirecturl'] = get_permalink($this -> get_managementpost());
                $options['emailvalidationextended'] = 0;
                $options['requireactivate'] = 'Y';
                $options['activateaction'] = "none";
                $options['activatereminder'] = 3;
                $options['activatedelete'] = 7;
                $options['activationemails'] = "single";
                $options['tcodemo'] = 'N';
                $options['tcovendorid'] = '123456';
                $options['tcosecret'] = __('secretstring', 'wp-mailinglist');
                $options['tcoaccount'] = "live";
                $options['adminordernotify'] = 'Y';
                $options['subscriberedirect'] = "N";
                $options['subscriberedirecturl'] = $this -> get_managementpost(true);
                $options['paymentmethod'] = array('2co', 'paypal');
                $options['csvdelimiter'] = ",";
                $options['captcha_type'] = ($this -> is_plugin_active('captcha')) ? 'rsc' : 'none';
                $options['recaptcha_type'] = "robot";
                $options['recaptcha_theme'] = "light";
                $options['recaptcha_language'] = "en";
                $options['recaptcha_customcss'] = '.recaptcha_widget { margin: 10px 0 15px 0; }
                    .recaptcha_widget .recaptcha_image { margin: 10px 0 5px 0; }
                    .recaptcha_widget .recaptcha_image img { width: 250px; box-shadow: none; }
                    .recaptcha_widget .recaptcha_links { font-size: 85%; }
                    .recaptcha_widget .recaptcha_response { }';
                $options['captcha_rgb'] = array(255, 255, 255);
                $options['captcha_bg'] = "#FFFFFF";
                $options['captcha_fg'] = "#333333";
                $options['farbtastic_fg'] = "#000000";
                $options['captcha_size'] = array('w' => 72, 'h' => 24);
                $options['captcha_chars'] = "4";
                $options['captcha_font'] = "14";
                $options['captchainterval'] = "hourly";

                $options['recaptcha_publickey']  = '';
                $options['recaptcha_privatekey'] = '';

                $options['recaptcha3_publickey']  = '';
                $options['recaptcha3_privatekey'] = '';
                $options['recaptcha3_score'] = "0.5";

                $this -> captchacleanup_scheduling();
                $options['commentformcheckbox'] = "Y";
                $options['commentformlabel'] = __('Receive news updates via email from this site', 'wp-mailinglist');
                $options['commentformautocheck'] = "N";
                $options['commentformlist'] = "1";
                $options['excerpt_settings'] = 1;
                $options['excerpt_length'] = 55;
                $options['excerpt_more'] = __('Read more', 'wp-mailinglist');
                $options['timezone_set'] = 0;
                $options['croninterval'] = "5minutes";

                // Email scheduling settings
                $options['scheduleinterval'] = "1minute";
                $options['scheduleintervalseconds'] = 60;
                $options['emailsperinterval'] = 99;

                $options['paypalemail'] = get_option('admin_email');
                $options['paypalsubscriptions'] = "N";
                $options['paypalsandbox'] = "N";
                $options['paypalliveurl'] = "https://www.paypal.com/cgi-bin/webscr";
                $options['paypalsandurl'] = "https://www.sandbox.paypal.com/cgi-bin/webscr";
                $options['countriesinserted'] = "N";
                $options['generalredirect'] = $this -> get_managementpost(true);
                $options['offsitetitle'] = get_bloginfo('name');
                $options['offsitelist'] = 'checkboxes';
                $options['offsitewidth'] = 400;
                $options['offsiteheight'] = 300;
                $options['offsitebutton'] = __('Subscribe Now', 'wp-mailinglist');
                $options['currency'] = 'USD';
                include $this -> plugin_base() . DS . 'includes' . DS . 'currencies.php';
                $options['currencies'] = $currencies;

                $intervals = array(
                    'daily'			=>	__('Daily', 'wp-mailinglist'),
                    'weekly'		=>	__('Weekly', 'wp-mailinglist'),
                    'monthly'		=>	__('Monthly', 'wp-mailinglist'),
                    '2months'		=>	__('Every Two Months', 'wp-mailinglist'),
                    '3months'		=>	__('Every Three Months', 'wp-mailinglist'),
                    'biannually'	=>	__('Twice Yearly (Six Months)', 'wp-mailinglist'),
                    '9months'		=>	__('Every Nine Months', 'wp-mailinglist'),
                    'yearly'		=>	__('Yearly', 'wp-mailinglist'),
                    'once'			=>	__('Once Off', 'wp-mailinglist'),
                );

                $options['intervals'] = maybe_serialize($intervals);

                $embed = array(
                    'acknowledgement'		=>	__('Thank you for subscribing.', 'wp-mailinglist'),			//default acknowledgement message
                    'subtitle'				=>	__('Subscribe to our newsletter.', 'wp-mailinglist'),		//subtitle of the subscription form
                    'subscribeagain'		=>	"N",															//show a "Subscribe again" link?
                    'ajax'					=>	"N",															//turn on Ajax features?
                    'button'				=>	__('Subscribe Now', 'wp-mailinglist'),						//button text
                    'scroll'				=>	"Y",															//scroll to the subscription form?
                    'captcha'				=>	"N",															//security CAPTCHA image?
                );

                if ($this -> language_do()) {
                    foreach ($embed as $ekey => $eval) {
                        if(isset($embed[$ekey][$this -> language_default()])) {
                            $embed[$ekey] = array();
                            $embed[$ekey][$this -> language_default()] = $eval;
                        }
                    }
                }

                $options['embed'] = $embed;

                $poststatuses = array(
                    'publish'			=>	__('Published', 'wp-mailinglist'),
                    'pending'			=>	__('Pending', 'wp-mailinglist'),
                    'draft'				=>	__('Draft', 'wp-mailinglist'),
                    'private'			=>	__('Private', 'wp-mailinglist')
                );

                $options['poststatuses'] = $poststatuses;

                // API Stuff
                $options['api_key'] = strtoupper(md5($_SERVER['SERVER_NAME']));

                foreach ($options as $okey => $oval) {
                    $this -> add_option($okey, $oval);
                }

                $this -> theme_folder_functions();
                // Styles & Scripts
                include($this -> plugin_base() . DS . 'includes' . DS . 'variables.php');
                if (!empty($defaultstyles)) {
                    $loadstyles = array();
                    foreach ($defaultstyles as $handle => $style) {
                        $loadstyles[] = $handle;
                    }
                    $this -> add_option('loadstyles', $loadstyles);
                }
                if (!empty($defaultscripts)) {
                    $loadscripts = array();
                    foreach ($defaultscripts as $handle => $script) {
                        $loadscripts[] = $handle;
                    }
                    $this -> add_option('loadscripts', $loadscripts);
                }

                // Scheduled tasks
                $ratereview_scheduled = $this -> get_option('ratereview_scheduled');
                if (empty($ratereview_scheduled)) {
                    wp_schedule_single_event(strtotime("+30 day"), 'newsletters_ratereviewhook', array(30));
                    wp_schedule_single_event(strtotime("+60 day"), 'newsletters_ratereviewhook', array(60));
                    wp_schedule_single_event(strtotime("+90 day"), 'newsletters_ratereviewhook', array(90));
                    $this -> update_option('ratereview_scheduled', true);
                }

                wp_schedule_single_event(time(), 'newsletters_upgradehook', array(1));
                wp_schedule_single_event(strtotime("+7 day"), 'newsletters_upgradehook', array(7));
                wp_schedule_single_event(strtotime("+14 day"), 'newsletters_upgradehook', array(14));

                $this -> get_imagespost();
                $this -> get_managementpost();

                $themesquery = "SELECT `id` FROM `" . $wpdb -> prefix . $Theme -> table . "` LIMIT 1";
                $themes = $wpdb -> get_results($themesquery);
                if (empty($themes)) { $this -> initialize_default_themes(); }

                $permissions = $this -> get_option('permissions');
                if (empty($permissions)) { $this -> init_roles(); }
                $this -> check_roles();

                $this -> qp_scheduling();
                $this -> scheduling();
                $this -> countries_scheduling();
                $this -> optimize_scheduling();
                $this -> emailarchive_scheduling();
                $this -> autoresponder_scheduling();
                $this -> init_fieldtypes();
                $this -> predefined_templates();

                $Field -> check_default_fields();
                return $wpml_add_option_count;
            }

            function predefined_templates() {
                require_once $this -> plugin_base() . DS . 'includes' . DS . 'email-templates.php';

                if (!empty($email_templates)) {
                    foreach ($email_templates as $etk => $email_template) {
                        $this -> add_option('etsubject_' . $etk, $email_template['subject']);
                        $this -> add_option('etmessage_' . $etk, $email_template['message']);
                    }
                }
            }

            function init_fieldtypes() {
                global $wpdb;

                $fieldtypes = array(
                    'hidden'		=> 	__('Hidden', 'wp-mailinglist'),
                    'special'		=>	__('Special', 'wp-mailinglist'),
                    'text'			=>	__('Text Field', 'wp-mailinglist'),
                    'textarea'		=>	__('Text Area', 'wp-mailinglist'),
                    'select'		=>	__('Select Drop Down', 'wp-mailinglist'),
                    'radio'			=>	__('Radio Buttons', 'wp-mailinglist'),
                    'checkbox'		=>	__('Checkboxes', 'wp-mailinglist'),
                    'file'			=>	__('File Upload', 'wp-mailinglist'),
                    'pre_country'	=>	__('Predefined : Country Select', 'wp-mailinglist'),
                    'pre_date'		=>	__('Predefined : Date Picker (YYYY-MM-DD)', 'wp-mailinglist'),
                    'pre_gender'	=>	__('Predefined : Gender', 'wp-mailinglist'),
                );

                $this -> update_option('fieldtypes', $fieldtypes);

                $fieldtypesquery = "ALTER TABLE `" . $wpdb -> prefix . "wpmlfields` CHANGE `type` `type` VARCHAR(255) NOT NULL DEFAULT 'text';";
                $wpdb -> query($fieldtypesquery);
                return true;
            }

            function check_roles() {
                global $wp_roles;
                $permissions = $this -> get_option('permissions');

                if (empty($permissions) || !is_array($permissions)) {
                    $permissions = array();
                }

                if ($role = get_role('administrator')) {
                    if (!empty($this -> sections)) {
                        foreach ($this -> sections as $section_key => $section_menu) {
                            if (empty($role -> capabilities['newsletters_' . $section_key])) {
                                $role -> add_cap('newsletters_' . $section_key);

                                if (empty($permissions[$section_key]) || !is_array($permissions[$section_key])) {
                                    $permissions[$section_key] = array();
                                }

                                $permissions[$section_key][] = 'administrator';
                            }
                        }
                    }

                    if (!empty($this -> blocks)) {
                        foreach ($this -> blocks as $block) {
                            $role -> add_cap($block);
                            $permissions[$block][] = 'administrator';
                        }
                    }

                    $this -> update_option('permissions', $permissions);
                }

                return false;
            }

            function init_roles($sections = null) {
                global $wp_roles;
                $sections = $this -> sections;

                /* Get the administrator role. */
                $role = get_role('administrator');

                /* If the administrator role exists, add required capabilities for the plugin. */
                if (!empty($role)) {
                    if (!empty($sections)) {
                        foreach ($sections as $section_key => $section_menu) {
                            $role -> add_cap('newsletters_' . $section_key);
                        }
                    }

                    if (!empty($this -> blocks)) {
                        foreach ($this -> blocks as $block) {
                            $role -> add_cap($block);
                        }
                    }
                } elseif (empty($role) && !is_multisite()) {
                    $newrolecapabilities = array();
                    $newrolecapabilities[] = 'read';

                    if (!empty($sections)) {
                        foreach ($sections as $section_key => $section_menu) {
                            $newrolecapabilities[] = 'newsletters_' . $section_key;
                        }
                    }

                    if (!empty($this -> blocks)) {
                        foreach ($this -> blocks as $block) {
                            $newrolecapabilities[] = $block;
                        }
                    }

                    add_role(
                        'newsletters',
                        _e('Newsletters Manager', 'wp-mailinglist'),
                        $newrolecapabilities
                    );
                }

                if (!empty($sections)) {
                    $permissions = array();

                    foreach ($sections as $section_key => $section_menu) {
                        $wp_roles -> add_cap('administrator', 'newsletters_' . $section_key);
                        $permissions[$section_key][] = 'administrator';
                    }

                    foreach ($this -> blocks as $block) {
                        $wp_roles -> add_cap('administrator', $block);
                        $permissions[$block][] = 'administrator';
                    }

                    $this -> update_option('permissions', $permissions);
                }
            }

            function list_exists($list_id = null) {
                if (!empty($list_id)) {
                    if ($Mailinglist -> list_exists($list_id)) {
                        return true;
                    }
                }

                return false;
            }

            function array_to_object($array = array()) {
                if (!empty($array)) {
                    return (object) $array;
                }

                return false;
            }

            function truncatetext($text = null, $start = 0, $end = 0, $append = '...') {
                return substr($text, $start, $end) . $append;
            }

            function gen_date($format = "Y-m-d H:i:s", $time = null) {
                $newtime = (empty($time)) ? false : $time;
                return date_i18n($format, $newtime);
            }

            function override_mce_options($initArray = null) {
                if (!empty($_GET['page']) && in_array($_GET['page'], (array) $this -> sections)) {
                    $opts = '*[*]';
                    $initArray['valid_elements'] = $opts;
                    $initArray['extended_valid_elements'] = $opts;
                    //$initArray['entities'] = "169,copy,174,reg,8482,trade";
                    //$initArray['entity_encoding'] = "raw";
                    //$initArray['verify_html'] = 0;
                    //$initArray['cleanup'] = 0;
                    //$initArray['cleanup_on_startup'] = 0;
                    //$initArray['plugins'] .= ",fullpage";
                    //$initArray['validate_children'] = 0;
                    //$initArray['valid_children'] = $opts;
                }

                return $initArray;
            }

            function the_content($content = null) {
                if (!is_admin() && !defined('DOING_AJAX')) {
                    $showpostattachments = $this -> get_option('showpostattachments');
                    if (!empty($showpostattachments)) {
                        global $post, $Db;
                        if ($history = $this -> History() -> find(array('post_id' => $post -> ID))) {
                            if (!empty($history -> attachments)) {
                                $post_attachments = $this -> render('post-attachments', array('attachments' => $history -> attachments), false, 'default');
                                $content .= $post_attachments;
                            }
                        }
                    }
                }

                return $content;
            }

            function stripext($filename = null, $return = 'ext') {
                if (!empty($filename)) {
                    //$extArray = split("[/\\.]", $filename);

                    if ($return == 'ext') {
                        //$p = count($extArray) - 1;
                        //$extension = $extArray[$p];
                        $extension = pathinfo($filename, PATHINFO_EXTENSION);
                        return $extension;
                    } else {
                        ///$p = count($extArray) - 2;
                        //$filename = $extArray[$p];
                        $file = pathinfo($filename, PATHINFO_FILENAME);
                        return $file;
                    }
                }

                return false;
            }

            function bounce($email = null, $type = 'cgi', $status = null, $messageid = null) {
                global $wpdb, $Bounce, $Email, $Db, $Subscriber, $SubscribersList;

                $deleted_subscribers = 0;
                $deleted_emails = 0;

                $deleteonbounce = $this -> get_option('deleteonbounce');
                $bouncecount = $this -> get_option('bouncecount');

                do_action('newsletters_process_bounce', $email, $type, $status, $messageid);

                switch ($type) {
                    case 'cgi'              :
                        if (!empty($email)) {
                            $email = rawurldecode($email);
                            $status_text = __('Bounce detected via CGI', 'wp-mailinglist');
                            $parsed_recipient = null;

                            if (!class_exists('BounceHandler')) {
                                require_once($this -> plugin_base() . DS . 'vendors' . DS . 'bounce' . DS . 'bounce_driver.class.php');
                            }

                            $bouncehandler = new BounceHandler();
                            $the_facts = $bouncehandler -> get_the_facts($email);

                            if (!empty($the_facts[0]['recipient'])) {
                                $parsed_recipient = trim($the_facts[0]['recipient']);
                            }

                            if (!empty($the_facts[0]['status'])) {
                                $status_text = trim($the_facts[0]['status']);
                            }

                            if (empty($parsed_recipient)) {
                                preg_match_all("/<([^>]+)>/i", $email, $matches);
                                if (!empty($matches[1])) {
                                    foreach ($matches[1] as $match_email) {
                                        $match_email = trim($match_email);
                                        if (filter_var($match_email, FILTER_VALIDATE_EMAIL)) {
                                            $parsed_recipient = $match_email;
                                            break;
                                        }
                                    }
                                }
                            }

                            if (!empty($parsed_recipient) && filter_var($parsed_recipient, FILTER_VALIDATE_EMAIL)) {
                                $Db -> model = $Subscriber -> model;
                                if ($subscriber = $Db -> find(array('email' => $parsed_recipient))) {
                                    $Db -> model = $Subscriber -> model;
                                    if (!empty($deleteonbounce) && $deleteonbounce == "Y" && (empty($bouncecount) || $bouncecount == 1 || $bouncecount < 1 || (($subscriber -> bouncecount + 1) >= $bouncecount))) {
                                        $Db -> delete($subscriber -> id);
                                        $deleted_subscribers++;
                                    } else {
                                        $Db -> save_field('bouncecount', ($subscriber -> bouncecount + 1), array('id' => $subscriber -> id));
                                    }

                                    $bouncedata = array(
                                        'email'  => $subscriber -> email,
                                        'status' => $status_text
                                    );
                                    $Bounce -> save($bouncedata);

                                    do_action('newsletters_subscriber_bounce', $subscriber -> id, ($subscriber -> bouncecount + 1), false);

                                    //send a notification to the administrator
                                    $subscriber -> bouncecount = ($subscriber -> bouncecount + 1);
                                    $this -> admin_bounce_notification($subscriber);

                                    return true;
                                }
                            }
                        }

                        return false;
                        break;
                    case 'pop'					:
                        if (!extension_loaded('imap')) {
                            $error = __('The PHP IMAP extension is not installed/active. POP/IMAP bounce handling cannot run.', 'wp-mailinglist');
                            echo $error;
                            return false;
                        }

                        require_once($this -> plugin_base() . DS . 'vendors' . DS . 'bounce' . DS . 'bounce_driver.class.php');
                        $bouncehandler = new BounceHandler();

                        $deleted_subscribers = 0;
                        $deleted_emails = 0;

                        require($this -> plugin_base() . DS . 'vendor' . DS . 'autoload.php');

                        $type = $this -> get_option('bouncepop_type');
                        $host = $this -> get_option('bouncepop_host');
                        $user = $this -> get_option('bouncepop_user');
                        $pass = $this -> get_option('bouncepop_pass');
                        $port = $this -> get_option('bouncepop_port');
                        $bouncepop_prot = $this -> get_option('bouncepop_prot');
                        $ssl = (empty($bouncepop_prot)) ? false : (($bouncepop_prot == "ssl") ? true : false);

                        try {
                            $mailbox = new PhpImap\Mailbox('{' . $host . ':' . $port . '/' . $type . ((!empty($ssl)) ? '/ssl' : '') . '/novalidate-cert}INBOX', $user, $pass, false);

                            try {
                                $mailids = $mailbox -> searchMailbox('ALL');

                                if (!empty($mailids)) {
                                    $m = 0;

                                    foreach ($mailids as $mailid) {
                                        $mail = $mailbox -> getMail($mailid);
                                        $source = imap_fetchheader($mailbox -> getImapStream(), $mailid, FT_UID) . imap_body($mailbox -> getImapStream(), $mailid, FT_UID);
                                        $the_facts = $bouncehandler -> get_the_facts($source);

                                        $bouncedemail = false;
                                        $messageid = '';

                                        if (!empty($mail -> messageId)) {
                                            $messageid = $mail -> messageId;
                                        } elseif (!empty($mail -> headersRaw) && preg_match("/^Message-ID:(.*)$/mi", $mail -> headersRaw, $matches)) {
                                            $messageid = $matches[1];
                                        } elseif (preg_match("/^Message-ID:(.*)$/mi", $source, $matches)) {
                                            $messageid = $matches[1];
                                        }

                                        if (!empty($messageid)) {
                                            $messageid = trim($messageid);
                                            $messageid = trim($messageid, "<> \r\n\t");
                                            $Db -> model = $Email -> model;
                                            $bouncedemail = $Db -> find(array('messageid' => $messageid));
                                        }

                                        if (!empty($the_facts[0]['recipient']) && !empty($the_facts[0]['action'])) {
                                            if ($the_facts[0]['action'] == "failed") {
                                                $email = trim($the_facts[0]['recipient']);
                                                $status = trim($the_facts[0]['status']);

                                                include($this -> plugin_base() . DS . 'vendors' . DS . 'bounce' . DS . 'bounce_responses.php');
                                                $status_message = $bouncehandler -> fetch_status_messages(trim($the_facts[0]['status']));
                                                if (!empty($status_message)) {
                                                    $status .= ' - ' . $status_message[0][0] . ', ' . $status_message[1][0];
                                                }

                                                $Db -> model = $Subscriber -> model;
                                                if ($subscriber = $Db -> find(array('email' => $email))) {
                                                    $subscriber_id = $subscriber -> id;

                                                    $Db -> model = $Subscriber -> model;
                                                    if (!empty($deleteonbounce) && $deleteonbounce == "Y" && (empty($bouncecount) || $bouncecount == 1 || $bouncecount < 1 || (($subscriber -> bouncecount + 1) >= $bouncecount))) {
                                                        $Db -> delete($subscriber -> id);
                                                        $deleted_subscribers++;
                                                    } else {
                                                        $Db -> save_field('bouncecount', ($subscriber -> bouncecount + 1), array('id' => $subscriber -> id));
                                                    }

                                                    $history_id = (!empty($bouncedemail) && !empty($bouncedemail -> history_id)) ? $bouncedemail -> history_id : 0;

                                                    $bouncedata = array(
                                                        'email' 		=> 	$subscriber -> email,
                                                        'status' 		=> 	$status,
                                                        'history_id' 	=> 	$history_id
                                                    );

                                                    $Bounce -> save($bouncedata);

                                                    do_action('newsletters_subscriber_bounce', $subscriber -> id, ($subscriber -> bouncecount + 1), $history_id);

                                                    if (!empty($bouncedemail)) {
                                                        $Db -> model = $Email -> model;
                                                        $Db -> save_field('bounced', "Y", array('id' => $bouncedemail -> id));
                                                    }

                                                    //send a notification to the administrator
                                                    $subscriber -> bouncecount = ($subscriber -> bouncecount + 1);
                                                    $this -> admin_bounce_notification($subscriber);
                                                }
                                                $mailbox -> deleteMail($mailid);
                                                $deleted_emails++;
                                            }
                                        }


                                    }

                                    $mailbox -> expungeDeletedMails();

                                    return array($deleted_subscribers, $deleted_emails);
                                } else {
                                    $error = __('There are no emails in the mailbox', 'wp-mailinglist');
                                }
                            } catch (Exception $e) {
                                $error = $e -> getMessage();
                            }
                        } catch (Exception $e) {
                            $error = $e -> getMessage();
                        }

                        echo $error;
                        return false;
                        break;
                    case 'sendgrid'			:
                    case 'sns'				:
                    case 'mailgun'			:
                    case 'sparkpost'		:

                        $Db -> model = $Subscriber -> model;
                        if ($subscriber = $Db -> find(array('email' => $email))) {
                            $subscriber_id = $subscriber -> id;

                            $Db -> model = $Subscriber -> model;
                            if (!empty($deleteonbounce) && $deleteonbounce == "Y" && (empty($bouncecount) || $bouncecount == 1 || $bouncecount < 1 || (($subscriber -> bouncecount + 1) >= $bouncecount))) {
                                $Db -> delete($subscriber -> id);
                                $deleted_subscribers++;
                            } else {
                                $Db -> save_field('bouncecount', ($subscriber -> bouncecount + 1), array('id' => $subscriber -> id));
                            }

                            $bouncedemail = false;
                            $history_id = 0;

                            if (!empty($messageid)) {
                                $Db -> model = $Email -> model;
                                $bouncedemail = $Db -> find(array('messageid' => $messageid));
                                if (!empty($bouncedemail)) {
                                    $history_id = !empty($bouncedemail -> history_id) ? $bouncedemail -> history_id : 0;
                                    $Db -> model = $Email -> model;
                                    $Db -> save_field('bounced', "Y", array('id' => $bouncedemail -> id));
                                }
                            }

                            $bouncedata = array(
                                'email' 		=> 	$subscriber -> email,
                                'status'		=>	$status,
                                'history_id' 	=>	$history_id,
                            );

                            $Bounce -> save($bouncedata);

                            do_action('newsletters_subscriber_bounce', $subscriber -> id, ($subscriber -> bouncecount + 1), $history_id);

                            $subscriber -> bouncecount = ($subscriber -> bouncecount + 1);
                            $this -> admin_bounce_notification($subscriber);
                            $deleted_emails++;
                        }

                        return array($deleted_subscribers, $deleted_emails);
                    case 'mandrill-bounce'							:
                        $Db -> model = $Subscriber -> model;
                        if ($subscriber = $Db -> find(array('email' => $email))) {
                            $subscriber_id = $subscriber -> id;

                            $Db -> model = $Subscriber -> model;
                            if (!empty($deleteonbounce) && $deleteonbounce == "Y" && (empty($bouncecount) || $bouncecount == 1 || $bouncecount < 1 || (($subscriber -> bouncecount + 1) >= $bouncecount))) {
                                $Db -> delete($subscriber -> id);
                                $deleted_subscribers++;
                            } else {
                                $Db -> save_field('bouncecount', ($subscriber -> bouncecount + 1), array('id' => $subscriber -> id));
                            }

                            $bouncedata = array(
                                'email' 			=> 	$subscriber -> email,
                                'status'			=>	$status,
                            );

                            $Bounce -> save($bouncedata);
                            $subscriber -> bouncecount = ($subscriber -> bouncecount + 1);
                            $this -> admin_bounce_notification($subscriber);
                            $deleted_emails++;
                        }

                        return array($deleted_subscribers, $deleted_emails);
                        break;
                    case 'mandrill-delete'				:
                        $Db -> model = $Subscriber -> model;
                        if ($subscriber = $Db -> find(array('email' => $email))) {
                            $subscriber_id = $subscriber -> id;

                            $Db -> model = $Subscriber -> model;
                            $Db -> delete($subscriber -> id);
                            $deleted_subscribers++;

                            $bouncedata = array(
                                'email' 			=> 	$subscriber -> email,
                                'status'			=>	$status,
                            );

                            $Bounce -> save($bouncedata);
                            $subscriber -> bouncecount = ($subscriber -> bouncecount + 1);
                            $this -> admin_bounce_notification($subscriber);
                            $deleted_emails++;
                        }

                        return array($deleted_subscribers, $deleted_emails);
                        break;
                }
            }

            function add_action($action = null, $function = null, $priority = 10, $params = 1) {
                add_action($action, array($this, $function == '' ? $action : $function), $priority, $params);
            }

            function remove_action($action = null, $function = null) {
                remove_action($action, array($this, $function));
            }

            function add_filter($filter = null, $function = null, $priority = 10, $params = 1) {
                add_filter($filter, array($this, $function == '' ? $filter : $function), $priority, $params);
            }

            function plugin_base($path = null) {

                if (empty($path)) {
                    $path = __FILE__;
                }

                return rtrim(dirname($path), '/');
            }

            function url() {
                $url = rtrim(plugins_url(false, __FILE__));
                return $url;
            }

            function redirect($location = null, $msgtype = null, $message = null, $jsredirect = false) {
                global $Html;
                if (empty($location)) {
                    $url = remove_query_arg(array('action', 'action2', '_wpnonce', '_wp_http_referer'), wp_get_referer());
                } else {
                    $url = $location;
                }

                if (!empty($msgtype)) {
                    if (is_admin() && !defined('DOING_AJAX')) {
                        if ($msgtype == "message") {
                            $url = $Html -> retainquery($this -> pre . 'updated=true', $url);
                        } elseif ($msgtype == "error") {
                            $url = $Html -> retainquery($this -> pre . 'error=true', $url);
                        }
                    } else {
                        if ($msgtype == "success") {
                            $url = $Html -> retainquery('updated=1&success=' . $message, $url);
                        } elseif ($msgtype == "error") {
                            $url = $Html -> retainquery('updated=1&error=' . $message, $url);
                        }
                    }
                }

                if (!empty($message) && is_admin() && !defined('DOING_AJAX')) {
                    $message = rawurlencode($message);
                    $url = $Html -> retainquery($this -> pre . 'message=' . ($message), $url);
                }

                if (headers_sent() || $jsredirect == true) {
                    ?>

                    <script type="text/javascript">
                        window.location.href = '<?php echo addslashes($url); ?>';
                    </script>

                    <?php
                } else {
                    header("Location: " . $url . "");
                    exit();
                }
            }

            function render_error($message, $vars = array(), $dismissable = true, $type = null) {

                if (!empty($dismissable) && !empty($type)) {
                    $dismissed = $this -> get_option('dismissed-' . $type);
                    if (!empty($dismissed)) {
                        return;
                    }
                }

                //$message = esc_html($message); TO DO
                if (!empty($message) && is_numeric($message)) {
                    include $this -> plugin_base() . DS . 'includes' . DS . 'messages.php';
                    if (!empty($messages[$message])) {
                        $message = vsprintf($messages[$message], $vars);
                    }
                }

                $this -> render('error-top', array('message' => $message, 'dismissable' => $dismissable, 'type' => $type), true, 'admin');
            }

            function render_warning($message, $vars = array(), $dismissable = true, $type = null) {

                if (!empty($dismissable) && !empty($type)) {
                    $dismissed = $this -> get_option('dismissed-' . $type);
                    if (!empty($dismissed)) {
                        return;
                    }
                }

                if (!empty($message) && is_numeric($message)) {
                    include($this -> plugin_base() . DS . 'includes' . DS . 'messages.php');
                    if (!empty($messages[$message])) {
                        $message = vsprintf($messages[$message], $vars);
                    }
                }

                $this -> render('warning', array('message' => $message, 'dismissable' => $dismissable, 'type' => $type), true, 'admin');
            }

            function render_info($message, $vars = array(), $dismissable = true, $type = null) {

                if (!empty($dismissable) && !empty($type)) {
                    $dismissed = $this -> get_option('dismissed-' . $type);
                    if (!empty($dismissed)) {
                        return;
                    }
                }

                if (!empty($message) && is_numeric($message)) {
                    include($this -> plugin_base() . DS . 'includes' . DS . 'messages.php');
                    if (!empty($messages[$message])) {
                        $message = vsprintf($messages[$message], $vars);
                    }
                }

                $this -> render('info', array('message' => $message, 'dismissable' => $dismissable, 'type' => $type), true, 'admin');
            }

            function render_message($message, $vars = array(), $dismissable = true, $type = null) {
                if (!empty($dismissable) && !empty($type)) {
                    $dismissed = $this -> get_option('dismissed-' . $type);
                    if (!empty($dismissed)) {
                        return;
                    }
                }

                //$message = esc_html($message); TO DO
                if (!empty($message) && is_numeric($message)) {
                    include($this -> plugin_base() . DS . 'includes' . DS . 'messages.php');
                    if (!empty($messages[$message])) {
                        $message = vsprintf($messages[$message], $vars);
                    }
                }

                $this -> render('message', array('message' => $message, 'dismissable' => $dismissable, 'type' => $type), true, 'admin');
            }

            function et_template($type = null, $subscriber = null, $language = null) {
                $theme_id = $this -> default_theme_id('system');

                if (!empty($type)) {
                    if (!empty($language)) {
                        $configured_theme_id = $this -> language_use($language, $this -> get_option('ettemplate_' . $type));
                    } else {
                        $configured_theme_id = __($this -> get_option('ettemplate_' . $type));
                    }

                    if (!empty($configured_theme_id)) {
                        $theme_id = $configured_theme_id;
                    }
                }

                return $theme_id;
            }

            function et_subject($type = null, $subscriber = null, $language = null) {
                $subject = false;

                if (!empty($type)) {
                    if (!empty($language)) {
                        $subject = $this -> language_use($language, $this -> get_option('etsubject_' . $type));
                    } else {
                        $subject = __($this -> get_option('etsubject_' . $type));
                    }
                }
                $user = isset($user) ? $user : null;
                $subject = $this -> process_set_variables($subscriber, $user, $subject, false, false, true);
                return $subject;
            }

            function et_message($type = null, $subscriber = null, $language = null, $processvariables = true, $hidethubmnail = null) {
                $message = false;
            
                if (!empty($type)) {
                    $template = $this->get_option('etmessage_' . $type);
                    if ('Y' == $hidethubmnail) {
                        $template = str_replace("[newsletters_post_thumbnail]", "", $template);
                    }
            
                    if ($this->language_do()) {
                        if (empty($language)) {
                            $language = $this->language_current();
                        }
                    }
            
                    global $wpml_eflength, $wpml_eflength_incl_excerpt, $shortcode_posts; // New: eflength_incl_excerpt
                    $excerpt_length_applied = false; // Track if we applied a custom length
            
                    // Define named function for excerpt_length filter, only if not already defined
                    if (!function_exists('newsletters_excerpt_length')) {
                        function newsletters_excerpt_length($length) {
                            global $wpml_eflength;
                            return (int) $wpml_eflength;
                        }
                    }
            
                    // Apply filters for 'posts' or 'latestposts' if $wpml_eflength is set
                    if (in_array($type, array('posts', 'latestposts')) && !is_null($wpml_eflength) && is_numeric($wpml_eflength) && (int) $wpml_eflength > 0) {
                        $excerpt_length_applied = true;
                        add_filter('excerpt_length', 'newsletters_excerpt_length', 999);
                        // Custom excerpt trimming with ellipsis and read more button
                        add_filter('get_the_excerpt', function($excerpt) use ($wpml_eflength, $wpml_eflength_incl_excerpt) {
                            global $post, $shortcode_post_language;
                            if (!is_null($wpml_eflength) && is_numeric($wpml_eflength) && (int) $wpml_eflength > 0) {
                                // Check if post has a manual excerpt
                                $has_manual_excerpt = !empty($post->post_excerpt);
                                // Count words in the original excerpt
                                $word_count = str_word_count(strip_tags($excerpt));
            
                                // Apply eflength based on eflength_incl_excerpt
                                if (!$has_manual_excerpt || $wpml_eflength_incl_excerpt) {
                                    $trimmed_excerpt = wp_trim_words($excerpt, (int) $wpml_eflength, '');
                                    // Add ellipsis and "Read More" button only if excerpt was trimmed
                                    if ($word_count > (int) $wpml_eflength) {
                                        $excerpt_more = $this -> get_option('excerpt_more');
                                        if (is_array($excerpt_more)) {
                                            $excerpt_more = $this -> language_join($excerpt_more);
                                        }
                                        $excerpt_more = ($this -> language_do()) ? $this -> language_use($shortcode_post_language, $excerpt_more) : $excerpt_more;
    
                                        $readmore_text = !empty($excerpt_more) ? $excerpt_more : __('Read More', 'wp-mailinglist');
                                        $readmore_button = '<a href="' . get_permalink($post) . '" class="newsletters-readmore">' . $readmore_text . '</a>';
                                        $readmore_button = apply_filters('newsletters_readmore_button', $readmore_button, $post, $readmore_text);
                                        // Avoid adding ... if already present at the end
                                        $trimmed_excerpt = rtrim($trimmed_excerpt);
                                        if (!preg_match('/\.\.\.$/', $trimmed_excerpt)) {
                                            $trimmed_excerpt .= __('...', 'wp-mailinglist');
                                        }
                                        return $trimmed_excerpt . ' ' . $readmore_button;
                                    }
                                    return $trimmed_excerpt;
                                }
                                // Manual excerpt, eflength_incl_excerpt=false: return as-is
                                return $excerpt;
                            }
                            return $excerpt;
                        }, 999);
                    }
            
                    switch ($type) {
                        case 'posts'                :
                        case 'latestposts'          :
                            if (!empty($language) && $this->language_do()) {
                                $message = $this->language_use($language, $template, false);
                            } else {
                                $message = $template;
                            }
                            // Process shortcodes with custom excerpt length and read more in context
                            $message = do_shortcode($message);
                            break;
                        case 'sendas'               :
                            if (!empty($language) && $this->language_do()) {
                                $message = $this->language_use($language, $template, false);
                            } else {
                                $message = $template;
                            }
                            $message = do_shortcode($message);
                            break;
                        default                     :
                            if (!empty($language) && $this->language_do()) {
                                $message = wpautop($this->language_use($language, $template, false));
                            } else {
                                $message = wpautop($template);
                            }
                            // Should variables be processed? Shortcodes, etc.
                            if (!empty($processvariables)) {
                                $user = isset($user) ? $user : null;
                                $message = $this->process_set_variables($subscriber, $user, $message, false, false, true);
                            }
                            break;
                    }
            
                    // Remove filters if we applied them
                    if ($excerpt_length_applied) {
                        remove_filter('excerpt_length', 'newsletters_excerpt_length', 999);
                        remove_filter('get_the_excerpt', function($excerpt) use ($wpml_eflength, $wpml_eflength_incl_excerpt) {
                            global $post, $shortcode_post_language;
                            if (!is_null($wpml_eflength) && is_numeric($wpml_eflength) && (int) $wpml_eflength > 0) {
                                $has_manual_excerpt = !empty($post->post_excerpt);
                                $word_count = str_word_count(strip_tags($excerpt));
                                if (!$has_manual_excerpt || $wpml_eflength_incl_excerpt) {
                                    $trimmed_excerpt = wp_trim_words($excerpt, (int) $wpml_eflength, '');
                                    if ($word_count > (int) $wpml_eflength) {
                                        $excerpt_more = $this -> get_option('excerpt_more');
                                        if (is_array($excerpt_more)) {
                                            $excerpt_more = $this -> language_join($excerpt_more);
                                        }
                                        $excerpt_more = ($this -> language_do()) ? $this -> language_use($shortcode_post_language, $excerpt_more) : $excerpt_more;
                                        $readmore_text = !empty($excerpt_more) ? $excerpt_more : __('Read More', 'wp-mailinglist');
                                        $readmore_button = '<a href="' . get_permalink($post) . '" class="newsletters-readmore">' . $readmore_text . '</a>';
                                        $readmore_button = apply_filters('newsletters_readmore_button', $readmore_button, $post, $readmore_text);
                                        $trimmed_excerpt = rtrim($trimmed_excerpt);
                                        if (!preg_match('/\.\.\.$/', $trimmed_excerpt)) {
                                            $trimmed_excerpt .=  __('...', 'wp-mailinglist');
                                        }
                                        return $trimmed_excerpt . ' ' . $readmore_button;
                                 
                                    }
                                    return $trimmed_excerpt;
                                }
                                return $excerpt;
                            }
                            return $excerpt;
                        }, 999);
                    }
            
                    return $message;
                }
            
                return $message;
            }

            function get_themefolders() {
                $dir = $this -> plugin_base() . DS . 'views' . DS;
                $themefolders = array();

                if (is_dir($dir)) {
                    if ($dh = opendir($dir)) {
                        while (($file = readdir($dh)) !== false) {
                            $filetype = filetype($dir . $file);
                            if (!empty($filetype) && $filetype == "dir") {
                                if ($file != "admin" && $file != "email" && $file != "." && $file != "..") {
                                    $themefolders[] = $file;
                                }
                            }
                        }

                        closedir($dh);
                    }
                }

                return $themefolders;
            }

            function render($file = null, $params = array(), $output = true, $folder = 'default', $extension = null) {
                $this -> plugin_name = basename(NEWSLETTERS_DIR);
                $this -> sections = apply_filters('newsletters_sections', (object) $this -> sections);

                if (!empty($file)) {
                    $filename = $file . '.php';

                    if (!empty($folder) && $folder != "admin") {
                        $theme_folder = $this -> get_option('theme_folder');
                        $folder = (!empty($theme_folder)) ? $theme_folder : $folder;

                        $template_url = get_stylesheet_directory_uri();
                        $theme_path = get_stylesheet_directory();
                        $full_path = $theme_path . DS . 'newsletters' . DS . $filename;

                        if (!empty($theme_path) && file_exists($full_path)) {
                            $folder = $theme_path . DS . 'newsletters';
                            $theme_serve = true;
                        }
                    }

                    if (!empty($extension)) {
                        if ($extensions = $this -> get_extensions()) {
                            foreach ($extensions as $ext) {
                                if ($extension == $ext['slug']) {
                                    $extension_folder = $ext['plugin_name'];
                                }
                            }
                        }

                        $filepath = dirname(plugin_dir_path(__FILE__)) . DS . $extension_folder . DS;
                    } else {
                        if (empty($theme_serve)) {
                            $filepath = $this -> plugin_base() . DS . 'views' . DS . $folder . DS;
                        } else {
                            $filepath = $folder . DS;
                        }
                    }

                    $filefull = $filepath . $filename;

                    if (!empty($params)) {
                        foreach ($params as $key => $val) {
                            ${$key} = $val;
                        }
                    }

                    if (file_exists($filefull)) {
                        ob_start();

                        if (!empty($this -> classes)) {
                            foreach ($this -> classes as $class) {
                                global ${$class};
                            }
                        }

                        if (!empty($this -> models)) {
                            foreach ($this -> models as $model) {
                                global ${$model};
                            }
                        }

                        if (!empty($this -> helpers)) {
                            foreach ($this -> helpers as $helper) {
                                global ${$helper};
                            }
                        }

                        include($filefull);

                        $data = ob_get_clean();
                        $data = apply_filters('newsletters_render', $data, $file, $params, $output);

                        if ($output == false) {
                            return $data;
                        }

                        echo $data;
                        return true;
                    } else {
                        echo sprintf(__('Rendering of %s has failed!', 'wp-mailinglist'), '"' . $filefull . '"');
                    }
                } else {
                    echo __('No file was specified for rendering', 'wp-mailinglist');
                }
            }

            function has_child_theme_folder() {
                $theme_path = get_stylesheet_directory();
                $full_path = $theme_path . DS . 'newsletters';

                if (file_exists($full_path)) {
                    return true;
                }

                return false;
            }

            function active_theme_folder() {
                $theme_folder = $this -> get_option('theme_folder');
                $theme_folder = (!empty($theme_folder)) ? $theme_folder : 'default';

                if ($this -> has_child_theme_folder()) {
                    $theme_path = get_stylesheet_directory();
                    $theme_folder = $theme_path . DS . 'checkout' . DS;
                } else {
                    $theme_folder = $this -> plugin_base() . DS . 'views' . DS . $theme_folder . DS;
                }

                return $theme_folder;
            }

            function theme_folder_functions() {
                if ($theme_folder = $this -> active_theme_folder()) {
                    $functions_path = $theme_folder . 'functions.php';

                    $theme_folder_option = $this -> get_option('theme_folder');
                    $functions_path_original = $this -> plugin_base() . DS . 'views' . DS . $theme_folder_option . DS . 'functions.php';

                    if (file_exists($functions_path)) {
                        require_once($functions_path);

                        return true;
                    } elseif (file_exists($functions_path_original)) {
                        require_once($functions_path_original);

                        return true;
                    }
                }

                return false;
            }

            function render_url($file = null, $folder = 'admin', $extension = null) {
                $this -> plugin_name = basename(NEWSLETTERS_DIR);
                $folderurl = plugins_url() . '/' . $this -> plugin_name . '/';

                if (!empty($file)) {
                    if (!empty($extension)) {
                        if ($extensions = $this -> get_extensions()) {
                            foreach ($extensions as $ext) {
                                if ($extension == $ext['slug']) {
                                    $extension_folder = $ext['plugin_name'];
                                    $folderurl = plugins_url() . '/' . $extension_folder . '/';
                                }
                            }
                        }
                    } else {
                        if (!empty($folder) && $folder != "admin") {
                            $theme_folder = $this -> get_option('theme_folder');
                            $folder = (!empty($theme_folder)) ? $theme_folder : $folder;
                            $folderurl = plugins_url() . '/' . $this -> plugin_name . '/views/' . $folder . '/';

                            $template_url = get_stylesheet_directory_uri();
                            $theme_path = get_stylesheet_directory();
                            $full_path = $theme_path . DS . 'newsletters' . DS . $file;

                            if (!empty($theme_path) && file_exists($full_path)) {
                                $folderurl = $template_url . '/newsletters/';
                            }
                        } else {
                            $folderurl = plugins_url() . '/' . $this -> plugin_name . '/';
                        }
                    }

                    $url = $folderurl . $file;
                    return $url;
                }

                return false;
            }

            function default_theme_id($type = "sending") {
                global $Db, $Theme;
                $Db -> model = $Theme -> model;
                $theme_id = 0;

                switch ($type) {
                    case 'system'			:
                        if ($theme = $Db -> find(array('defsystem' => "Y"))) {
                            return $theme -> id;
                        }
                        break;
                    case 'sending'			:
                    default 				:
                        if ($theme = $Db -> find(array('def' => "Y"))) {
                            return $theme -> id;
                        }
                        break;
                }

                return $theme_id;
            }
            function make_bitly_url($url = null) {
                // Check if wp_remote_post function exists
                if (function_exists('wp_remote_post')) {
                    // Exclude certain URLs
                    $management_post_id = $this->get_managementpost();
                    $management_post = get_post($management_post_id);
            
                    if (!preg_match("/(" . $management_post->post_name . "|newsletters_method)/si", $url)) {
                        if (preg_match("/^http(s)?:\/\//si", $url)) {
                            // Get the access token
                            $access_token = $this->get_option('shortlinkAPI'); // Assuming the access token is stored here
            
                            $endpoint = 'https://api-ssl.bitly.com/v4/shorten';
            
                            // Build the request headers
                            $headers = array(
                                'Authorization' => 'Bearer ' . $access_token,
                                'Content-Type'  => 'application/json',
                            );
            
                            // Build the request body
                            $body = array(
                                'long_url' => $url,
                                'domain'   => 'bit.ly', // Optional, can be omitted if default domain is acceptable
                            );
            
                            // Build the request arguments
                            $args = array(
                                'headers' => $headers,
                                'body'    => json_encode($body),
                                'timeout' => 120,
                            );
            
                            // Allow filtering of the request arguments
                            $args = apply_filters('newsletters_bitly_args', $args);
            
                            // Send the request
                            $response = wp_remote_post($endpoint, $args);
            
                            if (!is_wp_error($response)) {
                                $response_code = wp_remote_retrieve_response_code($response);
                                $response_body = wp_remote_retrieve_body($response);
            
                                if ($response_code == 200) {
                                    $data = json_decode($response_body, true);
                                    if (isset($data['link']) && filter_var($data['link'], FILTER_VALIDATE_URL)) {
                                        $bitlink = $data['link'];
                                        return $bitlink;
                                    }
                                }
                            }
                        }
                    }
                }
            
                return $url;
            }
            

            function hashlink($link = null, $history_id = null, $subscriber_id = null, $user_id = null) {
                global $Html, $wpmlLink;
                $hashlink = $link;

                if (!empty($link)) {
                    //if (!preg_match("/(manage\-subscriptions|loginauth|wpml|wpmlmethod|jpg|png|gif|jpeg|bmp|wpmltrack|wpmllink)/si", $link)) {
                    $management_post_id = $this -> get_managementpost();
                    $management_post = get_post($management_post_id);

                    if (!preg_match("/(" . $management_post -> post_name . "|newsletters_method)/si", $link)) {
                        if (preg_match("/^http\:\/\//si", $link) || preg_match("/^https\:\/\//si", $link)) {
                            $hash = md5($link);

                            $queryargs = array();
                            $queryargs['newsletters_link'] = $hash;
                            $queryargs['history_id'] = $history_id;

                            if (!empty($subscriber_id)) $queryargs['subscriber_id'] = $subscriber_id;
                            if (!empty($user_id)) $queryargs['user_id'] = $user_id;

                            $queryargs = apply_filters('newsletters_hashlink_queryargs', $queryargs, $link, $hash, $history_id);
                            $hashlink = add_query_arg($queryargs, home_url());

                            if (!$curlink = $this -> Link() -> find(array('hash' => $hash))) {
                                $link_data = array(
                                    'link'			=>	$link,
                                    'hash'			=>	$hash,
                                );

                                $this -> Link() -> save($link_data, true);
                            }
                        }
                    }
                }

                $hashlink = apply_filters('newsletters_hashlink', $hashlink, $link, $history_id, $subscriber_id, $user_id);
                return $hashlink;
            }

            function admin_footer_text($text = null) {
                if (!empty($_GET['page']) && in_array($_GET['page'], (array) $this -> sections)) {
                    $plugin = '<a href="https://tribulant.com/plugins/view/1/wordpress-newsletter-plugin" target="_blank">Tribulant Newsletters</a>';

                    $stars = '<a href="https://wordpress.org/support/plugin/newsletters-lite/reviews/?rate=5#new-post" target="_blank"><span class="newsletters_footer_rating">
                          <span class="star"></span><span class="star"></span><span class="star"></span><span class="star"></span><span class="star"></span>
                        </span></a>';

                    $stars .= '<style type="text/css">
                        .newsletters_footer_rating {
                            unicode-bidi: bidi-override;
                            direction: rtl;
                            font-size: 16px;
                        }
        
                        .newsletters_footer_rating span.star {
                            font-family: FontAwesome !important;
                            font-weight: normal;
                            font-style: normal;
                            display: inline-block;
                        }
        
                        .newsletters_footer_rating span.star:before,
                        .newsletters_footer_rating span.star ~ span.star:before {
                            font-family: FontAwesome;
                            content: "\f005";
                            color: #e3cf7a;
                            padding-right: 2px;
                        }
                        </style>';

                    $newsletters_text = '</p><br class="clear" /><p class="alignleft">' . sprintf(__('If you like %s, please leave us a %s rating on WordPress.org. Thank you in advance!', 'wp-mailinglist'), $plugin, $stars) . '';
                    $text .= $newsletters_text;
                }

                return $text;
            }

            function render_email($file = null, $params = array(), $output = false, $html = true, $renderht = true, $theme_id = 0, $shortlinks = true, $fullbody = false) {
                global $newsletters_history_id, $newsletters_plaintext;
                $this -> plugin_name = basename(NEWSLETTERS_DIR);

                $render_email_label = 'render_email';
                $render_email_memory_start = function_exists('memory_get_usage') ? memory_get_usage(true) : null;
                $render_email_time_start = microtime(true);
                $render_email_last_memory = $render_email_memory_start;

                $render_email_stage = function($stage, $context = array()) use ($render_email_label, $render_email_memory_start, &$render_email_last_memory, $render_email_time_start) {
                    if (!function_exists('memory_get_usage')) {
                        return;
                    }

                    $current_memory = memory_get_usage(true);
                    $total_delta = ($render_email_memory_start !== null) ? $current_memory - $render_email_memory_start : 0;
                    $stage_delta = ($render_email_last_memory !== null) ? $current_memory - $render_email_last_memory : 0;
                    $render_email_last_memory = $current_memory;
                };

                $render_email_stage('start', array(
                    'file'      => $file,
                    'theme_id'  => $theme_id,
                    'fullbody'  => (bool) $fullbody,
                ));

                    if (!empty($file) || !empty($fullbody)) {
                        $defaulttemplate = $this -> get_option('defaulttemplate');
                    if (!empty($defaulttemplate)) {
                        $head = $this -> plugin_base() . DS . 'views' . DS . 'email' . DS . 'head-default.php';
                        $foot = $this -> plugin_base() . DS . 'views' . DS . 'email' . DS . 'foot-default.php';
                    } else {
                        $head = $this -> plugin_base() . DS . 'views' . DS . 'email' . DS . 'head.php';
                        $foot = $this -> plugin_base() . DS . 'views' . DS . 'email' . DS . 'foot.php';
                    }

                    /* Go through the parameters */
                    if (!empty($params)) {
                        foreach ($params as $pkey => $pval) {
                            ${$pkey} = $pval;

                            switch ($pkey) {
                                case 'subscriber'	:
                                    global $current_subscriber;
                                    $current_subscriber = $subscriber;
                                    break;
                                case 'message'		:
                                    global $orig_message;
                                    $orig_message = wp_unslash($pval);
                                    break;
                            }
                        }

                        $render_email_stage('params_prepared', array(
                            'has_subscriber' => (!empty($subscriber) && is_object($subscriber)),
                            'has_user'       => (!empty($user) && (is_object($user) || is_array($user))),
                        ));
                    }

                    if (!empty($this -> classes)) {
                        foreach ($this -> classes as $class) {
                            global ${$class};
                        }
                    }

                    if (!empty($this -> helpers)) {
                        foreach ($this -> helpers as $helper) {
                            global ${$helper};
                        }
                    }

                    /* Head */
                    if (true || $html == true) {
                        if ($renderht == true && file_exists($head)) {
                            if ($output == false) { ob_start(); }
                            include($head);
                            if ($output == false) { $head = ob_get_clean(); }
                        } else {
                            $head = "";
                        }

                        $render_email_stage('head_rendered', array('head_included' => ($head !== "")));
                    }

                    /** Body Part BEG **/
                    if (empty($fullbody)) {
                        $filefull = $this -> plugin_base() . DS . 'views' . DS . 'email' . DS . $file . '.php';

                        if (file_exists($filefull)) {
                            if ($output == false) { ob_start(); }

                            include($filefull);
                            if ($output == false) { $body = ob_get_clean(); }

                            if ($output == false && (true || $html == true)) {
                                $body = wpautop($body);
                            }

                            $render_email_stage('template_loaded', array(
                                'template_file' => $filefull,
                                'body_length'   => isset($body) && is_string($body) ? strlen($body) : 0,
                            ));
                        }
                    } else {
                        $body = "";
                        ob_start();
                        echo wpautop(wp_unslash($fullbody));
                        $body = ob_get_clean();

                        $render_email_stage('fullbody_prepared', array(
                            'body_length' => is_string($body) ? strlen($body) : 0,
                        ));
                    }

                    $bodyonly = $body;
                    /** Body Part END **/

                    /* Foot */
                    if (true || $html == true) {
                        if ($renderht == true && file_exists($foot)) {
                            if ($output == false) { ob_start(); }
                            include($foot);
                            if ($output == false) { $foot = ob_get_clean(); }
                        } else {
                            $foot = "";
                        }
                    }

                    if (!empty($history_id)) {
                        $this -> history_id = $newsletters_history_id = $history_id;
                        $history = $this -> History() -> get($history_id);

                        if (!empty($history -> post_id)) {
                            if ($getpost = get_post($history -> post_id)) {
                                global $post, $shortcode_post;
                                $post = $getpost;
                                $shortcode_post = $getpost;
                            }
                        }

                        if (!empty($history -> language)) {
                            $this -> language_set($history -> language);
                        }
                    }

                    /*$eunique = (empty($user)) ?
                        md5($subscriber -> id . $subscriber -> mailinglist_id . $email -> history_id . date_i18n("YmdH")) :
                        md5($user -> ID . $user -> roles[0] . $email -> history_id . date_i18n("YmdH"));*/

                    //$body = $this -> process_set_variables($subscriber, $user, wp_unslash($body), $history_id, $eunique);

                    //pass the $body through the shortcodes
                    //$body = do_shortcode(wp_unslash($body));
                    $body = str_replace("$", "&#36;", $body);
                    $body = preg_replace('/\$(\d)/', '\\\$$1', $body);

                    $themeintextversion = $this -> get_option('themeintextversion');
                    if (empty($themeintextversion)) {
                        global $wpml_textmessage;
                        $wpml_textmessage = wp_unslash($body);
                    }

                    if (empty($output) || $output == false) {
                        global $Db, $Theme;
                        $Db -> model = $Theme -> model;


                        if (!empty($history -> builderon)) {
                            $buildercontent = stripslashes($body);

                            $body = '';
                            $body .= '<!doctype html>';
                            $body .= '<html lang="en">';
                            $body .= '<head>';
                            $body .= '<meta name="viewport" content="width=device-width" />';
                            $body .= '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
                            $body .= '</head>';
                            $body .= '<body>';
                            $body .= $buildercontent;
                            $body .= '</body>';
                            $body .= '</html>';
                        } elseif (!empty($theme_id) && $theme = $Db -> find(array('id' => $theme_id))) {
                            $theme_content = "";
                            ob_start();
                            echo wp_unslash($theme -> content);
                            $theme_content = ob_get_clean();
                            $theme_content = apply_filters('newsletters_theme_before_wpmlcontent_replace', $theme_content);

                            $body = '<div class="newsletters_content">' . apply_filters($this -> pre . '_wpmlcontent_before_replace', $body) . '</div>';

                            $body = preg_replace("/\[(wpmlcontent|newscontent|newsletters_main_content)\]/si", wp_unslash($body), $theme_content);

                            if (!empty($theme -> themestylesheet)) {
                                $dom = new DOMDocument();
                                $dom -> loadHTML($body);
                                $css = 'body { background:red; }';
                                $stylesheet = get_stylesheet_uri();
                                $css_response = wp_remote_get($stylesheet);
                                $css = wp_remote_retrieve_body($css_response);
                                $style_el = $dom -> createElement('style', $css);
                                $style_el -> setAttribute('type', "text/css");
                                $head = $dom -> getElementsByTagName('head') -> item(0);
                                $head -> appendChild($style_el);
                                $body = $dom -> saveHTML();
                            }
                        } else {
                            // No theme, load default
                            $body = do_shortcode(wp_unslash($head)) . wp_unslash($body) . do_shortcode(wp_unslash($foot));
                        }

                        $render_email_stage('theme_applied', array(
                            'builder_on' => (!empty($history -> builderon)),
                            'theme_id'   => (!empty($theme_id) ? $theme_id : null),
                            'body_length'=> is_string($body) ? strlen($body) : 0,
                        ));

                        // Parse the content areas
                        $pattern = "/\[(\[?)(newsletters_content)(?![\w-])([^\]\/]*(?:\/(?!\])[^\]\/]*)*?)(?:(\/)\]|\](?:([^\[]*+(?:\[(?!\/\2\])[^\[]*+)*+)\[\/\2\])?)(\]?)/s";
                        $body = preg_replace_callback($pattern, array($this, 'newsletters_content'), $body);
                        $body = htmlspecialchars_decode($body, ENT_NOQUOTES);
                        $body = apply_filters($this -> pre . '_wpmlcontent_after_replace', $body);

                        // Remove width/height attributes from images
                        $body = $this -> remove_width_height_attr($body);

                        $render_email_stage('content_processed', array(
                            'body_length' => is_string($body) ? strlen($body) : 0,
                        ));

                        // Convert Relative urls to Absolute
                        $body = $this -> convert_relative_urls_to_absolute($body);
                        $render_email_stage('urls_converted');

                        /*$preheader = 'This is my custom preheader text that will show up in the auto preview on the email client to capture the attention of the reader reading the email.';

                            $doc = new DOMDocument();
                            $doc -> loadHTML($body);
                            $body = $doc -> getElementsByTagName('body') -> item(0);
                            $intro = $doc -> createElement('span', $preheader);
                            $intro -> setAttribute('style', "display:none !important; visibility:hidden; opacity:0; color:transparent; height:0; width:0;");
                            $body -> insertBefore($intro, $body -> firstChild);
                            $body = $doc -> saveHTML();*/

                        if (!empty($themeintextversion)) {
                            global $wpml_textmessage;
                            $wpml_textmessage = $body;
                        }

                        global $newsletters_plaintext;
                        $newsletters_plaintext = false;
                        if (empty($html) || $html != true || (!empty($history -> format) && $history -> format == "text")) {
                            if (version_compare(PHP_VERSION, '5.3.2') >= 0) {
                                if (class_exists('DOMDocument')) {
                                    require_once $this -> plugin_base() . DS . 'vendors' . DS . 'class.html2text.php';
                                    $html2text = new Html2Text();
                                    $body = $html2text -> convert($wpml_textmessage);
                                    $newsletters_plaintext = true;
                                }
                            }
                        } else {
                            $newsletters_plaintext = false;
                        }

                        $render_email_stage('format_finalized', array(
                            'plaintext'   => (bool) $newsletters_plaintext,
                            'body_length' => is_string($body) ? strlen($body) : 0,
                        ));

                        $render_email_stage('end');
                        return $body;
                    } else {
                        $render_email_stage('fullbody_returned');
                        return true;
                    }
                }

                $render_email_stage('skipped', array('reason' => 'empty_file'));
                return false;
            }


            function convert_relative_urls_to_absolute($html = null) {
                $base_url = get_site_url(); // Get the base URL of the website

                if (!empty($html) && !empty($base_url)) {
                    if (class_exists('DOMDocument')) {
                        $dom = new DOMDocument();
                        $dom->loadHTML($html);

                        foreach ($dom->getElementsByTagName('a') as $a) {
                            $href = $a->getAttribute('href');
                            if ($href && !filter_var($href, FILTER_VALIDATE_URL) && !preg_match('/^[\#\[]/', $href)) {
                                // Convert non-empty relative URL to absolute URL
                                $absolute_url = WP_Http::make_absolute_url($href, $base_url);
                                $a->setAttribute('href', $absolute_url);
                              //  error_log('test . ' . $absolute_url);
                            }
                        }

                        $html = rawurldecode($dom->saveHTML());
                        $html = trim(preg_replace(array("/^\<\!DOCTYPE.*?<html><body>/si", "!</body></html>$!si"), "", $html));
                    }
                }

                return $html;
            }

            function remove_width_height_attr($html = null) {
                $remove_width_height_attr = $this -> get_option('remove_width_height_attr');

                if (!empty($remove_width_height_attr)) {
                    if (class_exists('DOMDocument')) {
                        $dom = new DOMDocument();
                        $dom -> loadHTML($html);

                        foreach ($dom -> getElementsByTagName('img') as $img) {
                            $img -> removeAttribute('width');
                            $img -> removeAttribute('height');
                        }

                        $html = ($dom -> saveHTML());
                        $html = trim(preg_replace(array("/^\<\!DOCTYPE.*?<html><body>/si", "!</body></html>$!si"), "", $html));
                    }
                }

                return $html;
            }

            function newsletters_content($matches = null) {
                $output = "";
                if (!empty($matches)) {
                    $atts = shortcode_parse_atts($matches['3']);
                    if (!empty($this -> history_id) && !empty($atts['id'])) {
                        //if (is_object($this -> Content)) {
                        if ($contentarea = $this -> Content() -> find(array('number' => $atts['id'], 'history_id' => $this -> history_id))) {
                            /*
                                    Add a filter like this in your child theme to disable autop in email rendering
                                    function disable_wpautop_on_mail_rendering($disable) {
                                        return true; // Return true to disable wpautop
                                    }
                                    add_filter('wpml_disable_wpautop_on_mail_rendering', 'disable_wpautop_on_mail_rendering');
                                    */
                            $disable_wpautop = apply_filters('wpml_disable_wpautop_on_mail_rendering', false);
                            if ($disable_wpautop) {
                                // If the filter returns true, skip wpautop
                                $output = do_shortcode(wp_unslash($contentarea -> content));
                            } else {
                                // By default, apply wpautop
                                $output = wpautop(do_shortcode(wp_unslash($contentarea -> content)));
                            }
                        }
                        //}
                    }
                }

                return $output;
            }

            function check_uploaddir() {
                if (!is_admin() && !defined('DOING_AJAX')) return;

                global $uploaddir, $Html;
                $uploaddir = $Html -> uploads_path() . '/' . $this -> plugin_name . '/';

                if (file_exists($uploaddir)) {
                    /* Export subscribers folder */
                    $exportdir = $uploaddir . 'export' . DS;
                    if (!file_exists($exportdir)) {
                        @mkdir($exportdir, 0755);
                        @chmod($exportdir, 0755);
                    } else {
                        $exportindex = $exportdir . 'index.php';
                        $exportindexcontent = "<?php /* Silence */ ?>";
                        $exporthtaccess = $exportdir . '.htaccess';
                        $exporthtaccesscontent = "order allow,deny\r\ndeny from all\r\n\r\nOptions All -Indexes";
                        if (!file_exists($exportindex) && $fh = fopen($exportindex, "w")) { fwrite($fh, $exportindexcontent); fclose($fh); }
                        if (!file_exists($exporthtaccess) && $fh = fopen($exporthtaccess, "w")) { fwrite($fh, $exporthtaccesscontent); fclose($fh); }
                    }

                    /* Embedded images folder */
                    if ($this -> is_plugin_active('embedimages')) {
                        $embedimagesdir = $uploaddir . 'embedimages' . DS;
                        if (!file_exists($embedimagesdir)) {
                            @mkdir($embedimagesdir, 0755);
                            @chmod($embedimagesdir, 0755);
                        }
                    }
                } else {
                    @mkdir($uploaddir, 0755);
                    @chmod($uploaddir, 0755);
                }
            }

            function extension_vendor($name = null) {
                if (!empty($name)) {
                    switch ($name) {
                        /* Embedded Images */
                        case 'embedimages'						:
                            $filepath = 'newsletters-embedimages' . DS . 'embedimages.php';
                            break;
                    }

                    $filefull = dirname(plugin_dir_path(__FILE__)) . DS . $filepath;

                    if (file_exists($filefull)) {

                        require_once $filefull;
                        $class = $this -> pre . $name;

                        if (class_exists($class)) {
                            ${$name} = new $class;
                            return ${$name};
                        }
                    }
                }
            }

            function get_extensions() {
                include $this -> plugin_base() . DS . 'includes' . DS . 'extensions.php';
                $extensions = apply_filters($this -> pre . '_extensions_list', $extensions);
                $this -> extensions = $extensions;

                if (!empty($extensions) && is_array($extensions)) {
                    $titles = array();
                    foreach ($extensions as $extension) {
                        $titles[] = $extension['name'];
                    }

                    array_multisort($titles, SORT_ASC, $extensions);
                    return $extensions;
                }

                return false;
            }

            function is_plugin_active($name = null, $orinactive = false) {
                if (!empty($name)) {
                    global $Html;
                    $slug = $Html -> sanitize($name);

                    $hash = ('active' . $slug . $orinactive);
                    if ($ob_active = $this -> get_cache($hash, 'pluginactive')) {
                        return $ob_active;
                        $active = (!empty($ob_active) && $ob_active == "Y") ? true : false;
                        return $active;
                    }

                    require_once ABSPATH . 'wp-admin' . DS . 'includes' . DS . 'plugin.php';

                    if ($extensions = $this -> get_extensions()) {
                        foreach ($extensions as $extension) {
                            if ($name == $extension['slug']) {
                                $path = $extension['plugin_name'] . DS . $extension['plugin_file'];
                            }
                        }
                    }

                    if (empty($path)) {
                        switch ($name) {
                            case 'embedimages'							:
                                $path = 'newsletters-embedimages' . DS . 'embedimages.php';
                                break;
                            case 'newsletters-cforms'					:
                                $path = 'newsletters-cforms' . DS . 'cforms.php';
                                break;
                            case 'qtranslate'							:
                                $path = 'qtranslate' . DS . 'qtranslate.php';
                                break;
                            case 'qtranslate-x'							:
                                $path = 'qtranslate-x' . DS . 'qtranslate.php';
                                break;
                            case 'wpml'									:
                                $path = 'sitepress-multilingual-cms' . DS . 'sitepress.php';
                                break;
                            case 'polylang'								:
                                $path = 'polylang' . DS . 'polylang.php';
                                break;
                            case 'wpglobus'								:
                                $path = 'wpglobus' . DS . 'wpglobus.php';
                                break;
                            case 'captcha'								:
                                $path = 'really-simple-captcha' . DS . 'really-simple-captcha.php';
                                break;
                            case 'hcaptcha-for-forms-and-more'								:
                                $path = 'hcaptcha-for-forms-and-more' . DS . 'hcaptcha.php';
                                break;
                        }
                    }

                    if (!empty($path)) $path2 = str_replace("\\", "/", $path);

                    if (!empty($name) && $name == "qtranslate") {
                        $path2 = 'mqtranslate' . DS . 'mqtranslate.php';
                    }

                    if (!empty($path)) {
                        $plugins = get_plugins();

                        if (!empty($plugins)) {
                            if (array_key_exists($path, $plugins) || array_key_exists($path2, $plugins)) {
                                /* Let's see if the plugin is installed and activated */
                                if (is_plugin_active(plugin_basename($path)) ||
                                    is_plugin_active(plugin_basename($path2))) {

                                    $this -> set_cache($hash, true, 'pluginactive');

                                    return true;
                                }

                                /* Maybe the plugin is installed but just not activated? */
                                if (!empty($orinactive) && $orinactive == true) {
                                    if (is_plugin_inactive(plugin_basename($path)) ||
                                        is_plugin_inactive(plugin_basename($path2))) {
                                        $this -> set_cache($hash, true, 'pluginactive');

                                        return true;
                                    }
                                }
                            }
                        }
                    }
                }

                $this -> set_cache($hash, false, 'pluginactive');
                return false;
            }

            // Make sure that all metaboxes (fields) are closed when the form builder is loaded
            function closed_meta_boxes_form($closed = null) {
                $id = (int) sanitize_text_field(isset($_GET['id']) ? $_GET['id'] : 0);
                if (!empty($id)) {
                    if ($form = $this -> Subscribeform() -> find(array('id' => $id))) {
                        $closed = array();

                        if (!empty($form -> form_fields)) {
                            foreach ($form -> form_fields as $form_field) {
                                $id = 'newsletters_forms_field_' . $form_field -> field_id;
                                if (empty($closed) || !in_array($id, $closed)) {
                                    $closed[] = $id;
                                }
                            }
                        }
                    }
                }

                return $closed;
            }

            // Reset the meta box order on the save a form page
            // The meta boxes in WordPress are actually used as fields on the form here
            function meta_box_order($order = null, $option = null, $user = null) {
                if (!empty($order)) {
                    $order = false;
                }

                return $order;
            }
        function use_captcha($status = "Y") {
            if ($status == 'Y') {
                $captcha_type = $this->get_option('captcha_type');
                if (!empty($captcha_type)) {
                    switch ($captcha_type) {
                        case 'rsc':
                            if ($this->is_plugin_active('captcha')) {
                                return "rsc";
                            }
                            break;
                        case 'recaptcha':
                            return "recaptcha";
                            break;
                        case 'recaptcha3':
                            return "recaptcha3";
                            break;
                        case 'hcaptcha':
                            if ($this->is_plugin_active('hcaptcha-for-forms-and-more')) {
                                return "hcaptcha";
                            }
                            break;
                        case 'turnstile':
                            return 'turnstile';
                            break;
                        case 'none':
                        default:
                            return false;
                            break;
                    }
                }
            }

            return false;
        }
    }
}

if (!class_exists('fakemailer')) {
    class fakemailer {
        public function Send() {
            return 'Cancelling mail';
            //throw new fakephpmailerException('Cancelling mail');
        }
    }
}

if (!class_exists('fakephpmailerException' )) {
    /*class phpmailerException extends Exception {
    public function errorMessage() {
        $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
        return $errorMsg;
    }
}*/
}

    ?>