ddbfcef536c92ed6665cf7a53e8cbb81815120f1
[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     /**
42      * Generate the starting container html for a list of sections
43      * @return string HTML to output.
44      */
45     abstract protected function start_section_list();
47     /**
48      * Generate the closing container html for a list of sections
49      * @return string HTML to output.
50      */
51     abstract protected function end_section_list();
53     /**
54      * Generate the title for this section page
55      * @return string the page title
56      */
57     abstract protected function page_title();
59     /**
60      * Generate the section title
61      *
62      * @param stdClass $section The course_section entry from DB
63      * @param stdClass $course The course entry from DB
64      * @return string HTML to output.
65      */
66     public function section_title($section, $course) {
67         $title = get_section_name($course, $section);
68         if ($section->section != 0 && $course->coursedisplay == COURSE_DISPLAY_MULTIPAGE) {
69             $title = html_writer::link(course_get_url($course, $section->section), $title);
70         }
71         return $title;
72     }
74     /**
75      * Generate the content to displayed on the right part of a section
76      * before course modules are included
77      *
78      * @param stdClass $section The course_section entry from DB
79      * @param stdClass $course The course entry from DB
80      * @param bool $onsectionpage true if being printed on a section page
81      * @return string HTML to output.
82      */
83     protected function section_right_content($section, $course, $onsectionpage) {
84         $o = $this->output->spacer();
86         if ($section->section != 0) {
87             $controls = $this->section_edit_controls($course, $section, $onsectionpage);
88             if (!empty($controls)) {
89                 $o = implode('<br />', $controls);
90             }
91         }
93         return $o;
94     }
96     /**
97      * Generate the content to displayed on the left part of a section
98      * before course modules are included
99      *
100      * @param stdClass $section The course_section entry from DB
101      * @param stdClass $course The course entry from DB
102      * @param bool $onsectionpage true if being printed on a section page
103      * @return string HTML to output.
104      */
105     protected function section_left_content($section, $course, $onsectionpage) {
106         $o = $this->output->spacer();
108         if ($section->section != 0) {
109             // Only in the non-general sections.
110             if ($this->is_section_current($section, $course)) {
111                 $o = get_accesshide(get_string('currentsection', 'format_'.$course->format));
112             }
113         }
115         return $o;
116     }
118     /**
119      * Generate the display of the header part of a section before
120      * course modules are included
121      *
122      * @param stdClass $section The course_section entry from DB
123      * @param stdClass $course The course entry from DB
124      * @param bool $onsectionpage true if being printed on a single-section page
125      * @return string HTML to output.
126      */
127     protected function section_header($section, $course, $onsectionpage) {
128         global $PAGE;
130         $o = '';
131         $currenttext = '';
132         $sectionstyle = '';
134         if ($section->section != 0) {
135             // Only in the non-general sections.
136             if (!$section->visible) {
137                 $sectionstyle = ' hidden';
138             } else if ($this->is_section_current($section, $course)) {
139                 $sectionstyle = ' current';
140             }
141         }
143         $o.= html_writer::start_tag('li', array('id' => 'section-'.$section->section,
144             'class' => 'section main clearfix'.$sectionstyle));
146         $leftcontent = $this->section_left_content($section, $course, $onsectionpage);
147         $o.= html_writer::tag('div', $leftcontent, array('class' => 'left side'));
149         $rightcontent = $this->section_right_content($section, $course, $onsectionpage);
150         $o.= html_writer::tag('div', $rightcontent, array('class' => 'right side'));
151         $o.= html_writer::start_tag('div', array('class' => 'content'));
153         if (!$onsectionpage) {
154             $o.= $this->output->heading($this->section_title($section, $course), 3, 'sectionname');
155         }
157         $o.= html_writer::start_tag('div', array('class' => 'summary'));
158         $o.= $this->format_summary_text($section);
160         $context = context_course::instance($course->id);
161         if ($PAGE->user_is_editing() && has_capability('moodle/course:update', $context)) {
162             $url = new moodle_url('/course/editsection.php', array('id'=>$section->id));
164             if ($onsectionpage) {
165                 $url->param('sectionreturn', 1);
166             }
168             $o.= html_writer::link($url,
169                 html_writer::empty_tag('img', array('src' => $this->output->pix_url('t/edit'), 'class' => 'iconsmall edit')),
170                 array('title' => get_string('editsummary')));
171         }
172         $o.= html_writer::end_tag('div');
174         $o .= $this->section_availability_message($section);
176         return $o;
177     }
179     /**
180      * Generate the display of the footer part of a section
181      *
182      * @return string HTML to output.
183      */
184     protected function section_footer() {
185         $o = html_writer::end_tag('div');
186         $o.= html_writer::end_tag('li');
188         return $o;
189     }
191     /**
192      * Generate the edit controls of a section
193      *
194      * @param stdClass $course The course entry from DB
195      * @param stdClass $section The course_section entry from DB
196      * @param bool $onsectionpage true if being printed on a section page
197      * @return array of links with edit controls
198      */
199     protected function section_edit_controls($course, $section, $onsectionpage = false) {
200         global $PAGE;
202         if (!$PAGE->user_is_editing()) {
203             return array();
204         }
206         if (!has_capability('moodle/course:update', context_course::instance($course->id))) {
207             return array();
208         }
210         if ($onsectionpage) {
211             $baseurl = course_get_url($course, $section->section);
212         } else {
213             $baseurl = course_get_url($course);
214         }
215         $baseurl->param('sesskey', sesskey());
217         $controls = array();
219         $url = clone($baseurl);
220         if ($section->visible) { // Show the hide/show eye.
221             $strhidefromothers = get_string('hidefromothers', 'format_'.$course->format);
222             $url->param('hide', $section->section);
223             $controls[] = html_writer::link($url,
224                 html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/hide'),
225                 'class' => 'icon hide', 'alt' => $strhidefromothers)),
226                 array('title' => $strhidefromothers, 'class' => 'editing_showhide'));
227         } else {
228             $strshowfromothers = get_string('showfromothers', 'format_'.$course->format);
229             $url->param('show',  $section->section);
230             $controls[] = html_writer::link($url,
231                 html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/show'),
232                 'class' => 'icon hide', 'alt' => $strshowfromothers)),
233                 array('title' => $strshowfromothers, 'class' => 'editing_showhide'));
234         }
236         if (!$onsectionpage) {
237             $url = clone($baseurl);
238             if ($section->section > 1) { // Add a arrow to move section up.
239                 $url->param('section', $section->section);
240                 $url->param('move', -1);
241                 $strmoveup = get_string('moveup');
243                 $controls[] = html_writer::link($url,
244                     html_writer::empty_tag('img', array('src' => $this->output->pix_url('t/up'),
245                     'class' => 'icon up', 'alt' => $strmoveup)),
246                     array('title' => $strmoveup, 'class' => 'moveup'));
247             }
249             $url = clone($baseurl);
250             if ($section->section < $course->numsections) { // Add a arrow to move section down.
251                 $url->param('section', $section->section);
252                 $url->param('move', 1);
253                 $strmovedown =  get_string('movedown');
255                 $controls[] = html_writer::link($url,
256                     html_writer::empty_tag('img', array('src' => $this->output->pix_url('t/down'),
257                     'class' => 'icon down', 'alt' => $strmovedown)),
258                     array('title' => $strmovedown, 'class' => 'movedown'));
259             }
260         }
262         return $controls;
263     }
265     /**
266      * Generate a summary of a section for display on the 'coruse index page'
267      *
268      * @param stdClass $section The course_section entry from DB
269      * @param stdClass $course The course entry from DB
270      * @param array    $mods course modules indexed by id (from get_all_mods)
271      * @return string HTML to output.
272      */
273     protected function section_summary($section, $course, $mods) {
274         $classattr = 'section main section-summary clearfix';
275         $linkclasses = '';
277         // If section is hidden then display grey section link
278         if (!$section->visible) {
279             $classattr .= ' hidden';
280             $linkclasses .= ' dimmed_text';
281         } else if ($this->is_section_current($section, $course)) {
282             $classattr .= ' current';
283         }
285         $o = '';
286         $o .= html_writer::start_tag('li', array('id' => 'section-'.$section->section, 'class' => $classattr));
288         $o .= html_writer::tag('div', '', array('class' => 'left side'));
289         $o .= html_writer::tag('div', '', array('class' => 'right side'));
290         $o .= html_writer::start_tag('div', array('class' => 'content'));
292         $title = html_writer::tag('a', get_section_name($course, $section),
293                 array('href' => course_get_url($course, $section->section), 'class' => $linkclasses));
294         $o .= $this->output->heading($title, 3, 'section-title');
296         $o.= html_writer::start_tag('div', array('class' => 'summarytext'));
297         $o.= $this->format_summary_text($section);
298         $o.= html_writer::end_tag('div');
299         $o.= $this->section_activity_summary($section, $course, $mods);
301         $o.= $this->section_availability_message($section);
303         $o .= html_writer::end_tag('div');
304         $o .= html_writer::end_tag('li');
306         return $o;
307     }
309     /**
310      * Generate a summary of the activites in a section
311      *
312      * @param stdClass $section The course_section entry from DB
313      * @param stdClass $course the course record from DB
314      * @param array    $mods course modules indexed by id (from get_all_mods)
315      * @return string HTML to output.
316      */
317     private function section_activity_summary($section, $course, $mods) {
318         $completioninfo = new completion_info($course);
319         if (empty($section->sequence)) {
320             return '';
321         }
323         // Generate array with count of activities in this section:
324         $sectionmods = array();
325         $total = 0;
326         $complete = 0;
327         $modsequence = explode(',', $section->sequence);
328         foreach ($modsequence as $cmid) {
329             $thismod = $mods[$cmid];
331             if ($thismod->modname == 'label') {
332                 // Labels are special (not interesting for students)!
333                 continue;
334             }
336             if ($thismod->uservisible) {
337                 if (isset($sectionmods[$thismod->modname])) {
338                     $sectionmods[$thismod->modname]['count']++;
339                 } else {
340                     $sectionmods[$thismod->modname]['name'] = $thismod->modplural;
341                     $sectionmods[$thismod->modname]['count'] = 1;
342                 }
343                 if ($completioninfo->is_enabled($thismod) != COMPLETION_TRACKING_NONE && isloggedin() &&
344                                 !isguestuser() && $thismod->uservisible) {
345                     $total++;
346                     $completiondata = $completioninfo->get_data($thismod,true);
347                     if ($completiondata->completionstate == COMPLETION_COMPLETE) {
348                         $complete++;
349                     }
350                 }
351             }
352         }
354         if (empty($sectionmods)) {
355             // No sections
356             return '';
357         }
359         // Output section activities summary:
360         $o = '';
361         $o.= html_writer::start_tag('div', array('class' => 'section-summary-activities mdl-right'));
362         foreach ($sectionmods as $mod) {
363             $o.= html_writer::start_tag('span', array('class' => 'activity-count'));
364             $o.= $mod['name'].': '.$mod['count'];
365             $o.= html_writer::end_tag('span');
366         }
368         // Output section completion data
369         if ($completioninfo->is_enabled() != COMPLETION_TRACKING_NONE && isloggedin() &&
370                         !isguestuser()) {
371             $o.= html_writer::start_tag('span', array('class' => 'activity-count'));
372             $o.= get_string("completionstatus")." $complete / $total";
373             $o.= html_writer::end_tag('span');
374         }
375         $o.= html_writer::end_tag('div');
376         return $o;
377     }
379     /**
380      * If section is not visible to current user, display the message about that
381      * ('Not available until...', that sort of thing). Otherwise, returns blank.
382      *
383      * @param stdClass $section The course_section entry from DB
384      * @return string HTML to output
385      */
386     protected function section_availability_message($section) {
387         $o = '';
388         if (!$section->uservisible || $section->availableinfo) {
389             $o .= html_writer::start_tag('div', array('class' => 'availabilityinfo'));
390             if (!empty($section->availableinfo)) {
391                 $o .= $section->availableinfo;
392             } else {
393                 $o .= get_string('notavailable');
394             }
395             $o .= html_writer::end_tag('div');
396         }
397         return $o;
398     }
400     /**
401      * Show if something is on on the course clipboard (moving around)
402      *
403      * @param stdClass $course The course entry from DB
404      * @param int $sectionno The section number in the coruse which is being dsiplayed
405      * @return string HTML to output.
406      */
407     protected function course_activity_clipboard($course, $sectionno = 0) {
408         global $USER;
410         $o = '';
411         // If currently moving a file then show the current clipboard.
412         if (ismoving($course->id)) {
413             $url = new moodle_url('/course/mod.php',
414                 array('sesskey' => sesskey(),
415                       'cancelcopy' => true,
416                       'sr' => $sectionno,
417                 )
418             );
420             $o.= html_writer::start_tag('div', array('class' => 'clipboard'));
421             $o.= strip_tags(get_string('activityclipboard', '', $USER->activitycopyname));
422             $o.= ' ('.html_writer::link($url, get_string('cancel')).')';
423             $o.= html_writer::end_tag('div');
424         }
426         return $o;
427     }
429     /**
430      * Generate next/previous section links for naviation
431      *
432      * @param stdClass $course The course entry from DB
433      * @param array $sections The course_sections entries from the DB
434      * @param int $sectionno The section number in the coruse which is being dsiplayed
435      * @return array associative array with previous and next section link
436      */
437     protected function get_nav_links($course, $sections, $sectionno) {
438         // FIXME: This is really evil and should by using the navigation API.
439         $canviewhidden = has_capability('moodle/course:viewhiddensections', context_course::instance($course->id))
440             or !$course->hiddensections;
442         $links = array('previous' => '', 'next' => '');
443         $back = $sectionno - 1;
444         while ($back > 0 and empty($links['previous'])) {
445             if ($canviewhidden || $sections[$back]->visible) {
446                 $params = array();
447                 if (!$sections[$back]->visible) {
448                     $params = array('class' => 'dimmed_text');
449                 }
450                 $previouslink = html_writer::tag('span', $this->output->larrow(), array('class' => 'larrow'));
451                 $previouslink .= get_section_name($course, $sections[$back]);
452                 $links['previous'] = html_writer::link(course_get_url($course, $back), $previouslink, $params);
453             }
454             $back--;
455         }
457         $forward = $sectionno + 1;
458         while ($forward <= $course->numsections and empty($links['next'])) {
459             if ($canviewhidden || $sections[$forward]->visible) {
460                 $params = array();
461                 if (!$sections[$forward]->visible) {
462                     $params = array('class' => 'dimmed_text');
463                 }
464                 $nextlink = get_section_name($course, $sections[$forward]);
465                 $nextlink .= html_writer::tag('span', $this->output->rarrow(), array('class' => 'rarrow'));
466                 $links['next'] = html_writer::link(course_get_url($course, $forward), $nextlink, $params);
467             }
468             $forward++;
469         }
471         return $links;
472     }
474     /**
475      * Generate the header html of a stealth section
476      *
477      * @param int $sectionno The section number in the coruse which is being dsiplayed
478      * @return string HTML to output.
479      */
480     protected function stealth_section_header($sectionno) {
481         $o = '';
482         $o.= html_writer::start_tag('li', array('id' => 'section-'.$sectionno, 'class' => 'section main clearfix orphaned hidden'));
483         $o.= html_writer::tag('div', '', array('class' => 'left side'));
484         $o.= html_writer::tag('div', '', array('class' => 'right side'));
485         $o.= html_writer::start_tag('div', array('class' => 'content'));
486         $o.= $this->output->heading(get_string('orphanedactivities'), 3, 'sectionname');
487         return $o;
488     }
490     /**
491      * Generate footer html of a stealth section
492      *
493      * @return string HTML to output.
494      */
495     protected function stealth_section_footer() {
496         $o = html_writer::end_tag('div');
497         $o.= html_writer::end_tag('li');
498         return $o;
499     }
501     /**
502      * Generate the html for a hidden section
503      *
504      * @param int $sectionno The section number in the coruse which is being dsiplayed
505      * @return string HTML to output.
506      */
507     protected function section_hidden($sectionno) {
508         $o = '';
509         $o.= html_writer::start_tag('li', array('id' => 'section-'.$sectionno, 'class' => 'section main clearfix hidden'));
510         $o.= html_writer::tag('div', '', array('class' => 'left side'));
511         $o.= html_writer::tag('div', '', array('class' => 'right side'));
512         $o.= html_writer::start_tag('div', array('class' => 'content'));
513         $o.= get_string('notavailable');
514         $o.= html_writer::end_tag('div');
515         $o.= html_writer::end_tag('li');
516         return $o;
517     }
519     /**
520      * Output the html for a single section page .
521      *
522      * @param stdClass $course The course entry from DB
523      * @param array $sections The course_sections entries from the DB
524      * @param array $mods used for print_section()
525      * @param array $modnames used for print_section()
526      * @param array $modnamesused used for print_section()
527      * @param int $displaysection The section number in the course which is being displayed
528      */
529     public function print_single_section_page($course, $sections, $mods, $modnames, $modnamesused, $displaysection) {
530         global $PAGE;
532         // Can we view the section in question?
533         $context = context_course::instance($course->id);
534         $canviewhidden = has_capability('moodle/course:viewhiddensections', $context);
536         if (!isset($sections[$displaysection])) {
537             // This section doesn't exist
538             print_error('unknowncoursesection', 'error', null, $course->fullname);
539             return;
540         }
542         if (!$sections[$displaysection]->visible && !$canviewhidden) {
543             if (!$course->hiddensections) {
544                 echo $this->start_section_list();
545                 echo $this->section_hidden($displaysection);
546                 echo $this->end_section_list();
547             }
548             // Can't view this section.
549             return;
550         }
552         // Copy activity clipboard..
553         echo $this->course_activity_clipboard($course, $displaysection);
555         // General section if non-empty.
556         $thissection = $sections[0];
557         if ($thissection->summary or $thissection->sequence or $PAGE->user_is_editing()) {
558             echo $this->start_section_list();
559             echo $this->section_header($thissection, $course, true);
560             print_section($course, $thissection, $mods, $modnamesused, true);
561             if ($PAGE->user_is_editing()) {
562                 print_section_add_menus($course, 0, $modnames, false, false, true);
563             }
564             echo $this->section_footer();
565             echo $this->end_section_list();
566         }
568         // Start single-section div
569         echo html_writer::start_tag('div', array('class' => 'single-section'));
571         // Title with section navigation links.
572         $sectionnavlinks = $this->get_nav_links($course, $sections, $displaysection);
573         $sectiontitle = '';
574         $sectiontitle .= html_writer::start_tag('div', array('class' => 'section-navigation header headingblock'));
575         $sectiontitle .= html_writer::tag('span', $sectionnavlinks['previous'], array('class' => 'mdl-left'));
576         $sectiontitle .= html_writer::tag('span', $sectionnavlinks['next'], array('class' => 'mdl-right'));
577         // Title attributes
578         $titleattr = 'mdl-align title';
579         if (!$sections[$displaysection]->visible) {
580             $titleattr .= ' dimmed_text';
581         }
582         $sectiontitle .= html_writer::tag('div', get_section_name($course, $sections[$displaysection]), array('class' => $titleattr));
583         $sectiontitle .= html_writer::end_tag('div');
584         echo $sectiontitle;
586         // Now the list of sections..
587         echo $this->start_section_list();
589         // The requested section page.
590         $thissection = $sections[$displaysection];
591         echo $this->section_header($thissection, $course, true);
592         // Show completion help icon.
593         $completioninfo = new completion_info($course);
594         echo $completioninfo->display_help_icon();
596         print_section($course, $thissection, $mods, $modnamesused, true, '100%', false, true);
597         if ($PAGE->user_is_editing()) {
598             print_section_add_menus($course, $displaysection, $modnames, false, false, true);
599         }
600         echo $this->section_footer();
601         echo $this->end_section_list();
603         // Display section bottom navigation.
604         $courselink = html_writer::link(course_get_url($course), get_string('returntomaincoursepage'));
605         $sectionbottomnav = '';
606         $sectionbottomnav .= html_writer::start_tag('div', array('class' => 'section-navigation mdl-bottom'));
607         $sectionbottomnav .= html_writer::tag('span', $sectionnavlinks['previous'], array('class' => 'mdl-left'));
608         $sectionbottomnav .= html_writer::tag('span', $sectionnavlinks['next'], array('class' => 'mdl-right'));
609         $sectionbottomnav .= html_writer::tag('div', $courselink, array('class' => 'mdl-align'));
610         $sectionbottomnav .= html_writer::end_tag('div');
611         echo $sectionbottomnav;
613         // close single-section div.
614         echo html_writer::end_tag('div');
615     }
617     /**
618      * Output the html for a multiple section page
619      *
620      * @param stdClass $course The course entry from DB
621      * @param array $sections The course_sections entries from the DB
622      * @param array $mods used for print_section()
623      * @param array $modnames used for print_section()
624      * @param array $modnamesused used for print_section()
625      */
626     public function print_multiple_section_page($course, $sections, $mods, $modnames, $modnamesused) {
627         global $PAGE;
629         $context = context_course::instance($course->id);
630         // Title with completion help icon.
631         $completioninfo = new completion_info($course);
632         echo $completioninfo->display_help_icon();
633         echo $this->output->heading($this->page_title(), 2, 'accesshide');
635         // Copy activity clipboard..
636         echo $this->course_activity_clipboard($course);
638         // Now the list of sections..
639         echo $this->start_section_list();
641         // General section if non-empty.
642         $thissection = $sections[0];
643         unset($sections[0]);
644         if ($thissection->summary or $thissection->sequence or $PAGE->user_is_editing()) {
645             echo $this->section_header($thissection, $course, true);
646             print_section($course, $thissection, $mods, $modnamesused, true);
647             if ($PAGE->user_is_editing()) {
648                 print_section_add_menus($course, 0, $modnames);
649             }
650             echo $this->section_footer();
651         }
653         $canviewhidden = has_capability('moodle/course:viewhiddensections', $context);
654         for ($section = 1; $section <= $course->numsections; $section++) {
655             if (!empty($sections[$section])) {
656                 $thissection = $sections[$section];
657             } else {
658                 // This will create a course section if it doesn't exist..
659                 $thissection = get_course_section($section, $course->id);
661                 // The returned section is only a bare database object rather than
662                 // a section_info object - we will need at least the uservisible
663                 // field in it.
664                 $thissection->uservisible = true;
665                 $thissection->availableinfo = null;
666                 $thissection->showavailability = 0;
667             }
668             // Show the section if the user is permitted to access it, OR if it's not available
669             // but showavailability is turned on
670             $showsection = $thissection->uservisible ||
671                     ($thissection->visible && !$thissection->available && $thissection->showavailability);
672             if (!$showsection) {
673                 // Hidden section message is overridden by 'unavailable' control
674                 // (showavailability option).
675                 if (!$course->hiddensections && $thissection->available) {
676                     echo $this->section_hidden($section);
677                 }
679                 unset($sections[$section]);
680                 continue;
681             }
683             if (!$PAGE->user_is_editing() && $course->coursedisplay == COURSE_DISPLAY_MULTIPAGE) {
684                 // Display section summary only.
685                 echo $this->section_summary($thissection, $course, $mods);
686             } else {
687                 echo $this->section_header($thissection, $course, false);
688                 if ($thissection->uservisible) {
689                     print_section($course, $thissection, $mods, $modnamesused);
690                     if ($PAGE->user_is_editing()) {
691                         print_section_add_menus($course, $section, $modnames);
692                     }
693                 }
694                 echo $this->section_footer();
695             }
697             unset($sections[$section]);
698         }
700         if ($PAGE->user_is_editing() and has_capability('moodle/course:update', $context)) {
701             // Print stealth sections if present.
702             $modinfo = get_fast_modinfo($course);
703             foreach ($sections as $section => $thissection) {
704                 if (empty($modinfo->sections[$section])) {
705                     continue;
706                 }
707                 echo $this->stealth_section_header($section);
708                 print_section($course, $thissection, $mods, $modnamesused);
709                 echo $this->stealth_section_footer();
710             }
712             echo $this->end_section_list();
714             echo html_writer::start_tag('div', array('id' => 'changenumsections', 'class' => 'mdl-right'));
716             // Increase number of sections.
717             $straddsection = get_string('increasesections', 'moodle');
718             $url = new moodle_url('/course/changenumsections.php',
719                 array('courseid' => $course->id,
720                       'increase' => true,
721                       'sesskey' => sesskey()));
722             $icon = $this->output->pix_icon('t/switch_plus', $straddsection);
723             echo html_writer::link($url, $icon.get_accesshide($straddsection), array('class' => 'increase-sections'));
725             if ($course->numsections > 0) {
726                 // Reduce number of sections sections.
727                 $strremovesection = get_string('reducesections', 'moodle');
728                 $url = new moodle_url('/course/changenumsections.php',
729                     array('courseid' => $course->id,
730                           'increase' => false,
731                           'sesskey' => sesskey()));
732                 $icon = $this->output->pix_icon('t/switch_minus', $strremovesection);
733                 echo html_writer::link($url, $icon.get_accesshide($strremovesection), array('class' => 'reduce-sections'));
734             }
736             echo html_writer::end_tag('div');
737         } else {
738             echo $this->end_section_list();
739         }
741     }
743     /**
744      * Generate html for a section summary text
745      *
746      * @param stdClass $section The course_section entry from DB
747      * @return string HTML to output.
748      */
749     protected function format_summary_text($section) {
750         $context = context_course::instance($section->course);
751         $summarytext = file_rewrite_pluginfile_urls($section->summary, 'pluginfile.php',
752             $context->id, 'course', 'section', $section->id);
754         $options = new stdClass();
755         $options->noclean = true;
756         $options->overflowdiv = true;
757         return format_text($summarytext, $section->summaryformat, $options);
758     }
760     /**
761      * Is the section passed in the current section? (Note this isn't strictly
762      * a renderering method, but neater here).
763      *
764      * @param stdClass $course The course entry from DB
765      * @param stdClass $section The course_section entry from the DB
766      * @return bool true if the section is current
767      */
768     protected function is_section_current($section, $course) {
769         return ($course->marker == $section->section);
770     }