[ 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 * This file contains main class for the course format Weeks 19 * 20 * @since Moodle 2.0 21 * @package format_weeks 22 * @copyright 2009 Sam Hemelryk 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 require_once($CFG->dirroot. '/course/format/lib.php'); 28 29 /** 30 * Main class for the Weeks course format 31 * 32 * @package format_weeks 33 * @copyright 2012 Marina Glancy 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class format_weeks extends format_base { 37 38 /** 39 * Returns true if this course format uses sections 40 * 41 * @return bool 42 */ 43 public function uses_sections() { 44 return true; 45 } 46 47 /** 48 * Returns the display name of the given section that the course prefers. 49 * 50 * @param int|stdClass $section Section object from database or just field section.section 51 * @return string Display name that the course format prefers, e.g. "Topic 2" 52 */ 53 public function get_section_name($section) { 54 $section = $this->get_section($section); 55 if ((string)$section->name !== '') { 56 // Return the name the user set. 57 return format_string($section->name, true, array('context' => context_course::instance($this->courseid))); 58 } else { 59 return $this->get_default_section_name($section); 60 } 61 } 62 63 /** 64 * Returns the default section name for the weekly course format. 65 * 66 * If the section number is 0, it will use the string with key = section0name from the course format's lang file. 67 * Otherwise, the default format of "[start date] - [end date]" will be returned. 68 * 69 * @param stdClass $section Section object from database or just field course_sections section 70 * @return string The default value for the section name. 71 */ 72 public function get_default_section_name($section) { 73 if ($section->section == 0) { 74 // Return the general section. 75 return get_string('section0name', 'format_weeks'); 76 } else { 77 $dates = $this->get_section_dates($section); 78 79 // We subtract 24 hours for display purposes. 80 $dates->end = ($dates->end - 86400); 81 82 $dateformat = get_string('strftimedateshort'); 83 $weekday = userdate($dates->start, $dateformat); 84 $endweekday = userdate($dates->end, $dateformat); 85 return $weekday.' - '.$endweekday; 86 } 87 } 88 89 /** 90 * The URL to use for the specified course (with section) 91 * 92 * @param int|stdClass $section Section object from database or just field course_sections.section 93 * if omitted the course view page is returned 94 * @param array $options options for view URL. At the moment core uses: 95 * 'navigation' (bool) if true and section has no separate page, the function returns null 96 * 'sr' (int) used by multipage formats to specify to which section to return 97 * @return null|moodle_url 98 */ 99 public function get_view_url($section, $options = array()) { 100 global $CFG; 101 $course = $this->get_course(); 102 $url = new moodle_url('/course/view.php', array('id' => $course->id)); 103 104 $sr = null; 105 if (array_key_exists('sr', $options)) { 106 $sr = $options['sr']; 107 } 108 if (is_object($section)) { 109 $sectionno = $section->section; 110 } else { 111 $sectionno = $section; 112 } 113 if ($sectionno !== null) { 114 if ($sr !== null) { 115 if ($sr) { 116 $usercoursedisplay = COURSE_DISPLAY_MULTIPAGE; 117 $sectionno = $sr; 118 } else { 119 $usercoursedisplay = COURSE_DISPLAY_SINGLEPAGE; 120 } 121 } else { 122 $usercoursedisplay = $course->coursedisplay; 123 } 124 if ($sectionno != 0 && $usercoursedisplay == COURSE_DISPLAY_MULTIPAGE) { 125 $url->param('section', $sectionno); 126 } else { 127 if (empty($CFG->linkcoursesections) && !empty($options['navigation'])) { 128 return null; 129 } 130 $url->set_anchor('section-'.$sectionno); 131 } 132 } 133 return $url; 134 } 135 136 /** 137 * Returns the information about the ajax support in the given source format 138 * 139 * The returned object's property (boolean)capable indicates that 140 * the course format supports Moodle course ajax features. 141 * 142 * @return stdClass 143 */ 144 public function supports_ajax() { 145 $ajaxsupport = new stdClass(); 146 $ajaxsupport->capable = true; 147 return $ajaxsupport; 148 } 149 150 /** 151 * Loads all of the course sections into the navigation 152 * 153 * @param global_navigation $navigation 154 * @param navigation_node $node The course node within the navigation 155 */ 156 public function extend_course_navigation($navigation, navigation_node $node) { 157 global $PAGE; 158 // if section is specified in course/view.php, make sure it is expanded in navigation 159 if ($navigation->includesectionnum === false) { 160 $selectedsection = optional_param('section', null, PARAM_INT); 161 if ($selectedsection !== null && (!defined('AJAX_SCRIPT') || AJAX_SCRIPT == '0') && 162 $PAGE->url->compare(new moodle_url('/course/view.php'), URL_MATCH_BASE)) { 163 $navigation->includesectionnum = $selectedsection; 164 } 165 } 166 parent::extend_course_navigation($navigation, $node); 167 168 // We want to remove the general section if it is empty. 169 $modinfo = get_fast_modinfo($this->get_course()); 170 $sections = $modinfo->get_sections(); 171 if (!isset($sections[0])) { 172 // The general section is empty to find the navigation node for it we need to get its ID. 173 $section = $modinfo->get_section_info(0); 174 $generalsection = $node->get($section->id, navigation_node::TYPE_SECTION); 175 if ($generalsection) { 176 // We found the node - now remove it. 177 $generalsection->remove(); 178 } 179 } 180 } 181 182 /** 183 * Custom action after section has been moved in AJAX mode 184 * 185 * Used in course/rest.php 186 * 187 * @return array This will be passed in ajax respose 188 */ 189 function ajax_section_move() { 190 global $PAGE; 191 $titles = array(); 192 $current = -1; 193 $course = $this->get_course(); 194 $modinfo = get_fast_modinfo($course); 195 $renderer = $this->get_renderer($PAGE); 196 if ($renderer && ($sections = $modinfo->get_section_info_all())) { 197 foreach ($sections as $number => $section) { 198 $titles[$number] = $renderer->section_title($section, $course); 199 if ($this->is_section_current($section)) { 200 $current = $number; 201 } 202 } 203 } 204 return array('sectiontitles' => $titles, 'current' => $current, 'action' => 'move'); 205 } 206 207 /** 208 * Returns the list of blocks to be automatically added for the newly created course 209 * 210 * @return array of default blocks, must contain two keys BLOCK_POS_LEFT and BLOCK_POS_RIGHT 211 * each of values is an array of block names (for left and right side columns) 212 */ 213 public function get_default_blocks() { 214 return array( 215 BLOCK_POS_LEFT => array(), 216 BLOCK_POS_RIGHT => array('search_forums', 'news_items', 'calendar_upcoming', 'recent_activity') 217 ); 218 } 219 220 /** 221 * Definitions of the additional options that this course format uses for course 222 * 223 * Weeks format uses the following options: 224 * - coursedisplay 225 * - numsections 226 * - hiddensections 227 * 228 * @param bool $foreditform 229 * @return array of options 230 */ 231 public function course_format_options($foreditform = false) { 232 static $courseformatoptions = false; 233 if ($courseformatoptions === false) { 234 $courseconfig = get_config('moodlecourse'); 235 $courseformatoptions = array( 236 'numsections' => array( 237 'default' => $courseconfig->numsections, 238 'type' => PARAM_INT, 239 ), 240 'hiddensections' => array( 241 'default' => $courseconfig->hiddensections, 242 'type' => PARAM_INT, 243 ), 244 'coursedisplay' => array( 245 'default' => $courseconfig->coursedisplay, 246 'type' => PARAM_INT, 247 ), 248 ); 249 } 250 if ($foreditform && !isset($courseformatoptions['coursedisplay']['label'])) { 251 $courseconfig = get_config('moodlecourse'); 252 $sectionmenu = array(); 253 $max = $courseconfig->maxsections; 254 if (!isset($max) || !is_numeric($max)) { 255 $max = 52; 256 } 257 for ($i = 0; $i <= $max; $i++) { 258 $sectionmenu[$i] = "$i"; 259 } 260 $courseformatoptionsedit = array( 261 'numsections' => array( 262 'label' => new lang_string('numberweeks'), 263 'element_type' => 'select', 264 'element_attributes' => array($sectionmenu), 265 ), 266 'hiddensections' => array( 267 'label' => new lang_string('hiddensections'), 268 'help' => 'hiddensections', 269 'help_component' => 'moodle', 270 'element_type' => 'select', 271 'element_attributes' => array( 272 array( 273 0 => new lang_string('hiddensectionscollapsed'), 274 1 => new lang_string('hiddensectionsinvisible') 275 ) 276 ), 277 ), 278 'coursedisplay' => array( 279 'label' => new lang_string('coursedisplay'), 280 'element_type' => 'select', 281 'element_attributes' => array( 282 array( 283 COURSE_DISPLAY_SINGLEPAGE => new lang_string('coursedisplay_single'), 284 COURSE_DISPLAY_MULTIPAGE => new lang_string('coursedisplay_multi') 285 ) 286 ), 287 'help' => 'coursedisplay', 288 'help_component' => 'moodle', 289 ) 290 ); 291 $courseformatoptions = array_merge_recursive($courseformatoptions, $courseformatoptionsedit); 292 } 293 return $courseformatoptions; 294 } 295 296 /** 297 * Adds format options elements to the course/section edit form. 298 * 299 * This function is called from {@link course_edit_form::definition_after_data()}. 300 * 301 * @param MoodleQuickForm $mform form the elements are added to. 302 * @param bool $forsection 'true' if this is a section edit form, 'false' if this is course edit form. 303 * @return array array of references to the added form elements. 304 */ 305 public function create_edit_form_elements(&$mform, $forsection = false) { 306 $elements = parent::create_edit_form_elements($mform, $forsection); 307 308 // Increase the number of sections combo box values if the user has increased the number of sections 309 // using the icon on the course page beyond course 'maxsections' or course 'maxsections' has been 310 // reduced below the number of sections already set for the course on the site administration course 311 // defaults page. This is so that the number of sections is not reduced leaving unintended orphaned 312 // activities / resources. 313 if (!$forsection) { 314 $maxsections = get_config('moodlecourse', 'maxsections'); 315 $numsections = $mform->getElementValue('numsections'); 316 $numsections = $numsections[0]; 317 if ($numsections > $maxsections) { 318 $element = $mform->getElement('numsections'); 319 for ($i = $maxsections+1; $i <= $numsections; $i++) { 320 $element->addOption("$i", $i); 321 } 322 } 323 } 324 return $elements; 325 } 326 327 /** 328 * Updates format options for a course 329 * 330 * In case if course format was changed to 'weeks', we try to copy options 331 * 'coursedisplay', 'numsections' and 'hiddensections' from the previous format. 332 * If previous course format did not have 'numsections' option, we populate it with the 333 * current number of sections 334 * 335 * @param stdClass|array $data return value from {@link moodleform::get_data()} or array with data 336 * @param stdClass $oldcourse if this function is called from {@link update_course()} 337 * this object contains information about the course before update 338 * @return bool whether there were any changes to the options values 339 */ 340 public function update_course_format_options($data, $oldcourse = null) { 341 global $DB; 342 $data = (array)$data; 343 if ($oldcourse !== null) { 344 $oldcourse = (array)$oldcourse; 345 $options = $this->course_format_options(); 346 foreach ($options as $key => $unused) { 347 if (!array_key_exists($key, $data)) { 348 if (array_key_exists($key, $oldcourse)) { 349 $data[$key] = $oldcourse[$key]; 350 } else if ($key === 'numsections') { 351 // If previous format does not have the field 'numsections' 352 // and $data['numsections'] is not set, 353 // we fill it with the maximum section number from the DB 354 $maxsection = $DB->get_field_sql('SELECT max(section) from {course_sections} 355 WHERE course = ?', array($this->courseid)); 356 if ($maxsection) { 357 // If there are no sections, or just default 0-section, 'numsections' will be set to default 358 $data['numsections'] = $maxsection; 359 } 360 } 361 } 362 } 363 } 364 $changed = $this->update_format_options($data); 365 if ($changed && array_key_exists('numsections', $data)) { 366 // If the numsections was decreased, try to completely delete the orphaned sections (unless they are not empty). 367 $numsections = (int)$data['numsections']; 368 $maxsection = $DB->get_field_sql('SELECT max(section) from {course_sections} 369 WHERE course = ?', array($this->courseid)); 370 for ($sectionnum = $maxsection; $sectionnum > $numsections; $sectionnum--) { 371 if (!$this->delete_section($sectionnum, false)) { 372 break; 373 } 374 } 375 } 376 return $changed; 377 } 378 379 /** 380 * Return the start and end date of the passed section 381 * 382 * @param int|stdClass|section_info $section section to get the dates for 383 * @return stdClass property start for startdate, property end for enddate 384 */ 385 public function get_section_dates($section) { 386 $course = $this->get_course(); 387 if (is_object($section)) { 388 $sectionnum = $section->section; 389 } else { 390 $sectionnum = $section; 391 } 392 $oneweekseconds = 604800; 393 // Hack alert. We add 2 hours to avoid possible DST problems. (e.g. we go into daylight 394 // savings and the date changes. 395 $startdate = $course->startdate + 7200; 396 397 $dates = new stdClass(); 398 $dates->start = $startdate + ($oneweekseconds * ($sectionnum - 1)); 399 $dates->end = $dates->start + $oneweekseconds; 400 401 return $dates; 402 } 403 404 /** 405 * Returns true if the specified week is current 406 * 407 * @param int|stdClass|section_info $section 408 * @return bool 409 */ 410 public function is_section_current($section) { 411 if (is_object($section)) { 412 $sectionnum = $section->section; 413 } else { 414 $sectionnum = $section; 415 } 416 if ($sectionnum < 1) { 417 return false; 418 } 419 $timenow = time(); 420 $dates = $this->get_section_dates($section); 421 return (($timenow >= $dates->start) && ($timenow < $dates->end)); 422 } 423 424 /** 425 * Whether this format allows to delete sections 426 * 427 * Do not call this function directly, instead use {@link course_can_delete_section()} 428 * 429 * @param int|stdClass|section_info $section 430 * @return bool 431 */ 432 public function can_delete_section($section) { 433 return true; 434 } 435 436 /** 437 * Prepares the templateable object to display section name 438 * 439 * @param \section_info|\stdClass $section 440 * @param bool $linkifneeded 441 * @param bool $editable 442 * @param null|lang_string|string $edithint 443 * @param null|lang_string|string $editlabel 444 * @return \core\output\inplace_editable 445 */ 446 public function inplace_editable_render_section_name($section, $linkifneeded = true, 447 $editable = null, $edithint = null, $editlabel = null) { 448 if (empty($edithint)) { 449 $edithint = new lang_string('editsectionname', 'format_weeks'); 450 } 451 if (empty($editlabel)) { 452 $title = get_section_name($section->course, $section); 453 $editlabel = new lang_string('newsectionname', 'format_weeks', $title); 454 } 455 return parent::inplace_editable_render_section_name($section, $linkifneeded, $editable, $edithint, $editlabel); 456 } 457 } 458 459 /** 460 * Implements callback inplace_editable() allowing to edit values in-place 461 * 462 * @param string $itemtype 463 * @param int $itemid 464 * @param mixed $newvalue 465 * @return \core\output\inplace_editable 466 */ 467 function format_weeks_inplace_editable($itemtype, $itemid, $newvalue) { 468 global $DB, $CFG; 469 require_once($CFG->dirroot . '/course/lib.php'); 470 if ($itemtype === 'sectionname' || $itemtype === 'sectionnamenl') { 471 $section = $DB->get_record_sql( 472 'SELECT s.* FROM {course_sections} s JOIN {course} c ON s.course = c.id WHERE s.id = ? AND c.format = ?', 473 array($itemid, 'weeks'), MUST_EXIST); 474 return course_get_format($section->course)->inplace_editable_update_section_name($section, $itemtype, $newvalue); 475 } 476 }
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 |