AloFramework documentation
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Todo

Namespaces

  • Alo
    • Cache
    • CLI
    • Controller
    • Db
      • Query
    • Exception
    • FileSystem
    • Session
    • Traversables
    • Validators
    • Windows
  • Controller
  • None
  • PHP

Classes

  • Cookie
  • Cron
  • Curl
  • Email
  • Format
  • Handler
  • Locale
  • Profiler
  • Security
  • SFTP
  1 <?php
  2 
  3     namespace Alo;
  4 
  5     use Alo\Exception\CronException as CE;
  6     use Alo\Exception\OSException as OS;
  7     use Alo;
  8     use Log;
  9 
 10     if (!defined('GEN_START')) {
 11         http_response_code(404);
 12     } else {
 13 
 14         /**
 15          * The crontab editor class. You must call the commit() method to save your changes.
 16          *
 17          * @author Art <a.molcanovas@gmail.com>
 18          */
 19         class Cron {
 20 
 21             /**
 22              * Defines the day of the week as Sunday
 23              *
 24              * @var int
 25              */
 26             const WEEKDAY_SUN = 0;
 27             /**
 28              * Defines the day of the week as Monday
 29              *
 30              * @var int
 31              */
 32             const WEEKDAY_MON = 1;
 33             /**
 34              * Defines the day of the week as Tuesday
 35              *
 36              * @var int
 37              */
 38             const WEEKDAY_TUE = 2;
 39             /**
 40              * Defines the day of the week as Wednesday
 41              *
 42              * @var int
 43              */
 44             const WEEKDAY_WED = 3;
 45             /**
 46              * Defines the day of the week as Thursday
 47              *
 48              * @var int
 49              */
 50             const WEEKDAY_THU = 4;
 51             /**
 52              * Defines the day of the week as Friday
 53              *
 54              * @var int
 55              */
 56             const WEEKDAY_FRI = 5;
 57             /**
 58              * Defines the day of the week as Saturday
 59              *
 60              * @var int
 61              */
 62             const WEEKDAY_SAT = 6;
 63             /**
 64              * A pre-setting to run the cronjob yearly at 1 Jan, 00:00
 65              *
 66              * @var string
 67              */
 68             const CONST_YEARLY = '0 0 1 1 *';
 69             /**
 70              * A pre-setting to run the cronjob monthly at 00:00
 71              *
 72              * @var string
 73              */
 74             const CONST_MONTHLY = '0 0 1 * *';
 75             /**
 76              * A pre-setting to run the cronjob weekly on Sunday, 00:00
 77              *
 78              * @var string
 79              */
 80             const CONST_WEEKLY = '0 0 * * 0';
 81             /**
 82              * A pre-setting to run the cronjob daily at 00:00
 83              *
 84              * @var string
 85              */
 86             const CONST_DAILY = '0 0 * * *';
 87             /**
 88              * A pre-setting to run the cronjob hourly at 00 minutes
 89              *
 90              * @var string
 91              */
 92             const CONST_HOURLY = '0 * * * *';
 93             /**
 94              * A pre-setting to run the cronjob on server startup
 95              *
 96              * @var string
 97              */
 98             const CONST_REBOOT = '@reboot';
 99             /**
100              * Defines the month as January
101              *
102              * @var int
103              */
104             const MONTH_JAN = 1;
105             /**
106              * Defines the month as February
107              *
108              * @var int
109              */
110             const MONTH_FEB = 2;
111             /**
112              * Defines the month as March
113              *
114              * @var int
115              */
116             const MONTH_MAR = 3;
117             /**
118              * Defines the month as April
119              *
120              * @var int
121              */
122             const MONTH_APR = 4;
123             /**
124              * Defines the month as May
125              *
126              * @var int
127              */
128             const MONTH_MAY = 5;
129             /**
130              * Defines the month as June
131              *
132              * @var int
133              */
134             const MONTH_JUN = 6;
135             /**
136              * Defines the month as July
137              *
138              * @var int
139              */
140             const MONTH_JUL = 7;
141             /**
142              * Defines the month as August
143              *
144              * @var int
145              */
146             const MONTH_AUG = 8;
147             /**
148              * Defines the month as September
149              *
150              * @var int
151              */
152             const MONTH_SEP = 9;
153             /**
154              * Defines the month as October
155              *
156              * @var int
157              */
158             const MONTH_OCT = 10;
159             /**
160              * Defines the month as November
161              *
162              * @var int
163              */
164             const MONTH_NOV = 11;
165             /**
166              * Defines the month as December
167              *
168              * @var int
169              */
170             const MONTH_DEC = 12;
171             /**
172              * Static reference to the last instance of the class
173              *
174              * @var Cron
175              */
176             static $this;
177             /**
178              * Array of valid CRON constants
179              *
180              * @var array
181              */
182             protected static $validConstants = ['@yearly',
183                                                 '@annually',
184                                                 '@monthly',
185                                                 '@weekly',
186                                                 '@daily',
187                                                 '@hourly',
188                                                 '@reboot'];
189 
190             /**
191              * The current crontab data
192              *
193              * @var array
194              */
195             protected $crontab;
196 
197             /**
198              * Whether changes should be autocommited automatically
199              *
200              * @var bool
201              */
202             protected $autocommit;
203 
204             /**
205              * Instantiates the crontab handler
206              *
207              * @author Art <a.molcanovas@gmail.com>
208              * @throws OS When the machine is running Windows
209              */
210             function __construct() {
211                 if (\Alo::serverIsWindows()) {
212                     throw new OS('Windows does not support cron!', OS::E_UNSUPPORTED);
213                 } else {
214                     $this->autocommit = false;
215                     $this->reloadCrontab();
216                 }
217                 self::$this = &$this;
218             }
219 
220             /**
221              * (re)loads the cron job array
222              *
223              * @author Art <a.molcanovas@gmail.com>
224              * @return Cron
225              */
226             function reloadCrontab() {
227                 $this->crontab = shell_exec('crontab -l');
228 
229                 if ($this->crontab) {
230                     $this->crontab = trim($this->crontab);
231                     $this->crontab = explode("\n", $this->crontab);
232 
233                     //Make sure it's really empty
234                     $lastIndex = count($this->crontab) - 1;
235 
236                     while ($lastIndex >= 0 && !$this->crontab[$lastIndex]) {
237                         unset($this->crontab[$lastIndex]);
238                         $lastIndex--;
239                     }
240                 } else {
241                     $this->crontab = [];
242                 }
243 
244                 Log::debug('(Re)loaded crontab contents');
245 
246                 return $this;
247             }
248 
249             /**
250              * Instantiates the crontab handler
251              *
252              * @author Art <a.molcanovas@gmail.com>
253              * @throws OS When the machine is running Windows
254              * @return Cron
255              */
256             static function cron() {
257                 return new Cron();
258             }
259 
260             /**
261              * Edits the cron job at index $index. Can be substituded with the full
262              * CRON expression (schedule + command) to perform a search -
263              * use with caution!
264              *
265              * @author Art <a.molcanovas@gmail.com>
266              *
267              * @param int        $index   The job index in the crontab array
268              * @param string     $command The command to run
269              * @param int|string $minute  The minute parameter
270              * @param int|string $hour    The hour parameter
271              * @param int|string $day     The day of the month parameter
272              * @param int|string $month   The month parameter
273              * @param int|string $weekday The day of the week parameter
274              *
275              * @throws CE When the minute expression is invalid
276              * @throws CE When the parameters are invalid
277              * @throws CE When one or more parameters are non-scalar
278              * @return Cron
279              */
280             function editCronJob($index, $command, $minute = '*', $hour = '*', $day = '*', $month = '*',
281                                  $weekday = '*') {
282                 if (!is_numeric($index)) {
283                     $search = array_search($index, $this->crontab);
284 
285                     if ($search !== false) {
286                         $index = $search;
287                     }
288                 }
289 
290                 return $this->editCrontab($index, $command, $minute, $hour, $day, $month, $weekday);
291             }
292 
293             /**
294              * Performs modifiation on the crontab file
295              *
296              * @author Art <a.molcanovas@gmail.com>
297              *
298              * @param int        $index   The job index in the crontab array
299              * @param string     $command The command to run
300              * @param int|string $minute  The minute parameter
301              * @param int|string $hour    The hour parameter
302              * @param int|string $day     The day of the month parameter
303              * @param int|string $month   The month parameter
304              * @param int|string $weekday The day of the week parameter
305              *
306              * @return Cron
307              * @throws CE When the minute expression is invalid
308              * @throws CE When the parameters are invalid
309              * @throws CE When one or more parameters are non-scalar
310              */
311             protected function editCrontab($index, $command, $minute = '*', $hour = '*', $day = '*', $month = '*',
312                                            $weekday = '*') {
313 
314                 if (!is_scalar($command) || !is_scalar($minute) || !is_scalar($hour) || !is_scalar($day) ||
315                     !is_scalar($month) || !is_scalar($weekday)
316                 ) {
317                     throw new CE('All cron attributes must be scalar!', CE::E_ARGS_NONSCALAR);
318                 } elseif (!self::formatOK($minute, $hour, $day, $month, $weekday)) {
319                     throw new CE('Invalid schedule parameters: ' . json_encode(['minute/constant' => $minute,
320                                                                                 'hour'            => $hour,
321                                                                                 'day'             => $day,
322                                                                                 'month'           => $month,
323                                                                                 'weekday'         => $weekday,
324                                                                                 'cmd'             => $command,
325                                                                                 'index'           => $index]),
326                                  CE::E_INVALID_EXPR);
327                 } else {
328                     $add = $minute . ' ' . $hour . ' ' . $day . ' ' . $month . ' ' . $weekday . ' ' . $command;
329 
330                     if ($index === null) {
331                         $this->crontab[] = $add;
332                         Log::debug('Appended crontab with ' . $add);
333                     } else {
334                         $this->crontab[$index] = $add;
335                         Log::debug('Edited crontab index ' . $index . ' with ' . $add);
336                     }
337 
338                     if ($this->autocommit) {
339                         $this->commit();
340                     }
341                 }
342 
343                 return $this;
344             }
345 
346             /**
347              * Checks whether all the fields are formatted properly
348              *
349              * @author Art <a.molcanovas@gmail.com>
350              *
351              * @param int|string $min     The minute parameter
352              * @param int|string $hour    The hour parameter
353              * @param int|string $day     The day of the month parameter
354              * @param int|string $month   The month parameter
355              * @param int|string $weekday The day of the week parameter
356              *
357              * @return boolean
358              */
359             protected static function formatOK($min, $hour, $day, $month, $weekday) {
360                 $patMinHMth = '/^(\*|[0-9]{1,2}|\*\/[0-9]{1,2}|[0-9,]+|[0-9\-]+)$/';
361                 $patDay     = '/^(\*|[0-9]{1,2}|[0-9]{1,2}(L|W)|\*\/[0-9]{1,2}|[0-9,]+|[0-9\-]+)$/';
362                 $patWeekday = '/^(\*|[0-9]{1,2}|[0-9]{1,2}L|\*\/[0-9]{1,2}|[0-9,]+|[0-9\-]+)$/';
363 
364                 return preg_match($patMinHMth, $min) && preg_match($patMinHMth, $hour) &&
365                        preg_match($patMinHMth, $month) && preg_match($patDay, $day) &&
366                        preg_match($patWeekday, $weekday);
367             }
368 
369             /**
370              * Saves any changes made
371              *
372              * @author Art <a.molcanovas@gmail.com>
373              * @return bool
374              */
375             function commit() {
376                 $commit = trim(implode("\n", $this->crontab)) . "\n";
377                 $path   = DIR_TMP . 'crontab.txt';
378                 file_put_contents($path, $commit);
379 
380                 if (file_exists($path)) {
381                     $exec = shell_exec('crontab "' . $path . '"');
382                     echo $exec;
383                     unlink($path);
384                     Log::debug('Crontab change output: ' . $exec);
385 
386                     return true;
387                 } else {
388                     trigger_error(Log::error('Failed to save crontab: temporary file could not be created.'),
389                                   E_USER_WARNING);
390                 }
391 
392                 return false;
393             }
394 
395             /**
396              * Appends the crontab file
397              *
398              * @author Art <a.molcanovas@gmail.com>
399              *
400              * @param string     $command     The command to run
401              * @param int|string $minuteConst The minute parameter
402              * @param int|string $hour        The hour parameter
403              * @param int|string $day         The day of the month parameter
404              * @param int|string $month       The month parameter
405              * @param int|string $weekday     The day of the week parameter
406              *
407              * @throws CE When the minute expression is invalid
408              * @throws CE When the parameters are invalid
409              * @throws CE When one or more parameters are non-scalar
410              * @return Cron
411              */
412             function appendCrontab($command, $minuteConst = '*', $hour = '*', $day = '*', $month = '*',
413                                    $weekday = '*') {
414                 return $this->editCrontab(null, $command, $minuteConst, $hour, $day, $month, $weekday);
415             }
416 
417             /**
418              * Removes the cron job @ index $index
419              *
420              * @author Art <a.molcanovas@gmail.com>
421              *
422              * @param int $index The cron job's index in the array
423              *
424              * @return Cron
425              */
426             function deleteJob($index) {
427                 unset($this->crontab[$index]);
428                 Log::debug('Deleted crontab entry @ index ' . $index);
429 
430                 if ($this->autocommit) {
431                     $this->commit();
432                 }
433 
434                 return $this;
435             }
436 
437             /**
438              * Clears the crontab
439              *
440              * @author Art <a.molcanovas@gmail.com>
441              * @return Cron
442              */
443             function clearCrontab() {
444                 $this->crontab = [];
445 
446                 if ($this->autocommit) {
447                     $this->commit();
448                 }
449 
450                 return $this;
451             }
452 
453             /**
454              * If no parameter is passed or the parameter isn't TRUE/FALSE, returns the current autocommit setting, otherwise
455              * sets it. Use with caution!
456              *
457              * @author Art <a.molcanovas@gmail.com>
458              *
459              * @param bool|null $set The desired setting if changing
460              *
461              * @return Cron|bool $this if not changing the autocommit value or the value otherwise
462              */
463             function autocommit($set = null) {
464                 if (is_bool($set)) {
465                     $this->autocommit = $set;
466 
467                     return $this;
468                 } else {
469                     return $this->autocommit;
470                 }
471             }
472 
473             /**
474              * Returns crontab entry at index $i
475              *
476              * @author Art <a.molcanovas@gmail.com>
477              *
478              * @param int $i The index
479              *
480              * @return null|string
481              */
482             function getAtIndex($i) {
483                 return \get($this->crontab[$i]);
484             }
485 
486             /**
487              * Returns the crontab array
488              *
489              * @author Art <a.molcanovas@gmail.com>
490              * @return array
491              */
492             function getCrontab() {
493                 return $this->crontab;
494             }
495 
496             /**
497              * Returns a string representation of the object data
498              *
499              * @author Art <a.molcanovas@gmail.com>
500              * @return string
501              */
502             function __toString() {
503                 return \debugLite($this);
504             }
505 
506         }
507     }
508 
AloFramework documentation API documentation generated byApiGen 2.8.0