[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Scheduled task abstract class. 19 * 20 * @package core 21 * @category task 22 * @copyright 2013 Damyon Wiese 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 namespace core\task; 26 27 /** 28 * Abstract class defining a scheduled task. 29 * @copyright 2013 Damyon Wiese 30 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 31 */ 32 abstract class scheduled_task extends task_base { 33 34 /** Minimum minute value. */ 35 const MINUTEMIN = 0; 36 /** Maximum minute value. */ 37 const MINUTEMAX = 59; 38 39 /** Minimum hour value. */ 40 const HOURMIN = 0; 41 /** Maximum hour value. */ 42 const HOURMAX = 23; 43 44 /** Minimum dayofweek value. */ 45 const DAYOFWEEKMIN = 0; 46 /** Maximum dayofweek value. */ 47 const DAYOFWEEKMAX = 6; 48 49 /** @var string $hour - Pattern to work out the valid hours */ 50 private $hour = '*'; 51 52 /** @var string $minute - Pattern to work out the valid minutes */ 53 private $minute = '*'; 54 55 /** @var string $day - Pattern to work out the valid days */ 56 private $day = '*'; 57 58 /** @var string $month - Pattern to work out the valid months */ 59 private $month = '*'; 60 61 /** @var string $dayofweek - Pattern to work out the valid dayofweek */ 62 private $dayofweek = '*'; 63 64 /** @var int $lastruntime - When this task was last run */ 65 private $lastruntime = 0; 66 67 /** @var boolean $customised - Has this task been changed from it's default schedule? */ 68 private $customised = false; 69 70 /** @var int $disabled - Is this task disabled in cron? */ 71 private $disabled = false; 72 73 /** 74 * Get the last run time for this scheduled task. 75 * @return int 76 */ 77 public function get_last_run_time() { 78 return $this->lastruntime; 79 } 80 81 /** 82 * Set the last run time for this scheduled task. 83 * @param int $lastruntime 84 */ 85 public function set_last_run_time($lastruntime) { 86 $this->lastruntime = $lastruntime; 87 } 88 89 /** 90 * Has this task been changed from it's default config? 91 * @return bool 92 */ 93 public function is_customised() { 94 return $this->customised; 95 } 96 97 /** 98 * Has this task been changed from it's default config? 99 * @param bool 100 */ 101 public function set_customised($customised) { 102 $this->customised = $customised; 103 } 104 105 /** 106 * Setter for $minute. Accepts a special 'R' value 107 * which will be translated to a random minute. 108 * @param string $minute 109 */ 110 public function set_minute($minute) { 111 if ($minute === 'R') { 112 $minute = mt_rand(self::HOURMIN, self::HOURMAX); 113 } 114 $this->minute = $minute; 115 } 116 117 /** 118 * Getter for $minute. 119 * @return string 120 */ 121 public function get_minute() { 122 return $this->minute; 123 } 124 125 /** 126 * Setter for $hour. Accepts a special 'R' value 127 * which will be translated to a random hour. 128 * @param string $hour 129 */ 130 public function set_hour($hour) { 131 if ($hour === 'R') { 132 $hour = mt_rand(self::HOURMIN, self::HOURMAX); 133 } 134 $this->hour = $hour; 135 } 136 137 /** 138 * Getter for $hour. 139 * @return string 140 */ 141 public function get_hour() { 142 return $this->hour; 143 } 144 145 /** 146 * Setter for $month. 147 * @param string $month 148 */ 149 public function set_month($month) { 150 $this->month = $month; 151 } 152 153 /** 154 * Getter for $month. 155 * @return string 156 */ 157 public function get_month() { 158 return $this->month; 159 } 160 161 /** 162 * Setter for $day. 163 * @param string $day 164 */ 165 public function set_day($day) { 166 $this->day = $day; 167 } 168 169 /** 170 * Getter for $day. 171 * @return string 172 */ 173 public function get_day() { 174 return $this->day; 175 } 176 177 /** 178 * Setter for $dayofweek. 179 * @param string $dayofweek 180 */ 181 public function set_day_of_week($dayofweek) { 182 if ($dayofweek === 'R') { 183 $dayofweek = mt_rand(self::DAYOFWEEKMIN, self::DAYOFWEEKMAX); 184 } 185 $this->dayofweek = $dayofweek; 186 } 187 188 /** 189 * Getter for $dayofweek. 190 * @return string 191 */ 192 public function get_day_of_week() { 193 return $this->dayofweek; 194 } 195 196 /** 197 * Setter for $disabled. 198 * @param bool $disabled 199 */ 200 public function set_disabled($disabled) { 201 $this->disabled = (bool)$disabled; 202 } 203 204 /** 205 * Getter for $disabled. 206 * @return bool 207 */ 208 public function get_disabled() { 209 return $this->disabled; 210 } 211 212 /** 213 * Override this function if you want this scheduled task to run, even if the component is disabled. 214 * 215 * @return bool 216 */ 217 public function get_run_if_component_disabled() { 218 return false; 219 } 220 221 /** 222 * Take a cron field definition and return an array of valid numbers with the range min-max. 223 * 224 * @param string $field - The field definition. 225 * @param int $min - The minimum allowable value. 226 * @param int $max - The maximum allowable value. 227 * @return array(int) 228 */ 229 public function eval_cron_field($field, $min, $max) { 230 // Cleanse the input. 231 $field = trim($field); 232 233 // Format for a field is: 234 // <fieldlist> := <range>(/<step>)(,<fieldlist>) 235 // <step> := int 236 // <range> := <any>|<int>|<min-max> 237 // <any> := * 238 // <min-max> := int-int 239 // End of format BNF. 240 241 // This function is complicated but is covered by unit tests. 242 $range = array(); 243 244 $matches = array(); 245 preg_match_all('@[0-9]+|\*|,|/|-@', $field, $matches); 246 247 $last = 0; 248 $inrange = false; 249 $instep = false; 250 251 foreach ($matches[0] as $match) { 252 if ($match == '*') { 253 array_push($range, range($min, $max)); 254 } else if ($match == '/') { 255 $instep = true; 256 } else if ($match == '-') { 257 $inrange = true; 258 } else if (is_numeric($match)) { 259 if ($instep) { 260 $i = 0; 261 for ($i = 0; $i < count($range[count($range) - 1]); $i++) { 262 if (($i) % $match != 0) { 263 $range[count($range) - 1][$i] = -1; 264 } 265 } 266 $inrange = false; 267 } else if ($inrange) { 268 if (count($range)) { 269 $range[count($range) - 1] = range($last, $match); 270 } 271 $inrange = false; 272 } else { 273 if ($match >= $min && $match <= $max) { 274 array_push($range, $match); 275 } 276 $last = $match; 277 } 278 } 279 } 280 281 // Flatten the result. 282 $result = array(); 283 foreach ($range as $r) { 284 if (is_array($r)) { 285 foreach ($r as $rr) { 286 if ($rr >= $min && $rr <= $max) { 287 $result[$rr] = 1; 288 } 289 } 290 } else if (is_numeric($r)) { 291 if ($r >= $min && $r <= $max) { 292 $result[$r] = 1; 293 } 294 } 295 } 296 $result = array_keys($result); 297 sort($result, SORT_NUMERIC); 298 return $result; 299 } 300 301 /** 302 * Assuming $list is an ordered list of items, this function returns the item 303 * in the list that is greater than or equal to the current value (or 0). If 304 * no value is greater than or equal, this will return the first valid item in the list. 305 * If list is empty, this function will return 0. 306 * 307 * @param int $current The current value 308 * @param int[] $list The list of valid items. 309 * @return int $next. 310 */ 311 private function next_in_list($current, $list) { 312 foreach ($list as $l) { 313 if ($l >= $current) { 314 return $l; 315 } 316 } 317 if (count($list)) { 318 return $list[0]; 319 } 320 321 return 0; 322 } 323 324 /** 325 * Calculate when this task should next be run based on the schedule. 326 * @return int $nextruntime. 327 */ 328 public function get_next_scheduled_time() { 329 global $CFG; 330 331 $validminutes = $this->eval_cron_field($this->minute, self::MINUTEMIN, self::MINUTEMAX); 332 $validhours = $this->eval_cron_field($this->hour, self::HOURMIN, self::HOURMAX); 333 334 // We need to change to the server timezone before using php date() functions. 335 \core_date::set_default_server_timezone(); 336 337 $daysinmonth = date("t"); 338 $validdays = $this->eval_cron_field($this->day, 1, $daysinmonth); 339 $validdaysofweek = $this->eval_cron_field($this->dayofweek, 0, 7); 340 $validmonths = $this->eval_cron_field($this->month, 1, 12); 341 $nextvalidyear = date('Y'); 342 343 $currentminute = date("i") + 1; 344 $currenthour = date("H"); 345 $currentday = date("j"); 346 $currentmonth = date("n"); 347 $currentdayofweek = date("w"); 348 349 $nextvalidminute = $this->next_in_list($currentminute, $validminutes); 350 if ($nextvalidminute < $currentminute) { 351 $currenthour += 1; 352 } 353 $nextvalidhour = $this->next_in_list($currenthour, $validhours); 354 if ($nextvalidhour < $currenthour) { 355 $currentdayofweek += 1; 356 $currentday += 1; 357 } 358 $nextvaliddayofmonth = $this->next_in_list($currentday, $validdays); 359 $nextvaliddayofweek = $this->next_in_list($currentdayofweek, $validdaysofweek); 360 $daysincrementbymonth = $nextvaliddayofmonth - $currentday; 361 if ($nextvaliddayofmonth < $currentday) { 362 $daysincrementbymonth += $daysinmonth; 363 } 364 365 $daysincrementbyweek = $nextvaliddayofweek - $currentdayofweek; 366 if ($nextvaliddayofweek < $currentdayofweek) { 367 $daysincrementbyweek += 7; 368 } 369 370 // Special handling for dayofmonth vs dayofweek: 371 // if either field is * - use the other field 372 // otherwise - choose the soonest (see man 5 cron). 373 if ($this->dayofweek == '*') { 374 $daysincrement = $daysincrementbymonth; 375 } else if ($this->day == '*') { 376 $daysincrement = $daysincrementbyweek; 377 } else { 378 // Take the smaller increment of days by month or week. 379 $daysincrement = $daysincrementbymonth; 380 if ($daysincrementbyweek < $daysincrementbymonth) { 381 $daysincrement = $daysincrementbyweek; 382 } 383 } 384 385 $nextvaliddayofmonth = $currentday + $daysincrement; 386 if ($nextvaliddayofmonth > $daysinmonth) { 387 $currentmonth += 1; 388 $nextvaliddayofmonth -= $daysinmonth; 389 } 390 391 $nextvalidmonth = $this->next_in_list($currentmonth, $validmonths); 392 if ($nextvalidmonth < $currentmonth) { 393 $nextvalidyear += 1; 394 } 395 396 // Work out the next valid time. 397 $nexttime = mktime($nextvalidhour, 398 $nextvalidminute, 399 0, 400 $nextvalidmonth, 401 $nextvaliddayofmonth, 402 $nextvalidyear); 403 404 return $nexttime; 405 } 406 407 /** 408 * Get a descriptive name for this task (shown to admins). 409 * 410 * @return string 411 */ 412 public abstract function get_name(); 413 414 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |