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 // Section next/previous links.
417 $sectionnavlinks = $this->get_nav_links($course, $sections, $displaysection);
418 echo $sectionnavlinks;
420 // Can we view the section in question?
421 $context = context_course::instance($course->id);
422 $canviewhidden = has_capability('moodle/course:viewhiddensections', $context);
424 if (!$sections[$displaysection]->visible && !$canviewhidden) {
425 if (!$course->hiddensections) {
426 echo $this->start_section_list();
427 echo $this->section_hidden($displaysection);
428 echo $this->end_section_list();
429 echo $sectionnavlinks;
431 // Can't view this section.
435 // Title with completion help icon.
436 $completioninfo = new completion_info($course);
437 echo $completioninfo->display_help_icon();
438 $title = get_section_name($course, $sections[$displaysection]);
439 echo $this->output->heading($title, 2, 'headingblock header outline');
441 // Copy activity clipboard..
442 echo $this->course_activity_clipboard($course, $displaysection);
444 // Now the list of sections..
445 echo $this->start_section_list();
447 // General section if non-empty.
448 $thissection = $sections[0];
449 if ($thissection->summary or $thissection->sequence or $PAGE->user_is_editing()) {
450 echo $this->section_header($thissection, $course, true);
451 print_section($course, $thissection, $mods, $modnamesused, true);
452 if ($PAGE->user_is_editing()) {
453 print_section_add_menus($course, 0, $modnames);
455 echo $this->section_footer();
458 // The requested section page.
459 $thissection = $sections[$displaysection];
460 echo $this->section_header($thissection, $course, true);
461 print_section($course, $thissection, $mods, $modnamesused, true);
462 if ($PAGE->user_is_editing()) {
463 print_section_add_menus($course, $displaysection, $modnames);
465 echo $this->section_footer();
466 echo $sectionnavlinks;
467 echo $this->end_section_list();
471 * Output the html for a multiple section page
473 * @param stdClass $course The course entry from DB
474 * @param array $sections The course_sections entries from the DB
475 * @param array $mods used for print_section()
476 * @param array $modnames used for print_section()
477 * @param array $modnamesused used for print_section()
479 public function print_multiple_section_page($course, $sections, $mods, $modnames, $modnamesused) {
482 $context = context_course::instance($course->id);
483 // Title with completion help icon.
484 $completioninfo = new completion_info($course);
485 echo $completioninfo->display_help_icon();
486 echo $this->output->heading($this->page_title(), 2, 'accesshide');
488 // Copy activity clipboard..
489 echo $this->course_activity_clipboard($course);
491 // Now the list of sections..
492 echo $this->start_section_list();
494 // General section if non-empty.
495 $thissection = $sections[0];
497 if ($thissection->summary or $thissection->sequence or $PAGE->user_is_editing()) {
498 echo $this->section_header($thissection, $course, true);
499 print_section($course, $thissection, $mods, $modnamesused, true);
500 if ($PAGE->user_is_editing()) {
501 print_section_add_menus($course, 0, $modnames);
503 echo $this->section_footer();
506 $canviewhidden = has_capability('moodle/course:viewhiddensections', $context);
507 for ($section = 1; $section <= $course->numsections; $section++) {
508 if (!empty($sections[$section])) {
509 $thissection = $sections[$section];
511 // This will create a course section if it doesn't exist..
512 $thissection = get_course_section($section, $course->id);
514 $showsection = ($canviewhidden or $thissection->visible or !$course->hiddensections);
515 if (!$thissection->visible && !$canviewhidden) {
516 if (!$course->hiddensections) {
517 echo $this->section_hidden($section);
520 unset($sections[$section]);
524 if (!$PAGE->user_is_editing() && $course->coursedisplay == COURSE_DISPLAY_MULTIPAGE) {
525 // Display section summary only.
526 echo $this->section_summary($thissection, $course);
528 echo $this->section_header($thissection, $course, false);
529 print_section($course, $thissection, $mods, $modnamesused);
530 if ($PAGE->user_is_editing()) {
531 print_section_add_menus($course, $section, $modnames);
533 echo $this->section_footer();
536 unset($sections[$section]);
539 if ($PAGE->user_is_editing() and has_capability('moodle/course:update', $context)) {
540 // Print stealth sections if present.
541 $modinfo = get_fast_modinfo($course);
542 foreach ($sections as $section => $thissection) {
543 if (empty($modinfo->sections[$section])) {
546 echo $this->stealth_section_header($section);
547 print_section($course, $thissection, $mods, $modnamesused);
548 echo $this->stealth_section_footer();
551 $straddsection = get_string('addanadditionalsection', 'moodle');
552 echo html_writer::start_tag('div', array('class' => 'mdl-align'));
553 echo $this->output->action_link(
554 new moodle_url('/course/addsection.php',
555 array('courseid' => $course->id, 'sesskey' => sesskey())
556 ), $this->output->pix_icon('t/add', $straddsection).$straddsection, null,
557 array('class' => 'addsectionlink')
559 echo html_writer::end_tag('div');
562 echo $this->end_section_list();