<?php

/*
  MailBeez Automatic Trigger Email Campaigns
  http://www.mailbeez.com

  Copyright (c) 2010, 2011, 2012 MailBeez

  inspired and in parts based on
  Copyright (c) 2003 osCommerce

  Released under the GNU General Public License

  v2.7
 */


///////////////////////////////////////////////////////////////////////////////
///																			 //
///                 MailBeez Core file - do not edit                         //
///                                                                          //
///////////////////////////////////////////////////////////////////////////////

require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/classes/beez.php');
require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/classes/mailbeez_mailer.php');
require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/classes/mouseflow.php');
require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/classes/googleanalytics.php');
require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/classes/analytics_piwik.php');
require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/classes/analytics_econda.php');
require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/classes/analytics_custom.php');
require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/classes/clicktracker.php');
require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/functions/compatibility.php');
require_once(MH_DIR_CONFIG . 'config_process_control.php');

class mailbeez extends beez
{

    var $pathToCommonTemplates;
    var $pathToMailbeez;
    var $versionScope = 'MAILBEEZ_INSTALLED_VERSIONS';
    var $cert_check;
    var $subscription;
    var $order_status_list;
    var $is_mb_main = false;
    var $noblock;
    var $iteration;
    var $googleanalytics_enabled;
    var $googleanalytics_rewrite_mode;
    var $analytics_econda_enabled;
    var $analytics_econda_rewrite_mode;
    var $analytics_piwik_enabled;
    var $analytics_piwik_rewrite_mode;
    var $analytics_custom_enabled;
    var $analytics_custom_rewrite_mode;
    var $sender;
    var $sender_name;
    var $do_process;
    var $is_loop;
    var $template_control;
    var $do_run;
    var $mailchimp_ready;
    var $preview_maintemplate_id;
    var $preview_content_module_id;
    var $allow_preview;
    var $allow_reporting;
    var $allow_filter_check;
    var $is_prospect_enabled;
    var $is_customer_enabled;
    var $orderid_is_reference;
    var $is_service;

    var $allow_timing;
    var $htmlTemplateResource;
    var $txtTemplateResource;
    var $htmlBodyTemplateResource;
    var $txtBodyTemplateResource;
    var $subjectTemplateResource;
    var $preheaderTemplateResource;

    var $is_preview = false;
    var $is_preview_theme = false;
    var $is_preview_template = false;
    var $is_preview_main_template = false;

    var $txtTemplate = '';
    var $htmlTemplate = '';
    var $htmlBodyTemplate = '';
    var $txtBodyTemplate = '';
    var $subjectTemplate = '';
    var $preheaderTemplate = '';

    var $audience = array();
    var $additionalFields = array();


