2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * Base renderer for outputting course formats.
21 * @copyright 2012 Dan Poltawski
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') || die();
30 * This renderer is used by section based formats
33 * @copyright 2012 Dan Poltawski
34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37 abstract class format_renderer_base extends plugin_renderer_base {
40 * Generate the starting container html for a list of sections
41 * @return string HTML to output.
43 abstract public function start_section_list();
46 * Generate the closing container html for a list of sections
47 * @return string HTML to output.
49 abstract public function end_section_list();
52 * Generate the title for this section page
53 * @return string the page title
55 abstract public function page_title();
58 * Generate the content to displayed on the right part of a section
60 * before course modules are included
61 * @param stdClass $section The course_section entry from DB
62 * @param stdClass $course The course entry from DB
63 * @param bool $onsectionpage true if being printed on a section page
64 * @return string HTML to output.
66 public function section_right_content($section, $course, $onsectionpage) {
67 $o = $this->output->spacer();
69 if ($section->section != 0) {
70 $controls = $this->section_edit_controls($course, $section, $onsectionpage);
71 if (!empty($controls)) {
72 $o = implode('<br />', $controls);
80 * Generate the content to displayed on the left part of a section
82 * before course modules are included
83 * @param stdClass $section The course_section entry from DB
84 * @param stdClass $course The course entry from DB
85 * @param bool $onsectionpage true if being printed on a section page
86 * @return string HTML to output.
88 public function section_left_content($section, $course, $onsectionpage) {
89 $o = $this->output->spacer();
91 if ($section->section != 0) {
92 // Only in the non-general sections.
93 if ($course->marker == $section->section) {
94 $o = get_accesshide(get_string('currentsection', 'format_'.$course->format));
102 * Generate the display of the header part of a section before
103 * course modules are included
105 * @param stdClass $section The course_section entry from DB
106 * @param stdClass $course The course entry from DB
107 * @param bool $onsectionpage true if being printed on a section page
108 * @return string HTML to output.
110 public function section_header($section, $course, $onsectionpage) {
118 if ($section->section != 0 ) {
119 // Only in the non-general sections.
120 if (!$section->visible) {
121 $sectionstyle = ' hidden';
122 } else if ($course->marker == $section->section) {
123 $sectionstyle = ' current';
125 $linktitle = ($course->coursedisplay == COURSE_DISPLAY_MULTIPAGE);
128 $o.= html_writer::start_tag('li', array('id' => 'section-'.$section->section,
129 'class' => 'section main clearfix'.$sectionstyle));
131 $leftcontent = $this->section_left_content($section, $course, $onsectionpage);
132 $o.= html_writer::tag('div', $leftcontent, array('class' => 'left side'));
134 $rightcontent = $this->section_right_content($section, $course, $onsectionpage);
135 $o.= html_writer::tag('div', $rightcontent, array('class' => 'right side'));
136 $o.= html_writer::start_tag('div', array('class' => 'content'));
138 if (!$onsectionpage) {
139 $title = get_section_name($course, $section);
141 $title = html_writer::link(course_get_url($course, $section->section), $title);
143 $o.= $this->output->heading($title, 3, 'sectionname');
146 $o.= html_writer::start_tag('div', array('class' => 'summary'));
148 $context = context_course::instance($section->course);
149 $summarytext = file_rewrite_pluginfile_urls($section->summary, 'pluginfile.php',
150 $context->id, 'course', 'section', $section->id);
151 $summaryformatoptions = new stdClass();
152 $summaryformatoptions->noclean = true;
153 $summaryformatoptions->overflowdiv = true;
155 $o.= format_text($summarytext, $section->summaryformat, $summaryformatoptions);
157 if ($PAGE->user_is_editing() && has_capability('moodle/course:update', $context)) {
158 $url = new moodle_url('/course/editsection.php', array('id'=>$section->id));
160 if ($onsectionpage) {
161 $url->param('sectionreturn', 1);
164 $o.= html_writer::link($url,
165 html_writer::empty_tag('img', array('src' => $this->output->pix_url('t/edit'), 'class' => 'iconsmall edit')),
166 array('title' => get_string('editsummary')));
168 $o.= html_writer::end_tag('div');
174 * Generate the display of the footer part of a section
176 * @return string HTML to output.
178 public function section_footer() {
179 $o = html_writer::end_tag('div');
180 $o.= html_writer::end_tag('li');
186 * Generate the edit controls of a section
188 * @param stdClass $course The course entry from DB
189 * @param stdClass $section The course_section entry from DB
190 * @param bool $onsectionpage true if being printed on a section page
191 * @return array of links with edit controls
193 public function section_edit_controls($course, $section, $onsectionpage = false) {
196 if (!$PAGE->user_is_editing()) {
200 if (!has_capability('moodle/course:update', context_course::instance($course->id))) {
204 if ($onsectionpage) {
205 $baseurl = course_get_url($course, $section->section);
207 $baseurl = course_get_url($course);
209 $baseurl->param('sesskey', sesskey());
213 $url = clone($baseurl);
214 if ($section->visible) { // Show the hide/show eye.
215 $strhidefromothers = get_string('hidefromothers', 'format_'.$course->format);
216 $url->param('hide', $section->section);
217 $controls[] = html_writer::link($url,
218 html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/hide'),
219 'class' => 'icon hide', 'alt' => $strhidefromothers)),
220 array('title' => $strhidefromothers, 'class' => 'editing_showhide'));
222 $strshowfromothers = get_string('showfromothers', 'format_'.$course->format);
223 $url->param('show', $section->section);
224 $controls[] = html_writer::link($url,
225 html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/show'),
226 'class' => 'icon hide', 'alt' => $strshowfromothers)),
227 array('title' => $strshowfromothers, 'class' => 'editing_showhide'));
230 if (!$onsectionpage) {
231 $url = clone($baseurl);
232 if ($section->section > 1) { // Add a arrow to move section up.
233 $url->param('section', $section->section);
234 $url->param('move', -1);
235 $strmoveup = get_string('moveup');
237 $controls[] = html_writer::link($url,
238 html_writer::empty_tag('img', array('src' => $this->output->pix_url('t/up'),
239 'class' => 'icon up', 'alt' => $strmoveup)),
240 array('title' => $strmoveup, 'class' => 'moveup'));
243 $url = clone($baseurl);
244 if ($section->section < $course->numsections) { // Add a arrow to move section down.
245 $url->param('section', $section->section);
246 $url->param('move', 1);
247 $strmovedown = get_string('movedown');
249 $controls[] = html_writer::link($url,
250 html_writer::empty_tag('img', array('src' => $this->output->pix_url('t/down'),
251 'class' => 'icon down', 'alt' => $strmovedown)),
252 array('title' => $strmovedown, 'class' => 'movedown'));
260 * Generate a summary of a section for display on the 'coruse index page'
262 * @param stdClass $section The course_section entry from DB
263 * @param stdClass $course The course entry from DB
264 * @return string HTML to output.
266 public function section_summary($section, $course) {
269 $o.= html_writer::start_tag('li', array('id' => 'section-'.$section->section));
271 $title = get_section_name($course, $section);
272 $o.= html_writer::start_tag('div', array('class' => 'section-summary'));
273 $o.= html_writer::start_tag('a', array('href' => course_get_url($course, $section->section)));
274 $o.= $this->output->heading($title, 3, 'header section-title');
275 $o.= html_writer::end_tag('a');
277 $o.= html_writer::start_tag('div', array('class' => 'summarytext'));
278 $o.= format_text($section->summary, $section->summaryformat);
279 $o.= html_writer::end_tag('div');
280 $o.= html_writer::end_tag('div');
281 $o.= html_writer::end_tag('li');
287 * Show if something is on on the course clipboard (moving around)
289 * @param stdClass $course The course entry from DB
290 * @param int $sectionno The section number in the coruse which is being dsiplayed
291 * @return string HTML to output.
293 public function course_activity_clipboard($course, $sectionno = 0) {
297 // If currently moving a file then show the current clipboard.
298 if (ismoving($course->id)) {
299 $url = new moodle_url('/course/mod.php',
300 array('sesskey' => sesskey(),
301 'cancelcopy' => true,
306 $strcancel= get_string('cancel');
308 $o.= html_writer::start_tag('li', array('class' => 'clipboard'));
309 $o.= strip_tags(get_string('activityclipboard', '', $USER->activitycopyname));
310 $o.= ' ('.html_writer::link($url, get_string('cancel')).')';
311 $o.= html_writer::end_tag('li');
318 * Generate next/previous section links for naviation
320 * @param stdClass $course The course entry from DB
321 * @param array $sections The course_sections entries from the DB
322 * @param int $sectionno The section number in the coruse which is being dsiplayed
323 * @return string HTML to output.
325 public function get_nav_links($course, $sections, $sectionno) {
326 // FIXME: This is really evil and should by using the navigation API.
327 $canviewhidden = has_capability('moodle/course:viewhiddensections', context_course::instance($course->id))
328 or !$course->hiddensections;
330 $links = array('previous' => '', 'next' => '');
331 $back = $sectionno - 1;
332 while ($back > 0 and empty($links['previous'])) {
333 if ($canviewhidden || $sections[$back]->visible) {
334 $links['previous'] = html_writer::link(course_get_url($course, $back),
335 $this->output->larrow().$this->output->spacer().get_section_name($course, $sections[$back]));
340 $forward = $sectionno + 1;
341 while ($forward <= $course->numsections and empty($links['next'])) {
342 if ($canviewhidden || $sections[$forward]->visible) {
343 $links['next'] = html_writer::link(course_get_url($course, $forward),
344 get_section_name($course, $sections[$forward]).$this->output->spacer().$this->output->rarrow());
350 $o.= html_writer::start_tag('div', array('class' => 'section-navigation yui3-g'));
351 $o.= html_writer::tag('div', $links['previous'], array('class' => 'yui3-u'));
352 $o.= html_writer::tag('div', $links['next'], array('class' => 'right yui3-u'));
353 $o.= html_writer::end_tag('div');
359 * Generate the header html of a stealth section
361 * @param int $sectionno The section number in the coruse which is being dsiplayed
362 * @return string HTML to output.
364 public function stealth_section_header($sectionno) {
366 $o.= html_writer::start_tag('li', array('id' => 'section-'.$sectionno, 'class' => 'section main clearfix orphaned hidden'));
367 $o.= html_writer::tag('div', '', array('class' => 'left side'));
368 $o.= html_writer::tag('div', '', array('class' => 'right side'));
369 $o.= html_writer::start_tag('div', array('class' => 'content'));
370 $o.= $this->output->heading(get_string('orphanedactivities'), 3, 'sectionname');
375 * Generate footer html of a stealth section
377 * @return string HTML to output.
379 public function stealth_section_footer() {
380 $o = html_writer::end_tag('div');
381 $o.= html_writer::end_tag('li');
386 * Generate the html for a hidden section
388 * @param int $sectionno The section number in the coruse which is being dsiplayed
389 * @return string HTML to output.
391 public function section_hidden($sectionno) {
393 $o.= html_writer::start_tag('li', array('id' => 'section-'.$sectionno, 'class' => 'section main clearfix hidden'));
394 $o.= html_writer::tag('div', '', array('class' => 'left side'));
395 $o.= html_writer::tag('div', '', array('class' => 'right side'));
396 $o.= html_writer::start_tag('div', array('class' => 'content'));
397 $o.= get_string('notavailable');
398 $o.= html_writer::end_tag('div');
399 $o.= html_writer::end_tag('li');
404 * Output the html for a single section page .
406 * @param stdClass $course The course entry from DB
407 * @param array $sections The course_sections entries from the DB
408 * @param array $mods used for print_section()
409 * @param array $modnames used for print_section()
410 * @param array $modnamesused used for print_section()
411 * @param int $displaysection The section number in the course which is being displayed
413 public function print_single_section_page($course, $sections, $mods, $modnames, $modnamesused, $displaysection) {
416 // Can we view the section in question?
417 $context = context_course::instance($course->id);
418 $canviewhidden = has_capability('moodle/course:viewhiddensections', $context);
420 if (!$sections[$displaysection]->visible && !$canviewhidden) {
421 if (!$course->hiddensections) {
422 echo $this->start_section_list();
423 echo $this->section_hidden($displaysection);
424 echo $this->end_section_list();
425 echo $sectionnavlinks;
427 // Can't view this section.
431 // General section if non-empty.
432 $thissection = $sections[0];
433 if ($thissection->summary or $thissection->sequence or $PAGE->user_is_editing()) {
434 echo $this->start_section_list();
435 echo $this->section_header($thissection, $course, true);
436 print_section($course, $thissection, $mods, $modnamesused, true);
437 if ($PAGE->user_is_editing()) {
438 print_section_add_menus($course, 0, $modnames);
440 echo $this->section_footer();
441 echo $this->end_section_list();
444 // Section next/previous links.
445 $sectionnavlinks = $this->get_nav_links($course, $sections, $displaysection);
446 echo $sectionnavlinks;
449 // Title with completion help icon.
450 $completioninfo = new completion_info($course);
451 echo $completioninfo->display_help_icon();
452 $title = get_section_name($course, $sections[$displaysection]);
453 echo $this->output->heading($title, 2, 'headingblock header outline');
455 // Copy activity clipboard..
456 echo $this->course_activity_clipboard($course, $displaysection);
458 // Now the list of sections..
459 echo $this->start_section_list();
461 // The requested section page.
462 $thissection = $sections[$displaysection];
463 echo $this->section_header($thissection, $course, true);
464 print_section($course, $thissection, $mods, $modnamesused, true);
465 if ($PAGE->user_is_editing()) {
466 print_section_add_menus($course, $displaysection, $modnames);
468 echo $this->section_footer();
469 echo $sectionnavlinks;
470 echo $this->end_section_list();
474 * Output the html for a multiple section page
476 * @param stdClass $course The course entry from DB
477 * @param array $sections The course_sections entries from the DB
478 * @param array $mods used for print_section()
479 * @param array $modnames used for print_section()
480 * @param array $modnamesused used for print_section()
482 public function print_multiple_section_page($course, $sections, $mods, $modnames, $modnamesused) {
485 $context = context_course::instance($course->id);
486 // Title with completion help icon.
487 $completioninfo = new completion_info($course);
488 echo $completioninfo->display_help_icon();
489 echo $this->output->heading($this->page_title(), 2, 'accesshide');
491 // Copy activity clipboard..
492 echo $this->course_activity_clipboard($course);
494 // Now the list of sections..
495 echo $this->start_section_list();
497 // General section if non-empty.
498 $thissection = $sections[0];
500 if ($thissection->summary or $thissection->sequence or $PAGE->user_is_editing()) {
501 echo $this->section_header($thissection, $course, true);
502 print_section($course, $thissection, $mods, $modnamesused, true);
503 if ($PAGE->user_is_editing()) {
504 print_section_add_menus($course, 0, $modnames);
506 echo $this->section_footer();
509 $canviewhidden = has_capability('moodle/course:viewhiddensections', $context);
510 for ($section = 1; $section <= $course->numsections; $section++) {
511 if (!empty($sections[$section])) {
512 $thissection = $sections[$section];
514 // This will create a course section if it doesn't exist..
515 $thissection = get_course_section($section, $course->id);
517 $showsection = ($canviewhidden or $thissection->visible or !$course->hiddensections);
518 if (!$thissection->visible && !$canviewhidden) {
519 if (!$course->hiddensections) {
520 echo $this->section_hidden($section);
523 unset($sections[$section]);
527 if (!$PAGE->user_is_editing() && $course->coursedisplay == COURSE_DISPLAY_MULTIPAGE) {
528 // Display section summary only.
529 echo $this->section_summary($thissection, $course);
531 echo $this->section_header($thissection, $course, false);
532 print_section($course, $thissection, $mods, $modnamesused);
533 if ($PAGE->user_is_editing()) {
534 print_section_add_menus($course, $section, $modnames);
536 echo $this->section_footer();
539 unset($sections[$section]);
542 if ($PAGE->user_is_editing() and has_capability('moodle/course:update', $context)) {
543 // Print stealth sections if present.
544 $modinfo = get_fast_modinfo($course);
545 foreach ($sections as $section => $thissection) {
546 if (empty($modinfo->sections[$section])) {
549 echo $this->stealth_section_header($section);
550 print_section($course, $thissection, $mods, $modnamesused);
551 echo $this->stealth_section_footer();
554 $straddsection = get_string('addanadditionalsection', 'moodle');
555 echo html_writer::start_tag('div', array('class' => 'mdl-align'));
556 echo $this->output->action_link(
557 new moodle_url('/course/addsection.php',
558 array('courseid' => $course->id, 'sesskey' => sesskey())
559 ), $this->output->pix_icon('t/add', $straddsection).$straddsection, null,
560 array('class' => 'addsectionlink')
562 echo html_writer::end_tag('div');
565 echo $this->end_section_list();