<?php
/**
 * ExecuteService File
 *
 * @category Admin
 * @package  ClientExec
 * @author   Alberto Vasquez <alberto@clientexec.com>
 * @license  ClientExec License
 * @version  [someversion]
 * @link     http://www.clientexec.com
 */

require_once 'newedge/classes/NE_PluginCollection.php';

/**
 * ExecuteService Action Class
 *
 * @category Admin
 * @package  ClientExec
 * @author   Alberto Vasquez <alberto@clientexec.com>
 * @license  ClientExec License
 * @version  [someversion]
 * @link     http://www.clientexec.com
 */
class ExecuteService extends NE_Action
{
    var $permission     = '';

    // user authentication and permission validation done inside dispatch()

    /**
     * Action's dispatch method
     *
     * @return redirect
     */
    function dispatch()
    {
        if (defined('RUNNING_SERVICE_SCRIPT')) {
            // *************************
            // Running from outside CE
            // *************************
            $companyId = @$_SERVER['argv'][2];
            if ($companyId) {
                require_once 'modules/support/models/SupportExec/SupportExecCompanyGateway.php';
                NE_Registry::setCompany(SupportExecCompanyGateway::getById($companyId));
            }

            if (isset($_GET['service']) && $this->settings->get('Allow run services from URL')) {
                $runService = $_GET['service'];
                $logStr = "services.php called for service '$runService'";
                if ($companyId > 0) {
                    $logStr .= " for company $companyId";
                }
                $manuallyExecuted = 2;
                $this->logger->log(3, "** OUTSIDE SERVICE REQUEST **: $logStr");
            } elseif ($runService = @$_SERVER['argv'][1]) {
                $logStr = "services.php called for service '$runService'";
                if ($companyId > 0) {
                    $logStr .= " for company $companyId";
                }
                $this->logger->log(3, "** CRON REQUEST **: $logStr");
                $manuallyExecuted = 0;
            } else {
                die('Service not defined or services not set up to run from the URL.');
            }

            if ($this->settings->get("plugin_{$runService}_Enabled") != 1) {
                die("Service $runService is not Enabled.");
            }
        } else {
            // ************************
            // Running from inside CE
            // ************************
            if (!isset($_SESSION['userId'])) {
                NE_Lib::redirectPage('index.php?fuse=admin&amp;view=Login');
            }
            if (!$this->user->hasPermission('admin_manage_plugins')) {
                trigger_error("You don't have enough permissions to trigger this action", E_USER_ERROR);
                exit;
            }

            if (!isset($_GET['service'])) {
                die('Service not defined.');
            }
            $manuallyExecuted = 1;
            $runService = $_GET['service'];
        }
        
        // set timelimit to 0, as a service can take time to run.
        @set_time_limit(0);

        $info = $this->settings->get('service_' . $runService . '_info');
        if ( $info == null ) {
            $this->settings->insertValue('service_' . $runService . '_info', '', '');
            $this->db->query('UPDATE `setting` SET ishidden=1 WHERE name=?', 'service_' . $runService . '_info');
            $info = array();
        } else {
            $info = @unserialize($info);
        }

        // ServicePlugin required for service status defines.
        require_once 'modules/admin/models/ServicePlugin.php';
        include_once ("modules/admin/models/PluginGateway.php");
        $gateway = new PluginGateway($this->user);
        $plugin = $gateway->getServicePluginByName($runService);

        // Ensure we have data for the plugin before trying to use it.
        if ( is_array($info) && array_key_exists('status', $info) ) {
            $tmpInfo = $info;
            $oldInfo = $info;
        } else {
            $oldInfo = "";
        }
        $time = array();
        if(isset($tmpInfo['time'])){
            $time = NE_Lib::date_diff_hrs($tmpInfo['time'], date('Y-m-d H:i:s'));
        }
        
        // Stop running the service if it's till in process, and has been running for less then 30 minutes
        if ( isset($tmpInfo['status']) && $tmpInfo['status'] == SERVICE_STATUS_IN_PROCESS && isset($tmpInfo['time']) && $time['h'] == 0 && $time['m'] < 30 ) {
            $this->logger->log(3, "Service '$runService' is already running. Service request ignored.");
            return;
        }

        // Update to be in status.
        $tmpInfo['time'] = date('Y-m-d H:i:s');
        $tmpInfo['manually_executed'] = $manuallyExecuted;
        $tmpInfo['results'] = '';
        $tmpInfo['errors'] = '';
        $tmpInfo['status'] = SERVICE_STATUS_IN_PROCESS;
        $tmpInfo['extra_info'] = @$info['extra_info'];
        $this->settings->updateValue('service_' . $runService . '_info', serialize($tmpInfo));

        $messages = $plugin->execute($oldInfo);
        $errors = '';
        $results = '';
        if (is_array($messages)) {
            foreach ($messages as $message) {
                if (is_a($message, 'NE_Error')) {
                    $errors .= $message->getMessage()."\n";
                } else{
                    $results .= "$message\n";
                }
            }
        }

        // Grab an array of plugin information, since it could have been changed in the plugin
        $info = @unserialize($this->settings->get('service_' . $runService . '_info'));

        // Update to be finished
        $tmpInfo['time'] = date('Y-m-d H:i:s');
        $tmpInfo['manually_executed'] = $manuallyExecuted;
        $tmpInfo['results'] = $results;
        $tmpInfo['errors'] = $errors;
        $tmpInfo['status'] = SERVICE_STATUS_FINISHED;
        $tmpInfo['extra_info'] = @$info['extra_info'];
        $this->settings->updateValue('service_' . $runService . '_info', serialize($tmpInfo));

        if (defined('RUNNING_SERVICE_SCRIPT') && $errors) {
            echo "Errors calling plugin ".$plugin->getInternalName().":\n$errors\n";
            if ($recipients = $this->settings->get('Application Error Notification')) {
                include_once 'newedge/classes/NE_MailGateway.php';
                $mailGateway = new NE_MailGateway();
                $body = "ClientExec automated error notification\n\nThe service plugin ".$this->settings->get("plugin_".$plugin->getInternalName()."_Plugin Name")." generated the following error(s):\n$errors\n";

                $recipients = explode("\r\n", $recipients);
                foreach ($recipients as $recipient) {
                    // bypass mail queue, because it could be it the one failing, creating thus an infinite loop
                    $mailSend = $mailGateway->mailMessageEmail( 
                        array('HTML' => null, 'plainText' => $body),
                        $this->settings->get('Support E-mail'),
                        $this->settings->get('Support E-mail'),
                        $recipient,
                        '',
                        'ClientExec Service Plugin Error Notification',
                        1
                    );
                    if (is_a($mailSend, 'NE_Error')) {
                        echo $mailSend->getMessage();
                    }
                }
            }
        }

        if (!defined('RUNNING_SERVICE_SCRIPT') && $errors) {
            NE_Lib::addMessage(nl2br($errors));
            NE_Lib::addMessage(nl2br($results));
        }

        if (!defined('RUNNING_SERVICE_SCRIPT') && !$errors) {
            NE_Lib::addMessage($this->lang('Service executed successfully'));
            NE_Lib::addMessage(nl2br($results));
        }

        if (!defined('RUNNING_SERVICE_SCRIPT')) {
            NE_Lib::redirectPage("index.php?setting=".$_REQUEST['service']."&amp;fuse=admin&amp;view=Services");
        }
    }
}
?>