    function __construct()
    {
        parent::__construct();

        $this->code = ''; // unique id for admin-module
        $this->module = ''; // for tracking / can be shared by a group of modules /  same as folder name for e.g. templates
        $this->version = '1.0'; // float value
        $this->required_mb_version = 1.6;
        $this->iteration = 1; // e.g. for reminder
        $this->title = '';
        $this->description = '';
        $this->sort_order = '';
        $this->enabled = '';
        $this->googleanalytics_enabled = mh_cfg('MAILBEEZ_MAILHIVE_GA_ENABLED'); // by default global settings
        $this->googleanalytics_rewrite_mode = mh_cfg('MAILBEEZ_MAILHIVE_GA_REWRITE_MODE'); // by default rewrite all urls
        $this->analytics_econda_enabled = mh_cfg('MAILBEEZ_MAILHIVE_ECONDA_ENABLED'); // by default global settings
        $this->analytics_econda_rewrite_mode = mh_cfg('MAILBEEZ_MAILHIVE_ECONDA_REWRITE_MODE'); // by default rewrite all urls
        $this->analytics_piwik_enabled = mh_cfg('MAILBEEZ_MAILHIVE_PIWIK_ENABLED'); // by default global settings
        $this->analytics_piwik_rewrite_mode = mh_cfg('MAILBEEZ_MAILHIVE_PIWIK_REWRITE_MODE'); // by default rewrite all urls
        $this->analytics_custom_enabled = mh_cfg('MAILBEEZ_MAILHIVE_ANALYTICS_CUSTOM_ENABLED'); // by default global settings
        $this->analytics_custom_rewrite_mode = mh_cfg('MAILBEEZ_MAILHIVE_ANALYTICS_CUSTOM_REWRITE_MODE'); // by default rewrite all urls
        $this->admin_action_plugins_path = MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'mailbeez/'; // default-path to include admin action plugins from
        $this->admin_action_plugins = ''; // list of admin frontend action plugins ("file1;file2")
        $this->common_admin_action_plugins = 'view_template.php;list_recipients.php;send_testemail.php;run_module.php'; // list of common gui plugins ("file1;file2")
        $this->sender = '';
        $this->sender_name = '';
        $this->status_key = '';
        $this->icon = '../../common/images/icon_module.png';
        $this->description_image = '../../common/images/icon_module_64.png';
        $this->documentation_root = 'https://www.mailbeez.com/documentation/mailbeez/';
        $this->documentation_key = '';
        $this->has_submodules = false; // has submodules
        $this->is_submodule_of = ''; // is a submodule
        $this->display_as_submodule_of = ''; // display a submodule
        $this->is_loop = false;
        $this->removable = true; // can't be removed
        $this->stealth = false; // don't list as an installed module
        $this->hidden = false; // hide submodule / module
        $this->do_process = true; // a processable module
        $this->do_run = true; // run this module
        $this->is_editable = true; // allow editor
        $this->is_configurable = true; // edit configs
        $this->on_cfg_save_clear_template_c = false; // clear compiled templates when changing settings
        $this->template_control = false;
        $this->mailchimp_ready = false;
        $this->preview_maintemplate_id = false;
        $this->preview_content_module_id = false;
        $this->allow_preview = true; // this module can be previewed in main template
        $this->allow_reporting = true; // this module is included in reporting
        $this->allow_filter_check = true;
        $this->allow_group_filter_check = true;
        $this->is_prospect_enabled = false;
        $this->is_customer_enabled = true;

        $this->orderid_is_reference = false; // order id is used as reference id - hide in mail generation context

        $this->is_service = !$this->allow_preview; // simple midterm solution
        $this->allow_timing = $this->allow_preview; // simple midterm solution


        $this->pathToCommonTemplates = mh_cfg('MH_DIR_FS_CATALOG') . mh_cfg('MH_ROOT_PATH') . 'common/templates/';
        $this->pathToMailbeez = mh_cfg('MH_DIR_FS_CATALOG') . mh_cfg('MH_ROOT_PATH') . 'mailbeez/';


        if (mh_cfg('MH_PLATFORM') == 'zencart' && mh_cfg('MAILBEEZ_MAILHIVE_ZENCART_OVERRIDE') == 'False') {
            // use mail templates from zencart
            $this->htmlTemplateResource = 'email_html_zencart.tpl'; // located in common/templates
        } else {
            $this->htmlTemplateResource = 'email_html.tpl'; // located in common/templates
        }

        $this->txtTemplateResource = 'email_txt.tpl'; // located in common/templates


        // default files support
        if (!file_exists($this->pathToCommonTemplates . $this->htmlTemplateResource)) {
            $this->htmlTemplateResource = 'default_' . $this->htmlTemplateResource;
        }
        if (!file_exists($this->pathToCommonTemplates . $this->txtTemplateResource)) {
            $this->txtTemplateResource = 'default_' . $this->txtTemplateResource;
        }

        $this->htmlBodyTemplateResource = 'body_html.tpl'; // located in folder of this module
        $this->txtBodyTemplateResource = 'body_txt.tpl'; // located in folder of this module
        $this->subjectTemplateResource = 'subject.tpl'; // located in folder of this module
        $this->preheaderTemplateResource = 'preheader.tpl'; // located in folder of this module


        $this->is_preview = false;
        $this->is_preview_theme = false;
        $this->is_preview_template = false;
        $this->is_preview_main_template = false;

        $this->txtTemplate = '';
        $this->htmlTemplate = '';
        $this->htmlBodyTemplate = '';
        $this->txtBodyTemplate = '';
        $this->subjectTemplate = '';
        $this->preheaderTemplate = '';

        $this->audience = array();
        $this->additionalFields = array();




        @mhpi('mailbeez_3', $this);


        if (file_exists(MH_DIR_CONFIG . 'config_editor/classes/template_manager.php')) {
            require_once(MH_DIR_CONFIG . 'config_editor/classes/template_manager.php');

            $lng_id = mh_get('lng_id', mh_session('languages_id'));


            // only if parameter content_module_id is set!
            if (mh_get('content_module_id') && mh_get('content_module_id') != 'MAIN') {
               // body template
                $this->is_preview_template = true;
                $content_module_id = mh_get('content_module_id');
                // user module
                $htmlBodyTemplate_content = false;
                if (stristr(mh_get('content_module_id'), 'user_module_template')) {
                    $preview_language_id = $lng_id;
                    list($htmlBodyTemplate_content, $htmlBodyTemplate_date_added, $htmlBodyTemplate_last_modified) =
                        mh_load_language_object($content_module_id, $preview_language_id, 'htmlBodyTemplate', $this);
                } else {
                    // get file based template
                    require_once(MH_DIR_CONFIG . 'config_editor/classes/template_manager.php');

                    $tmpl = new template_manager('body');
                    $file_template_id = $content_module_id;
                    list($template_content, $style_serialized) = $tmpl->read_file_template($file_template_id . '/');

                    if (isset($template_content[$lng_id])) {
                        $htmlBodyTemplate_content = $template_content[$lng_id];
                    } else {
                        $htmlBodyTemplate_content = array_pop($template_content);
                    }
                }
                if ($htmlBodyTemplate_content) {
                    $this->htmlBodyTemplatePreview = $htmlBodyTemplate_content;
                }
            } elseif (mh_get('module') == 'MAIN' && !stristr(mh_get('maintemplate_id'), 'user_template')) {
                // main template
                $this->is_preview_main_template = true;
                // get file based template
                require_once(MH_DIR_CONFIG . 'config_editor/classes/template_manager.php');
                $tmpl = new template_manager('MAIN');
                $file_template_id = mh_get('maintemplate_id');
                list($template_content, $style_serialized) = $tmpl->read_file_template($file_template_id . '/');
                if (isset($template_content[$lng_id])) {
                    $htmlTemplate_content = $template_content[$lng_id];
                } else {
                    $htmlTemplate_content = array_pop($template_content);
                }
                // load file based template
                $this->htmlTemplatePreview = $htmlTemplate_content;

            }
        }

        mh_event_log('MAILBEEZ_MODULE_INIT', 'class constructed', get_class($this), $class = '', $parameters = '');
    }

