      1: <?php
      2:
      3: // load config
      4: if(!isset($config)) {
      5:     require_once 'AlphaConfig.inc';
      6:     $config = AlphaConfig::getInstance();
      7:
      8:     require_once $config->get('app.root').'alpha/util/AlphaAutoLoader.inc';
      9: }
     10:
     11: /**
     12:  *
     13:  * The main class responsible for running custom cron tasks found under the [webapp]/tasks
     14:  * directory.  This class should be executed from Linux cron via the CLI.
     15:  *
     16:  * @package alpha::util
     17:  * @since 1.0
     18:  * @author John Collins <dev@alphaframework.org>
     19:  * @version $Id: AlphaCronManager.inc 1548 2012-07-29 17:07:07Z alphadevx $
     20:  * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
     21:  * @copyright Copyright (c) 2012, John Collins (founder of Alpha Framework).
     22:  * All rights reserved.
     23:  *
     24:  * <pre>
     25:  * Redistribution and use in source and binary forms, with or
     26:  * without modification, are permitted provided that the
     27:  * following conditions are met:
     28:  *
     29:  * * Redistributions of source code must retain the above
     30:  *   copyright notice, this list of conditions and the
     31:  *   following disclaimer.
     32:  * * Redistributions in binary form must reproduce the above
     33:  *   copyright notice, this list of conditions and the
     34:  *   following disclaimer in the documentation and/or other
     35:  *   materials provided with the distribution.
     36:  * * Neither the name of the Alpha Framework nor the names
     37:  *   of its contributors may be used to endorse or promote
     38:  *   products derived from this software without specific
     39:  *   prior written permission.
     40:  *
     41:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
     42:  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
     43:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     44:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     45:  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     46:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     47:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     48:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     49:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     50:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     51:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     52:  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     53:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     54:  * </pre>
     55:  *
     56:  */
     57: class AlphaCronManager {
     58:     /**
     59:      * Trace logger
     60:      *
     61:      * @var Logger
     62:      * @since 1.0
     63:      */
     64:     private static $logger = null;
     65:
     66:     /**
     67:      * Constructor
     68:      *
     69:      * @since 1.0
     70:      */
     71:     public function __construct() {
     72:         global $config;
     73:
     74:         self::$logger = new Logger('AlphaCronManager');
     75:         self::$logger->setLogFile($config->get('app.root').'logs/tasks.log');
     76:
     77:         self::$logger->debug('>>__construct()');
     78:
     79:         self::$logger->info('New AlphaCronManager invoked');
     80:
     81:         $taskList = self::getTaskClassNames();
     82:
     83:         self::$logger->info('Found ['.count($taskList).'] tasks in the directory ['.$config->get('app.root').'tasks]');
     84:
     85:         foreach($taskList as $taskClass) {
     86:             self::$logger->info('Loading task ['.$taskClass.']');
     87:             self::loadClassDef($taskClass);
     88:             $task = new $taskClass;
     89:
     90:             $startTime = microtime(true);
     91:             $maxAllowedTime = $startTime+$task->getMaxRunTime();
     92:
     93:             self::$logger->info('Start time is ['.$startTime.'], maximum task run time is ['.$task->getMaxRunTime().']');
     94:
     95:             // only continue to execute for the task max time
     96:             set_time_limit($task->getMaxRunTime());
     97:             $task->doTask();
     98:
     99:             self::$logger->info('Done in ['.round(microtime(true)-$startTime, 5).'] seconds');
    100:         }
    101:
    102:         self::$logger->info('Finished processing all cron tasks');
    103:
    104:         self::$logger->debug('<<__construct');
    105:     }
    106:
    107:     /**
    108:      * Loops over the /tasks directory and builds an array of all of the task
    109:      * class names in the system.
    110:      *
    111:      * @return array
    112:      * @since 1.0
    113:      */
    114:     public static function getTaskClassNames() {
    115:         global $config;
    116:
    117:         if(self::$logger == null) {
    118:             self::$logger = new Logger('AlphaCronManager');
    119:             self::$logger->setLogFile($config->get('app.root').'logs/tasks.log');
    120:         }
    121:         self::$logger->debug('>>getTaskClassNames()');
    122:
    123:         global $config;
    124:
    125:         $classNameArray = array();
    126:
    127:         $handle = opendir($config->get('app.root').'tasks');
    128:
    129:         // loop over the custom task directory
    130:         while (false !== ($file = readdir($handle))) {
    131:             if (preg_match("/Task.inc/", $file)) {
    132:                 $classname = substr($file, 0, -4);
    133:
    134:                 array_push($classNameArray, $classname);
    135:             }
    136:         }
    137:
    138:         $handle = opendir($config->get('app.root').'alpha/tasks');
    139:
    140:         // loop over the custom task directory
    141:         while (false !== ($file = readdir($handle))) {
    142:             if (preg_match("/Task.inc/", $file)) {
    143:                 $classname = substr($file, 0, -4);
    144:
    145:                 array_push($classNameArray, $classname);
    146:             }
    147:         }
    148:
    149:         self::$logger->debug('<<getTaskClassNames ['.var_export($classNameArray, true).']');
    150:         return $classNameArray;
    151:     }
    152:
    153:     /**
    154:      * Loads the definition for the task classname provided
    155:      *
    156:      * @param string $classname
    157:      * @since 1.0
    158:      */
    159:     public static function loadClassDef($classname) {
    160:         global $config;
    161:
    162:         if(self::$logger == null) {
    163:             self::$logger = new Logger('AlphaCronManager');
    164:             self::$logger->setLogFile($config->get('app.root').'logs/tasks.log');
    165:         }
    166:         self::$logger->debug('>>loadClassDef(classname=['.$classname.'])');
    167:
    168:         if(file_exists($config->get('app.root').'tasks/'.$classname.'.inc'))
    169:             require_once $config->get('app.root').'tasks/'.$classname.'.inc';
    170:         elseif(file_exists($config->get('app.root').'alpha/tasks/'.$classname.'.inc'))
    171:             require_once $config->get('app.root').'alpha/tasks/'.$classname.'.inc';
    172:         else
    173:             throw new IllegalArguementException('The class ['.$classname.'] is not defined anywhere!');
    174:
    175:         self::$logger->debug('<<loadClassDef');
    176:     }
    177: }
    178:
    179: // invoke a cron manager object
    180: $processor = new AlphaCronManager();
    181:
    182: ?>