Cron.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. <?php
  2. namespace app\framework\Cron;
  3. use app\common\services\SystemMsgService;
  4. use Illuminate\Support\Facades\Redis;
  5. /**
  6. * Cron
  7. *
  8. * Cron job management
  9. * NOTE: The excellent library mtdowling/cron-expression (https://github.com/mtdowling/cron-expression) is required.
  10. *
  11. * @package Cron
  12. * @author Marc Liebig
  13. */
  14. class Cron
  15. {
  16. /**
  17. * @static
  18. * @var array Saves all the cron jobs
  19. */
  20. private static $cronJobs = array();
  21. /**
  22. * @static
  23. * @var \Monolog\Logger Logger object Monolog logger object if logging is wished or null if nothing should be logged to this logger
  24. */
  25. private static $logger;
  26. function __construct()
  27. {
  28. }
  29. /**
  30. * Add a cron job
  31. *
  32. * Expression definition:
  33. *
  34. * * * * * * *
  35. * - - - - - -
  36. * | | | | | |
  37. * | | | | | + year [optional]
  38. * | | | | +----- day of week (0 - 7) (Sunday=0 or 7)
  39. * | | | +---------- month (1 - 12)
  40. * | | +--------------- day of month (1 - 31)
  41. * | +-------------------- hour (0 - 23)
  42. * +------------------------- min (0 - 59)
  43. *
  44. * @static
  45. * @param string $name The name for the cron job - has to be unique
  46. * @param string $expression The cron job expression (e.g. for every minute: '* * * * *')
  47. * @param callable $function The anonymous function which will be executed
  48. * @param bool $isEnabled optional If the cron job should be enabled or disabled - the standard configuration is enabled
  49. * @throws \InvalidArgumentException if one of the parameters has the wrong data type, is incorrect or is not set
  50. */
  51. public static function add($name, $expression, $function, $isEnabled = true)
  52. {
  53. // Check if the given job name is set and is a string
  54. if (!isset($name) || !is_string($name)) {
  55. throw new \InvalidArgumentException('Method argument $name is not set or not a string.');
  56. }
  57. // Check if the given expression is set and is correct
  58. if (!isset($expression) || count(explode(' ', $expression)) < 5 || count(explode(' ', $expression)) > 6) {
  59. throw new \InvalidArgumentException('Method argument $expression is not set or invalid.');
  60. }
  61. // Check if the given closure is set and is callabale
  62. if (!isset($function) || !is_callable($function)) {
  63. throw new \InvalidArgumentException('Method argument $function is not set or not callable.');
  64. }
  65. // Check if the given isEnabled flag is set and is a boolean
  66. if (!isset($isEnabled) || !is_bool($isEnabled)) {
  67. throw new \InvalidArgumentException('Method argument $isEnabled is not set or not a boolean.');
  68. }
  69. // Check if the name is unique
  70. foreach (self::$cronJobs as $job) {
  71. if ($job['name'] === $name) {
  72. \Log::error('Cron job $name "' . $name . '" is not unique and already used.',$job);
  73. throw new \InvalidArgumentException('Cron job $name "' . $name . '" is not unique and already used.');
  74. }
  75. }
  76. // Create the CronExpression - all the magic goes here
  77. $expression = \Cron\CronExpression::factory($expression);
  78. // Add the new created cron job to the many other little cron jobs
  79. array_push(self::$cronJobs, array('name' => $name, 'expression' => $expression, 'enabled' => $isEnabled, 'function' => $function));
  80. }
  81. /**
  82. * Remove a cron job by name
  83. *
  84. * @static
  85. * @param string $name The name of the cron job which should be removed from execution
  86. * @return bool Return true if a cron job with the given name was found and was successfully removed or return false if no job with the given name was found
  87. */
  88. public static function remove($name)
  89. {
  90. foreach (self::$cronJobs as $jobKey => $jobValue) {
  91. if ($jobValue['name'] === $name) {
  92. unset(self::$cronJobs[$jobKey]);
  93. return true;
  94. }
  95. }
  96. return false;
  97. }
  98. private static function lockJob($jobName)
  99. {
  100. if ($pid = Redis::hget('RunningCronJobs', $jobName)) {
  101. if (posix_kill($pid, 0)) {
  102. // 正在运行
  103. return false;
  104. }else{
  105. Redis::hdel('RunningCronJobs', $jobName);
  106. }
  107. }
  108. Redis::hset('RunningCronJobs', $jobName, getmypid());
  109. return true;
  110. }
  111. private static function unlockJob($jobName)
  112. {
  113. Redis::hdel('RunningCronJobs', $jobName);
  114. }
  115. /**
  116. * Run the cron jobs
  117. * This method checks and runs all the defined cron jobs at the right time
  118. * This method (route) should be called automatically by a server or service
  119. *
  120. * @static
  121. * @param bool $checkRundateOnce optional When we check if a cronjob is due do we take into account the time when the run function was called ($checkRundateOnce = true) or do we take into account the time when each individual cronjob is executed ($checkRundateOnce = false) - default value is true
  122. * @return array Return an array with the rundate, runtime, errors and a result cron job array (with name, function return value, runtime in seconds)
  123. */
  124. public static function run($checkRundateOnce = true)
  125. {
  126. // If a new lock file is created, $overlappingLockFile will be equals the file path
  127. $overlappingLockFile = "";
  128. try {
  129. // Get the rundate
  130. $runDate = new \DateTime();
  131. // Fire event before the Cron run will be executed
  132. \Event::dispatch('cron.beforeRun', array($runDate->getTimestamp()));
  133. // Check if prevent job overlapping is enabled and create lock file if true
  134. $preventOverlapping = self::getConfig('preventOverlapping', false);
  135. if (is_bool($preventOverlapping) && $preventOverlapping) {
  136. $storagePath = "";
  137. // Fallback function for Laravel3 with helper function path('storage')
  138. if (function_exists('storage_path')) {
  139. $storagePath = storage_path();
  140. } else if (function_exists('path')) {
  141. $storagePath = path('storage');
  142. }
  143. if (!empty($storagePath)) {
  144. $lockFile = $storagePath . DIRECTORY_SEPARATOR . 'cron.lock';
  145. if (file_exists($lockFile)) {
  146. self::log('warning', 'Lock file found - Cron is still running and prevent job overlapping is enabled - second Cron run will be terminated.');
  147. // Fire the Cron locked event
  148. \Event::dispatch('cron.locked', array('lockfile' => $lockFile));
  149. // Fire the after run event, because we are done here
  150. \Event::dispatch('cron.afterRun', array('rundate' => $runDate->getTimestamp(), 'inTime' => -1, 'runtime' => -1, 'errors' => 0, 'crons' => array(), 'lastRun' => array()));
  151. return array('rundate' => $runDate->getTimestamp(), 'inTime' => -1, 'runtime' => -1, 'errors' => 0, 'crons' => array(), 'lastRun' => array());
  152. } else {
  153. // Create lock file
  154. touch($lockFile);
  155. if (!file_exists($lockFile)) {
  156. self::log('error', 'Could not create Cron lock file at ' . $lockFile . '.');
  157. } else {
  158. // Lockfile created successfully
  159. // $overlappingLockFile is used to delete the lock file after Cron run
  160. $overlappingLockFile = $lockFile;
  161. }
  162. }
  163. } else {
  164. self::log('error', 'Could not get the path to the Laravel storage directory.');
  165. }
  166. }
  167. // Get the run interval from Laravel config
  168. // Initialize the job and job error array and start the runtime calculation
  169. $allJobs = array();
  170. $errorJobs = array();
  171. $beforeAll = microtime(true);
  172. // Should we check if the cron expression is due once at method call
  173. if ($checkRundateOnce) {
  174. $checkTime = $runDate;
  175. } else {
  176. // or do we compare it to 'now'
  177. $checkTime = 'now';
  178. }
  179. // For all defined cron jobs run this
  180. self::log('info', $checkTime->getTimestamp() .' 定时任务开始');
  181. foreach (self::$cronJobs as $job) {
  182. // If the job is enabled and if the time for this job has come
  183. if ($job['enabled'] && $job['expression']->isDue($checkTime)) {
  184. // Get the start time of the job runtime
  185. $beforeOne = microtime(true);
  186. // Run the function and save the return to $return - all the magic goes here
  187. try {
  188. self::log('info', $checkTime->getTimestamp().':'.$job['name'] .' start');
  189. if (!self::lockJob($job['name'])) {
  190. // 避免重复运行
  191. continue;
  192. }
  193. $return = $job['function']();
  194. self::unlockJob($job['name']);
  195. self::log('info', $checkTime->getTimestamp().':'.$job['name'] .' finish');
  196. } catch (\Exception $e) {
  197. // If an uncaught exception occurs
  198. SystemMsgService::addWorkMessage(['title'=>'定时任务执行错误','content'=>"{$job['name']}:{$e->getMessage()}"]);
  199. $return = get_class($e) . ' in job ' . $job['name'] . ': ' . $e->getMessage();
  200. self::log('error', get_class($e) . ' in job ' . $job['name'] . ': ' . $e->getMessage() . "\r\n" . $e->getTraceAsString());
  201. }
  202. // Get the end time of the job runtime
  203. $afterOne = microtime(true);
  204. // If the function returned not null then we assume that there was an error
  205. if (!is_null($return)) {
  206. // Add to error array
  207. array_push($errorJobs, array('name' => $job['name'], 'return' => $return, 'runtime' => ($afterOne - $beforeOne)));
  208. // Log error job
  209. self::log('error', 'Job with the name ' . $job['name'] . ' was run with errors.');
  210. // Fire event after executing a job with erros
  211. \Event::dispatch('cron.jobError', array('name' => $job['name'], 'return' => $return, 'runtime' => ($afterOne - $beforeOne), 'rundate' => $runDate->getTimestamp()));
  212. } else {
  213. // Fire event after executing a job successfully
  214. \Event::dispatch('cron.jobSuccess', array('name' => $job['name'], 'runtime' => ($afterOne - $beforeOne), 'rundate' => $runDate->getTimestamp()));
  215. }
  216. // Push the information of the ran cron job to the allJobs array (including name, return value, runtime)
  217. array_push($allJobs, array('name' => $job['name'], 'return' => $return, 'runtime' => ($afterOne - $beforeOne)));
  218. }
  219. }
  220. self::log('info', $checkTime->getTimestamp() .' 定时任务结束');
  221. // Get the end runtime after all cron job executions
  222. $afterAll = microtime(true);
  223. // todo log中记录执行时间
  224. // If database logging is enabled, save manager und jobs to db
  225. if (self::isDatabaseLogging()) {
  226. // todo 记录错误数据$errorJobs
  227. }
  228. // Removing overlapping lock file if lockfile was created
  229. if (!empty($overlappingLockFile)) {
  230. self::deleteLockFile($overlappingLockFile);
  231. }
  232. $returnArray = array('rundate' => $runDate->getTimestamp(), 'inTime' => $inTime, 'runtime' => ($afterAll - $beforeAll), 'errors' => count($errorJobs), 'crons' => $allJobs);
  233. // If Cron was called before, add the latest call to the $returnArray
  234. if (isset($lastManager[0]) && !empty($lastManager[0])) {
  235. $returnArray['lastRun'] = array('rundate' => $lastManager[0]->rundate, 'runtime' => $lastManager[0]->runtime);
  236. } else {
  237. $returnArray['lastRun'] = array();
  238. }
  239. // Fire event after the Cron run was executed
  240. \Event::dispatch('cron.afterRun', $returnArray);
  241. // Return the cron jobs array (including rundate, in-time boolean, runtime in seconds, number of errors and an array with the cron jobs reports)
  242. return $returnArray;
  243. } catch (\Exception $ex) {
  244. // Removing overlapping lock file if lockfile was created
  245. if (!empty($overlappingLockFile)) {
  246. self::deleteLockFile($overlappingLockFile);
  247. }
  248. throw($ex);
  249. }
  250. }
  251. /**
  252. * Delete lock file
  253. *
  254. * @static
  255. * @param string $file Path and name of the lock file which should be deleted
  256. */
  257. private static function deleteLockFile($file)
  258. {
  259. if (file_exists($file)) {
  260. if (is_writable($file)) {
  261. unlink($file);
  262. if (file_exists($file)) {
  263. self::log('critical', 'Could not delete Cron lock file at ' . $file . ' - please delete this file manually - as long as this lock file exists, Cron will not run.');
  264. }
  265. } else {
  266. self::log('critical', 'Could not delete Cron lock file at ' . $file . ' because it is not writable - please delete this file manually - as long as this lock file exists, Cron will not run.');
  267. }
  268. } else {
  269. self::log('warning', 'Could not delete Cron lock file at ' . $file . ' because file is not found.');
  270. }
  271. }
  272. /**
  273. * Add a custom Monolog logger object
  274. *
  275. * @static
  276. * @param \Monolog\Logger $logger optional The Monolog logger object which will be used for cron logging, if this parameter is null the logger will be removed - default value is null
  277. */
  278. public static function setLogger(\Monolog\Logger $logger = null)
  279. {
  280. self::$logger = $logger;
  281. }
  282. /**
  283. * Get the Monolog logger object
  284. *
  285. * @static
  286. * @return \Monolog\Logger|null Return the set logger object or null if no logger is set
  287. */
  288. public static function getLogger()
  289. {
  290. return self::$logger;
  291. }
  292. /**
  293. * Log a message with the given level to Monolog logger if one is set and to Laravels build in Logger if it is enabled
  294. *
  295. * @static
  296. * @param string $level The logger level as string which can be debug, info, notice, warning, error, critival, alert, emergency
  297. * @param string $message The message which will be logged to Monolog
  298. * @throws \InvalidArgumentException if the parameter $level or $message is not of the data type string or if the $level parameter does not match with debug, info, notice, warning, error, critival, alert or emergency
  299. */
  300. private static function log($level, $message)
  301. {
  302. // Check parameter
  303. if (!is_string($level) || !is_string($message)) {
  304. throw new \InvalidArgumentException('Function paramter $level or $message is not of the data type string.');
  305. }
  306. // If a Monolog logger object is set, use it
  307. if (!empty(self::$logger)) {
  308. // Switch the lower case level string and log the message with the given level
  309. switch (strtolower($level)) {
  310. case "debug":
  311. self::$logger->addDebug($message);
  312. break;
  313. case "info":
  314. self::$logger->addInfo($message);
  315. break;
  316. case "notice":
  317. self::$logger->addNotice($message);
  318. break;
  319. case "warning":
  320. self::$logger->addWarning($message);
  321. break;
  322. case "error":
  323. self::$logger->addError($message);
  324. break;
  325. case "critical":
  326. self::$logger->addCritical($message);
  327. break;
  328. case "alert":
  329. self::$logger->addAlert($message);
  330. break;
  331. case "emergency":
  332. self::$logger->addEmergency($message);
  333. break;
  334. default:
  335. throw new \InvalidArgumentException('Invalid log $level parameter with string ' . $level . '.');
  336. }
  337. }
  338. $laravelLogging = self::getConfig('laravelLogging');
  339. // If Laravel logging is enabled
  340. if (is_bool($laravelLogging) && $laravelLogging) {
  341. switch (strtolower($level)) {
  342. case "debug":
  343. \Log::debug($message);
  344. break;
  345. case "info":
  346. \Log::info($message);
  347. break;
  348. case "notice":
  349. \Log::notice($message);
  350. break;
  351. case "warning":
  352. \Log::warning($message);
  353. break;
  354. case "error":
  355. \Log::error($message);
  356. break;
  357. case "critical":
  358. \Log::critical($message);
  359. break;
  360. case "alert":
  361. \Log::alert($message);
  362. break;
  363. case "emergency":
  364. \Log::emergency($message);
  365. break;
  366. default:
  367. throw new \InvalidArgumentException('Invalid log $level parameter with string ' . $level . '.');
  368. }
  369. }
  370. }
  371. /**
  372. * Enable or disable Laravels build in logging
  373. *
  374. * @static
  375. * @param bool $bool Set to enable or disable Laravels logging
  376. * @throws \InvalidArgumentException if the $bool function paramter is not a boolean
  377. */
  378. public static function setLaravelLogging($bool)
  379. {
  380. if (is_bool($bool)) {
  381. self::setConfig('laravelLogging', $bool);
  382. } else {
  383. throw new \InvalidArgumentException('Function paramter $bool with value "' . $bool . '" is not a boolean.');
  384. }
  385. }
  386. /**
  387. * Is Laravels build in logging enabled or disabled
  388. *
  389. * @static
  390. * @return bool Return boolean which indicates if Laravels logging is enabled or disabled
  391. * @throws \UnexpectedValueException if the cron::laravelLogging config value is not a boolean or NULL
  392. */
  393. public static function isLaravelLogging()
  394. {
  395. $laravelLogging = self::getConfig('laravelLogging');
  396. if (is_null($laravelLogging) || is_bool($laravelLogging)) {
  397. return $laravelLogging;
  398. } else {
  399. throw new \UnexpectedValueException('Config option "laravelLogging" is not a boolean or not equals NULL.');
  400. }
  401. }
  402. /**
  403. * Enable or disable database logging
  404. *
  405. * @static
  406. * @param bool $bool Set to enable or disable database logging
  407. * @throws \InvalidArgumentException if the $bool function paramter is not a boolean
  408. */
  409. public static function setDatabaseLogging($bool)
  410. {
  411. if (is_bool($bool)) {
  412. self::setConfig('databaseLogging', $bool);
  413. } else {
  414. throw new \InvalidArgumentException('Function paramter $bool with value "' . $bool . '" is not a boolean.');
  415. }
  416. }
  417. /**
  418. * Is logging to database enabled or disabled
  419. *
  420. * @static
  421. * @return boolean Return boolean which indicates if database logging is enabled or disabled
  422. * @throws \UnexpectedValueException if the cron::databaseLogging config value is not a boolean
  423. */
  424. public static function isDatabaseLogging()
  425. {
  426. $databaseLogging = self::getConfig('databaseLogging');
  427. if (is_null($databaseLogging)) {
  428. // If the value is not set, return false
  429. return false;
  430. } else if (is_bool($databaseLogging)) {
  431. return $databaseLogging;
  432. } else {
  433. throw new \UnexpectedValueException('Config option "databaseLogging" is not a boolean or not equals NULL.');
  434. }
  435. }
  436. /**
  437. * Enable or disable logging error jobs only to database
  438. * NOTE: This works only if database logging is enabled
  439. *
  440. * @static
  441. * @param bool $bool Set to enable or disable logging error jobs only
  442. * @throws \InvalidArgumentException if the $bool function paramter is not a boolean
  443. */
  444. public static function setLogOnlyErrorJobsToDatabase($bool)
  445. {
  446. if (is_bool($bool)) {
  447. self::setConfig('logOnlyErrorJobsToDatabase', $bool);
  448. } else {
  449. throw new \InvalidArgumentException('Function paramter $bool with value "' . $bool . '" is not a boolean.');
  450. }
  451. }
  452. /**
  453. * Check if log error jobs to database only is enabled or disabled
  454. *
  455. * @return bool Return boolean which indicates if logging only error jobs to database is enabled or disabled
  456. * @throws \UnexpectedValueException if the cron::logOnlyErrorJobsToDatabase config value is not a boolean
  457. */
  458. public static function isLogOnlyErrorJobsToDatabase()
  459. {
  460. $logOnlyErrorJobsToDatabase = self::getConfig('logOnlyErrorJobsToDatabase');
  461. if (is_null($logOnlyErrorJobsToDatabase)) {
  462. // If the value is not set, return false
  463. return false;
  464. } else if (is_bool($logOnlyErrorJobsToDatabase)) {
  465. return $logOnlyErrorJobsToDatabase;
  466. } else {
  467. throw new \UnexpectedValueException('Config option "logOnlyErrorJobsToDatabase" is not a boolean or not equals NULL.');
  468. }
  469. }
  470. /**
  471. * Reset the Cron class
  472. * Remove the cron jobs array and the logger object
  473. *
  474. * @static
  475. */
  476. public static function reset()
  477. {
  478. self::$cronJobs = array();
  479. self::$logger = null;
  480. }
  481. /**
  482. * Set the run interval - the run interval is the time between two cron job route calls
  483. *
  484. * @static
  485. * @param int $minutes Set the interval in minutes
  486. * @throws \InvalidArgumentException if the $minutes function paramter is not an integer
  487. */
  488. public static function setRunInterval($minutes)
  489. {
  490. if (is_int($minutes)) {
  491. self::setConfig('runInterval', $minutes);
  492. } else {
  493. throw new \InvalidArgumentException('Function paramter $minutes with value "' . $minutes . '" is not an integer.');
  494. }
  495. }
  496. /**
  497. * Set the delete time of old database entries in hours
  498. *
  499. * @static
  500. * @param int $hours optional Set the delete time in hours, if this value is 0 the delete old database entries function will be disabled - default value is 0
  501. * @throws \InvalidArgumentException if the $hours function paramter is not an integer
  502. */
  503. public static function setDeleteDatabaseEntriesAfter($hours = 0)
  504. {
  505. if (is_int($hours)) {
  506. self::setConfig('deleteDatabaseEntriesAfter', $hours);
  507. } else {
  508. throw new \InvalidArgumentException('Function paramter $hours with value "' . $hours . '" is not an integer.');
  509. }
  510. }
  511. /**
  512. * Get the current delete time value in hours for old database entries
  513. *
  514. * @return int|null Return the current delete time value in hours or NULL if no value was set
  515. * @throws \UnexpectedValueException if the cron::deleteDatabaseEntriesAfter config value is not an integer or NULL
  516. */
  517. public static function getDeleteDatabaseEntriesAfter()
  518. {
  519. $deleteDatabaseEntriesAfter = self::getConfig('deleteDatabaseEntriesAfter');
  520. if (is_null($deleteDatabaseEntriesAfter) || is_int($deleteDatabaseEntriesAfter)) {
  521. return $deleteDatabaseEntriesAfter;
  522. } else {
  523. throw new \UnexpectedValueException('Config option "deleteDatabaseEntriesAfter" is not an integer or not equals NULL.');
  524. }
  525. }
  526. /**
  527. * Enable a job by job name
  528. *
  529. * @static
  530. * @param string $jobname The name of the job which should be enabled
  531. * @param bool $enable The trigger for enable (true) or disable (false) the job with the given name
  532. * @return bool Return true if job was enabled successfully or false if no job with the $jobname parameter was found
  533. * @throws \InvalidArgumentException if the $enable function paramter is not a boolean
  534. */
  535. public static function setEnableJob($jobname, $enable = true)
  536. {
  537. // Check patameter
  538. if (!is_bool($enable)) {
  539. throw new \InvalidArgumentException('Function paramter $enable with value "' . $enable . '" is not a boolean.');
  540. }
  541. // Walk through the cron jobs and find the job with the given name
  542. foreach (self::$cronJobs as $jobKey => $jobValue) {
  543. if ($jobValue['name'] === $jobname) {
  544. // If a job with the given name is found, set the enable boolean
  545. self::$cronJobs[$jobKey]['enabled'] = $enable;
  546. return true;
  547. }
  548. }
  549. return false;
  550. }
  551. /**
  552. * Disable a job by job name
  553. *
  554. * @static
  555. * @param String $jobname The name of the job which should be disabled
  556. * @return bool Return true if job was disabled successfully or false if no job with the $jobname parameter was found
  557. */
  558. public static function setDisableJob($jobname)
  559. {
  560. return self::setEnableJob($jobname, false);
  561. }
  562. /**
  563. * Is the given job by name enabled or disabled
  564. *
  565. * @static
  566. * @param String $jobname The name of the job which should be checked
  567. * @return bool|null Return boolean if job is enabled (true) or disabled (false) or null if no job with the given name is found
  568. */
  569. public static function isJobEnabled($jobname)
  570. {
  571. // Walk through the cron jobs and find the job with the given name
  572. foreach (self::$cronJobs as $jobKey => $jobValue) {
  573. if ($jobValue['name'] === $jobname) {
  574. // If a job with the given name is found, return the is enabled boolean
  575. return self::$cronJobs[$jobKey]['enabled'];
  576. }
  577. }
  578. return;
  579. }
  580. /**
  581. * Enable prevent job overlapping
  582. *
  583. * @static
  584. */
  585. public static function setEnablePreventOverlapping()
  586. {
  587. self::setConfig('preventOverlapping', true);
  588. }
  589. /**
  590. * Disable prevent job overlapping
  591. *
  592. * @static
  593. */
  594. public static function setDisablePreventOverlapping()
  595. {
  596. self::setConfig('preventOverlapping', false);
  597. }
  598. /**
  599. * Is prevent job overlapping enabled or disabled
  600. *
  601. * @static
  602. * @return bool Return boolean if prevent job overlapping is enabled (true) or disabled (false)
  603. */
  604. public static function isPreventOverlapping()
  605. {
  606. $preventOverlapping = self::getConfig('preventOverlapping');
  607. if (is_bool($preventOverlapping)) {
  608. return $preventOverlapping;
  609. } else {
  610. // If no value or not a boolean value is given, prevent overlapping is disabled
  611. return false;
  612. }
  613. }
  614. /**
  615. * Enable the Cron run in time check
  616. *
  617. * @static
  618. */
  619. public static function setEnableInTimeCheck()
  620. {
  621. self::setConfig('inTimeCheck', true);
  622. }
  623. /**
  624. * Disable the Cron run in time check
  625. *
  626. * @static
  627. */
  628. public static function setDisableInTimeCheck()
  629. {
  630. self::setConfig('inTimeCheck', false);
  631. }
  632. /**
  633. * Is the Cron run in time check enabled or disabled
  634. *
  635. * @static
  636. * @return bool Return boolean if the Cron run in time check is enabled (true) or disabled (false)
  637. */
  638. public static function isInTimeCheck()
  639. {
  640. $inTimeCheck = self::getConfig('inTimeCheck');
  641. if (is_bool($inTimeCheck)) {
  642. return $inTimeCheck;
  643. } else {
  644. // If no value or not a boolean value is given, in time check should be enabled
  645. return true;
  646. }
  647. }
  648. /**
  649. * Get added Cron jobs as array
  650. *
  651. * @static
  652. * @return array Return array of the added Cron jobs
  653. */
  654. public static function getCronJobs()
  655. {
  656. return self::$cronJobs;
  657. }
  658. /**
  659. * Get Config value
  660. *
  661. * @static
  662. * @param string $key Config key to get the value for
  663. * @param mixed $defaultValue If no value for the given key is available, return this default value
  664. */
  665. private static function getConfig($key, $defaultValue = NULL)
  666. {
  667. return \Config::get('cron::' . $key) ?: $defaultValue;
  668. }
  669. /**
  670. * Set config value
  671. *
  672. * @static
  673. * @param string $key Config key to set the value for
  674. * @param mixed $value Value which should be set
  675. */
  676. private static function setConfig($key, $value)
  677. {
  678. \Config::set('liebigCron.' . $key, $value);
  679. }
  680. }