    function boot() {
            return true;
    }

    function booted() {
      parent::booted(); // TODO: Change the autogenerated stub
    }


// class methods

    static function gc_process() {
        return mh_db_query("delete from " . TABLE_MAILBEEZ_PROCESS . " where date_added < DATE_SUB(NOW() , INTERVAL 2 DAY)");
    }

    static function lock($lock, $owner = '',  $lifetime = 3600) {

        $owner = mb_substr($lock, 0, 32);

        $sql_data_array = [
            'lock_key' => md5($lock),
            'owner' => (string)$owner,
            'expiration' => time() + (int)$lifetime
        ];


        $query = mh_db_query("SELECT EXISTS(SELECT 1 FROM ". TABLE_MAILBEEZ_LOCK . " WHERE lock_key = '" .$sql_data_array['lock_key'] . "') as c");
        $check = mh_db_fetch_array($query);
        if ($check['c']) {
            return false;
        }

        try {
            mh_db_perform(TABLE_MAILBEEZ_LOCK, $sql_data_array);
            $acquired = true;
        } catch (Exception $exception) {
            // entry already exists
            $acquired = false;
        }

        if (random_int(1, 100) <= 2) {
            mh_db_query("delete from " . TABLE_MAILBEEZ_LOCK . " where expiration <= " . time());
        }

        return $acquired;
    }



    static function check_process_lock()
    {

//        if (mh_cfg('MAILBEEZ_MAILHIVE_PROCESS_CONTROL') == 'False') {
//            return false;
//        }

        $lock_period = mh_cfg('MAILBEEZ_MAILHIVE_PROCESS_CONTROL_LOCK_PERIOD');

        // see if there is a running process

        // V2.7.6 added SQL_NO_CACHE
        $check_query_sql = "select SQL_NO_CACHE lock_value, batch_id, worker_id
                                from " . TABLE_MAILBEEZ_PROCESS . "
                            where lock_key='RUN_LOCK_TIMESTAMP' order by lock_id desc ";

        $check_query = mh_db_query($check_query_sql);

        if (mh_db_num_rows($check_query) > 0) {
            $check = mh_db_fetch_array($check_query);

            list($module, $lock_timestamp) = explode('|', $check['lock_value']);

            if ($check['batch_id'] == mh_cfg('MAILBBEEZ_EVENTLOG_BATCH_ID')

//            || $check['batch_id'] == 'mailhive_closed'

            ) {
                return false; // current batch or closed batch
            }

            if ($lock_timestamp + $lock_period > time()) {
                return $lock_timestamp + $lock_period; // process locked
            } else {
                return false; // lock not valid
            }
        }
        return false; // no lock yet
    }


    /**
    * return the first avaiable worker id
    */

