MDL-43083 Course: Swapping the edit/cog for the right size icon
[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, 'role'=>'region',
161             'aria-label'=> get_section_name($course, $section)));
163         $leftcontent = $this->section_left_content($section, $course, $onsectionpage);
164         $o.= html_writer::tag('div', $leftcontent, array('class' => 'left side'));
166         $rightcontent = $this->section_right_content($section, $course, $onsectionpage);
167         $o.= html_writer::tag('div', $rightcontent, array('class' => 'right side'));
168         $o.= html_writer::start_tag('div', array('class' => 'content'));
170         // When not on a section page, we display the section titles except the general section if null
171         $hasnamenotsecpg = (!$onsectionpage && ($section->section != 0 || !is_null($section->name)));
173         // When on a section page, we only display the general section title, if title is not the default one
174         $hasnamesecpg = ($onsectionpage && ($section->section == 0 && !is_null($section->name)));
176         $classes = ' accesshide';
177         if ($hasnamenotsecpg || $hasnamesecpg) {
178             $classes = '';
179         }
180         $o.= $this->output->heading($this->section_title($section, $course), 3, 'sectionname' . $classes);
182         $o.= html_writer::start_tag('div', array('class' => 'summary'));
183         $o.= $this->format_summary_text($section);
185         $context = context_course::instance($course->id);
186         if ($PAGE->user_is_editing() && has_capability('moodle/course:update', $context)) {
187             $url = new moodle_url('/course/editsection.php', array('id'=>$section->id, 'sr'=>$sectionreturn));
188             $o.= html_writer::link($url,
189                 html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/settings'),
190                     'class' => 'iconsmall edit', 'alt' => get_string('edit'))),
191                 array('title' => get_string('editsummary')));
192         }
193         $o.= html_writer::end_tag('div');
195         $o .= $this->section_availability_message($section,
196                 has_capability('moodle/course:viewhiddensections', $context));
198         return $o;
199     }
201     /**
202      * Generate the display of the footer part of a section
203      *
204      * @return string HTML to output.
205      */
206     protected function section_footer() {
207         $o = html_writer::end_tag('div');
208         $o.= html_writer::end_tag('li');
210         return $o;
211     }
213     /**
214      * Generate the edit controls of a section
215      *
216      * @param stdClass $course The course entry from DB
217      * @param stdClass $section The course_section entry from DB
218      * @param bool $onsectionpage true if being printed on a section page
219      * @return array of links with edit controls
220      */
221     protected function section_edit_controls($course, $section, $onsectionpage = false) {
222         global $PAGE;
224         if (!$PAGE->user_is_editing()) {
225             return array();
226         }
228         $coursecontext = context_course::instance($course->id);
230         if ($onsectionpage) {
231             $baseurl = course_get_url($course, $section->section);
232         } else {
233             $baseurl = course_get_url($course);
234         }
235         $baseurl->param('sesskey', sesskey());
237         $controls = array();
239         $url = clone($baseurl);
240         if (has_capability('moodle/course:sectionvisibility', $coursecontext)) {
241             if ($section->visible) { // Show the hide/show eye.
242                 $strhidefromothers = get_string('hidefromothers', 'format_'.$course->format);
243                 $url->param('hide', $section->section);
244                 $controls[] = html_writer::link($url,
245                     html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/hide'),
246                     'class' => 'icon hide', 'alt' => $strhidefromothers)),
247                     array('title' => $strhidefromothers, 'class' => 'editing_showhide'));
248             } else {
249                 $strshowfromothers = get_string('showfromothers', 'format_'.$course->format);
250                 $url->param('show',  $section->section);
251                 $controls[] = html_writer::link($url,
252                     html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/show'),
253                     'class' => 'icon hide', 'alt' => $strshowfromothers)),
254                     array('title' => $strshowfromothers, 'class' => 'editing_showhide'));
255             }
256         }
258         if (!$onsectionpage && has_capability('moodle/course:movesections', $coursecontext)) {
259             $url = clone($baseurl);
260             if ($section->section > 1) { // Add a arrow to move section up.
261                 $url->param('section', $section->section);
262                 $url->param('move', -1);
263                 $strmoveup = get_string('moveup');
265                 $controls[] = html_writer::link($url,
266                     html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/up'),
267                     'class' => 'icon up', 'alt' => $strmoveup)),
268                     array('title' => $strmoveup, 'class' => 'moveup'));
269             }
271             $url = clone($baseurl);
272             if ($section->section < $course->numsections) { // Add a arrow to move section down.
273                 $url->param('section', $section->section);
274                 $url->param('move', 1);
275                 $strmovedown =  get_string('movedown');
277                 $controls[] = html_writer::link($url,
278                     html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/down'),
279                     'class' => 'icon down', 'alt' => $strmovedown)),
280                     array('title' => $strmovedown, 'class' => 'movedown'));
281             }
282         }
284         return $controls;
285     }
287     /**
288      * Generate a summary of a section for display on the 'coruse index page'
289      *
290      * @param stdClass $section The course_section entry from DB
291      * @param stdClass $course The course entry from DB
292      * @param array    $mods (argument not used)
293      * @return string HTML to output.
294      */
295     protected function section_summary($section, $course, $mods) {
296         $classattr = 'section main section-summary clearfix';
297         $linkclasses = '';
299         // If section is hidden then display grey section link
300         if (!$section->visible) {
301             $classattr .= ' hidden';
302             $linkclasses .= ' dimmed_text';
303         } else if (course_get_format($course)->is_section_current($section)) {
304             $classattr .= ' current';
305         }
307         $title = get_section_name($course, $section);
308         $o = '';
309         $o .= html_writer::start_tag('li', array('id' => 'section-'.$section->section,
310             'class' => $classattr, 'role'=>'region', 'aria-label'=> $title));
312         $o .= html_writer::tag('div', '', array('class' => 'left side'));
313         $o .= html_writer::tag('div', '', array('class' => 'right side'));
314         $o .= html_writer::start_tag('div', array('class' => 'content'));
316         if ($section->uservisible) {
317             $title = html_writer::tag('a', $title,
318                     array('href' => course_get_url($course, $section->section), 'class' => $linkclasses));
319         }
320         $o .= $this->output->heading($title, 3, 'section-title');
322         $o.= html_writer::start_tag('div', array('class' => 'summarytext'));
323         $o.= $this->format_summary_text($section);
324         $o.= html_writer::end_tag('div');
325         $o.= $this->section_activity_summary($section, $course, null);
327         $context = context_course::instance($course->id);
328         $o .= $this->section_availability_message($section,
329                 has_capability('moodle/course:viewhiddensections', $context));
331         $o .= html_writer::end_tag('div');
332         $o .= html_writer::end_tag('li');
334         return $o;
335     }
337     /**
338      * Generate a summary of the activites in a section
339      *
340      * @param stdClass $section The course_section entry from DB
341      * @param stdClass $course the course record from DB
342      * @param array    $mods (argument not used)
343      * @return string HTML to output.
344      */
345     protected function section_activity_summary($section, $course, $mods) {
346         $modinfo = get_fast_modinfo($course);
347         if (empty($modinfo->sections[$section->section])) {
348             return '';
349         }
351         // Generate array with count of activities in this section:
352         $sectionmods = array();
353         $total = 0;
354         $complete = 0;
355         $cancomplete = isloggedin() && !isguestuser();
356         $completioninfo = new completion_info($course);
357         foreach ($modinfo->sections[$section->section] as $cmid) {
358             $thismod = $modinfo->cms[$cmid];
360             if ($thismod->modname == 'label') {
361                 // Labels are special (not interesting for students)!
362                 continue;
363             }
365             if ($thismod->uservisible) {
366                 if (isset($sectionmods[$thismod->modname])) {
367                     $sectionmods[$thismod->modname]['name'] = $thismod->modplural;
368                     $sectionmods[$thismod->modname]['count']++;
369                 } else {
370                     $sectionmods[$thismod->modname]['name'] = $thismod->modfullname;
371                     $sectionmods[$thismod->modname]['count'] = 1;
372                 }
373                 if ($cancomplete && $completioninfo->is_enabled($thismod) != COMPLETION_TRACKING_NONE) {
374                     $total++;
375                     $completiondata = $completioninfo->get_data($thismod, true);
376                     if ($completiondata->completionstate == COMPLETION_COMPLETE) {
377                         $complete++;
378                     }
379                 }
380             }
381         }
383         if (empty($sectionmods)) {
384             // No sections
385             return '';
386         }
388         // Output section activities summary:
389         $o = '';
390         $o.= html_writer::start_tag('div', array('class' => 'section-summary-activities mdl-right'));
391         foreach ($sectionmods as $mod) {
392             $o.= html_writer::start_tag('span', array('class' => 'activity-count'));
393             $o.= $mod['name'].': '.$mod['count'];
394             $o.= html_writer::end_tag('span');
395         }
396         $o.= html_writer::end_tag('div');
398         // Output section completion data
399         if ($total > 0) {
400             $a = new stdClass;
401             $a->complete = $complete;
402             $a->total = $total;
404             $o.= html_writer::start_tag('div', array('class' => 'section-summary-activities mdl-right'));
405             $o.= html_writer::tag('span', get_string('progresstotal', 'completion', $a), array('class' => 'activity-count'));
406             $o.= html_writer::end_tag('div');
407         }
409         return $o;
410     }
412     /**
413      * If section is not visible, display the message about that ('Not available
414      * until...', that sort of thing). Otherwise, returns blank.
415      *
416      * For users with the ability to view hidden sections, it shows the
417      * information even though you can view the section and also may include
418      * slightly fuller information (so that teachers can tell when sections
419      * are going to be unavailable etc). This logic is the same as for
420      * activities.
421      *
422      * @param stdClass $section The course_section entry from DB
423      * @param bool $canviewhidden True if user can view hidden sections
424      * @return string HTML to output
425      */
426     protected function section_availability_message($section, $canviewhidden) {
427         global $CFG;
428         $o = '';
429         if (!$section->uservisible) {
430             $o .= html_writer::start_tag('div', array('class' => 'availabilityinfo'));
431             // Note: We only get to this function if availableinfo is non-empty,
432             // so there is definitely something to print.
433             $o .= $section->availableinfo;
434             $o .= html_writer::end_tag('div');
435         } else if ($canviewhidden && !empty($CFG->enableavailability) && $section->visible) {
436             $ci = new condition_info_section($section);
437             $fullinfo = $ci->get_full_information();
438             if ($fullinfo) {
439                 $o .= html_writer::start_tag('div', array('class' => 'availabilityinfo'));
440                 $o .= get_string(
441                         ($section->showavailability ? 'userrestriction_visible' : 'userrestriction_hidden'),
442                         'condition', $fullinfo);
443                 $o .= html_writer::end_tag('div');
444             }
445         }
446         return $o;
447     }
449     /**
450      * Show if something is on on the course clipboard (moving around)
451      *
452      * @param stdClass $course The course entry from DB
453      * @param int $sectionno The section number in the coruse which is being dsiplayed
454      * @return string HTML to output.
455      */
456     protected function course_activity_clipboard($course, $sectionno = null) {
457         global $USER;
459         $o = '';
460         // If currently moving a file then show the current clipboard.
461         if (ismoving($course->id)) {
462             $url = new moodle_url('/course/mod.php',
463                 array('sesskey' => sesskey(),
464                       'cancelcopy' => true,
465                       'sr' => $sectionno,
466                 )
467             );
469             $o.= html_writer::start_tag('div', array('class' => 'clipboard'));
470             $o.= strip_tags(get_string('activityclipboard', '', $USER->activitycopyname));
471             $o.= ' ('.html_writer::link($url, get_string('cancel')).')';
472             $o.= html_writer::end_tag('div');
473         }
475         return $o;
476     }
478     /**
479      * Generate next/previous section links for naviation
480      *
481      * @param stdClass $course The course entry from DB
482      * @param array $sections The course_sections entries from the DB
483      * @param int $sectionno The section number in the coruse which is being dsiplayed
484      * @return array associative array with previous and next section link
485      */
486     protected function get_nav_links($course, $sections, $sectionno) {
487         // FIXME: This is really evil and should by using the navigation API.
488         $course = course_get_format($course)->get_course();
489         $canviewhidden = has_capability('moodle/course:viewhiddensections', context_course::instance($course->id))
490             or !$course->hiddensections;
492         $links = array('previous' => '', 'next' => '');
493         $back = $sectionno - 1;
494         while ($back > 0 and empty($links['previous'])) {
495             if ($canviewhidden || $sections[$back]->uservisible) {
496                 $params = array();
497                 if (!$sections[$back]->visible) {
498                     $params = array('class' => 'dimmed_text');
499                 }
500                 $previouslink = html_writer::tag('span', $this->output->larrow(), array('class' => 'larrow'));
501                 $previouslink .= get_section_name($course, $sections[$back]);
502                 $links['previous'] = html_writer::link(course_get_url($course, $back), $previouslink, $params);
503             }
504             $back--;
505         }
507         $forward = $sectionno + 1;
508         while ($forward <= $course->numsections and empty($links['next'])) {
509             if ($canviewhidden || $sections[$forward]->uservisible) {
510                 $params = array();
511                 if (!$sections[$forward]->visible) {
512                     $params = array('class' => 'dimmed_text');
513                 }
514                 $nextlink = get_section_name($course, $sections[$forward]);
515                 $nextlink .= html_writer::tag('span', $this->output->rarrow(), array('class' => 'rarrow'));
516                 $links['next'] = html_writer::link(course_get_url($course, $forward), $nextlink, $params);
517             }
518             $forward++;
519         }
521         return $links;
522     }
524     /**
525      * Generate the header html of a stealth section
526      *
527      * @param int $sectionno The section number in the coruse which is being dsiplayed
528      * @return string HTML to output.
529      */
530     protected function stealth_section_header($sectionno) {
531         $o = '';
532         $o.= html_writer::start_tag('li', array('id' => 'section-'.$sectionno, 'class' => 'section main clearfix orphaned hidden'));
533         $o.= html_writer::tag('div', '', array('class' => 'left side'));
534         $o.= html_writer::tag('div', '', array('class' => 'right side'));
535         $o.= html_writer::start_tag('div', array('class' => 'content'));
536         $o.= $this->output->heading(get_string('orphanedactivitiesinsectionno', '', $sectionno), 3, 'sectionname');
537         return $o;
538     }
540     /**
541      * Generate footer html of a stealth section
542      *
543      * @return string HTML to output.
544      */
545     protected function stealth_section_footer() {
546         $o = html_writer::end_tag('div');
547         $o.= html_writer::end_tag('li');
548         return $o;
549     }
551     /**
552      * Generate the html for a hidden section
553      *
554      * @param int $sectionno The section number in the coruse which is being dsiplayed
555      * @return string HTML to output.
556      */
557     protected function section_hidden($sectionno) {
558         $o = '';
559         $o.= html_writer::start_tag('li', array('id' => 'section-'.$sectionno, 'class' => 'section main clearfix hidden'));
560         $o.= html_writer::tag('div', '', array('class' => 'left side'));
561         $o.= html_writer::tag('div', '', array('class' => 'right side'));
562         $o.= html_writer::start_tag('div', array('class' => 'content'));
563         $o.= get_string('notavailable');
564         $o.= html_writer::end_tag('div');
565         $o.= html_writer::end_tag('li');
566         return $o;
567     }
569     /**
570      * Generate the html for the 'Jump to' menu on a single section page.
571      *
572      * @param stdClass $course The course entry from DB
573      * @param array $sections The course_sections entries from the DB
574      * @param $displaysection the current displayed section number.
575      *
576      * @return string HTML to output.
577      */
578     protected function section_nav_selection($course, $sections, $displaysection) {
579         global $CFG;
580         $o = '';
581         $sectionmenu = array();
582         $sectionmenu[course_get_url($course)->out(false)] = get_string('maincoursepage');
583         $modinfo = get_fast_modinfo($course);
584         $section = 1;
585         while ($section <= $course->numsections) {
586             $thissection = $modinfo->get_section_info($section);
587             $showsection = $thissection->uservisible or !$course->hiddensections;
588             if (($showsection) && ($section != $displaysection) && ($url = course_get_url($course, $section))) {
589                 $sectionmenu[$url->out(false)] = get_section_name($course, $section);
590             }
591             $section++;
592         }
594         $select = new url_select($sectionmenu, '', array('' => get_string('jumpto')));
595         $select->class = 'jumpmenu';
596         $select->formid = 'sectionmenu';
597         $o .= $this->output->render($select);
599         return $o;
600     }
602     /**
603      * Output the html for a single section page .
604      *
605      * @param stdClass $course The course entry from DB
606      * @param array $sections (argument not used)
607      * @param array $mods (argument not used)
608      * @param array $modnames (argument not used)
609      * @param array $modnamesused (argument not used)
610      * @param int $displaysection The section number in the course which is being displayed
611      */
612     public function print_single_section_page($course, $sections, $mods, $modnames, $modnamesused, $displaysection) {
613         global $PAGE;
615         $modinfo = get_fast_modinfo($course);
616         $course = course_get_format($course)->get_course();
618         // Can we view the section in question?
619         if (!($sectioninfo = $modinfo->get_section_info($displaysection))) {
620             // This section doesn't exist
621             print_error('unknowncoursesection', 'error', null, $course->fullname);
622             return;
623         }
625         if (!$sectioninfo->uservisible) {
626             if (!$course->hiddensections) {
627                 echo $this->start_section_list();
628                 echo $this->section_hidden($displaysection);
629                 echo $this->end_section_list();
630             }
631             // Can't view this section.
632             return;
633         }
635         // Copy activity clipboard..
636         echo $this->course_activity_clipboard($course, $displaysection);
637         $thissection = $modinfo->get_section_info(0);
638         if ($thissection->summary or !empty($modinfo->sections[0]) or $PAGE->user_is_editing()) {
639             echo $this->start_section_list();
640             echo $this->section_header($thissection, $course, true, $displaysection);
641             echo $this->courserenderer->course_section_cm_list($course, $thissection, $displaysection);
642             echo $this->courserenderer->course_section_add_cm_control($course, 0, $displaysection);
643             echo $this->section_footer();
644             echo $this->end_section_list();
645         }
647         // Start single-section div
648         echo html_writer::start_tag('div', array('class' => 'single-section'));
650         // The requested section page.
651         $thissection = $modinfo->get_section_info($displaysection);
653         // Title with section navigation links.
654         $sectionnavlinks = $this->get_nav_links($course, $modinfo->get_section_info_all(), $displaysection);
655         $sectiontitle = '';
656         $sectiontitle .= html_writer::start_tag('div', array('class' => 'section-navigation navigationtitle'));
657         $sectiontitle .= html_writer::tag('span', $sectionnavlinks['previous'], array('class' => 'mdl-left'));
658         $sectiontitle .= html_writer::tag('span', $sectionnavlinks['next'], array('class' => 'mdl-right'));
659         // Title attributes
660         $classes = 'sectionname';
661         if (!$thissection->visible) {
662             $classes .= ' dimmed_text';
663         }
664         $sectiontitle .= $this->output->heading(get_section_name($course, $displaysection), 3, $classes);
666         $sectiontitle .= html_writer::end_tag('div');
667         echo $sectiontitle;
669         // Now the list of sections..
670         echo $this->start_section_list();
672         echo $this->section_header($thissection, $course, true, $displaysection);
673         // Show completion help icon.
674         $completioninfo = new completion_info($course);
675         echo $completioninfo->display_help_icon();
677         echo $this->courserenderer->course_section_cm_list($course, $thissection, $displaysection);
678         echo $this->courserenderer->course_section_add_cm_control($course, $displaysection, $displaysection);
679         echo $this->section_footer();
680         echo $this->end_section_list();
682         // Display section bottom navigation.
683         $sectionbottomnav = '';
684         $sectionbottomnav .= html_writer::start_tag('div', array('class' => 'section-navigation mdl-bottom'));
685         $sectionbottomnav .= html_writer::tag('span', $sectionnavlinks['previous'], array('class' => 'mdl-left'));
686         $sectionbottomnav .= html_writer::tag('span', $sectionnavlinks['next'], array('class' => 'mdl-right'));
687         $sectionbottomnav .= html_writer::tag('div', $this->section_nav_selection($course, $sections, $displaysection),
688             array('class' => 'mdl-align'));
689         $sectionbottomnav .= html_writer::end_tag('div');
690         echo $sectionbottomnav;
692         // Close single-section div.
693         echo html_writer::end_tag('div');
694     }
696     /**
697      * Output the html for a multiple section page
698      *
699      * @param stdClass $course The course entry from DB
700      * @param array $sections (argument not used)
701      * @param array $mods (argument not used)
702      * @param array $modnames (argument not used)
703      * @param array $modnamesused (argument not used)
704      */
705     public function print_multiple_section_page($course, $sections, $mods, $modnames, $modnamesused) {
706         global $PAGE;
708         $modinfo = get_fast_modinfo($course);
709         $course = course_get_format($course)->get_course();
711         $context = context_course::instance($course->id);
712         // Title with completion help icon.
713         $completioninfo = new completion_info($course);
714         echo $completioninfo->display_help_icon();
715         echo $this->output->heading($this->page_title(), 2, 'accesshide');
717         // Copy activity clipboard..
718         echo $this->course_activity_clipboard($course, 0);
720         // Now the list of sections..
721         echo $this->start_section_list();
723         foreach ($modinfo->get_section_info_all() as $section => $thissection) {
724             if ($section == 0) {
725                 // 0-section is displayed a little different then the others
726                 if ($thissection->summary or !empty($modinfo->sections[0]) or $PAGE->user_is_editing()) {
727                     echo $this->section_header($thissection, $course, false, 0);
728                     echo $this->courserenderer->course_section_cm_list($course, $thissection, 0);
729                     echo $this->courserenderer->course_section_add_cm_control($course, 0, 0);
730                     echo $this->section_footer();
731                 }
732                 continue;
733             }
734             if ($section > $course->numsections) {
735                 // activities inside this section are 'orphaned', this section will be printed as 'stealth' below
736                 continue;
737             }
738             // Show the section if the user is permitted to access it, OR if it's not available
739             // but showavailability is turned on (and there is some available info text).
740             $showsection = $thissection->uservisible ||
741                     ($thissection->visible && !$thissection->available && $thissection->showavailability
742                     && !empty($thissection->availableinfo));
743             if (!$showsection) {
744                 // Hidden section message is overridden by 'unavailable' control
745                 // (showavailability option).
746                 if (!$course->hiddensections && $thissection->available) {
747                     echo $this->section_hidden($section);
748                 }
750                 continue;
751             }
753             if (!$PAGE->user_is_editing() && $course->coursedisplay == COURSE_DISPLAY_MULTIPAGE) {
754                 // Display section summary only.
755                 echo $this->section_summary($thissection, $course, null);
756             } else {
757                 echo $this->section_header($thissection, $course, false, 0);
758                 if ($thissection->uservisible) {
759                     echo $this->courserenderer->course_section_cm_list($course, $thissection, 0);
760                     echo $this->courserenderer->course_section_add_cm_control($course, $section, 0);
761                 }
762                 echo $this->section_footer();
763             }
764         }
766         if ($PAGE->user_is_editing() and has_capability('moodle/course:update', $context)) {
767             // Print stealth sections if present.
768             foreach ($modinfo->get_section_info_all() as $section => $thissection) {
769                 if ($section <= $course->numsections or empty($modinfo->sections[$section])) {
770                     // this is not stealth section or it is empty
771                     continue;
772                 }
773                 echo $this->stealth_section_header($section);
774                 echo $this->courserenderer->course_section_cm_list($course, $thissection, 0);
775                 echo $this->stealth_section_footer();
776             }
778             echo $this->end_section_list();
780             echo html_writer::start_tag('div', array('id' => 'changenumsections', 'class' => 'mdl-right'));
782             // Increase number of sections.
783             $straddsection = get_string('increasesections', 'moodle');
784             $url = new moodle_url('/course/changenumsections.php',
785                 array('courseid' => $course->id,
786                       'increase' => true,
787                       'sesskey' => sesskey()));
788             $icon = $this->output->pix_icon('t/switch_plus', $straddsection);
789             echo html_writer::link($url, $icon.get_accesshide($straddsection), array('class' => 'increase-sections'));
791             if ($course->numsections > 0) {
792                 // Reduce number of sections sections.
793                 $strremovesection = get_string('reducesections', 'moodle');
794                 $url = new moodle_url('/course/changenumsections.php',
795                     array('courseid' => $course->id,
796                           'increase' => false,
797                           'sesskey' => sesskey()));
798                 $icon = $this->output->pix_icon('t/switch_minus', $strremovesection);
799                 echo html_writer::link($url, $icon.get_accesshide($strremovesection), array('class' => 'reduce-sections'));
800             }
802             echo html_writer::end_tag('div');
803         } else {
804             echo $this->end_section_list();
805         }
807     }
809     /**
810      * Generate html for a section summary text
811      *
812      * @param stdClass $section The course_section entry from DB
813      * @return string HTML to output.
814      */
815     protected function format_summary_text($section) {
816         $context = context_course::instance($section->course);
817         $summarytext = file_rewrite_pluginfile_urls($section->summary, 'pluginfile.php',
818             $context->id, 'course', 'section', $section->id);
820         $options = new stdClass();
821         $options->noclean = true;
822         $options->overflowdiv = true;
823         return format_text($summarytext, $section->summaryformat, $options);
824     }
826     /**
827      * Is the section passed in the current section?
828      *
829      * @deprecated since 2.4
830      * @see format_base::is_section_current()
831      *
832      * @param stdClass $course The course entry from DB
833      * @param stdClass $section The course_section entry from the DB
834      * @return bool true if the section is current
835      */
836     protected final function is_section_current($section, $course) {
837         debugging('Function format_section_renderer_base::is_section_current() is deprecated. '.
838                 'Use course_get_format($course)->is_section_current($section) instead', DEBUG_DEVELOPER);
839         return course_get_format($course)->is_section_current($section);
840     }