<?php    
class cron extends control
{
    /**
     * Ajax exec cron.
     * 
     * @access public
     * @return void
     */
    public function ajaxExec()
    {
        ignore_user_abort(true);
        set_time_limit(0);
        session_write_close();
        /* Check cron turnon. */
        if(empty($this->config->global->cron)) die();
    
        /* make cron status to running. */
        $configID = $this->cron->getConfigID();
        $configID = $this->cron->markCronStatus('running', $configID);
    
        /* Get and parse crons. */
        $crons       = $this->cron->getCrons('nostop');
        $parsedCrons = $this->cron->parseCron($crons);
    
        /* Update last time. */
        $this->cron->changeStatus(key($parsedCrons), 'normal', true);
        $startedTime = time();
        while(true)
        {
            dao::$cache = array();
            /* When cron is null then die. */
            if(empty($crons)) break;
            if(empty($parsedCrons)) break;
            if(!$this->config->global->cron) break;
    
            /* Run crons. */
            $now = new datetime('now');
            foreach($parsedCrons as $id => $cron)
            {
                $cronInfo = $this->cron->getById($id);
                /* Skip empty and stop cron.*/
                if(empty($cronInfo) or $cronInfo->status == 'stop') continue;
                /* Skip cron that status is running and run time is less than max. */
                if($cronInfo->status == 'running' and (time() - strtotime($cronInfo->lastTime)) < $this->config->cron->maxRunTime) continue;
                /* Skip cron that last time is more than this cron time. */
                if($cronInfo->lastTime > $cron['time']->format(DT_DATETIME1)) die();
    
                if($now > $cron['time'])
                {
                    $this->cron->changeStatus($id, 'running');
                    $parsedCrons[$id]['time'] = $cron['cron']->getNextRunDate();
    
                    /* Execution command. */
                    $output = '';
                    $return = '';
                    if($cron['command'])
                    {
                        if(isset($crons[$id]) and $crons[$id]->type == 'ranzhi')
                        {
                            parse_str($cron['command'], $customParams);
                            unset($customParams['moduleName']);
                            unset($customParams['methodName']);
                            unset($customParams['appName']);
    
                            parse_str($cron['command'], $params);
                            if(isset($params['moduleName']) and isset($params['methodName']) and isset($params['appName']))
                            {
                                $output = $this->fetch($params['moduleName'], $params['methodName'], $customParams, $params['appName']);
                            }
                        }
                        if(isset($crons[$id]) and $crons[$id]->type == 'xuanxuan')
                        {
                            parse_str($cron['command'], $params);
                            if(isset($params['moduleName']) and isset($params['methodName']))
                            {
                                $output = $this->fetch($params['moduleName'], $params['methodName']);
                            }
                        }
                        elseif(isset($crons[$id]) and $crons[$id]->type == 'system')
                        {
                            exec($cron['command'], $output, $return);
                            if($output) $output = join("\n", $output);
                        }
    
                        /* Save log. */
                        $log  = '';
                        $time = $now->format('G:i:s');
                        $log  = "$time task " .  $id . " executed,\ncommand: $cron[command].\nreturn : $return.\noutput : $output\n";
                        $this->cron->logCron($log);
                        unset($log);
                    }
    
                    /* Revert cron status. */
                    $this->cron->changeStatus($id, 'normal');
                }
            }
    
            /* Check whether the task change. */
            $newCrons = $this->cron->getCrons('nostop');
            $changed  = $this->cron->checkChange();
            if(count($newCrons) != count($crons) or $changed)
    
            {
                $crons       = $newCrons;
                $parsedCrons = $this->cron->parseCron($newCrons);
            }
    
            /* Sleep some seconds. */
            $sleepTime = 60 - ((time() - $now->getTimestamp()) % 60);
            sleep($sleepTime);
    
            /* Break while. */
            if(connection_status() != CONNECTION_NORMAL) break;
            if(((time() - $startedTime) / 3600 / 24) >= $this->config->cron->maxRunDays) break;
        }
    
        /* Revert cron status to stop. */
        $this->cron->markCronStatus('stop', $configID);
    }
}