    static function get_process_worker() {
        if (!class_exists('mb_newsletter')) {
            return 1;
        }

        $workers_max = mb_newsletter::get_worker_count();

        $lock_period = max(60, 2 * (int)mh_cfg('MAILBEEZ_MAILHIVE_PROCESS_CONTROL_LOCK_PERIOD'));

        // 30s wait after sending -> process is dead
        $lock_period = 30;

        $sql = "select SQL_NO_CACHE GROUP_CONCAT(w_ids SEPARATOR ',') as worker_ids
            from (
                select GROUP_CONCAT(distinct worker_id SEPARATOR ',') as w_ids, batch_id
                    from " . TABLE_MAILBEEZ_PROCESS . "
                        where lock_key='RUN_LOCK_TIMESTAMP' and DATE_ADD(date_added, INTERVAL {$lock_period} SECOND) > NOW()
                        /* and lock_value like 'mailhive_open|%' */
                        group by batch_id having batch_id not in (
                        select batch_id from " . TABLE_MAILBEEZ_PROCESS . " where lock_value like 'mailhive_closed|%'
                        )
            ) as a
            group by null";
//echo $sql;
//        $sql = "select SQL_NO_CACHE GROUP_CONCAT(worker_id SEPARATOR ',') as worker_ids, batch_id from " . TABLE_MAILBEEZ_PROCESS . " where lock_key='RUN_LOCK_TIMESTAMP' not in ( select worker_id)";
        $query = mh_db_query($sql);

        // todo
        // make sure every workid is used
        // incremental !!!!


        $worker_id = 1;
        $check = mh_db_fetch_array($query);
        if (!mh_arr_val($check, 'worker_ids')) {
            return $worker_id;
        }
        echo "busy worker IDs: {$check['worker_ids']}<br>";
        $active_workers = explode(',', $check['worker_ids']);
        while($worker_id <= $workers_max){
            if (!in_array($worker_id, $active_workers)) {
                echo "first available worker ID: {$worker_id}<br>";
                return $worker_id;
            }
            $worker_id ++;
        }
        // no available worker
        return null;

    }


    static function get_process_lock_info($process_lock_timestamp)
    {
        return "MailHive process locked until " . date('Y-m-d G:i:s ', $process_lock_timestamp) . " (" . ($process_lock_timestamp - time()) . " secs left) ";
    }

    function listAudience()
    {
        $this->getAudience();


        $this->outputListHeader();
        $row = 0;
        foreach ($this->audience as $key => $mail) {
            $mail = mailbeez_mailer::sanitize_data($mail);
            $row++;
            $this->outputListItem($mail, $row);
            echo '<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">  scrolldown(); </SCRIPT>';
            echo str_repeat(" ", 4096); // force a flush
            ob_flush();
            flush();
        }
        return $row;
    }

    function getAudience()
    {
        return false;
        // just an example

        /*
        $query_raw = "";

        $query = mh_db_query($query_raw);
        while ($item = mh_db_fetch_array($query)) {
            // mandatory fields:
            // - firstname
            // - lastname
            // - email_address
            // - customers_id (can be virtual but unique for this recipient)
            //
            // for dynamic iteration:
            // - _iteration
            // other keys are replaced while sending: $<key>

            $this->audience[$item['customers_id']] = array('firstname' => $item['customers_firstname'],
                'lastname' => $item['customers_lastname'],
                'email_address' => $item['customers_email_address']);
        }
        */
    }


    function outputListHeader()
    {
        echo $this->outputProcessInfo('Listing Audience...');
    }

    function get_module_id_iteration() {
        if ($this->is_loop) {
            return $this->module . '-' . $this->iteration . '-loop-' . $this->is_loop;
        } else {
            return $this->module . '-' . $this->iteration;
        }
    }

    static function remove_module_id_iteration($module_id_iteration) {
        list($module_id, ) = explode('-', $module_id_iteration);
        return $module_id;
    }


    function outputListItem($mail, $row)
    {

        // todo
        // requires to load js in inc_mailhive.php
        /* <a href="#" onclick="return openCISPopup('<?php echo $mail['customers_id']; ?>', 'view_overview');">... </a> */
        ?>


        <div class="rc" onclick="return openCISPopup('<?php echo $mail['customers_id']; ?>', 'view_overview');">
        <div class="rn"><?php echo $row; ?></div>
        <div class="r">
        <?php echo $mail['email_address']; ?> - <?php echo $mail['firstname']; ?> <?php echo $mail['lastname']; ?>
        <br/>
        <?php
        $additionFields = $this->additionalFields;
        if (sizeof($additionFields) > 0) {
            $data = [];
            foreach ($additionFields as $fieldKey => $value) {
                $data[] =  $fieldKey . ': ' . $mail[$fieldKey];
            }
            echo '<div style="opacity: 0.6">' . implode(' | ', $data) . '</div>';
        }
        ?>
        </div>
        </div>
        <?php
    }

