Merge branch 'MDL-40833-master' of git://github.com/phalacee/moodle
[moodle.git] / course / format / renderer.php
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/>.
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  */
26 defined('MOODLE_INTERNAL') || die();
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 {
41     /** @var contains instance of core course renderer */
42     protected $courserenderer;
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     }
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();
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();
67     /**
68      * Generate the title for this section page
69      * @return string the page title
70      */
71     abstract protected function page_title();
73     /**
74      * Generate the section title
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     }
89     /**
90      * Generate the content to displayed on the right part of a section
91      * before course modules are included
92      *
93      * @param stdClass $section The course_section entry from DB
94      * @param stdClass $course The course entry from DB
95      * @param bool $onsectionpage true if being printed on a section page
96      * @return string HTML to output.
97      */
98     protected function section_right_content($section, $course, $onsectionpage) {
99         $o = $this->output->spacer();
101         if ($section->section != 0) {
102             $controls = $this->section_edit_controls($course, $section, $onsectionpage);
103             if (!empty($controls)) {
104                 $o = implode('<br />', $controls);
105             }
106         }
108         return $o;
109     }
111     /**
112      * Generate the content to displayed on the left part of a section
113      * before course modules are included
114      *
115      * @param stdClass $section The course_section entry from DB
116      * @param stdClass $course The course entry from DB
117      * @param bool $onsectionpage true if being printed on a section page
118      * @return string HTML to output.
119      */
120     protected function section_left_content($section, $course, $onsectionpage) {
121         $o = $this->output->spacer();
123         if ($section->section != 0) {
124             // Only in the non-general sections.
125             if (course_get_format($course)->is_section_current($section)) {
126                 $o = get_accesshide(get_string('currentsection', 'format_'.$course->format));
127             }
128         }
130         return $o;
131     }
133     /**
134      * Generate the display of the header part of a section before
135      * course modules are included
136      *
137      * @param stdClass $section The course_section entry from DB
138      * @param stdClass $course The course entry from DB
139      * @param bool $onsectionpage true if being printed on a single-section page
140      * @param int $sectionreturn The section to return to after an action
141      * @return string HTML to output.
142      */
143     protected function section_header($section, $course, $onsectionpage, $sectionreturn=null) {
144         global $PAGE;
146         $o = '';
147         $currenttext = '';
148         $sectionstyle = '';
150         if ($section->section != 0) {
151             // Only in the non-general sections.
152             if (!$section->visible) {
153                 $sectionstyle = ' hidden';
154             } else if (course_get_format($course)->is_section_current($section)) {
155                 $sectionstyle = ' current';
156             }
157         }
159         $o.= html_writer::start_tag('li', array('id' => 'section-'.$section->section,
160             'class' => 'section main clearfix'.$sectionstyle));
162         $leftcontent = $this->section_left_content($section, $course, $onsectionpage);
163         $o.= html_writer::tag('div', $leftcontent, array('class' => 'left side'));
165         $rightcontent = $this->section_right_content($section, $course, $onsectionpage);
166         $o.= html_writer::tag('div', $rightcontent, array('class' => 'right side'));
167         $o.= html_writer::start_tag('div', array('class' => 'content'));
169         // When not on a section page, we display the section titles except the general section if null
170         $hasnamenotsecpg = (!$onsectionpage && ($section->section != 0 || !is_null($section->name)));
172         // When on a section page, we only display the general section title, if title is not the default one
173         $hasnamesecpg = ($onsectionpage && ($section->section == 0 && !is_null($section->name)));
175         $classes = ' accesshide';
176         if ($hasnamenotsecpg || $hasnamesecpg) {
177             $classes = '';
178         }
179         $o.= $this->output->heading($this->section_title($section, $course), 3, 'sectionname' . $classes);
181         $o.= html_writer::start_tag('div', array('class' => 'summary'));
182         $o.= $this->format_summary_text($section);
184         $context = context_course::instance($course->id);
185         if ($PAGE->user_is_editing() && has_capability('moodle/course:update', $context)) {
186             $url = new moodle_url('/course/editsection.php', array('id'=>$section->id, 'sr'=>$sectionreturn));
187             $o.= html_writer::link($url,
188                 html_writer::empty_tag('img', array('src' => $this->output->pix_url('t/edit'),
189                     'class' => 'iconsmall edit', 'alt' => get_string('edit'))),
190                 array('title' => get_string('editsummary')));
191         }
192         $o.= html_writer::end_tag('div');
194         $o .= $this->section_availability_message($section,
195                 has_capability('moodle/course:viewhiddensections', $context));
197         return $o;
198     }
200     /**
201      * Generate the display of the footer part of a section
202      *
203      * @return string HTML to output.
204      */
205     protected function section_footer() {
206         $o = html_writer::end_tag('div');
207         $o.= html_writer::end_tag('li');
209         return $o;
210     }
212     /**
213      * Generate the edit controls of a section
214      *
215      * @param stdClass $course The course entry from DB
216      * @param stdClass $section The course_section entry from DB
217      * @param bool $onsectionpage true if being printed on a section page
218      * @return array of links with edit controls
219      */
220     protected function section_edit_controls($course, $section, $onsectionpage = false) {
221         global $PAGE;
223         if (!$PAGE->user_is_editing()) {
224             return array();
225         }
227         $coursecontext = context_course::instance($course->id);
229         if ($onsectionpage) {
230             $baseurl = course_get_url($course, $section->section);
231         } else {
232             $baseurl = course_get_url($course);
233         }
234         $baseurl->param('sesskey', sesskey());
236         $controls = array();
238         $url = clone($baseurl);
239         if (has_capability('moodle/course:sectionvisibility', $coursecontext)) {
240             if ($section->visible) { // Show the hide/show eye.
241                 $strhidefromothers = get_string('hidefromothers', 'format_'.$course->format);
242                 $url->param('hide', $section->section);
243                 $controls[] = html_writer::link($url,
244                     html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/hide'),
245                     'class' => 'icon hide', 'alt' => $strhidefromothers)),
246                     array('title' => $strhidefromothers, 'class' => 'editing_showhide'));
247             } else {
248                 $strshowfromothers = get_string('showfromothers', 'format_'.$course->format);
249                 $url->param('show',  $section->section);
250                 $controls[] = html_writer::link($url,
251                     html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/show'),
252                     'class' => 'icon hide', 'alt' => $strshowfromothers)),
253                     array('title' => $strshowfromothers, 'class' => 'editing_showhide'));
254             }
255         }
257         if (!$onsectionpage && has_capability('moodle/course:movesections', $coursecontext)) {
258             $url = clone($baseurl);
259             if ($section->section > 1) { // Add a arrow to move section up.
260                 $url->param('section', $section->section);
261                 $url->param('move', -1);
262                 $strmoveup = get_string('moveup');
264                 $controls[] = html_writer::link($url,
265                     html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/up'),
266                     'class' => 'icon up', 'alt' => $strmoveup)),
267                     array('title' => $strmoveup, 'class' => 'moveup'));
268             }
270             $url = clone($baseurl);
271             if ($section->section < $course->numsections) { // Add a arrow to move section down.
272                 $url->param('section', $section->section);
273                 $url->param('move', 1);
274                 $strmovedown =  get_string('movedown');
276                 $controls[] = html_writer::link($url,
277                     html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/down'),
278                     'class' => 'icon down', 'alt' => $strmovedown)),
279                     array('title' => $strmovedown, 'class' => 'movedown'));
280             }
281         }
283         return $controls;
284     }
286     /**
287      * Generate a summary of a section for display on the 'coruse index page'
288      *
289      * @param stdClass $section The course_section entry from DB
290      * @param stdClass $course The course entry from DB
291      * @param array    $mods (argument not used)
292      * @return string HTML to output.
293      */
294     protected function section_summary($section, $course, $mods) {
295         $classattr = 'section main section-summary clearfix';
296         $linkclasses = '';
298         // If section is hidden then display grey section link
299         if (!$section->visible) {
300             $classattr .= ' hidden';
301             $linkclasses .= ' dimmed_text';
302         } else if (course_get_format($course)->is_section_current($section)) {
303             $classattr .= ' current';
304         }
306         $o = '';
307         $o .= html_writer::start_tag('li', array('id' => 'section-'.$section->section, 'class' => $classattr));
309         $o .= html_writer::tag('div', '', array('class' => 'left side'));
310         $o .= html_writer::tag('div', '', array('class' => 'right side'));
311         $o .= html_writer::start_tag('div', array('class' => 'content'));
313         $title = get_section_name($course, $section);
314         if ($section->uservisible) {
315             $title = html_writer::tag('a', $title,
316                     array('href' => course_get_url($course, $section->section), 'class' => $linkclasses));
317         }
318         $o .= $this->output->heading($title, 3, 'section-title');
320         $o.= html_writer::start_tag('div', array('class' => 'summarytext'));
321         $o.= $this->format_summary_text($section);
322         $o.= html_writer::end_tag('div');
323         $o.= $this->section_activity_summary($section, $course, null);
325         $context = context_course::instance($course->id);
326         $o .= $this->section_availability_message($section,
327                 has_capability('moodle/course:viewhiddensections', $context));
329         $o .= html_writer::end_tag('div');
330         $o .= html_writer::end_tag('li');
332         return $o;
333     }
335     /**
336      * Generate a summary of the activites in a section
337      *
338      * @param stdClass $section The course_section entry from DB
339      * @param stdClass $course the course record from DB
340      * @param array    $mods (argument not used)
341      * @return string HTML to output.
342      */
343     protected function section_activity_summary($section, $course, $mods) {
344         $modinfo = get_fast_modinfo($course);
345         if (empty($modinfo->sections[$section->section])) {
346             return '';
347         }
349         // Generate array with count of activities in this section:
350         $sectionmods = array();
351         $total = 0;
352         $complete = 0;
353         $cancomplete = isloggedin() && !isguestuser();
354         $completioninfo = new completion_info($course);
355         foreach ($modinfo->sections[$section->section] as $cmid) {
356             $thismod = $modinfo->cms[$cmid];
358             if ($thismod->modname == 'label') {
359                 // Labels are special (not interesting for students)!
360                 continue;
361             }
363             if ($thismod->uservisible) {
364                 if (isset($sectionmods[$thismod->modname])) {
365                     $sectionmods[$thismod->modname]['name'] = $thismod->modplural;
366                     $sectionmods[$thismod->modname]['count']++;
367                 } else {
368                     $sectionmods[$thismod->modname]['name'] = $thismod->modfullname;
369                     $sectionmods[$thismod->modname]['count'] = 1;
370                 }
371                 if ($cancomplete && $completioninfo->is_enabled($thismod) != COMPLETION_TRACKING_NONE) {
372                     $total++;
373                     $completiondata = $completioninfo->get_data($thismod, true);
374                     if ($completiondata->completionstate == COMPLETION_COMPLETE) {
375                         $complete++;
376                     }
377                 }
378             }
379         }
381         if (empty($sectionmods)) {
382             // No sections
383             return '';
384         }
386         // Output section activities summary:
387         $o = '';
388         $o.= html_writer::start_tag('div', array('class' => 'section-summary-activities mdl-right'));
389         foreach ($sectionmods as $mod) {
390             $o.= html_writer::start_tag('span', array('class' => 'activity-count'));
391             $o.= $mod['name'].': '.$mod['count'];
392             $o.= html_writer::end_tag('span');
393         }
394         $o.= html_writer::end_tag('div');
396         // Output section completion data
397         if ($total > 0) {
398             $a = new stdClass;
399             $a->complete = $complete;
400             $a->total = $total;
402             $o.= html_writer::start_tag('div', array('class' => 'section-summary-activities mdl-right'));
403             $o.= html_writer::tag('span', get_string('progresstotal', 'completion', $a), array('class' => 'activity-count'));
404             $o.= html_writer::end_tag('div');
405         }
407         return $o;
408     }
410     /**
411      * If section is not visible, display the message about that ('Not available
412      * until...', that sort of thing). Otherwise, returns blank.
413      *
414      * For users with the ability to view hidden sections, it shows the
415      * information even though you can view the section and also may include
416      * slightly fuller information (so that teachers can tell when sections
417      * are going to be unavailable etc). This logic is the same as for
418      * activities.
419      *
420      * @param stdClass $section The course_section entry from DB
421      * @param bool $canviewhidden True if user can view hidden sections
422      * @return string HTML to output
423      */
424     protected function section_availability_message($section, $canviewhidden) {
425         global $CFG;
426         $o = '';
427         if (!$section->uservisible) {
428             $o .= html_writer::start_tag('div', array('class' => 'availabilityinfo'));
429             // Note: We only get to this function if availableinfo is non-empty,
430             // so there is definitely something to print.
431             $o .= $section->availableinfo;
432             $o .= html_writer::end_tag('div');
433         } else if ($canviewhidden && !empty($CFG->enableavailability) && $section->visible) {
434             $ci = new condition_info_section($section);
435             $fullinfo = $ci->get_full_information();
436             if ($fullinfo) {
437                 $o .= html_writer::start_tag('div', array('class' => 'availabilityinfo'));
438                 $o .= get_string(
439                         ($section->showavailability ? 'userrestriction_visible' : 'userrestriction_hidden'),
440                         'condition', $fullinfo);
441                 $o .= html_writer::end_tag('div');
442             }
443         }
444         return $o;
445     }
447     /**
448      * Show if something is on on the course clipboard (moving around)
449      *
450      * @param stdClass $course The course entry from DB
451      * @param int $sectionno The section number in the coruse which is being dsiplayed
452      * @return string HTML to output.
453      */
454     protected function course_activity_clipboard($course, $sectionno = null) {
455         global $USER;
457         $o = '';
458         // If currently moving a file then show the current clipboard.
459         if (ismoving($course->id)) {
460             $url = new moodle_url('/course/mod.php',
461                 array('sesskey' => sesskey(),
462                       'cancelcopy' => true,
463                       'sr' => $sectionno,
464                 )
465             );
467             $o.= html_writer::start_tag('div', array('class' => 'clipboard'));
468             $o.= strip_tags(get_string('activityclipboard', '', $USER->activitycopyname));
469             $o.= ' ('.html_writer::link($url, get_string('cancel')).')';
470             $o.= html_writer::end_tag('div');
471         }
473         return $o;
474     }
476     /**
477      * Generate next/previous section links for naviation
478      *
479      * @param stdClass $course The course entry from DB
480      * @param array $sections The course_sections entries from the DB
481      * @param int $sectionno The section number in the coruse which is being dsiplayed
482      * @return array associative array with previous and next section link
483      */
484     protected function get_nav_links($course, $sections, $sectionno) {
485         // FIXME: This is really evil and should by using the navigation API.
486         $course = course_get_format($course)->get_course();
487         $canviewhidden = has_capability('moodle/course:viewhiddensections', context_course::instance($course->id))
488             or !$course->hiddensections;
490         $links = array('previous' => '', 'next' => '');
491         $back = $sectionno - 1;
492         while ($back > 0 and empty($links['previous'])) {
493             if ($canviewhidden || $sections[$back]->uservisible) {
494                 $params = array();
495                 if (!$sections[$back]->visible) {
496                     $params = array('class' => 'dimmed_text');
497                 }
498                 $previouslink = html_writer::tag('span', $this->output->larrow(), array('class' => 'larrow'));
499                 $previouslink .= get_section_name($course, $sections[$back]);
500                 $links['previous'] = html_writer::link(course_get_url($course, $back), $previouslink, $params);
501             }
502             $back--;
503         }
505         $forward = $sectionno + 1;
506         while ($forward <= $course->numsections and empty($links['next'])) {
507             if ($canviewhidden || $sections[$forward]->uservisible) {
508                 $params = array();
509                 if (!$sections[$forward]->visible) {
510                     $params = array('class' => 'dimmed_text');
511                 }
512                 $nextlink = get_section_name($course, $sections[$forward]);
513                 $nextlink .= html_writer::tag('span', $this->output->rarrow(), array('class' => 'rarrow'));
514                 $links['next'] = html_writer::link(course_get_url($course, $forward), $nextlink, $params);
515             }
516             $forward++;
517         }
519         return $links;
520     }
522     /**
523      * Generate the header html of a stealth section
524      *
525      * @param int $sectionno The section number in the coruse which is being dsiplayed
526      * @return string HTML to output.
527      */
528     protected function stealth_section_header($sectionno) {
529         $o = '';
530         $o.= html_writer::start_tag('li', array('id' => 'section-'.$sectionno, 'class' => 'section main clearfix orphaned hidden'));
531         $o.= html_writer::tag('div', '', array('class' => 'left side'));
532         $o.= html_writer::tag('div', '', array('class' => 'right side'));
533         $o.= html_writer::start_tag('div', array('class' => 'content'));
534         $o.= $this->output->heading(get_string('orphanedactivities'), 3, 'sectionname');
535         return $o;
536     }
538     /**
539      * Generate footer html of a stealth section
540      *
541      * @return string HTML to output.
542      */
543     protected function stealth_section_footer() {
544         $o = html_writer::end_tag('div');
545         $o.= html_writer::end_tag('li');
546         return $o;
547     }
549     /**
550      * Generate the html for a hidden section
551      *
552      * @param int $sectionno The section number in the coruse which is being dsiplayed
553      * @return string HTML to output.
554      */
555     protected function section_hidden($sectionno) {
556         $o = '';
557         $o.= html_writer::start_tag('li', array('id' => 'section-'.$sectionno, 'class' => 'section main clearfix hidden'));
558         $o.= html_writer::tag('div', '', array('class' => 'left side'));
559         $o.= html_writer::tag('div', '', array('class' => 'right side'));
560         $o.= html_writer::start_tag('div', array('class' => 'content'));
561         $o.= get_string('notavailable');
562         $o.= html_writer::end_tag('div');
563         $o.= html_writer::end_tag('li');
564         return $o;
565     }
567     /**
568      * Generate the html for the 'Jump to' menu on a single section page.
569      *
570      * @param stdClass $course The course entry from DB
571      * @param array $sections The course_sections entries from the DB
572      * @param $displaysection the current displayed section number.
573      *
574      * @return string HTML to output.
575      */
576     protected function section_nav_selection($course, $sections, $displaysection) {
577         global $CFG;
578         $o = '';
579         $sectionmenu = array();
580         $sectionmenu[course_get_url($course)->out(false)] = get_string('maincoursepage');
581         $modinfo = get_fast_modinfo($course);
582         $section = 1;
583         while ($section <= $course->numsections) {
584             $thissection = $modinfo->get_section_info($section);
585             $showsection = $thissection->uservisible or !$course->hiddensections;
586             if (($showsection) && ($section != $displaysection) && ($url = course_get_url($course, $section))) {
587                 $sectionmenu[$url->out(false)] = get_section_name($course, $section);
588             }
589             $section++;
590         }
592         $select = new url_select($sectionmenu, '', array('' => get_string('jumpto')));
593         $select->class = 'jumpmenu';
594         $select->formid = 'sectionmenu';
595         $o .= $this->output->render($select);
597         return $o;
598     }
600     /**
601      * Output the html for a single section page .
602      *
603      * @param stdClass $course The course entry from DB
604      * @param array $sections (argument not used)
605      * @param array $mods (argument not used)
606      * @param array $modnames (argument not used)
607      * @param array $modnamesused (argument not used)
608      * @param int $displaysection The section number in the course which is being displayed
609      */
610     public function print_single_section_page($course, $sections, $mods, $modnames, $modnamesused, $displaysection) {
611         global $PAGE;
613         $modinfo = get_fast_modinfo($course);
614         $course = course_get_format($course)->get_course();
616         // Can we view the section in question?
617         if (!($sectioninfo = $modinfo->get_section_info($displaysection))) {
618             // This section doesn't exist
619             print_error('unknowncoursesection', 'error', null, $course->fullname);
620             return;
621         }
623         if (!$sectioninfo->uservisible) {
624             if (!$course->hiddensections) {
625                 echo $this->start_section_list();
626                 echo $this->section_hidden($displaysection);
627                 echo $this->end_section_list();
628             }
629             // Can't view this section.
630             return;
631         }
633         // Copy activity clipboard..
634         echo $this->course_activity_clipboard($course, $displaysection);
635         $thissection = $modinfo->get_section_info(0);
636         if ($thissection->summary or !empty($modinfo->sections[0]) or $PAGE->user_is_editing()) {
637             echo $this->start_section_list();
638             echo $this->section_header($thissection, $course, true, $displaysection);
639             echo $this->courserenderer->course_section_cm_list($course, $thissection, $displaysection);
640             echo $this->courserenderer->course_section_add_cm_control($course, 0, $displaysection);
641             echo $this->section_footer();
642             echo $this->end_section_list();
643         }
645         // Start single-section div
646         echo html_writer::start_tag('div', array('class' => 'single-section'));
648         // The requested section page.
649         $thissection = $modinfo->get_section_info($displaysection);
651         // Title with section navigation links.
652         $sectionnavlinks = $this->get_nav_links($course, $modinfo->get_section_info_all(), $displaysection);
653         $sectiontitle = '';
654         $sectiontitle .= html_writer::start_tag('div', array('class' => 'section-navigation header headingblock'));
655         $sectiontitle .= html_writer::tag('span', $sectionnavlinks['previous'], array('class' => 'mdl-left'));
656         $sectiontitle .= html_writer::tag('span', $sectionnavlinks['next'], array('class' => 'mdl-right'));
657         // Title attributes
658         $classes = 'sectionname';
659         if (!$thissection->visible) {
660             $classes .= ' dimmed_text';
661         }
662         $sectiontitle .= $this->output->heading(get_section_name($course, $displaysection), 3, $classes);
664         $sectiontitle .= html_writer::end_tag('div');
665         echo $sectiontitle;
667         // Now the list of sections..
668         echo $this->start_section_list();
670         echo $this->section_header($thissection, $course, true, $displaysection);
671         // Show completion help icon.
672         $completioninfo = new completion_info($course);
673         echo $completioninfo->display_help_icon();
675         echo $this->courserenderer->course_section_cm_list($course, $thissection, $displaysection);
676         echo $this->courserenderer->course_section_add_cm_control($course, $displaysection, $displaysection);
677         echo $this->section_footer();
678         echo $this->end_section_list();
680         // Display section bottom navigation.
681         $sectionbottomnav = '';
682         $sectionbottomnav .= html_writer::start_tag('div', array('class' => 'section-navigation mdl-bottom'));
683         $sectionbottomnav .= html_writer::tag('span', $sectionnavlinks['previous'], array('class' => 'mdl-left'));
684         $sectionbottomnav .= html_writer::tag('span', $sectionnavlinks['next'], array('class' => 'mdl-right'));
685         $sectionbottomnav .= html_writer::tag('div', $this->section_nav_selection($course, $sections, $displaysection),
686             array('class' => 'mdl-align'));
687         $sectionbottomnav .= html_writer::end_tag('div');
688         echo $sectionbottomnav;
690         // Close single-section div.
691         echo html_writer::end_tag('div');
692     }
694     /**
695      * Output the html for a multiple section page
696      *
697      * @param stdClass $course The course entry from DB
698      * @param array $sections (argument not used)
699      * @param array $mods (argument not used)
700      * @param array $modnames (argument not used)
701      * @param array $modnamesused (argument not used)
702      */
703     public function print_multiple_section_page($course, $sections, $mods, $modnames, $modnamesused) {
704         global $PAGE;
706         $modinfo = get_fast_modinfo($course);
707         $course = course_get_format($course)->get_course();
709         $context = context_course::instance($course->id);
710         // Title with completion help icon.
711         $completioninfo = new completion_info($course);
712         echo $completioninfo->display_help_icon();
713         echo $this->output->heading($this->page_title(), 2, 'accesshide');
715         // Copy activity clipboard..
716         echo $this->course_activity_clipboard($course, 0);
718         // Now the list of sections..
719         echo $this->start_section_list();
721         foreach ($modinfo->get_section_info_all() as $section => $thissection) {
722             if ($section == 0) {
723                 // 0-section is displayed a little different then the others
724                 if ($thissection->summary or !empty($modinfo->sections[0]) or $PAGE->user_is_editing()) {
725                     echo $this->section_header($thissection, $course, false, 0);
726                     echo $this->courserenderer->course_section_cm_list($course, $thissection, 0);
727                     echo $this->courserenderer->course_section_add_cm_control($course, 0, 0);
728                     echo $this->section_footer();
729                 }
730                 continue;
731             }
732             if ($section > $course->numsections) {
733                 // activities inside this section are 'orphaned', this section will be printed as 'stealth' below
734                 continue;
735             }
736             // Show the section if the user is permitted to access it, OR if it's not available
737             // but showavailability is turned on (and there is some available info text).
738             $showsection = $thissection->uservisible ||
739                     ($thissection->visible && !$thissection->available && $thissection->showavailability
740                     && !empty($thissection->availableinfo));
741             if (!$showsection) {
742                 // Hidden section message is overridden by 'unavailable' control
743                 // (showavailability option).
744                 if (!$course->hiddensections && $thissection->available) {
745                     echo $this->section_hidden($section);
746                 }
748                 continue;
749             }
751             if (!$PAGE->user_is_editing() && $course->coursedisplay == COURSE_DISPLAY_MULTIPAGE) {
752                 // Display section summary only.
753                 echo $this->section_summary($thissection, $course, null);
754             } else {
755                 echo $this->section_header($thissection, $course, false, 0);
756                 if ($thissection->uservisible) {
757                     echo $this->courserenderer->course_section_cm_list($course, $thissection, 0);
758                     echo $this->courserenderer->course_section_add_cm_control($course, $section, 0);
759                 }
760                 echo $this->section_footer();
761             }
762         }
764         if ($PAGE->user_is_editing() and has_capability('moodle/course:update', $context)) {
765             // Print stealth sections if present.
766             foreach ($modinfo->get_section_info_all() as $section => $thissection) {
767                 if ($section <= $course->numsections or empty($modinfo->sections[$section])) {
768                     // this is not stealth section or it is empty
769                     continue;
770                 }
771                 echo $this->stealth_section_header($section);
772                 echo $this->courserenderer->course_section_cm_list($course, $thissection, 0);
773                 echo $this->stealth_section_footer();
774             }
776             echo $this->end_section_list();
778             echo html_writer::start_tag('div', array('id' => 'changenumsections', 'class' => 'mdl-right'));
780             // Increase number of sections.
781             $straddsection = get_string('increasesections', 'moodle');
782             $url = new moodle_url('/course/changenumsections.php',
783                 array('courseid' => $course->id,
784                       'increase' => true,
785                       'sesskey' => sesskey()));
786             $icon = $this->output->pix_icon('t/switch_plus', $straddsection);
787             echo html_writer::link($url, $icon.get_accesshide($straddsection), array('class' => 'increase-sections'));
789             if ($course->numsections > 0) {
790                 // Reduce number of sections sections.
791                 $strremovesection = get_string('reducesections', 'moodle');
792                 $url = new moodle_url('/course/changenumsections.php',
793                     array('courseid' => $course->id,
794                           'increase' => false,
795                           'sesskey' => sesskey()));
796                 $icon = $this->output->pix_icon('t/switch_minus', $strremovesection);
797                 echo html_writer::link($url, $icon.get_accesshide($strremovesection), array('class' => 'reduce-sections'));
798             }
800             echo html_writer::end_tag('div');
801         } else {
802             echo $this->end_section_list();
803         }
805     }
807     /**
808      * Generate html for a section summary text
809      *
810      * @param stdClass $section The course_section entry from DB
811      * @return string HTML to output.
812      */
813     protected function format_summary_text($section) {
814         $context = context_course::instance($section->course);
815         $summarytext = file_rewrite_pluginfile_urls($section->summary, 'pluginfile.php',
816             $context->id, 'course', 'section', $section->id);
818         $options = new stdClass();
819         $options->noclean = true;
820         $options->overflowdiv = true;
821         return format_text($summarytext, $section->summaryformat, $options);
822     }
824     /**
825      * Is the section passed in the current section?
826      *
827      * @deprecated since 2.4
828      * @see format_base::is_section_current()
829      *
830      * @param stdClass $course The course entry from DB
831      * @param stdClass $section The course_section entry from the DB
832      * @return bool true if the section is current
833      */
834     protected final function is_section_current($section, $course) {
835         debugging('Function format_section_renderer_base::is_section_current() is deprecated. '.
836                 'Use course_get_format($course)->is_section_current($section) instead', DEBUG_DEVELOPER);
837         return course_get_format($course)->is_section_current($section);
838     }