Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403]
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 * Date condition. 19 * 20 * @package availability_date 21 * @copyright 2014 The Open University 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace availability_date; 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 /** 30 * Date condition. 31 * 32 * @package availability_date 33 * @copyright 2014 The Open University 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class condition extends \core_availability\condition { 37 /** @var string Availabile only from specified date. */ 38 const DIRECTION_FROM = '>='; 39 40 /** @var string Availabile only until specified date. */ 41 const DIRECTION_UNTIL = '<'; 42 43 /** @var string One of the DIRECTION_xx constants. */ 44 private $direction; 45 46 /** @var int Time (Unix epoch seconds) for condition. */ 47 private $time; 48 49 /** @var int Forced current time (for unit tests) or 0 for normal. */ 50 private static $forcecurrenttime = 0; 51 52 /** 53 * Constructor. 54 * 55 * @param \stdClass $structure Data structure from JSON decode 56 * @throws \coding_exception If invalid data structure. 57 */ 58 public function __construct($structure) { 59 // Get direction. 60 if (isset($structure->d) && in_array($structure->d, 61 array(self::DIRECTION_FROM, self::DIRECTION_UNTIL))) { 62 $this->direction = $structure->d; 63 } else { 64 throw new \coding_exception('Missing or invalid ->d for date condition'); 65 } 66 67 // Get time. 68 if (isset($structure->t) && is_int($structure->t)) { 69 $this->time = $structure->t; 70 } else { 71 throw new \coding_exception('Missing or invalid ->t for date condition'); 72 } 73 } 74 75 public function save() { 76 return (object)array('type' => 'date', 77 'd' => $this->direction, 't' => $this->time); 78 } 79 80 /** 81 * Returns a JSON object which corresponds to a condition of this type. 82 * 83 * Intended for unit testing, as normally the JSON values are constructed 84 * by JavaScript code. 85 * 86 * @param string $direction DIRECTION_xx constant 87 * @param int $time Time in epoch seconds 88 * @return stdClass Object representing condition 89 */ 90 public static function get_json($direction, $time) { 91 return (object)array('type' => 'date', 'd' => $direction, 't' => (int)$time); 92 } 93 94 public function is_available($not, \core_availability\info $info, $grabthelot, $userid) { 95 return $this->is_available_for_all($not); 96 } 97 98 public function is_available_for_all($not = false) { 99 // Check condition. 100 $now = self::get_time(); 101 switch ($this->direction) { 102 case self::DIRECTION_FROM: 103 $allow = $now >= $this->time; 104 break; 105 case self::DIRECTION_UNTIL: 106 $allow = $now < $this->time; 107 break; 108 default: 109 throw new \coding_exception('Unexpected direction'); 110 } 111 if ($not) { 112 $allow = !$allow; 113 } 114 115 return $allow; 116 } 117 118 /** 119 * Obtains the actual direction of checking based on the $not value. 120 * 121 * @param bool $not True if condition is negated 122 * @return string Direction constant 123 * @throws \coding_exception 124 */ 125 protected function get_logical_direction($not) { 126 switch ($this->direction) { 127 case self::DIRECTION_FROM: 128 return $not ? self::DIRECTION_UNTIL : self::DIRECTION_FROM; 129 case self::DIRECTION_UNTIL: 130 return $not ? self::DIRECTION_FROM : self::DIRECTION_UNTIL; 131 default: 132 throw new \coding_exception('Unexpected direction'); 133 } 134 } 135 136 public function get_description($full, $not, \core_availability\info $info) { 137 return $this->get_either_description($not, false); 138 } 139 140 public function get_standalone_description( 141 $full, $not, \core_availability\info $info) { 142 return $this->get_either_description($not, true); 143 } 144 145 /** 146 * Shows the description using the different lang strings for the standalone 147 * version or the full one. 148 * 149 * @param bool $not True if NOT is in force 150 * @param bool $standalone True to use standalone lang strings 151 */ 152 protected function get_either_description($not, $standalone) { 153 $direction = $this->get_logical_direction($not); 154 $midnight = self::is_midnight($this->time); 155 $midnighttag = $midnight ? '_date' : ''; 156 $satag = $standalone ? 'short_' : 'full_'; 157 switch ($direction) { 158 case self::DIRECTION_FROM: 159 return get_string($satag . 'from' . $midnighttag, 'availability_date', 160 self::show_time($this->time, $midnight, false)); 161 case self::DIRECTION_UNTIL: 162 return get_string($satag . 'until' . $midnighttag, 'availability_date', 163 self::show_time($this->time, $midnight, true)); 164 } 165 } 166 167 protected function get_debug_string() { 168 return $this->direction . ' ' . gmdate('Y-m-d H:i:s', $this->time); 169 } 170 171 /** 172 * Gets time. This function is implemented here rather than calling time() 173 * so that it can be overridden in unit tests. (Would really be nice if 174 * Moodle had a generic way of doing that, but it doesn't.) 175 * 176 * @return int Current time (seconds since epoch) 177 */ 178 protected static function get_time() { 179 if (self::$forcecurrenttime) { 180 return self::$forcecurrenttime; 181 } else { 182 return time(); 183 } 184 } 185 186 /** 187 * Forces the current time for unit tests. 188 * 189 * @param int $forcetime Time to return from the get_time function 190 */ 191 public static function set_current_time_for_test($forcetime = 0) { 192 self::$forcecurrenttime = $forcetime; 193 } 194 195 /** 196 * Shows a time either as a date or a full date and time, according to 197 * user's timezone. 198 * 199 * @param int $time Time 200 * @param bool $dateonly If true, uses date only 201 * @param bool $until If true, and if using date only, shows previous date 202 * @return string Date 203 */ 204 protected function show_time($time, $dateonly, $until = false) { 205 // For 'until' dates that are at midnight, e.g. midnight 5 March, it 206 // is better to word the text as 'until end 4 March'. 207 $daybefore = false; 208 if ($until && $dateonly) { 209 $daybefore = true; 210 $time = strtotime('-1 day', $time); 211 } 212 return userdate($time, 213 get_string($dateonly ? 'strftimedate' : 'strftimedatetime', 'langconfig')); 214 } 215 216 /** 217 * Checks whether a given time refers exactly to midnight (in current user 218 * timezone). 219 * 220 * @param int $time Time 221 * @return bool True if time refers to midnight, false otherwise 222 */ 223 protected static function is_midnight($time) { 224 return usergetmidnight($time) == $time; 225 } 226 227 public function update_after_restore( 228 $restoreid, $courseid, \base_logger $logger, $name) { 229 // Update the date, if restoring with changed date. 230 $dateoffset = \core_availability\info::get_restore_date_offset($restoreid); 231 if ($dateoffset) { 232 $this->time += $dateoffset; 233 return true; 234 } 235 return false; 236 } 237 238 /** 239 * Changes all date restrictions on a course by the specified shift amount. 240 * Used by the course reset feature. 241 * 242 * @param int $courseid Course id 243 * @param int $timeshift Offset in seconds 244 */ 245 public static function update_all_dates($courseid, $timeshift) { 246 global $DB; 247 248 $modinfo = get_fast_modinfo($courseid); 249 $anychanged = false; 250 251 // Adjust dates from all course modules. 252 foreach ($modinfo->cms as $cm) { 253 if (!$cm->availability) { 254 continue; 255 } 256 $info = new \core_availability\info_module($cm); 257 $tree = $info->get_availability_tree(); 258 $dates = $tree->get_all_children('availability_date\condition'); 259 $changed = false; 260 foreach ($dates as $date) { 261 $date->time += $timeshift; 262 $changed = true; 263 } 264 265 // Save the updated course module. 266 if ($changed) { 267 $DB->set_field('course_modules', 'availability', json_encode($tree->save()), 268 array('id' => $cm->id)); 269 $anychanged = true; 270 } 271 } 272 273 // Adjust dates from all course sections. 274 foreach ($modinfo->get_section_info_all() as $section) { 275 if (!$section->availability) { 276 continue; 277 } 278 279 $info = new \core_availability\info_section($section); 280 $tree = $info->get_availability_tree(); 281 $dates = $tree->get_all_children('availability_date\condition'); 282 $changed = false; 283 foreach ($dates as $date) { 284 $date->time += $timeshift; 285 $changed = true; 286 } 287 288 // Save the updated course module. 289 if ($changed) { 290 $updatesection = new \stdClass(); 291 $updatesection->id = $section->id; 292 $updatesection->availability = json_encode($tree->save()); 293 $updatesection->timemodified = time(); 294 $DB->update_record('course_sections', $updatesection); 295 // Invalidate the section cache by given section id. 296 \course_modinfo::purge_course_section_cache_by_id($courseid, $section->id); 297 298 $anychanged = true; 299 } 300 } 301 302 if ($anychanged) { 303 // Partial rebuild the sections which have been invalidated. 304 rebuild_course_cache($courseid, true, true); 305 } 306 } 307 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body