    function sendTest($email)
    {
        $audience = array();
        $audience[0] = $this->loadDefaultFields($email);

        list($audience[0]) = @mhpi('mailbeez_1', $audience[0], $this);

        return $this->process($audience, 'test');
    }

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// common methods

    function loadDefaultFields($email = 'TestEmail')
    {

        if (function_exists('mh_get_default_language_info')) {
            $default_language_array = mh_get_languages_directory(mh_cfg('DEFAULT_LANGUAGE'));
            $test_language_id = $default_language_array['languages_id'];
        } else {
            $test_language_id = mh_get('lng_id', mh_session('languages_id'));
        }
        $fields = array();
        $fields = array('firstname' => mh_cfg('MAILBEEZ_PREVIEW_FIRSTNAME'),
            'lastname' => mh_cfg('MAILBEEZ_PREVIEW_LASTNAME'),
            'email_address' => $email,
            'customers_id' => mh_cfg('MAILBEEZ_PREVIEW_CUSTOMERS_ID'),
            'customers_language_id' => $test_language_id,
            'order_id' => mh_cfg('MAILBEEZ_PREVIEW_ORDERS_ID'),
            'preview' => true
            );

        $additionFields = $this->additionalFields;
        if (sizeof($additionFields) > 0) {
            foreach ($additionFields as $fieldKey => $testValue) {
                $fields[$fieldKey] = $testValue;
            }
        }
        return $fields;
    }

    function process($audience = '', $mode = '')
    {
        //$customers_language = mh_get_languages_directory(mh_cfg('DEFAULT_LANGUAGE'));
        if ($audience == '') {
            $this->getAudience();
            $audience = $this->audience;
        } else {
            $this->audience = $audience;
        }

        $this->ct = new mb_clicktracker();
        $this->mf = new mb_mouseflow();
        $this->ga = new googleAnalytics(mh_cfg('MAILBEEZ_MAILHIVE_GA_MEDIUM'), $this->module, mh_cfg('MAILBEEZ_MAILHIVE_GA_SOURCE'));
        $this->pa = new analyticsPiwik(mh_cfg('MAILBEEZ_MAILHIVE_PIWIK_CAMPAIGN'), $this->module);
        $this->ea = new analyticsEconda(mh_cfg('MAILBEEZ_MAILHIVE_ECONDA_CAMPAIGN'), $this->module);
        $this->ca = new analyticsCustom(mh_cfg('MAILBEEZ_MAILHIVE_ANALYTICS_CUSTOM_PARAMETER'), $this->module);

        mh_log('mailbeez::process audience: %s', $audience);

        $this->loadAllTemplates();
        $mailbeez_mailer = new mailbeez_mailer($this, true);

        echo $this->outputProcessInfo();

        mailbeez::update_process_lock('', $this->get_module_id());

        return $mailbeez_mailer->sendBeez($this->get_module_id(), $this->iteration, $mode);
    }

    function loadAllTemplates()
    {
        $this->loadTxtTemplateResource();
        $this->loadHtmlTemplateResource();
        $this->loadTxtBodyTemplateResource();
        $this->loadHtmlBodyTemplateResource();
        $this->loadSubjectTemplateResource();
    }

    function loadTxtTemplateResource()
    {
        list($this->txtTemplate, $this->txtTemplate_mtime) = $this->loadResource($this->pathToCommonTemplates . $this->txtTemplateResource);
    }

    function loadResource($filename, $defaut_support = false)
    {
        if ($defaut_support) {
            $path = $this->pathToMailbeez . $this->module . '/email/';
            // default files support

            $resource = $path . $filename;
            if (!file_exists($resource)) {
                $resource = $path . 'default_' . $filename;
            }
        } else {
            $resource = $filename;
        }

        if (!file_exists($resource)) {
            return array(false, false);
        } else {
            return array(file_get_contents($resource), filemtime($resource));
        }

    }

    function loadHtmlTemplateResource()
    {
        list($this->htmlTemplate, $this->htmlTemplate_mtime) = $this->loadResource($this->pathToCommonTemplates . $this->htmlTemplateResource);
    }

    function loadTxtBodyTemplateResource()
    {
        list($this->txtBodyTemplate, $this->txtBodyTemplate_mtime) = $this->loadResource($this->txtBodyTemplateResource, true);
    }

    function loadHtmlBodyTemplateResource()
    {
        list($this->htmlBodyTemplate, $this->htmlBodyTemplate_mtime) = $this->loadResource($this->htmlBodyTemplateResource, true);
    }

    function loadSubjectTemplateResource()
    {
        list($this->subjectTemplate, $this->subjectTemplate_mtime) = $this->loadResource($this->subjectTemplateResource, true);
    }

    function loadPreheaderTemplateResource()
    {
        list($this->preheaderTemplate, $this->preheaderTemplate_mtime) = $this->loadResource($this->preheaderTemplateResource, true);
    }

    function outputProcessInfo($message = 'Processing...') {
        return '<div style="background-color: #f5f5f5;
            padding: 10px 20px;
            margin: 0 -20px 0px -20px;
            position: fixed;
            width: 100%;
            bottom: 0;
            font-size: 12px;
            font-family: \'SFMono-Regular\', Consolas, \'Liberation Mono\', Menlo, Courier, monospace;
            opacity: 1.0;">' .

            'MailBeez System Console: <br />' .
			'&gt; Module: ' . $this->module . '<br />' .
            '&gt; ' . $message . '<br />' .
			'</div><div></div>';
    }


    static function update_process_lock($timestamp = '', $module = '')
    {
        if (
//                mh_cfg('MAILBEEZ_MAILHIVE_PROCESS_CONTROL') == 'False' ||
        !isset($GLOBALS['MAILBEEZ_MAILHIVE_PROCESS_CONTROL_INIT'])) {
            return false;
        }

        if ($timestamp != -1) {
            $kill_check = config_process_control::check_kill(mh_cfg('MAILBBEEZ_EVENTLOG_BATCH_ID'));

            if ($kill_check) {
                mailbeez::update_process_lock('-1', 'mailhive_killed');
            }
        }

        $timestamp_lock = ($timestamp == '') ? time() : $timestamp;
        $module_lock = $module;
        $data = array('lock_key' => 'RUN_LOCK_TIMESTAMP',
            'lock_value' => ($module_lock . '|' . $timestamp_lock),
            'batch_id' => mh_cfg('MAILBBEEZ_EVENTLOG_BATCH_ID'),
            'worker_id' => mh_cfg('MAILBBEEZ_EVENTLOG_WORKER_ID', 0),
            'date_added' => 'now()');
        mh_db_perform(TABLE_MAILBEEZ_PROCESS, $data);
        if ($timestamp == -1) {
            // killed
            echo 'process killed';
            mh_exit();
        }

        if ($timestamp == 1) {
            // clean up
            return mh_db_query("delete from " . TABLE_MAILBEEZ_PROCESS . " where batch_id <  " . ( ( (int) mh_cfg('MAILBBEEZ_EVENTLOG_BATCH_ID') ) - 100 ) . " ");
        }
    }

    function viewMail($format, $strip_editor_codes = true, $preparse_template_codes = true, $strip_main_template_editor_codes = true)
    {

        if (mh_get('realview')) {
            $cfg_editor = new mailbeez_editor();
            return $cfg_editor->realview($this, false);
        }


        $out = 'default';

        $this->ct = new mb_clicktracker();
        $this->mf = new mb_mouseflow();
        $this->ga = new googleAnalytics(mh_cfg('MAILBEEZ_MAILHIVE_GA_MEDIUM'), $this->module, mh_cfg('MAILBEEZ_MAILHIVE_GA_SOURCE'));
        $this->pa = new analyticsPiwik(mh_cfg('MAILBEEZ_MAILHIVE_PIWIK_CAMPAIGN'), $this->module);
        $this->ea = new analyticsEconda(mh_cfg('MAILBEEZ_MAILHIVE_ECONDA_CAMPAIGN'), $this->module);
        $this->ca = new analyticsCustom(mh_cfg('MAILBEEZ_MAILHIVE_ANALYTICS_CUSTOM_PARAMETER'), $this->module);
        $this->loadAllTemplates();
        $mailbeez_mailer = new mailbeez_mailer($this, true);

        $smarty = new mh_Smarty;
        $smarty->compile_id = $this->code;

        $smarty->assign('viewTemplate', true);

        $mail = $this->loadDefaultFields();

        if ($strip_main_template_editor_codes && !$this->is_mb_main) {
            // todo
            // refresh compiled templates
            $smarty->force_compile = true;
            $smarty->compile_id = $this->code . '_e';

            if (method_exists($smarty, 'clear_compiled_tpl')) {
                // smarty 2
                $smarty->clear_compiled_tpl();
            } else {
                // smarty 3
                $smarty->clearCompiledTemplate();
            }

            $smarty->assign('stripMainTemplateEditorCodes', true);
        }
        list($mail) = @mhpi('mailbeez_1', $mail);
        list($smarty, ,) = @mhpi('mailbeez_2', $smarty, $this, $mail);


        list($output_subject, $output_content_html, $output_content_txt, $output_preheader) = mh_smarty_generate_mail($mailbeez_mailer, $mail, $this->module, $smarty, $strip_editor_codes, $preparse_template_codes);

        $output_content_html = mh_template_emogrify($output_content_html);

        // build html email
        if ($format == 'html') {
            $out = $output_content_html;
        } elseif ($format == 'txt') {
            // build txt email
            $out = $output_content_txt;
        } else {
            $out = 'unknown format: ' . $format;
        }
        return $out;
    }

