See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401]
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 * Contains event class for displaying the month view. 19 * 20 * @package core_calendar 21 * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace core_calendar\external; 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 use core\external\exporter; 30 use renderer_base; 31 use moodle_url; 32 33 /** 34 * Class for displaying the month view. 35 * 36 * @package core_calendar 37 * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk> 38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 39 */ 40 class month_exporter extends exporter { 41 42 /** @var int Number of calendar instances displayed. */ 43 protected static $calendarinstances = 0; 44 45 /** @var int This calendar instance's ID. */ 46 protected $calendarinstanceid = 0; 47 48 /** 49 * @var \calendar_information $calendar The calendar to be rendered. 50 */ 51 protected $calendar; 52 53 /** 54 * @var int $firstdayofweek The first day of the week. 55 */ 56 protected $firstdayofweek; 57 58 /** 59 * @var moodle_url $url The URL for the events page. 60 */ 61 protected $url; 62 63 /** 64 * @var bool $includenavigation Whether navigation should be included on the output. 65 */ 66 protected $includenavigation = true; 67 68 /** 69 * @var bool $initialeventsloaded Whether the events have been loaded for this month. 70 */ 71 protected $initialeventsloaded = true; 72 73 /** 74 * @var bool $showcoursefilter Whether to render the course filter selector as well. 75 */ 76 protected $showcoursefilter = false; 77 78 /** 79 * Constructor for month_exporter. 80 * 81 * @param \calendar_information $calendar The calendar being represented 82 * @param \core_calendar\type_base $type The calendar type (e.g. Gregorian) 83 * @param array $related The related information 84 */ 85 public function __construct(\calendar_information $calendar, \core_calendar\type_base $type, $related) { 86 // Increment the calendar instances count on initialisation. 87 self::$calendarinstances++; 88 // Assign this instance an ID based on the latest calendar instances count. 89 $this->calendarinstanceid = self::$calendarinstances; 90 $this->calendar = $calendar; 91 $this->firstdayofweek = $type->get_starting_weekday(); 92 93 $this->url = new moodle_url('/calendar/view.php', [ 94 'view' => 'month', 95 'time' => $calendar->time, 96 ]); 97 98 if ($this->calendar->course && SITEID !== $this->calendar->course->id) { 99 $this->url->param('course', $this->calendar->course->id); 100 } else if ($this->calendar->categoryid) { 101 $this->url->param('category', $this->calendar->categoryid); 102 } 103 104 $related['type'] = $type; 105 106 $data = [ 107 'url' => $this->url->out(false), 108 ]; 109 110 parent::__construct($data, $related); 111 } 112 113 protected static function define_properties() { 114 return [ 115 'url' => [ 116 'type' => PARAM_URL, 117 ], 118 ]; 119 } 120 121 /** 122 * Return the list of additional properties. 123 * 124 * @return array 125 */ 126 protected static function define_other_properties() { 127 return [ 128 'courseid' => [ 129 'type' => PARAM_INT, 130 ], 131 'categoryid' => [ 132 'type' => PARAM_INT, 133 'optional' => true, 134 'default' => 0, 135 ], 136 'filter_selector' => [ 137 'type' => PARAM_RAW, 138 'optional' => true, 139 ], 140 'weeks' => [ 141 'type' => week_exporter::read_properties_definition(), 142 'multiple' => true, 143 ], 144 'daynames' => [ 145 'type' => day_name_exporter::read_properties_definition(), 146 'multiple' => true, 147 ], 148 'view' => [ 149 'type' => PARAM_ALPHA, 150 ], 151 'date' => [ 152 'type' => date_exporter::read_properties_definition(), 153 ], 154 'periodname' => [ 155 // Note: We must use RAW here because the calendar type returns the formatted month name based on a 156 // calendar format. 157 'type' => PARAM_RAW, 158 ], 159 'includenavigation' => [ 160 'type' => PARAM_BOOL, 161 'default' => true, 162 ], 163 // Tracks whether the first set of events have been loaded and provided 164 // to the exporter. 165 'initialeventsloaded' => [ 166 'type' => PARAM_BOOL, 167 'default' => true, 168 ], 169 'previousperiod' => [ 170 'type' => date_exporter::read_properties_definition(), 171 ], 172 'previousperiodlink' => [ 173 'type' => PARAM_URL, 174 ], 175 'previousperiodname' => [ 176 // Note: We must use RAW here because the calendar type returns the formatted month name based on a 177 // calendar format. 178 'type' => PARAM_RAW, 179 ], 180 'nextperiod' => [ 181 'type' => date_exporter::read_properties_definition(), 182 ], 183 'nextperiodname' => [ 184 // Note: We must use RAW here because the calendar type returns the formatted month name based on a 185 // calendar format. 186 'type' => PARAM_RAW, 187 ], 188 'nextperiodlink' => [ 189 'type' => PARAM_URL, 190 ], 191 'larrow' => [ 192 // The left arrow defined by the theme. 193 'type' => PARAM_RAW, 194 ], 195 'rarrow' => [ 196 // The right arrow defined by the theme. 197 'type' => PARAM_RAW, 198 ], 199 'defaulteventcontext' => [ 200 'type' => PARAM_INT, 201 'default' => 0, 202 ], 203 'calendarinstanceid' => [ 204 'type' => PARAM_INT, 205 'default' => 0, 206 ], 207 'viewingmonth' => [ 208 'type' => PARAM_BOOL, 209 'default' => true, 210 ], 211 'showviewselector' => [ 212 'type' => PARAM_BOOL, 213 'default' => true, 214 ], 215 'viewinginblock' => [ 216 'type' => PARAM_BOOL, 217 'default' => false, 218 ], 219 ]; 220 } 221 222 /** 223 * Get the additional values to inject while exporting. 224 * 225 * @param renderer_base $output The renderer. 226 * @return array Keys are the property names, values are their values. 227 */ 228 protected function get_other_values(renderer_base $output) { 229 $previousperiod = $this->get_previous_month_data(); 230 $nextperiod = $this->get_next_month_data(); 231 $date = $this->related['type']->timestamp_to_date_array($this->calendar->time); 232 233 $nextperiodlink = new moodle_url($this->url); 234 $nextperiodlink->param('time', $nextperiod[0]); 235 236 $previousperiodlink = new moodle_url($this->url); 237 $previousperiodlink->param('time', $previousperiod[0]); 238 239 $viewmode = $this->calendar->get_viewmode() ?? 'month'; 240 241 $return = [ 242 'courseid' => $this->calendar->courseid, 243 'weeks' => $this->get_weeks($output), 244 'daynames' => $this->get_day_names($output), 245 'view' => $viewmode, 246 'date' => (new date_exporter($date))->export($output), 247 'periodname' => userdate($this->calendar->time, get_string('strftimemonthyear')), 248 'previousperiod' => (new date_exporter($previousperiod))->export($output), 249 'previousperiodname' => userdate($previousperiod[0], get_string('strftimemonth')), 250 'previousperiodlink' => $previousperiodlink->out(false), 251 'nextperiod' => (new date_exporter($nextperiod))->export($output), 252 'nextperiodname' => userdate($nextperiod[0], get_string('strftimemonth')), 253 'nextperiodlink' => $nextperiodlink->out(false), 254 'larrow' => $output->larrow(), 255 'rarrow' => $output->rarrow(), 256 'includenavigation' => $this->includenavigation, 257 'initialeventsloaded' => $this->initialeventsloaded, 258 'calendarinstanceid' => $this->calendarinstanceid, 259 'showviewselector' => $viewmode === 'month', 260 'viewinginblock' => $viewmode === 'monthblock', 261 ]; 262 263 if ($this->showcoursefilter) { 264 $return['filter_selector'] = $this->get_course_filter_selector($output); 265 } 266 267 if ($context = $this->get_default_add_context()) { 268 $return['defaulteventcontext'] = $context->id; 269 } 270 271 if ($this->calendar->categoryid) { 272 $return['categoryid'] = $this->calendar->categoryid; 273 } 274 275 return $return; 276 } 277 278 /** 279 * Get the course filter selector. 280 * 281 * @param renderer_base $output 282 * @return string The html code for the course filter selector. 283 */ 284 protected function get_course_filter_selector(renderer_base $output) { 285 $content = ''; 286 $content .= $output->course_filter_selector($this->url, '', $this->calendar->course->id, $this->calendarinstanceid); 287 288 return $content; 289 } 290 291 /** 292 * Get the list of day names for display, re-ordered from the first day 293 * of the week. 294 * 295 * @param renderer_base $output 296 * @return day_name_exporter[] 297 */ 298 protected function get_day_names(renderer_base $output) { 299 $weekdays = $this->related['type']->get_weekdays(); 300 $daysinweek = count($weekdays); 301 302 $daynames = []; 303 for ($i = 0; $i < $daysinweek; $i++) { 304 // Bump the currentdayno and ensure it loops. 305 $dayno = ($i + $this->firstdayofweek + $daysinweek) % $daysinweek; 306 $dayname = new day_name_exporter($dayno, $weekdays[$dayno]); 307 $daynames[] = $dayname->export($output); 308 } 309 310 return $daynames; 311 } 312 313 /** 314 * Get the list of week days, ordered into weeks and padded according 315 * to the value of the first day of the week. 316 * 317 * @param renderer_base $output 318 * @return array The list of weeks. 319 */ 320 protected function get_weeks(renderer_base $output) { 321 $weeks = []; 322 $alldays = $this->get_days(); 323 324 $daysinweek = count($this->related['type']->get_weekdays()); 325 326 // Calculate which day number is the first, and last day of the week. 327 $firstdayofweek = $this->firstdayofweek; 328 329 // The first week is special as it may have padding at the beginning. 330 $day = reset($alldays); 331 $firstdayno = $day['wday']; 332 333 $prepadding = ($firstdayno + $daysinweek - $firstdayofweek) % $daysinweek; 334 $daysinfirstweek = $daysinweek - $prepadding; 335 $days = array_slice($alldays, 0, $daysinfirstweek); 336 $week = new week_exporter($this->calendar, $days, $prepadding, ($daysinweek - count($days) - $prepadding), $this->related); 337 $weeks[] = $week->export($output); 338 339 // Now chunk up the remaining day. and turn them into weeks. 340 $daychunks = array_chunk(array_slice($alldays, $daysinfirstweek), $daysinweek); 341 foreach ($daychunks as $days) { 342 $week = new week_exporter($this->calendar, $days, 0, ($daysinweek - count($days)), $this->related); 343 $weeks[] = $week->export($output); 344 } 345 346 return $weeks; 347 } 348 349 /** 350 * Get the list of days with the matching date array. 351 * 352 * @return array 353 */ 354 protected function get_days() { 355 $date = $this->related['type']->timestamp_to_date_array($this->calendar->time); 356 $monthdays = $this->related['type']->get_num_days_in_month($date['year'], $date['mon']); 357 358 $days = []; 359 for ($dayno = 1; $dayno <= $monthdays; $dayno++) { 360 // Get the gregorian representation of the day. 361 $timestamp = $this->related['type']->convert_to_timestamp($date['year'], $date['mon'], $dayno); 362 363 $days[] = $this->related['type']->timestamp_to_date_array($timestamp); 364 } 365 366 return $days; 367 } 368 369 /** 370 * Returns a list of objects that are related. 371 * 372 * @return array 373 */ 374 protected static function define_related() { 375 return [ 376 'events' => '\core_calendar\local\event\entities\event_interface[]', 377 'cache' => '\core_calendar\external\events_related_objects_cache', 378 'type' => '\core_calendar\type_base', 379 ]; 380 } 381 382 /** 383 * Get the current month timestamp. 384 * 385 * @return int The month timestamp. 386 */ 387 protected function get_month_data() { 388 $date = $this->related['type']->timestamp_to_date_array($this->calendar->time); 389 $monthtime = $this->related['type']->convert_to_gregorian($date['year'], $date['month'], 1); 390 391 return make_timestamp($monthtime['year'], $monthtime['month']); 392 } 393 394 /** 395 * Get the previous month timestamp. 396 * 397 * @return int The previous month timestamp. 398 */ 399 protected function get_previous_month_data() { 400 $type = $this->related['type']; 401 $date = $type->timestamp_to_date_array($this->calendar->time); 402 list($date['mon'], $date['year']) = $type->get_prev_month($date['year'], $date['mon']); 403 $time = $type->convert_to_timestamp($date['year'], $date['mon'], 1); 404 405 return $type->timestamp_to_date_array($time); 406 } 407 408 /** 409 * Get the next month timestamp. 410 * 411 * @return int The next month timestamp. 412 */ 413 protected function get_next_month_data() { 414 $type = $this->related['type']; 415 $date = $type->timestamp_to_date_array($this->calendar->time); 416 list($date['mon'], $date['year']) = $type->get_next_month($date['year'], $date['mon']); 417 $time = $type->convert_to_timestamp($date['year'], $date['mon'], 1); 418 419 return $type->timestamp_to_date_array($time); 420 } 421 422 /** 423 * Set whether the navigation should be shown. 424 * 425 * @param bool $include 426 * @return $this 427 */ 428 public function set_includenavigation($include) { 429 $this->includenavigation = $include; 430 431 return $this; 432 } 433 434 /** 435 * Set whether the initial events have already been loaded and 436 * provided to the exporter. 437 * 438 * @param bool $loaded 439 * @return $this 440 */ 441 public function set_initialeventsloaded(bool $loaded) { 442 $this->initialeventsloaded = $loaded; 443 444 return $this; 445 } 446 447 /** 448 * Set whether the course filter selector should be shown. 449 * 450 * @param bool $show 451 * @return $this 452 */ 453 public function set_showcoursefilter(bool $show) { 454 $this->showcoursefilter = $show; 455 456 return $this; 457 } 458 459 /** 460 * Get the default context for use when adding a new event. 461 * 462 * @return null|\context 463 */ 464 protected function get_default_add_context() { 465 if (calendar_user_can_add_event($this->calendar->course)) { 466 return \context_course::instance($this->calendar->course->id); 467 } 468 469 return null; 470 } 471 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body