Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
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 * Base renderer for outputting course formats. 19 * 20 * @package core 21 * @copyright 2012 Dan Poltawski 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 * @since Moodle 2.3 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 29 /** 30 * This is a convenience renderer which can be used by section based formats 31 * to reduce code duplication. It is not necessary for all course formats to 32 * use this and its likely to change in future releases. 33 * 34 * @package core 35 * @copyright 2012 Dan Poltawski 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 * @since Moodle 2.3 38 */ 39 abstract class format_section_renderer_base extends plugin_renderer_base { 40 41 /** @var core_course_renderer contains instance of core course renderer */ 42 protected $courserenderer; 43 44 /** 45 * Constructor method, calls the parent constructor 46 * 47 * @param moodle_page $page 48 * @param string $target one of rendering target constants 49 */ 50 public function __construct(moodle_page $page, $target) { 51 parent::__construct($page, $target); 52 $this->courserenderer = $this->page->get_renderer('core', 'course'); 53 } 54 55 /** 56 * Generate the starting container html for a list of sections 57 * @return string HTML to output. 58 */ 59 abstract protected function start_section_list(); 60 61 /** 62 * Generate the closing container html for a list of sections 63 * @return string HTML to output. 64 */ 65 abstract protected function end_section_list(); 66 67 /** 68 * Generate the title for this section page 69 * @return string the page title 70 */ 71 abstract protected function page_title(); 72 73 /** 74 * Generate the section title, wraps it in a link to the section page if page is to be displayed on a separate page 75 * 76 * @param stdClass $section The course_section entry from DB 77 * @param stdClass $course The course entry from DB 78 * @return string HTML to output. 79 */ 80 public function section_title($section, $course) { 81 $title = get_section_name($course, $section); 82 $url = course_get_url($course, $section->section, array('navigation' => true)); 83 if ($url) { 84 $title = html_writer::link($url, $title); 85 } 86 return $title; 87 } 88 89 /** 90 * Generate the section title to be displayed on the section page, without a link 91 * 92 * @param stdClass $section The course_section entry from DB 93 * @param stdClass $course The course entry from DB 94 * @return string HTML to output. 95 */ 96 public function section_title_without_link($section, $course) { 97 return get_section_name($course, $section); 98 } 99 100 /** 101 * Generate the edit control action menu 102 * 103 * @param array $controls The edit control items from section_edit_control_items 104 * @param stdClass $course The course entry from DB 105 * @param stdClass $section The course_section entry from DB 106 * @return string HTML to output. 107 */ 108 protected function section_edit_control_menu($controls, $course, $section) { 109 $o = ""; 110 if (!empty($controls)) { 111 $menu = new action_menu(); 112 $menu->set_menu_trigger(get_string('edit')); 113 $menu->attributes['class'] .= ' section-actions'; 114 foreach ($controls as $value) { 115 $url = empty($value['url']) ? '' : $value['url']; 116 $icon = empty($value['icon']) ? '' : $value['icon']; 117 $name = empty($value['name']) ? '' : $value['name']; 118 $attr = empty($value['attr']) ? array() : $value['attr']; 119 $class = empty($value['pixattr']['class']) ? '' : $value['pixattr']['class']; 120 $al = new action_menu_link_secondary( 121 new moodle_url($url), 122 new pix_icon($icon, '', null, array('class' => "smallicon " . $class)), 123 $name, 124 $attr 125 ); 126 $menu->add($al); 127 } 128 129 $o .= html_writer::div($this->render($menu), 'section_action_menu', 130 array('data-sectionid' => $section->id)); 131 } 132 133 return $o; 134 } 135 136 /** 137 * Generate the content to displayed on the right part of a section 138 * before course modules are included 139 * 140 * @param stdClass $section The course_section entry from DB 141 * @param stdClass $course The course entry from DB 142 * @param bool $onsectionpage true if being printed on a section page 143 * @return string HTML to output. 144 */ 145 protected function section_right_content($section, $course, $onsectionpage) { 146 $o = $this->output->spacer(); 147 148 $controls = $this->section_edit_control_items($course, $section, $onsectionpage); 149 $o .= $this->section_edit_control_menu($controls, $course, $section); 150 151 return $o; 152 } 153 154 /** 155 * Generate the content to displayed on the left part of a section 156 * before course modules are included 157 * 158 * @param stdClass $section The course_section entry from DB 159 * @param stdClass $course The course entry from DB 160 * @param bool $onsectionpage true if being printed on a section page 161 * @return string HTML to output. 162 */ 163 protected function section_left_content($section, $course, $onsectionpage) { 164 $o = ''; 165 166 if ($section->section != 0) { 167 // Only in the non-general sections. 168 if (course_get_format($course)->is_section_current($section)) { 169 $o = get_accesshide(get_string('currentsection', 'format_'.$course->format)); 170 } 171 } 172 173 return $o; 174 } 175 176 /** 177 * Generate the display of the header part of a section before 178 * course modules are included 179 * 180 * @param stdClass $section The course_section entry from DB 181 * @param stdClass $course The course entry from DB 182 * @param bool $onsectionpage true if being printed on a single-section page 183 * @param int $sectionreturn The section to return to after an action 184 * @return string HTML to output. 185 */ 186 protected function section_header($section, $course, $onsectionpage, $sectionreturn=null) { 187 $o = ''; 188 $currenttext = ''; 189 $sectionstyle = ''; 190 191 if ($section->section != 0) { 192 // Only in the non-general sections. 193 if (!$section->visible) { 194 $sectionstyle = ' hidden'; 195 } 196 if (course_get_format($course)->is_section_current($section)) { 197 $sectionstyle = ' current'; 198 } 199 } 200 201 $o .= html_writer::start_tag('li', [ 202 'id' => 'section-'.$section->section, 203 'class' => 'section main clearfix'.$sectionstyle, 204 'role' => 'region', 205 'aria-labelledby' => "sectionid-{$section->id}-title", 206 'data-sectionid' => $section->section, 207 'data-sectionreturnid' => $sectionreturn 208 ]); 209 210 $leftcontent = $this->section_left_content($section, $course, $onsectionpage); 211 $o.= html_writer::tag('div', $leftcontent, array('class' => 'left side')); 212 213 $rightcontent = $this->section_right_content($section, $course, $onsectionpage); 214 $o.= html_writer::tag('div', $rightcontent, array('class' => 'right side')); 215 $o.= html_writer::start_tag('div', array('class' => 'content')); 216 217 // When not on a section page, we display the section titles except the general section if null 218 $hasnamenotsecpg = (!$onsectionpage && ($section->section != 0 || !is_null($section->name))); 219 220 // When on a section page, we only display the general section title, if title is not the default one 221 $hasnamesecpg = ($onsectionpage && ($section->section == 0 && !is_null($section->name))); 222 223 $classes = ' accesshide'; 224 if ($hasnamenotsecpg || $hasnamesecpg) { 225 $classes = ''; 226 } 227 $sectionname = html_writer::tag('span', $this->section_title($section, $course)); 228 $o .= $this->output->heading($sectionname, 3, 'sectionname' . $classes, "sectionid-{$section->id}-title"); 229 230 $o .= $this->section_availability($section); 231 232 $o .= html_writer::start_tag('div', array('class' => 'summary')); 233 if ($section->uservisible || $section->visible) { 234 // Show summary if section is available or has availability restriction information. 235 // Do not show summary if section is hidden but we still display it because of course setting 236 // "Hidden sections are shown in collapsed form". 237 $o .= $this->format_summary_text($section); 238 } 239 $o .= html_writer::end_tag('div'); 240 241 return $o; 242 } 243 244 /** 245 * Generate the display of the footer part of a section 246 * 247 * @return string HTML to output. 248 */ 249 protected function section_footer() { 250 $o = html_writer::end_tag('div'); 251 $o.= html_writer::end_tag('li'); 252 253 return $o; 254 } 255 256 /** 257 * @deprecated since Moodle 3.0 MDL-48947 - Use format_section_renderer_base::section_edit_control_items() instead 258 */ 259 protected function section_edit_controls() { 260 throw new coding_exception('section_edit_controls() can not be used anymore. Please use ' . 261 'section_edit_control_items() instead.'); 262 } 263 264 /** 265 * Generate the edit control items of a section 266 * 267 * @param stdClass $course The course entry from DB 268 * @param stdClass $section The course_section entry from DB 269 * @param bool $onsectionpage true if being printed on a section page 270 * @return array of edit control items 271 */ 272 protected function section_edit_control_items($course, $section, $onsectionpage = false) { 273 if (!$this->page->user_is_editing()) { 274 return array(); 275 } 276 277 $sectionreturn = $onsectionpage ? $section->section : null; 278 279 $coursecontext = context_course::instance($course->id); 280 $numsections = course_get_format($course)->get_last_section_number(); 281 $isstealth = $section->section > $numsections; 282 283 $baseurl = course_get_url($course, $sectionreturn); 284 $baseurl->param('sesskey', sesskey()); 285 286 $controls = array(); 287 288 if (!$isstealth && has_capability('moodle/course:update', $coursecontext)) { 289 if ($section->section > 0 290 && get_string_manager()->string_exists('editsection', 'format_'.$course->format)) { 291 $streditsection = get_string('editsection', 'format_'.$course->format); 292 } else { 293 $streditsection = get_string('editsection'); 294 } 295 296 $controls['edit'] = array( 297 'url' => new moodle_url('/course/editsection.php', array('id' => $section->id, 'sr' => $sectionreturn)), 298 'icon' => 'i/settings', 299 'name' => $streditsection, 300 'pixattr' => array('class' => ''), 301 'attr' => array('class' => 'icon edit')); 302 } 303 304 if ($section->section) { 305 $url = clone($baseurl); 306 if (!$isstealth) { 307 if (has_capability('moodle/course:sectionvisibility', $coursecontext)) { 308 if ($section->visible) { // Show the hide/show eye. 309 $strhidefromothers = get_string('hidefromothers', 'format_'.$course->format); 310 $url->param('hide', $section->section); 311 $controls['visiblity'] = array( 312 'url' => $url, 313 'icon' => 'i/hide', 314 'name' => $strhidefromothers, 315 'pixattr' => array('class' => ''), 316 'attr' => array('class' => 'icon editing_showhide', 317 'data-sectionreturn' => $sectionreturn, 'data-action' => 'hide')); 318 } else { 319 $strshowfromothers = get_string('showfromothers', 'format_'.$course->format); 320 $url->param('show', $section->section); 321 $controls['visiblity'] = array( 322 'url' => $url, 323 'icon' => 'i/show', 324 'name' => $strshowfromothers, 325 'pixattr' => array('class' => ''), 326 'attr' => array('class' => 'icon editing_showhide', 327 'data-sectionreturn' => $sectionreturn, 'data-action' => 'show')); 328 } 329 } 330 331 if (!$onsectionpage) { 332 if (has_capability('moodle/course:movesections', $coursecontext)) { 333 $url = clone($baseurl); 334 if ($section->section > 1) { // Add a arrow to move section up. 335 $url->param('section', $section->section); 336 $url->param('move', -1); 337 $strmoveup = get_string('moveup'); 338 $controls['moveup'] = array( 339 'url' => $url, 340 'icon' => 'i/up', 341 'name' => $strmoveup, 342 'pixattr' => array('class' => ''), 343 'attr' => array('class' => 'icon moveup')); 344 } 345 346 $url = clone($baseurl); 347 if ($section->section < $numsections) { // Add a arrow to move section down. 348 $url->param('section', $section->section); 349 $url->param('move', 1); 350 $strmovedown = get_string('movedown'); 351 $controls['movedown'] = array( 352 'url' => $url, 353 'icon' => 'i/down', 354 'name' => $strmovedown, 355 'pixattr' => array('class' => ''), 356 'attr' => array('class' => 'icon movedown')); 357 } 358 } 359 } 360 } 361 362 if (course_can_delete_section($course, $section)) { 363 if (get_string_manager()->string_exists('deletesection', 'format_'.$course->format)) { 364 $strdelete = get_string('deletesection', 'format_'.$course->format); 365 } else { 366 $strdelete = get_string('deletesection'); 367 } 368 $url = new moodle_url('/course/editsection.php', array( 369 'id' => $section->id, 370 'sr' => $sectionreturn, 371 'delete' => 1, 372 'sesskey' => sesskey())); 373 $controls['delete'] = array( 374 'url' => $url, 375 'icon' => 'i/delete', 376 'name' => $strdelete, 377 'pixattr' => array('class' => ''), 378 'attr' => array('class' => 'icon editing_delete')); 379 } 380 } 381 382 return $controls; 383 } 384 385 /** 386 * Generate a summary of a section for display on the 'course index page' 387 * 388 * @param stdClass $section The course_section entry from DB 389 * @param stdClass $course The course entry from DB 390 * @param array $mods (argument not used) 391 * @return string HTML to output. 392 */ 393 protected function section_summary($section, $course, $mods) { 394 $classattr = 'section main section-summary clearfix'; 395 $linkclasses = ''; 396 397 // If section is hidden then display grey section link 398 if (!$section->visible) { 399 $classattr .= ' hidden'; 400 $linkclasses .= ' dimmed_text'; 401 } else if (course_get_format($course)->is_section_current($section)) { 402 $classattr .= ' current'; 403 } 404 405 $title = get_section_name($course, $section); 406 $o = ''; 407 $o .= html_writer::start_tag('li', [ 408 'id' => 'section-'.$section->section, 409 'class' => $classattr, 410 'role' => 'region', 411 'aria-label' => $title, 412 'data-sectionid' => $section->section 413 ]); 414 415 $o .= html_writer::tag('div', '', array('class' => 'left side')); 416 $o .= html_writer::tag('div', '', array('class' => 'right side')); 417 $o .= html_writer::start_tag('div', array('class' => 'content')); 418 419 if ($section->uservisible) { 420 $title = html_writer::tag('a', $title, 421 array('href' => course_get_url($course, $section->section), 'class' => $linkclasses)); 422 } 423 $o .= $this->output->heading($title, 3, 'section-title'); 424 425 $o .= $this->section_availability($section); 426 $o.= html_writer::start_tag('div', array('class' => 'summarytext')); 427 428 if ($section->uservisible || $section->visible) { 429 // Show summary if section is available or has availability restriction information. 430 // Do not show summary if section is hidden but we still display it because of course setting 431 // "Hidden sections are shown in collapsed form". 432 $o .= $this->format_summary_text($section); 433 } 434 $o.= html_writer::end_tag('div'); 435 $o.= $this->section_activity_summary($section, $course, null); 436 437 $o .= html_writer::end_tag('div'); 438 $o .= html_writer::end_tag('li'); 439 440 return $o; 441 } 442 443 /** 444 * Generate a summary of the activites in a section 445 * 446 * @param stdClass $section The course_section entry from DB 447 * @param stdClass $course the course record from DB 448 * @param array $mods (argument not used) 449 * @return string HTML to output. 450 */ 451 protected function section_activity_summary($section, $course, $mods) { 452 $modinfo = get_fast_modinfo($course); 453 if (empty($modinfo->sections[$section->section])) { 454 return ''; 455 } 456 457 // Generate array with count of activities in this section: 458 $sectionmods = array(); 459 $total = 0; 460 $complete = 0; 461 $cancomplete = isloggedin() && !isguestuser(); 462 $completioninfo = new completion_info($course); 463 foreach ($modinfo->sections[$section->section] as $cmid) { 464 $thismod = $modinfo->cms[$cmid]; 465 466 if ($thismod->uservisible) { 467 if (isset($sectionmods[$thismod->modname])) { 468 $sectionmods[$thismod->modname]['name'] = $thismod->modplural; 469 $sectionmods[$thismod->modname]['count']++; 470 } else { 471 $sectionmods[$thismod->modname]['name'] = $thismod->modfullname; 472 $sectionmods[$thismod->modname]['count'] = 1; 473 } 474 if ($cancomplete && $completioninfo->is_enabled($thismod) != COMPLETION_TRACKING_NONE) { 475 $total++; 476 $completiondata = $completioninfo->get_data($thismod, true); 477 if ($completiondata->completionstate == COMPLETION_COMPLETE || 478 $completiondata->completionstate == COMPLETION_COMPLETE_PASS) { 479 $complete++; 480 } 481 } 482 } 483 } 484 485 if (empty($sectionmods)) { 486 // No sections 487 return ''; 488 } 489 490 // Output section activities summary: 491 $o = ''; 492 $o.= html_writer::start_tag('div', array('class' => 'section-summary-activities pr-2 mdl-right')); 493 foreach ($sectionmods as $mod) { 494 $o.= html_writer::start_tag('span', array('class' => 'activity-count')); 495 $o.= $mod['name'].': '.$mod['count']; 496 $o.= html_writer::end_tag('span'); 497 } 498 $o.= html_writer::end_tag('div'); 499 500 // Output section completion data 501 if ($total > 0) { 502 $a = new stdClass; 503 $a->complete = $complete; 504 $a->total = $total; 505 506 $o.= html_writer::start_tag('div', array('class' => 'section-summary-activities pr-2 mdl-right')); 507 $o.= html_writer::tag('span', get_string('progresstotal', 'completion', $a), array('class' => 'activity-count')); 508 $o.= html_writer::end_tag('div'); 509 } 510 511 return $o; 512 } 513 514 /** 515 * If section is not visible, display the message about that ('Not available 516 * until...', that sort of thing). Otherwise, returns blank. 517 * 518 * For users with the ability to view hidden sections, it shows the 519 * information even though you can view the section and also may include 520 * slightly fuller information (so that teachers can tell when sections 521 * are going to be unavailable etc). This logic is the same as for 522 * activities. 523 * 524 * @param section_info $section The course_section entry from DB 525 * @param bool $canviewhidden True if user can view hidden sections 526 * @return string HTML to output 527 */ 528 protected function section_availability_message($section, $canviewhidden) { 529 global $CFG; 530 $o = ''; 531 if (!$section->visible) { 532 if ($canviewhidden) { 533 $o .= $this->courserenderer->availability_info(get_string('hiddenfromstudents'), 'ishidden'); 534 } else { 535 // We are here because of the setting "Hidden sections are shown in collapsed form". 536 // Student can not see the section contents but can see its name. 537 $o .= $this->courserenderer->availability_info(get_string('notavailable'), 'ishidden'); 538 } 539 } else if (!$section->uservisible) { 540 if ($section->availableinfo) { 541 // Note: We only get to this function if availableinfo is non-empty, 542 // so there is definitely something to print. 543 $formattedinfo = \core_availability\info::format_info( 544 $section->availableinfo, $section->course); 545 $o .= $this->courserenderer->availability_info($formattedinfo, 'isrestricted'); 546 } 547 } else if ($canviewhidden && !empty($CFG->enableavailability)) { 548 // Check if there is an availability restriction. 549 $ci = new \core_availability\info_section($section); 550 $fullinfo = $ci->get_full_information(); 551 if ($fullinfo) { 552 $formattedinfo = \core_availability\info::format_info( 553 $fullinfo, $section->course); 554 $o .= $this->courserenderer->availability_info($formattedinfo, 'isrestricted isfullinfo'); 555 } 556 } 557 return $o; 558 } 559 560 /** 561 * Displays availability information for the section (hidden, not available unles, etc.) 562 * 563 * @param section_info $section 564 * @return string 565 */ 566 public function section_availability($section) { 567 $context = context_course::instance($section->course); 568 $canviewhidden = has_capability('moodle/course:viewhiddensections', $context); 569 return html_writer::div($this->section_availability_message($section, $canviewhidden), 'section_availability'); 570 } 571 572 /** 573 * Show if something is on on the course clipboard (moving around) 574 * 575 * @param stdClass $course The course entry from DB 576 * @param int $sectionno The section number in the course which is being displayed 577 * @return string HTML to output. 578 */ 579 protected function course_activity_clipboard($course, $sectionno = null) { 580 global $USER; 581 582 $o = ''; 583 // If currently moving a file then show the current clipboard. 584 if (ismoving($course->id)) { 585 $url = new moodle_url('/course/mod.php', 586 array('sesskey' => sesskey(), 587 'cancelcopy' => true, 588 'sr' => $sectionno, 589 ) 590 ); 591 592 $o.= html_writer::start_tag('div', array('class' => 'clipboard')); 593 $o.= strip_tags(get_string('activityclipboard', '', $USER->activitycopyname)); 594 $o.= ' ('.html_writer::link($url, get_string('cancel')).')'; 595 $o.= html_writer::end_tag('div'); 596 } 597 598 return $o; 599 } 600 601 /** 602 * Generate next/previous section links for naviation 603 * 604 * @param stdClass $course The course entry from DB 605 * @param array $sections The course_sections entries from the DB 606 * @param int $sectionno The section number in the course which is being displayed 607 * @return array associative array with previous and next section link 608 */ 609 protected function get_nav_links($course, $sections, $sectionno) { 610 // FIXME: This is really evil and should by using the navigation API. 611 $course = course_get_format($course)->get_course(); 612 $canviewhidden = has_capability('moodle/course:viewhiddensections', context_course::instance($course->id)) 613 or !$course->hiddensections; 614 615 $links = array('previous' => '', 'next' => ''); 616 $back = $sectionno - 1; 617 while ($back > 0 and empty($links['previous'])) { 618 if ($canviewhidden || $sections[$back]->uservisible) { 619 $params = array(); 620 if (!$sections[$back]->visible) { 621 $params = array('class' => 'dimmed_text'); 622 } 623 $previouslink = html_writer::tag('span', $this->output->larrow(), array('class' => 'larrow')); 624 $previouslink .= get_section_name($course, $sections[$back]); 625 $links['previous'] = html_writer::link(course_get_url($course, $back), $previouslink, $params); 626 } 627 $back--; 628 } 629 630 $forward = $sectionno + 1; 631 $numsections = course_get_format($course)->get_last_section_number(); 632 while ($forward <= $numsections and empty($links['next'])) { 633 if ($canviewhidden || $sections[$forward]->uservisible) { 634 $params = array(); 635 if (!$sections[$forward]->visible) { 636 $params = array('class' => 'dimmed_text'); 637 } 638 $nextlink = get_section_name($course, $sections[$forward]); 639 $nextlink .= html_writer::tag('span', $this->output->rarrow(), array('class' => 'rarrow')); 640 $links['next'] = html_writer::link(course_get_url($course, $forward), $nextlink, $params); 641 } 642 $forward++; 643 } 644 645 return $links; 646 } 647 648 /** 649 * Generate the header html of a stealth section 650 * 651 * @param int $sectionno The section number in the course which is being displayed 652 * @return string HTML to output. 653 */ 654 protected function stealth_section_header($sectionno) { 655 $o = ''; 656 $o .= html_writer::start_tag('li', [ 657 'id' => 'section-'.$sectionno, 658 'class' => 'section main clearfix orphaned hidden', 659 'data-sectionid' => $sectionno 660 ]); 661 $o .= html_writer::tag('div', '', array('class' => 'left side')); 662 $course = course_get_format($this->page->course)->get_course(); 663 $section = course_get_format($this->page->course)->get_section($sectionno); 664 $rightcontent = $this->section_right_content($section, $course, false); 665 $o .= html_writer::tag('div', $rightcontent, array('class' => 'right side')); 666 $o .= html_writer::start_tag('div', array('class' => 'content')); 667 $o .= $this->output->heading( 668 get_string('orphanedactivitiesinsectionno', '', $sectionno), 669 3, 670 'sectionname' 671 ); 672 return $o; 673 } 674 675 /** 676 * Generate footer html of a stealth section 677 * 678 * @return string HTML to output. 679 */ 680 protected function stealth_section_footer() { 681 $o = html_writer::end_tag('div'); 682 $o.= html_writer::end_tag('li'); 683 return $o; 684 } 685 686 /** 687 * Generate the html for a hidden section 688 * 689 * @param int $sectionno The section number in the course which is being displayed 690 * @param int|stdClass $courseorid The course to get the section name for (object or just course id) 691 * @return string HTML to output. 692 */ 693 protected function section_hidden($sectionno, $courseorid = null) { 694 if ($courseorid) { 695 $sectionname = get_section_name($courseorid, $sectionno); 696 $strnotavailable = get_string('notavailablecourse', '', $sectionname); 697 } else { 698 $strnotavailable = get_string('notavailable'); 699 } 700 701 $o = ''; 702 $o .= html_writer::start_tag('li', [ 703 'id' => 'section-'.$sectionno, 704 'class' => 'section main clearfix hidden', 705 'data-sectionid' => $sectionno 706 ]); 707 $o.= html_writer::tag('div', '', array('class' => 'left side')); 708 $o.= html_writer::tag('div', '', array('class' => 'right side')); 709 $o.= html_writer::start_tag('div', array('class' => 'content')); 710 $o.= html_writer::tag('div', $strnotavailable); 711 $o.= html_writer::end_tag('div'); 712 $o.= html_writer::end_tag('li'); 713 return $o; 714 } 715 716 /** 717 * Generate the html for the 'Jump to' menu on a single section page. 718 * 719 * @param stdClass $course The course entry from DB 720 * @param array $sections The course_sections entries from the DB 721 * @param $displaysection the current displayed section number. 722 * 723 * @return string HTML to output. 724 */ 725 protected function section_nav_selection($course, $sections, $displaysection) { 726 global $CFG; 727 $o = ''; 728 $sectionmenu = array(); 729 $sectionmenu[course_get_url($course)->out(false)] = get_string('maincoursepage'); 730 $modinfo = get_fast_modinfo($course); 731 $section = 1; 732 $numsections = course_get_format($course)->get_last_section_number(); 733 while ($section <= $numsections) { 734 $thissection = $modinfo->get_section_info($section); 735 $showsection = $thissection->uservisible or !$course->hiddensections; 736 if (($showsection) && ($section != $displaysection) && ($url = course_get_url($course, $section))) { 737 $sectionmenu[$url->out(false)] = get_section_name($course, $section); 738 } 739 $section++; 740 } 741 742 $select = new url_select($sectionmenu, '', array('' => get_string('jumpto'))); 743 $select->class = 'jumpmenu'; 744 $select->formid = 'sectionmenu'; 745 $o .= $this->output->render($select); 746 747 return $o; 748 } 749 750 /** 751 * Output the html for a single section page . 752 * 753 * @param stdClass $course The course entry from DB 754 * @param array $sections (argument not used) 755 * @param array $mods (argument not used) 756 * @param array $modnames (argument not used) 757 * @param array $modnamesused (argument not used) 758 * @param int $displaysection The section number in the course which is being displayed 759 */ 760 public function print_single_section_page($course, $sections, $mods, $modnames, $modnamesused, $displaysection) { 761 $modinfo = get_fast_modinfo($course); 762 $course = course_get_format($course)->get_course(); 763 764 // Can we view the section in question? 765 if (!($sectioninfo = $modinfo->get_section_info($displaysection)) || !$sectioninfo->uservisible) { 766 // This section doesn't exist or is not available for the user. 767 // We actually already check this in course/view.php but just in case exit from this function as well. 768 print_error('unknowncoursesection', 'error', course_get_url($course), 769 format_string($course->fullname)); 770 } 771 772 // Copy activity clipboard.. 773 echo $this->course_activity_clipboard($course, $displaysection); 774 $thissection = $modinfo->get_section_info(0); 775 if ($thissection->summary or !empty($modinfo->sections[0]) or $this->page->user_is_editing()) { 776 echo $this->start_section_list(); 777 echo $this->section_header($thissection, $course, true, $displaysection); 778 echo $this->courserenderer->course_section_cm_list($course, $thissection, $displaysection); 779 echo $this->courserenderer->course_section_add_cm_control($course, 0, $displaysection); 780 echo $this->section_footer(); 781 echo $this->end_section_list(); 782 } 783 784 // Start single-section div 785 echo html_writer::start_tag('div', array('class' => 'single-section')); 786 787 // The requested section page. 788 $thissection = $modinfo->get_section_info($displaysection); 789 790 // Title with section navigation links. 791 $sectionnavlinks = $this->get_nav_links($course, $modinfo->get_section_info_all(), $displaysection); 792 $sectiontitle = ''; 793 $sectiontitle .= html_writer::start_tag('div', array('class' => 'section-navigation navigationtitle')); 794 $sectiontitle .= html_writer::tag('span', $sectionnavlinks['previous'], array('class' => 'mdl-left')); 795 $sectiontitle .= html_writer::tag('span', $sectionnavlinks['next'], array('class' => 'mdl-right')); 796 // Title attributes 797 $classes = 'sectionname'; 798 if (!$thissection->visible) { 799 $classes .= ' dimmed_text'; 800 } 801 $sectionname = html_writer::tag('span', $this->section_title_without_link($thissection, $course)); 802 $sectiontitle .= $this->output->heading($sectionname, 3, $classes); 803 804 $sectiontitle .= html_writer::end_tag('div'); 805 echo $sectiontitle; 806 807 // Now the list of sections.. 808 echo $this->start_section_list(); 809 810 echo $this->section_header($thissection, $course, true, $displaysection); 811 812 echo $this->courserenderer->course_section_cm_list($course, $thissection, $displaysection); 813 echo $this->courserenderer->course_section_add_cm_control($course, $displaysection, $displaysection); 814 echo $this->section_footer(); 815 echo $this->end_section_list(); 816 817 // Display section bottom navigation. 818 $sectionbottomnav = ''; 819 $sectionbottomnav .= html_writer::start_tag('div', array('class' => 'section-navigation mdl-bottom')); 820 $sectionbottomnav .= html_writer::tag('span', $sectionnavlinks['previous'], array('class' => 'mdl-left')); 821 $sectionbottomnav .= html_writer::tag('span', $sectionnavlinks['next'], array('class' => 'mdl-right')); 822 $sectionbottomnav .= html_writer::tag('div', $this->section_nav_selection($course, $sections, $displaysection), 823 array('class' => 'mdl-align')); 824 $sectionbottomnav .= html_writer::end_tag('div'); 825 echo $sectionbottomnav; 826 827 // Close single-section div. 828 echo html_writer::end_tag('div'); 829 } 830 831 /** 832 * Output the html for a multiple section page 833 * 834 * @param stdClass $course The course entry from DB 835 * @param array $sections (argument not used) 836 * @param array $mods (argument not used) 837 * @param array $modnames (argument not used) 838 * @param array $modnamesused (argument not used) 839 */ 840 public function print_multiple_section_page($course, $sections, $mods, $modnames, $modnamesused) { 841 $modinfo = get_fast_modinfo($course); 842 $course = course_get_format($course)->get_course(); 843 844 $context = context_course::instance($course->id); 845 echo $this->output->heading($this->page_title(), 2, 'accesshide'); 846 847 // Copy activity clipboard.. 848 echo $this->course_activity_clipboard($course, 0); 849 850 // Now the list of sections.. 851 echo $this->start_section_list(); 852 $numsections = course_get_format($course)->get_last_section_number(); 853 854 foreach ($modinfo->get_section_info_all() as $section => $thissection) { 855 if ($section == 0) { 856 // 0-section is displayed a little different then the others 857 if ($thissection->summary or !empty($modinfo->sections[0]) or $this->page->user_is_editing()) { 858 echo $this->section_header($thissection, $course, false, 0); 859 echo $this->courserenderer->course_section_cm_list($course, $thissection, 0); 860 echo $this->courserenderer->course_section_add_cm_control($course, 0, 0); 861 echo $this->section_footer(); 862 } 863 continue; 864 } 865 if ($section > $numsections) { 866 // activities inside this section are 'orphaned', this section will be printed as 'stealth' below 867 continue; 868 } 869 // Show the section if the user is permitted to access it, OR if it's not available 870 // but there is some available info text which explains the reason & should display, 871 // OR it is hidden but the course has a setting to display hidden sections as unavilable. 872 $showsection = $thissection->uservisible || 873 ($thissection->visible && !$thissection->available && !empty($thissection->availableinfo)) || 874 (!$thissection->visible && !$course->hiddensections); 875 if (!$showsection) { 876 continue; 877 } 878 879 if (!$this->page->user_is_editing() && $course->coursedisplay == COURSE_DISPLAY_MULTIPAGE) { 880 // Display section summary only. 881 echo $this->section_summary($thissection, $course, null); 882 } else { 883 echo $this->section_header($thissection, $course, false, 0); 884 if ($thissection->uservisible) { 885 echo $this->courserenderer->course_section_cm_list($course, $thissection, 0); 886 echo $this->courserenderer->course_section_add_cm_control($course, $section, 0); 887 } 888 echo $this->section_footer(); 889 } 890 } 891 892 if ($this->page->user_is_editing() and has_capability('moodle/course:update', $context)) { 893 // Print stealth sections if present. 894 foreach ($modinfo->get_section_info_all() as $section => $thissection) { 895 if ($section <= $numsections or empty($modinfo->sections[$section])) { 896 // this is not stealth section or it is empty 897 continue; 898 } 899 echo $this->stealth_section_header($section); 900 echo $this->courserenderer->course_section_cm_list($course, $thissection, 0); 901 echo $this->stealth_section_footer(); 902 } 903 904 echo $this->end_section_list(); 905 906 echo $this->change_number_sections($course, 0); 907 } else { 908 echo $this->end_section_list(); 909 } 910 911 } 912 913 /** 914 * Returns controls in the bottom of the page to increase/decrease number of sections 915 * 916 * @param stdClass $course 917 * @param int|null $sectionreturn 918 * @return string 919 */ 920 protected function change_number_sections($course, $sectionreturn = null) { 921 $coursecontext = context_course::instance($course->id); 922 if (!has_capability('moodle/course:update', $coursecontext)) { 923 return ''; 924 } 925 926 $format = course_get_format($course); 927 $options = $format->get_format_options(); 928 $maxsections = $format->get_max_sections(); 929 $lastsection = $format->get_last_section_number(); 930 $supportsnumsections = array_key_exists('numsections', $options); 931 932 if ($supportsnumsections) { 933 // Current course format has 'numsections' option, which is very confusing and we suggest course format 934 // developers to get rid of it (see MDL-57769 on how to do it). 935 // Display "Increase section" / "Decrease section" links. 936 937 echo html_writer::start_tag('div', array('id' => 'changenumsections', 'class' => 'mdl-right')); 938 939 // Increase number of sections. 940 if ($lastsection < $maxsections) { 941 $straddsection = get_string('increasesections', 'moodle'); 942 $url = new moodle_url('/course/changenumsections.php', 943 array('courseid' => $course->id, 944 'increase' => true, 945 'sesskey' => sesskey())); 946 $icon = $this->output->pix_icon('t/switch_plus', $straddsection); 947 echo html_writer::link($url, $icon.get_accesshide($straddsection), array('class' => 'increase-sections')); 948 } 949 950 if ($course->numsections > 0) { 951 // Reduce number of sections sections. 952 $strremovesection = get_string('reducesections', 'moodle'); 953 $url = new moodle_url('/course/changenumsections.php', 954 array('courseid' => $course->id, 955 'increase' => false, 956 'sesskey' => sesskey())); 957 $icon = $this->output->pix_icon('t/switch_minus', $strremovesection); 958 echo html_writer::link($url, $icon.get_accesshide($strremovesection), array('class' => 'reduce-sections')); 959 } 960 961 echo html_writer::end_tag('div'); 962 963 } else if (course_get_format($course)->uses_sections()) { 964 if ($lastsection >= $maxsections) { 965 // Don't allow more sections if we already hit the limit. 966 return; 967 } 968 // Current course format does not have 'numsections' option but it has multiple sections suppport. 969 // Display the "Add section" link that will insert a section in the end. 970 // Note to course format developers: inserting sections in the other positions should check both 971 // capabilities 'moodle/course:update' and 'moodle/course:movesections'. 972 echo html_writer::start_tag('div', array('id' => 'changenumsections', 'class' => 'mdl-right')); 973 if (get_string_manager()->string_exists('addsections', 'format_'.$course->format)) { 974 $straddsections = get_string('addsections', 'format_'.$course->format); 975 } else { 976 $straddsections = get_string('addsections'); 977 } 978 $url = new moodle_url('/course/changenumsections.php', 979 ['courseid' => $course->id, 'insertsection' => 0, 'sesskey' => sesskey()]); 980 if ($sectionreturn !== null) { 981 $url->param('sectionreturn', $sectionreturn); 982 } 983 $icon = $this->output->pix_icon('t/add', ''); 984 $newsections = $maxsections - $lastsection; 985 echo html_writer::link($url, $icon . $straddsections, 986 array('class' => 'add-sections', 'data-add-sections' => $straddsections, 'data-new-sections' => $newsections)); 987 echo html_writer::end_tag('div'); 988 } 989 } 990 991 /** 992 * Generate html for a section summary text 993 * 994 * @param stdClass $section The course_section entry from DB 995 * @return string HTML to output. 996 */ 997 protected function format_summary_text($section) { 998 $context = context_course::instance($section->course); 999 $summarytext = file_rewrite_pluginfile_urls($section->summary, 'pluginfile.php', 1000 $context->id, 'course', 'section', $section->id); 1001 1002 $options = new stdClass(); 1003 $options->noclean = true; 1004 $options->overflowdiv = true; 1005 return format_text($summarytext, $section->summaryformat, $options); 1006 } 1007 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body