    function getLastOrderId($customer_id)
    {
        $cache_key = 'cache_last_order_id_' . "$customer_id";
        if (isset($GLOBALS[$cache_key]) && mh_cfg('MAILBEEZ_CHECK_CACHE')) {
            return $GLOBALS[$cache_key];
        }

        $last_id_query = mh_db_query("select orders_id as orders_id_last from " . TABLE_ORDERS . " where customers_id='" . (int)$customer_id . "' order by date_purchased desc limit 1");
        $last_id = mh_db_fetch_array($last_id_query);

        $result = mh_arr_val($last_id, 'orders_id_last');
        if (mh_cfg('MAILBEEZ_CHECK_CACHE')) {
            $GLOBALS[$cache_key] = $result;
        }
        return $result;
    }

    function beforeFilter($mail, $mode)
    {
        return $mail;
    }

    function beforeFilterData($mail, $mode)
    {
        return $mail;
    }

    function afterFilterData($mail, $mode)
    {
        return $mail;
    }

    function beforeFilterContent($mail, $mode)
    {
        return $mail;
    }

    function afterFilterContent($mail, $mode)
    {
        return $mail;
    }

    function beforeGenerate($mail, $mode)
    {
        return $mail;
    }

    function afterGenerateMail($mail, $mode)
    {
        return $mail;
    }

    function beforeFilterModify($mail, $mode)
    {
        return $mail;
    }

    function afterFilterModify($mail, $mode)
    {
        return $mail;
    }

    function afterFilter($mail, $mode)
    {
        return $mail;
    }

    function beforeSend($mail, $mode)
    {
        return $mail;
    }

    function beforePerformSend($output_subject, $output_content_html, $output_content_txt, $mode)
    {
        return array($output_subject, $output_content_html, $output_content_txt);
    }

    function afterSend($mail, $mode)
    {
        return false;
    }

    function afterTrack($mail, $mode)
    {
        return false;
    }

    function replace_variables($text_in, $replace_variables)
    {
        $text = (is_array($text_in)) ? $text_in[0] : $text_in;

        if (is_array($replace_variables)) {
            uksort($replace_variables, "sortbykeylength");

            foreach ($replace_variables as $key => $value) {
                $text = str_replace('$' . $key, $value, $text);
            }
        }
        return $text;
    }

    function _rewriteImgSrc($input, $server)
    {
        return preg_replace('#<img src="#', '<img src="' . $server, $input);
    }

    // external callable methods, must start with external_
    // block this module

    function external_block($parameters, $source = 0, $show_output = true, $request_confirmation = true)
    {
        require_once(mh_cfg('MH_DIR_CONFIG') . 'config_block.php');
        list($customers_id, $email_address, $mode, $behaviour) = explode('|', base64_decode($parameters));

        $cfg_block = new config_block();

        if (mh_post('List-Unsubscribe') == 'One-Click') {
            $request_confirmation = false;
            $result = $cfg_block->process_block($this->module, $customers_id, $email_address, $source, true, $mode, $behaviour, $show_output, $request_confirmation);
        }

        $result = $cfg_block->process_block($this->module, $customers_id, $email_address, $source, true, $mode, $behaviour, $show_output, $request_confirmation);

        if ($show_output) {
            echo $result;
        } else {
            return $result;
        }
        mh_exit();
        return false;
    }


    function external_block_confirmed($parameters, $source = 0, $show_output = true, $request_confirmation = true) {
        return $this->external_block($parameters, $source, $show_output, false);
    }

    function external_unblock($parameters, $source = 0, $show_output = true)
    {
        require_once(mh_cfg('MH_DIR_CONFIG') . 'config_block.php');
        list($customers_id, $email_address, $mode, $behaviour) = explode('|', base64_decode($parameters));
        $cfg_block = new config_block();
        $result = $cfg_block->process_unblock($this->module, $customers_id, $email_address, $source, true, $mode, $behaviour);

        if ($show_output) {
            echo $result;
        } else {
            return $result;
        }

        mh_exit();
        return false;
    }

