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