Guest User

Untitled

a guest
Nov 14th, 2012
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <?php
  2.  
  3. /**
  4.  * The abstract class which every cron job class needs to be extending for it
  5.  * to function properly. Nothing here needs to be changed, but if you feel it's
  6.  * required to do so, please contact the author first.
  7.  *
  8.  * @author Stefan van Beusekom
  9.  * @version 1.1
  10.  * @abstract
  11.  */
  12. abstract class Callcenter_Model_Cron_Abstract {
  13.  
  14.     protected $_errorList = array();
  15.     protected $_handleExecList = false;
  16.     protected $_lastExecuted = false;
  17.     protected $_startScript = false;
  18.     protected $_endScript = false;
  19.     protected $_executionSuccessful = false;
  20.  
  21.     /**
  22.      * Set the time limit for script execution
  23.      *
  24.      * @author Stefan van Beusekom
  25.      * @since 1.1
  26.      */
  27.     protected function setTimelimit() {
  28.         $childClass = get_called_class();
  29.         set_time_limit(($childClass::CRON_TIMEOUT_MINUTES * 60) + $childClass::CRON_TIMEOUT_SECONDS);
  30.         return $this;
  31.     }
  32.  
  33.     /**
  34.      * Set the date and time string of when this cronjob was started
  35.      *
  36.      * @author Stefan van Beusekom
  37.      * @since 1.1
  38.      */
  39.     protected function setStartScript() {
  40.         $dateTime = new DateTime();
  41.         $this->_startScript = $dateTime->format("Y-m-d H:i:s");
  42.         return $this;
  43.     }
  44.  
  45.     /**
  46.      * Set the date and time string of when this cronjob ended
  47.      *
  48.      * @author Stefan van Beusekom
  49.      * @since 1.1
  50.      */
  51.     protected function setEndScript() {
  52.         $dateTime = new DateTime();
  53.         $this->_endScript = $dateTime->format("Y-m-d H:i:s");
  54.         return $this;
  55.     }
  56.  
  57.     /**
  58.      * Get the path to the cronjob folder
  59.      *
  60.      * @author Stefan van Beusekom
  61.      * @since 1.0
  62.      * @return string
  63.      */
  64.     protected function getCronPath($file = null) {
  65.         return APPLICATION_PATH . "/../cron/" . $file;
  66.     }
  67.  
  68.     /**
  69.      * Add an error for the current cronjob
  70.      *
  71.      * @author Stefan van Beusekom
  72.      * @since 1.0
  73.      * @param string $error Error message
  74.      */
  75.     protected function addError($error) {
  76.         array_push($this->_errorList, $error);
  77.     }
  78.  
  79.     /**
  80.      * Return a list of errors for the current cronjob
  81.      *
  82.      * @author Stefan van Beusekom
  83.      * @since 1.0
  84.      * @return array
  85.      */
  86.     protected function getErrors() {
  87.         return $this->_errorList;
  88.     }
  89.  
  90.     /**
  91.      * Set the current timestamp of when this cronjob was last executed
  92.      *
  93.      * @author Stefan van Beusekom
  94.      * @since 1.0
  95.      */
  96.     protected function setLastExecuted() {
  97.         $this->_handleExecList = fopen($this->getCronPath(get_called_class() . ".cron"), "w+");
  98.         $cronArray = fread($this->_handleExecList, filesize($this->getCronPath(get_called_class() . ".cron")));
  99.         if (($cronArray) == '')
  100.             $cronArray = array();
  101.         else
  102.             $cronArray = unserialize($cronArray);
  103.         $this->_lastExecuted = time();
  104.         $cronArray[get_called_class()] = $this->_lastExecuted;
  105.         fwrite($this->_handleExecList, serialize($cronArray));
  106.         fclose($this->_handleExecList);
  107.         return $this;
  108.     }
  109.  
  110.     /**
  111.      * Get the timestamp of when this cronjob was last executed
  112.      *
  113.      * @author Stefan van Beusekom
  114.      * @since 1.0
  115.      * @return int|boolean
  116.      */
  117.     protected function getLastExecuted() {
  118.         if (!$this->_lastExecuted) {
  119.             if (file_exists($this->getCronPath(get_called_class() . ".cron"))) {
  120.                 $this->_handleExecList = fopen($this->getCronPath(get_called_class() . ".cron"), "r");
  121.                 $cronArray = fread($this->_handleExecList, filesize($this->getCronPath(get_called_class() . ".cron")));
  122.                 if (!$cronArray)
  123.                     $cronArray = array();
  124.                 else
  125.                     $cronArray = unserialize($cronArray);
  126.                 return (key_exists(get_called_class(), $cronArray)) ? $cronArray[get_called_class()] : 0;
  127.             } else {
  128.                 return 0;
  129.             }
  130.         } else {
  131.             return $this->_lastExecuted;
  132.         }
  133.     }
  134.  
  135.     /**
  136.      * Return a true or false if the current cronjob is allowed to run based on
  137.      * the timestamps.
  138.      *
  139.      * @author Stefan van Beusekom
  140.      * @since 1.0
  141.      * @return boolean
  142.      */
  143.     protected function allowExecute() {
  144.         $childClass = get_called_class();
  145.         $dateTimePre = new DateTime();
  146.         $dateTimePre->setTimestamp($this->getLastExecuted());
  147.         $dateTimePre->setTime($dateTimePre->format("H"), $dateTimePre->format("i"), 0);
  148.  
  149.         if ($childClass::CRON_INTERVAL_HOURS != 0)
  150.             $dateTimePre->setTime($dateTimePre->format("H"), 0, 0);
  151.         if ($childClass::CRON_INTERVAL_DAYS != 0)
  152.             $dateTimePre->setTime(0, 0, 0);
  153.  
  154.         $currentSeconds = (time() - $dateTimePre->getTimestamp());
  155.         $intervalSeconds = ($childClass::CRON_INTERVAL_DAYS * 24 * 60 * 60) + ($childClass::CRON_INTERVAL_HOURS * 60 * 60) + ($childClass::CRON_INTERVAL_MINUTES * 60);
  156.  
  157.         $curDateObj = new DateTime();
  158.         $allDateObj = new DateTime($childClass::CRON_START_DATETIME);
  159.  
  160.         if ($curDateObj->getTimestamp() < $allDateObj->getTimestamp())
  161.             return false;
  162.  
  163.         if ($currentSeconds >= $intervalSeconds)
  164.             return true;
  165.         else
  166.             return false;
  167.     }
  168.  
  169.     /**
  170.      * Append the log with data pertaining to the execution, or failure thereof
  171.      *
  172.      * @author Stefan van Beusekom
  173.      * @since 1.0
  174.      */
  175.     protected function addLog() {
  176.         $fileHandle = fopen($this->getCronPath(get_called_class() . ".txt"), "a");
  177.         $dateObjectStart = new DateTime($this->_startScript);
  178.         $dateObjectEnd = new DateTime($this->_endScript);
  179.         $datePrefix = "[" . $dateObjectStart->format("d-m-Y H:i:s") . "][" . $dateObjectEnd->format("d-m-Y H:i:s") . "] ";
  180.         $logEntry = "";
  181.         if ($this->isSuccessful()) {
  182.             $logEntry .= $datePrefix . "Cronjob was completed successfully." . "\r\n";
  183.         } else {
  184.             $errorPrefix = str_pad("", strlen($datePrefix), " ", STR_PAD_LEFT);
  185.             $logEntry .= $datePrefix . "Cronjob could not be completed. The following errors occurred:" . "\r\n";
  186.             foreach ($this->getErrors() as $error) {
  187.                 $logEntry .= $errorPrefix . $error . "\r\n";
  188.             }
  189.         }
  190.         fwrite($fileHandle, $logEntry);
  191.         fclose($fileHandle);
  192.     }
  193.  
  194.     /**
  195.      * Return a true or false if the current cronjob has been successful
  196.      *
  197.      * @author Stefan van Beusekom
  198.      * @since 1.0
  199.      * @return boolean
  200.      */
  201.     protected function isSuccessful() {
  202.         return ((count($this->getErrors()) == 0) ? true : false);
  203.     }
  204.  
  205.     /**
  206.      * The on exit callback which will produce an error message despite an
  207.      * uncatchable error being thrown.
  208.      *
  209.      * @author Stefan van Beusekom
  210.      * @since 1.1
  211.      * @todo Although this method logs the error, nothing can be done about its
  212.      *       ability to continue running other cronjobs. Search for possible
  213.      *       solution to this problem. Might use a redirect with 'failedClass'
  214.      *       parameter, so the controller can remove it from the queue, and run
  215.      *       the non-faulty cron jobs.
  216.      */
  217.     public function onExecute() {
  218.         if (!$this->_executionSuccessful) {
  219.             $errorMessage = "CRITICAL ERROR - Entire cron process was abruptly halted due to an uncatchable error. Please disable this class until the problem has been resolved. - No stack trace is available for debugging, but common errors are: faulty code, maximum execution time exceeded, or a server crash.";
  220.             $this->addError($errorMessage);
  221.             $this->addLog();
  222.         }
  223.     }
  224.  
  225.     /**
  226.      * Execute the cronjob
  227.      *
  228.      * @author Stefan van Beusekom
  229.      * @since 1.0
  230.      * @return boolean
  231.      */
  232.     public function execute() {
  233.         register_shutdown_function(array($this, "onExecute"));
  234.         $this->setTimelimit();
  235.         if ($this->allowExecute()) {
  236.             $this->setStartScript();
  237.             try {
  238.                 $this->task();
  239.             } catch (Exception $e) {
  240.                 $this->addError("The current task generated an exception, message: " . $e->getMessage());
  241.             }
  242.             if ($this->isSuccessful()) {
  243.                 $this->addLog();
  244.                 $this->setEndScript();
  245.                 $this->setLastExecuted();
  246.             } else {
  247.                 $this->addLog();
  248.             }
  249.             $this->_executionSuccessful = true;
  250.             return $this->isSuccessful();
  251.         }
  252.         $this->_executionSuccessful = true;
  253.         return false;
  254.     }
  255.  
  256.     /**
  257.      * Task to be executed
  258.      *
  259.      * @author Stefan van Beusekom
  260.      * @since 1.0
  261.      */
  262.     protected abstract function task();
  263. }
  264.  
  265. ?>
Advertisement
Add Comment
Please, Sign In to add comment