    function get_do_run()
    {
        if (mh_cfg('MAILBEEZ_CRON_ADVANCED_STATUS') == 'True' && file_exists(mh_cfg('MH_DIR_CONFIG') . 'config_cron_advanced.php')) {
            require_once(mh_cfg('MH_DIR_CONFIG') . 'config_cron_advanced.php');
            return config_cron_advanced::check_do_run_module($this->module, $this->get_module_id());
        }
        return $this->do_run;
    }

    function apply_theme($theme_id = '', $template_id = '')
    {
        return false;

        // deprecated
    }

    function set_preview_maintemplate_id($main_template_id) {
        $this->preview_maintemplate_id = $main_template_id;

    }

    function check_cloud() {
        if (mh_cfg('is_cloud')) {
            $this->enabled = false;
            $this->hidden = true;
        }
    }

    function set_preview_content_module_id($content_module_id) {
        $this->preview_content_module_id = $content_module_id;

    }




    function update($installed_version = null)
    {
        if (!mh_cfg('MAILBEEZ_INSTALLED_VERSIONS')) {
            return false;
        }

        $old_version = $this->get_installed_version($this->module);

        $updated = preg_replace('/' . $this->module . '\|' . $old_version . '/', $this->module . '|' . $this->version, mh_cfg('MAILBEEZ_INSTALLED_VERSIONS'));

        mh_insert_config_value(array('configuration_title' => 'Installed Modules',
            'configuration_key' => 'MAILBEEZ_INSTALLED_VERSIONS',
            'configuration_value' => $updated,
            'configuration_description' => 'This is automatically updated. No need to edit.',
            'set_function' => ''
        ), true);

        mh_reset_config_cache();
        return true;
    }

    function simulation_restart()
    {
        // todo
        return false;
    }

    static function html_header($stylesheet = '')
    {
        global $request_type;

        ob_start();
        ?><!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html <?php echo mh_cfg('HTML_PARAMS'); ?>>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=<?php echo mh_cfg('CHARSET'); ?>">
            <title>MAILHIVE MEMORY <?php echo ini_get('memory_limit'); ?></title>
            <base href="<?php echo (($request_type == 'SSL') ? HTTPS_SERVER : HTTP_SERVER) . MH_DIR_WS_CATALOG; ?>">

            <link rel="stylesheet" type="text/css" media="print, projection, screen"
                  href="<?php echo mh_cfg('MH_CATALOG_SERVER') . mh_cfg('MH_DIR_WS_CATALOG') . mh_cfg('MH_ROOT_PATH'); ?>common/common.css?ver=<?php echo mh_cfg('MAILBEEZ_VERSION'); ?>">
            <?php if ($stylesheet != '') { ?>
                <link rel="stylesheet" type="text/css" media="print, projection, screen"
                      href="<?php echo mh_cfg('MH_CATALOG_SERVER') . mh_cfg('MH_DIR_WS_CATALOG') . mh_cfg('MH_ROOT_PATH'); ?><?php echo $stylesheet ?>">
            <?php } ?>
        </head>
    <body marginwidth="0" marginheight="0" topmargin="0" bottommargin="0" leftmargin="0" rightmargin="0">
        <?php
        $output = ob_get_contents();
        ob_end_clean();
        return $output;
    }


    static function html_footer()
    {
        ob_start();
        ?>
        </body>
        </html>
        <?php
        $output = ob_get_contents();
        ob_end_clean();
        return $output;
    }


    static function output_flush()
    {
        echo str_repeat(" ", 4096); // force a flush
        echo '<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">
      <!--
      scrolldown();
      //-->
      </SCRIPT>';
        ob_flush();
        flush();
    }

// added mailbeez V2.803


    function get_maintemplate_id() {
        if (class_exists('template_manager')) {
            if (method_exists('template_manager','get_maintemplate_id')) {
                return template_manager::get_maintemplate_id($this);
            }
        }
        return false;
    }


    function get_content_module_id() {
        if (class_exists('template_manager')) {
            if (method_exists('template_manager','get_content_module_id')) {
                return template_manager::get_content_module_id($this);
            }
        }
        return false;
    }



    function get_mainstyling_id() {
        if (class_exists('template_manager')) {
            if (method_exists('template_manager','get_mainstyling_id')) {
                return template_manager::get_mainstyling_id($this);
            }
        }
        return false;
    }


}

// end of class
