Commit | Line | Data |
---|---|---|
24e27ac0 SH |
1 | <?php |
2 | ||
3 | // This file is part of Moodle - http://moodle.org/ | |
4 | // | |
5 | // Moodle is free software: you can redistribute it and/or modify | |
6 | // it under the terms of the GNU General Public License as published by | |
7 | // the Free Software Foundation, either version 3 of the License, or | |
8 | // (at your option) any later version. | |
9 | // | |
10 | // Moodle is distributed in the hope that it will be useful, | |
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | // GNU General Public License for more details. | |
14 | // | |
15 | // You should have received a copy of the GNU General Public License | |
16 | // along with Moodle. If not, see <http://www.gnu.org/licenses/>. | |
17 | ||
18 | /** | |
19 | * Renderer for use with the course section and all the goodness that falls | |
20 | * within it. | |
21 | * | |
22 | * This renderer should contain methods useful to courses, and categories. | |
23 | * | |
24 | * @package moodlecore | |
25 | * @copyright 2010 Sam Hemelryk | |
26 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
27 | */ | |
28 | ||
29 | /** | |
30 | * The core course renderer | |
31 | * | |
32 | * Can be retrieved with the following: | |
33 | * $renderer = $PAGE->get_renderer('core','course'); | |
34 | */ | |
35 | class core_course_renderer extends plugin_renderer_base { | |
36 | ||
37 | /** | |
38 | * A cache of strings | |
39 | * @var stdClass | |
40 | */ | |
41 | protected $strings; | |
42 | ||
43 | /** | |
44 | * Override the constructor so that we can initialise the string cache | |
45 | * | |
46 | * @param moodle_page $page | |
47 | * @param string $target | |
48 | */ | |
49 | public function __construct(moodle_page $page, $target) { | |
50 | $this->strings = new stdClass; | |
51 | parent::__construct($page, $target); | |
a03dfb7d MG |
52 | $this->add_modchoosertoggle(); |
53 | } | |
54 | ||
55 | /** | |
56 | * Adds the item in course settings navigation to toggle modchooser | |
57 | * | |
58 | * Theme can overwrite as an empty function to exclude it (for example if theme does not | |
59 | * use modchooser at all) | |
60 | */ | |
61 | protected function add_modchoosertoggle() { | |
62 | global $CFG; | |
63 | static $modchoosertoggleadded = false; | |
64 | // Add the module chooser toggle to the course page | |
65 | if ($modchoosertoggleadded || $this->page->state > moodle_page::STATE_PRINTING_HEADER || | |
66 | $this->page->course->id == SITEID || | |
aa2b293e MG |
67 | !$this->page->user_is_editing() || |
68 | !($context = context_course::instance($this->page->course->id)) || | |
69 | !has_capability('moodle/course:update', $context) || | |
70 | !course_ajax_enabled($this->page->course) || | |
71 | !($coursenode = $this->page->settingsnav->find('courseadmin', navigation_node::TYPE_COURSE)) || | |
72 | !$coursenode->get('editsettings')) { | |
a03dfb7d | 73 | // too late or we are on site page or we could not find the course settings node |
aa2b293e | 74 | // or we are not allowed to edit |
a03dfb7d MG |
75 | return; |
76 | } | |
77 | $modchoosertoggleadded = true; | |
78 | if ($this->page->url->compare(new moodle_url('/course/view.php'), URL_MATCH_BASE)) { | |
79 | // We are on the course page, retain the current page params e.g. section. | |
80 | $modchoosertoggleurl = clone($this->page->url); | |
81 | } else { | |
82 | // Edit on the main course page. | |
83 | $modchoosertoggleurl = new moodle_url('/course/view.php', array('id' => $this->page->course->id, | |
84 | 'return' => $this->page->url->out_as_local_url(false))); | |
85 | } | |
86 | $modchoosertoggleurl->param('sesskey', sesskey()); | |
87 | if ($usemodchooser = get_user_preferences('usemodchooser', $CFG->modchooserdefault)) { | |
88 | $modchoosertogglestring = get_string('modchooserdisable', 'moodle'); | |
89 | $modchoosertoggleurl->param('modchooser', 'off'); | |
90 | } else { | |
91 | $modchoosertogglestring = get_string('modchooserenable', 'moodle'); | |
92 | $modchoosertoggleurl->param('modchooser', 'on'); | |
93 | } | |
94 | $modchoosertoggle = navigation_node::create($modchoosertogglestring, $modchoosertoggleurl, navigation_node::TYPE_SETTING); | |
95 | $coursenode->add_node($modchoosertoggle, 'editsettings'); | |
96 | $modchoosertoggle->add_class('modchoosertoggle'); | |
97 | $modchoosertoggle->add_class('visibleifjs'); | |
98 | user_preference_allow_ajax_update('usemodchooser', PARAM_BOOL); | |
24e27ac0 SH |
99 | } |
100 | ||
cb76fec0 PS |
101 | /** |
102 | * Renders course info box. | |
103 | * | |
104 | * @param stdClass $course | |
105 | * @return string | |
106 | */ | |
107 | public function course_info_box(stdClass $course) { | |
108 | global $CFG; | |
109 | ||
110 | $context = context_course::instance($course->id); | |
111 | ||
112 | $content = ''; | |
113 | $content .= $this->output->box_start('generalbox info'); | |
114 | ||
115 | $summary = file_rewrite_pluginfile_urls($course->summary, 'pluginfile.php', $context->id, 'course', 'summary', null); | |
116 | $content .= format_text($summary, $course->summaryformat, array('overflowdiv'=>true), $course->id); | |
117 | if (!empty($CFG->coursecontact)) { | |
118 | $coursecontactroles = explode(',', $CFG->coursecontact); | |
119 | foreach ($coursecontactroles as $roleid) { | |
49ee37d3 | 120 | if ($users = get_role_users($roleid, $context, true, '', null, false)) { |
cb76fec0 PS |
121 | foreach ($users as $teacher) { |
122 | $role = new stdClass(); | |
123 | $role->id = $teacher->roleid; | |
124 | $role->name = $teacher->rolename; | |
125 | $role->shortname = $teacher->roleshortname; | |
126 | $role->coursealias = $teacher->rolecoursealias; | |
127 | $fullname = fullname($teacher, has_capability('moodle/site:viewfullnames', $context)); | |
128 | $namesarray[] = role_get_name($role, $context).': <a href="'.$CFG->wwwroot.'/user/view.php?id='. | |
129 | $teacher->id.'&course='.SITEID.'">'.$fullname.'</a>'; | |
130 | } | |
131 | } | |
132 | } | |
133 | ||
134 | if (!empty($namesarray)) { | |
135 | $content .= "<ul class=\"teachers\">\n<li>"; | |
136 | $content .= implode('</li><li>', $namesarray); | |
137 | $content .= "</li></ul>"; | |
138 | } | |
139 | } | |
140 | ||
141 | $content .= $this->output->box_end(); | |
142 | ||
143 | return $content; | |
144 | } | |
145 | ||
24e27ac0 SH |
146 | /** |
147 | * Renderers a structured array of courses and categories into a nice | |
148 | * XHTML tree structure. | |
149 | * | |
150 | * This method was designed initially to display the front page course/category | |
151 | * combo view. The structure can be retrieved by get_course_category_tree() | |
152 | * | |
153 | * @param array $structure | |
154 | * @return string | |
155 | */ | |
156 | public function course_category_tree(array $structure) { | |
24e27ac0 SH |
157 | $this->strings->summary = get_string('summary'); |
158 | ||
159 | // Generate an id and the required JS call to make this a nice widget | |
160 | $id = html_writer::random_id('course_category_tree'); | |
c8ffba95 | 161 | $this->page->requires->js_init_call('M.util.init_toggle_class_on_click', array($id, '.category.with_children .category_label', 'collapsed', '.category.with_children')); |
24e27ac0 SH |
162 | |
163 | // Start content generation | |
164 | $content = html_writer::start_tag('div', array('class'=>'course_category_tree', 'id'=>$id)); | |
165 | foreach ($structure as $category) { | |
166 | $content .= $this->course_category_tree_category($category); | |
167 | } | |
168 | $content .= html_writer::start_tag('div', array('class'=>'controls')); | |
169 | $content .= html_writer::tag('div', get_string('collapseall'), array('class'=>'addtoall expandall')); | |
170 | $content .= html_writer::tag('div', get_string('expandall'), array('class'=>'removefromall collapseall')); | |
171 | $content .= html_writer::end_tag('div'); | |
172 | $content .= html_writer::end_tag('div'); | |
df997f84 | 173 | |
24e27ac0 SH |
174 | // Return the course category tree HTML |
175 | return $content; | |
176 | } | |
177 | ||
178 | /** | |
179 | * Renderers a category for use with course_category_tree | |
180 | * | |
181 | * @param array $category | |
182 | * @param int $depth | |
183 | * @return string | |
184 | */ | |
185 | protected function course_category_tree_category(stdClass $category, $depth=1) { | |
186 | $content = ''; | |
3754f4f3 ARN |
187 | $hassubcategories = (isset($category->categories) && count($category->categories)>0); |
188 | $hascourses = (isset($category->courses) && count($category->courses)>0); | |
24e27ac0 SH |
189 | $classes = array('category'); |
190 | if ($category->parent != 0) { | |
191 | $classes[] = 'subcategory'; | |
192 | } | |
d703f226 SH |
193 | if (empty($category->visible)) { |
194 | $classes[] = 'dimmed_category'; | |
195 | } | |
24e27ac0 SH |
196 | if ($hassubcategories || $hascourses) { |
197 | $classes[] = 'with_children'; | |
198 | if ($depth > 1) { | |
199 | $classes[] = 'collapsed'; | |
200 | } | |
201 | } | |
9a5e297b | 202 | $categoryname = format_string($category->name, true, array('context' => context_coursecat::instance($category->id))); |
63390481 | 203 | |
24e27ac0 SH |
204 | $content .= html_writer::start_tag('div', array('class'=>join(' ', $classes))); |
205 | $content .= html_writer::start_tag('div', array('class'=>'category_label')); | |
63390481 | 206 | $content .= html_writer::link(new moodle_url('/course/category.php', array('id'=>$category->id)), $categoryname, array('class'=>'category_link')); |
24e27ac0 SH |
207 | $content .= html_writer::end_tag('div'); |
208 | if ($hassubcategories) { | |
209 | $content .= html_writer::start_tag('div', array('class'=>'subcategories')); | |
210 | foreach ($category->categories as $subcategory) { | |
211 | $content .= $this->course_category_tree_category($subcategory, $depth+1); | |
212 | } | |
213 | $content .= html_writer::end_tag('div'); | |
214 | } | |
215 | if ($hascourses) { | |
216 | $content .= html_writer::start_tag('div', array('class'=>'courses')); | |
217 | $coursecount = 0; | |
6a1273cb | 218 | $strinfo = new lang_string('info'); |
24e27ac0 SH |
219 | foreach ($category->courses as $course) { |
220 | $classes = array('course'); | |
d2fd38be PS |
221 | $linkclass = 'course_link'; |
222 | if (!$course->visible) { | |
223 | $linkclass .= ' dimmed'; | |
224 | } | |
24e27ac0 SH |
225 | $coursecount ++; |
226 | $classes[] = ($coursecount%2)?'odd':'even'; | |
227 | $content .= html_writer::start_tag('div', array('class'=>join(' ', $classes))); | |
f4c23f03 | 228 | $content .= html_writer::link(new moodle_url('/course/view.php', array('id'=>$course->id)), format_string($course->fullname), array('class'=>$linkclass)); |
24e27ac0 SH |
229 | $content .= html_writer::start_tag('div', array('class'=>'course_info clearfix')); |
230 | ||
bf423bb1 PS |
231 | // print enrol info |
232 | if ($icons = enrol_get_course_info_icons($course)) { | |
233 | foreach ($icons as $pix_icon) { | |
234 | $content .= $this->render($pix_icon); | |
235 | } | |
236 | } | |
237 | ||
24e27ac0 | 238 | if ($course->summary) { |
6a1273cb | 239 | $url = new moodle_url('/course/info.php', array('id' => $course->id)); |
24e27ac0 | 240 | $image = html_writer::empty_tag('img', array('src'=>$this->output->pix_url('i/info'), 'alt'=>$this->strings->summary)); |
6a1273cb | 241 | $content .= $this->action_link($url, $image, new popup_action('click', $url, 'courseinfo'), array('title' => $this->strings->summary)); |
24e27ac0 SH |
242 | } |
243 | $content .= html_writer::end_tag('div'); | |
244 | $content .= html_writer::end_tag('div'); | |
245 | } | |
246 | $content .= html_writer::end_tag('div'); | |
247 | } | |
248 | $content .= html_writer::end_tag('div'); | |
249 | return $content; | |
250 | } | |
01e0e704 ARN |
251 | |
252 | /** | |
253 | * Build the HTML for the module chooser javascript popup | |
254 | * | |
255 | * @param array $modules A set of modules as returned form @see | |
256 | * get_module_metadata | |
257 | * @param object $course The course that will be displayed | |
258 | * @return string The composed HTML for the module | |
259 | */ | |
260 | public function course_modchooser($modules, $course) { | |
697ff999 MG |
261 | static $isdisplayed = false; |
262 | if ($isdisplayed) { | |
263 | return ''; | |
264 | } | |
265 | $isdisplayed = true; | |
266 | ||
267 | // Add the module chooser | |
268 | $this->page->requires->yui_module('moodle-course-modchooser', | |
269 | 'M.course.init_chooser', | |
270 | array(array('courseid' => $course->id, 'closeButtonTitle' => get_string('close', 'editor'))) | |
271 | ); | |
272 | $this->page->requires->strings_for_js(array( | |
273 | 'addresourceoractivity', | |
274 | 'modchooserenable', | |
275 | 'modchooserdisable', | |
276 | ), 'moodle'); | |
01e0e704 ARN |
277 | |
278 | // Add the header | |
1edff8c7 | 279 | $header = html_writer::tag('div', get_string('addresourceoractivity', 'moodle'), |
255dd8d1 | 280 | array('class' => 'hd choosertitle')); |
01e0e704 ARN |
281 | |
282 | $formcontent = html_writer::start_tag('form', array('action' => new moodle_url('/course/jumpto.php'), | |
283 | 'id' => 'chooserform', 'method' => 'post')); | |
284 | $formcontent .= html_writer::start_tag('div', array('id' => 'typeformdiv')); | |
285 | $formcontent .= html_writer::tag('input', '', array('type' => 'hidden', 'id' => 'course', | |
286 | 'name' => 'course', 'value' => $course->id)); | |
287 | $formcontent .= html_writer::tag('input', '', | |
0a2fb910 | 288 | array('type' => 'hidden', 'class' => 'jump', 'name' => 'jump', 'value' => '')); |
01e0e704 ARN |
289 | $formcontent .= html_writer::tag('input', '', array('type' => 'hidden', 'name' => 'sesskey', |
290 | 'value' => sesskey())); | |
291 | $formcontent .= html_writer::end_tag('div'); | |
292 | ||
293 | // Put everything into one tag 'options' | |
294 | $formcontent .= html_writer::start_tag('div', array('class' => 'options')); | |
295 | $formcontent .= html_writer::tag('div', get_string('selectmoduletoviewhelp', 'moodle'), | |
296 | array('class' => 'instruction')); | |
297 | // Put all options into one tag 'alloptions' to allow us to handle scrolling | |
298 | $formcontent .= html_writer::start_tag('div', array('class' => 'alloptions')); | |
299 | ||
5035ed63 MA |
300 | // Activities |
301 | $activities = array_filter($modules, function($mod) { | |
302 | return ($mod->archetype !== MOD_ARCHETYPE_RESOURCE && $mod->archetype !== MOD_ARCHETYPE_SYSTEM); | |
303 | }); | |
01e0e704 ARN |
304 | if (count($activities)) { |
305 | $formcontent .= $this->course_modchooser_title('activities'); | |
306 | $formcontent .= $this->course_modchooser_module_types($activities); | |
307 | } | |
308 | ||
463ccee1 | 309 | // Resources |
5035ed63 MA |
310 | $resources = array_filter($modules, function($mod) { |
311 | return ($mod->archetype === MOD_ARCHETYPE_RESOURCE); | |
312 | }); | |
48a5e55e ARN |
313 | if (count($resources)) { |
314 | $formcontent .= $this->course_modchooser_title('resources'); | |
315 | $formcontent .= $this->course_modchooser_module_types($resources); | |
316 | } | |
317 | ||
01e0e704 ARN |
318 | $formcontent .= html_writer::end_tag('div'); // modoptions |
319 | $formcontent .= html_writer::end_tag('div'); // types | |
320 | ||
321 | $formcontent .= html_writer::start_tag('div', array('class' => 'submitbuttons')); | |
af75421c | 322 | $formcontent .= html_writer::tag('input', '', |
0a2fb910 | 323 | array('type' => 'submit', 'name' => 'submitbutton', 'class' => 'submitbutton', 'value' => get_string('add'))); |
8ff6c5ee | 324 | $formcontent .= html_writer::tag('input', '', |
0a2fb910 | 325 | array('type' => 'submit', 'name' => 'addcancel', 'class' => 'addcancel', 'value' => get_string('cancel'))); |
01e0e704 ARN |
326 | $formcontent .= html_writer::end_tag('div'); |
327 | $formcontent .= html_writer::end_tag('form'); | |
328 | ||
329 | // Wrap the whole form in a div | |
330 | $formcontent = html_writer::tag('div', $formcontent, array('id' => 'chooseform')); | |
331 | ||
332 | // Put all of the content together | |
333 | $content = $formcontent; | |
334 | ||
255dd8d1 ARN |
335 | $content = html_writer::tag('div', $content, array('class' => 'choosercontainer')); |
336 | return $header . html_writer::tag('div', $content, array('class' => 'chooserdialoguebody')); | |
01e0e704 ARN |
337 | } |
338 | ||
339 | /** | |
340 | * Build the HTML for a specified set of modules | |
341 | * | |
342 | * @param array $modules A set of modules as used by the | |
343 | * course_modchooser_module function | |
344 | * @return string The composed HTML for the module | |
345 | */ | |
346 | protected function course_modchooser_module_types($modules) { | |
347 | $return = ''; | |
348 | foreach ($modules as $module) { | |
349 | if (!isset($module->types)) { | |
350 | $return .= $this->course_modchooser_module($module); | |
351 | } else { | |
352 | $return .= $this->course_modchooser_module($module, array('nonoption')); | |
353 | foreach ($module->types as $type) { | |
354 | $return .= $this->course_modchooser_module($type, array('option', 'subtype')); | |
355 | } | |
356 | } | |
357 | } | |
358 | return $return; | |
359 | } | |
360 | ||
361 | /** | |
362 | * Return the HTML for the specified module adding any required classes | |
363 | * | |
364 | * @param object $module An object containing the title, and link. An | |
365 | * icon, and help text may optionally be specified. If the module | |
366 | * contains subtypes in the types option, then these will also be | |
367 | * displayed. | |
368 | * @param array $classes Additional classes to add to the encompassing | |
369 | * div element | |
370 | * @return string The composed HTML for the module | |
371 | */ | |
372 | protected function course_modchooser_module($module, $classes = array('option')) { | |
373 | $output = ''; | |
374 | $output .= html_writer::start_tag('div', array('class' => implode(' ', $classes))); | |
375 | $output .= html_writer::start_tag('label', array('for' => 'module_' . $module->name)); | |
376 | if (!isset($module->types)) { | |
377 | $output .= html_writer::tag('input', '', array('type' => 'radio', | |
378 | 'name' => 'jumplink', 'id' => 'module_' . $module->name, 'value' => $module->link)); | |
379 | } | |
380 | ||
381 | $output .= html_writer::start_tag('span', array('class' => 'modicon')); | |
382 | if (isset($module->icon)) { | |
383 | // Add an icon if we have one | |
384 | $output .= $module->icon; | |
385 | } | |
386 | $output .= html_writer::end_tag('span'); | |
387 | ||
388 | $output .= html_writer::tag('span', $module->title, array('class' => 'typename')); | |
389 | if (!isset($module->help)) { | |
390 | // Add help if found | |
391 | $module->help = get_string('nohelpforactivityorresource', 'moodle'); | |
392 | } | |
393 | ||
394 | // Format the help text using markdown with the following options | |
395 | $options = new stdClass(); | |
396 | $options->trusted = false; | |
397 | $options->noclean = false; | |
398 | $options->smiley = false; | |
399 | $options->filter = false; | |
400 | $options->para = true; | |
401 | $options->newlines = false; | |
402 | $options->overflowdiv = false; | |
403 | $module->help = format_text($module->help, FORMAT_MARKDOWN, $options); | |
404 | $output .= html_writer::tag('span', $module->help, array('class' => 'typesummary')); | |
405 | $output .= html_writer::end_tag('label'); | |
406 | $output .= html_writer::end_tag('div'); | |
407 | ||
408 | return $output; | |
409 | } | |
410 | ||
411 | protected function course_modchooser_title($title, $identifier = null) { | |
412 | $module = new stdClass(); | |
413 | $module->name = $title; | |
414 | $module->types = array(); | |
415 | $module->title = get_string($title, $identifier); | |
416 | $module->help = ''; | |
417 | return $this->course_modchooser_module($module, array('moduletypetitle')); | |
418 | } | |
f558b291 MG |
419 | |
420 | /** | |
421 | * Renders HTML for displaying the sequence of course module editing buttons | |
422 | * | |
423 | * @see course_get_cm_edit_actions() | |
424 | * | |
425 | * @param array $actions array of action_link or pix_icon objects | |
426 | * @return string | |
427 | */ | |
428 | public function course_section_cm_edit_actions($actions) { | |
429 | $output = html_writer::start_tag('span', array('class' => 'commands')); | |
430 | foreach ($actions as $action) { | |
431 | if ($action instanceof renderable) { | |
432 | $output .= $this->output->render($action); | |
433 | } else { | |
434 | $output .= $action; | |
435 | } | |
436 | } | |
437 | $output .= html_writer::end_tag('span'); | |
438 | return $output; | |
439 | } | |
9a6aa5c1 MG |
440 | |
441 | /** | |
442 | * Renders HTML for the menus to add activities and resources to the current course | |
443 | * | |
a03dfb7d MG |
444 | * Note, if theme overwrites this function and it does not use modchooser, |
445 | * see also {@link core_course_renderer::add_modchoosertoggle()} | |
446 | * | |
9a6aa5c1 MG |
447 | * @param stdClass $course |
448 | * @param int $section relative section number (field course_sections.section) | |
449 | * @param int $sectionreturn The section to link back to | |
450 | * @param array $displayoptions additional display options, for example blocks add | |
451 | * option 'inblock' => true, suggesting to display controls vertically | |
452 | * @return string | |
453 | */ | |
454 | function course_section_add_cm_control($course, $section, $sectionreturn = null, $displayoptions = array()) { | |
455 | global $CFG; | |
456 | ||
457 | $vertical = !empty($displayoptions['inblock']); | |
458 | ||
459 | // check to see if user can add menus and there are modules to add | |
460 | if (!has_capability('moodle/course:manageactivities', context_course::instance($course->id)) | |
461 | || !$this->page->user_is_editing() | |
462 | || !($modnames = get_module_types_names()) || empty($modnames)) { | |
463 | return ''; | |
464 | } | |
465 | ||
466 | // Retrieve all modules with associated metadata | |
467 | $modules = get_module_metadata($course, $modnames, $sectionreturn); | |
468 | $urlparams = array('section' => $section); | |
469 | ||
470 | // We'll sort resources and activities into two lists | |
471 | $activities = array(MOD_CLASS_ACTIVITY => array(), MOD_CLASS_RESOURCE => array()); | |
472 | ||
473 | foreach ($modules as $module) { | |
474 | if (!array_key_exists($module->archetype, $activities)) { | |
475 | // System modules cannot be added by user, do not add to dropdown | |
476 | } else if (isset($module->types)) { | |
477 | // This module has a subtype | |
478 | // NOTE: this is legacy stuff, module subtypes are very strongly discouraged!! | |
479 | $subtypes = array(); | |
480 | foreach ($module->types as $subtype) { | |
481 | $link = $subtype->link->out(true, $urlparams); | |
482 | $subtypes[$link] = $subtype->title; | |
483 | } | |
484 | ||
485 | // Sort module subtypes into the list | |
486 | if (!empty($module->title)) { | |
487 | // This grouping has a name | |
488 | $activities[$module->archetype][] = array($module->title => $subtypes); | |
489 | } else { | |
490 | // This grouping does not have a name | |
491 | $activities[$module->archetype] = array_merge($activities[$module->archetype], $subtypes); | |
492 | } | |
493 | } else { | |
494 | // This module has no subtypes | |
495 | $link = $module->link->out(true, $urlparams); | |
496 | $activities[$module->archetype][$link] = $module->title; | |
497 | } | |
498 | } | |
499 | ||
500 | $straddactivity = get_string('addactivity'); | |
501 | $straddresource = get_string('addresource'); | |
502 | $sectionname = get_section_name($course, $section); | |
503 | $strresourcelabel = get_string('addresourcetosection', null, $sectionname); | |
504 | $stractivitylabel = get_string('addactivitytosection', null, $sectionname); | |
505 | ||
506 | $output = html_writer::start_tag('div', array('class' => 'section_add_menus', 'id' => 'add_menus-section-' . $section)); | |
507 | ||
508 | if (!$vertical) { | |
509 | $output .= html_writer::start_tag('div', array('class' => 'horizontal')); | |
510 | } | |
511 | ||
512 | if (!empty($activities[MOD_CLASS_RESOURCE])) { | |
513 | $select = new url_select($activities[MOD_CLASS_RESOURCE], '', array(''=>$straddresource), "ressection$section"); | |
514 | $select->set_help_icon('resources'); | |
515 | $select->set_label($strresourcelabel, array('class' => 'accesshide')); | |
516 | $output .= $this->output->render($select); | |
517 | } | |
518 | ||
519 | if (!empty($activities[MOD_CLASS_ACTIVITY])) { | |
520 | $select = new url_select($activities[MOD_CLASS_ACTIVITY], '', array(''=>$straddactivity), "section$section"); | |
521 | $select->set_help_icon('activities'); | |
522 | $select->set_label($stractivitylabel, array('class' => 'accesshide')); | |
523 | $output .= $this->output->render($select); | |
524 | } | |
525 | ||
526 | if (!$vertical) { | |
527 | $output .= html_writer::end_tag('div'); | |
528 | } | |
529 | ||
530 | $output .= html_writer::end_tag('div'); | |
531 | ||
532 | if (course_ajax_enabled($course) && $course->id == $this->page->course->id) { | |
533 | // modchooser can be added only for the current course set on the page! | |
534 | $straddeither = get_string('addresourceoractivity'); | |
535 | // The module chooser link | |
536 | $modchooser = html_writer::start_tag('div', array('class' => 'mdl-right')); | |
537 | $modchooser.= html_writer::start_tag('div', array('class' => 'section-modchooser')); | |
538 | $icon = $this->output->pix_icon('t/add', ''); | |
539 | $span = html_writer::tag('span', $straddeither, array('class' => 'section-modchooser-text')); | |
540 | $modchooser .= html_writer::tag('span', $icon . $span, array('class' => 'section-modchooser-link')); | |
541 | $modchooser.= html_writer::end_tag('div'); | |
542 | $modchooser.= html_writer::end_tag('div'); | |
543 | ||
544 | // Wrap the normal output in a noscript div | |
545 | $usemodchooser = get_user_preferences('usemodchooser', $CFG->modchooserdefault); | |
546 | if ($usemodchooser) { | |
547 | $output = html_writer::tag('div', $output, array('class' => 'hiddenifjs addresourcedropdown')); | |
548 | $modchooser = html_writer::tag('div', $modchooser, array('class' => 'visibleifjs addresourcemodchooser')); | |
549 | } else { | |
550 | // If the module chooser is disabled, we need to ensure that the dropdowns are shown even if javascript is disabled | |
551 | $output = html_writer::tag('div', $output, array('class' => 'show addresourcedropdown')); | |
552 | $modchooser = html_writer::tag('div', $modchooser, array('class' => 'hide addresourcemodchooser')); | |
553 | } | |
554 | $output = $this->course_modchooser($modules, $course) . $modchooser . $output; | |
555 | } | |
556 | ||
557 | return $output; | |
558 | } | |
7e29340f | 559 | |
f4b571ab MG |
560 | /** |
561 | * Renders html to display a course search form | |
562 | * | |
563 | * @param string $value default value to populate the search field | |
564 | * @param string $format display format - 'plain' (default), 'short' or 'navbar' | |
565 | * @return string | |
566 | */ | |
567 | function course_search_form($value = '', $format = 'plain') { | |
568 | static $count = 0; | |
569 | $formid = 'coursesearch'; | |
570 | if ((++$count) > 1) { | |
571 | $formid .= $count; | |
572 | } | |
573 | ||
574 | switch ($format) { | |
575 | case 'navbar' : | |
576 | $formid = 'coursesearchnavbar'; | |
577 | $inputid = 'navsearchbox'; | |
578 | $inputsize = 20; | |
579 | break; | |
580 | case 'short' : | |
581 | $inputid = 'shortsearchbox'; | |
582 | $inputsize = 12; | |
583 | break; | |
584 | default : | |
585 | $inputid = 'coursesearchbox'; | |
586 | $inputsize = 30; | |
587 | } | |
588 | ||
589 | $strsearchcourses= get_string("searchcourses"); | |
590 | $searchurl = new moodle_url('/course/search.php'); | |
591 | ||
592 | $output = html_writer::start_tag('form', array('id' => $formid, 'action' => $searchurl, 'method' => 'get')); | |
593 | $output .= html_writer::start_tag('fieldset', array('class' => 'coursesearchbox invisiblefieldset')); | |
594 | $output .= html_writer::tag('lavel', $strsearchcourses.': ', array('for' => $inputid)); | |
595 | $output .= html_writer::empty_tag('input', array('type' => 'text', 'id' => $inputid, | |
596 | 'size' => $inputsize, 'name' => 'search', 'value' => s($value))); | |
597 | $output .= html_writer::empty_tag('input', array('type' => 'submit', | |
598 | 'value' => get_string('go'))); | |
599 | $output .= html_writer::end_tag('fieldset'); | |
600 | $output .= html_writer::end_tag('form'); | |
601 | ||
602 | return $output; | |
603 | } | |
604 | ||
7e29340f MG |
605 | /** |
606 | * Renders html for completion box on course page | |
607 | * | |
608 | * If completion is disabled, returns empty string | |
609 | * If completion is automatic, returns an icon of the current completion state | |
610 | * If completion is manual, returns a form (with an icon inside) that allows user to | |
611 | * toggle completion | |
612 | * | |
613 | * @param stdClass $course course object | |
614 | * @param completion_info $completioninfo completion info for the course, it is recommended | |
615 | * to fetch once for all modules in course/section for performance | |
616 | * @param cm_info $mod module to show completion for | |
617 | * @param array $displayoptions display options, not used in core | |
618 | * @return string | |
619 | */ | |
620 | public function course_section_cm_completion($course, &$completioninfo, cm_info $mod, $displayoptions = array()) { | |
621 | global $CFG; | |
622 | $output = ''; | |
623 | if (!empty($displayoptions['hidecompletion']) || !isloggedin() || isguestuser() || !$mod->uservisible) { | |
624 | return $output; | |
625 | } | |
626 | if ($completioninfo === null) { | |
627 | $completioninfo = new completion_info($course); | |
628 | } | |
629 | $completion = $completioninfo->is_enabled($mod); | |
630 | if ($completion == COMPLETION_TRACKING_NONE) { | |
631 | return $output; | |
632 | } | |
633 | ||
634 | $completiondata = $completioninfo->get_data($mod, true); | |
635 | $completionicon = ''; | |
636 | ||
637 | if ($this->page->user_is_editing()) { | |
638 | switch ($completion) { | |
639 | case COMPLETION_TRACKING_MANUAL : | |
640 | $completionicon = 'manual-enabled'; break; | |
641 | case COMPLETION_TRACKING_AUTOMATIC : | |
642 | $completionicon = 'auto-enabled'; break; | |
643 | } | |
644 | } else if ($completion == COMPLETION_TRACKING_MANUAL) { | |
645 | switch($completiondata->completionstate) { | |
646 | case COMPLETION_INCOMPLETE: | |
647 | $completionicon = 'manual-n'; break; | |
648 | case COMPLETION_COMPLETE: | |
649 | $completionicon = 'manual-y'; break; | |
650 | } | |
651 | } else { // Automatic | |
652 | switch($completiondata->completionstate) { | |
653 | case COMPLETION_INCOMPLETE: | |
654 | $completionicon = 'auto-n'; break; | |
655 | case COMPLETION_COMPLETE: | |
656 | $completionicon = 'auto-y'; break; | |
657 | case COMPLETION_COMPLETE_PASS: | |
658 | $completionicon = 'auto-pass'; break; | |
659 | case COMPLETION_COMPLETE_FAIL: | |
660 | $completionicon = 'auto-fail'; break; | |
661 | } | |
662 | } | |
663 | if ($completionicon) { | |
664 | $formattedname = $mod->get_formatted_name(); | |
665 | $imgalt = get_string('completion-alt-' . $completionicon, 'completion', $formattedname); | |
666 | if ($completion == COMPLETION_TRACKING_MANUAL && !$this->page->user_is_editing()) { | |
667 | $imgtitle = get_string('completion-title-' . $completionicon, 'completion', $formattedname); | |
668 | $newstate = | |
669 | $completiondata->completionstate == COMPLETION_COMPLETE | |
670 | ? COMPLETION_INCOMPLETE | |
671 | : COMPLETION_COMPLETE; | |
672 | // In manual mode the icon is a toggle form... | |
673 | ||
674 | // If this completion state is used by the | |
675 | // conditional activities system, we need to turn | |
676 | // off the JS. | |
677 | $extraclass = ''; | |
678 | if (!empty($CFG->enableavailability) && | |
679 | condition_info::completion_value_used_as_condition($course, $mod)) { | |
680 | $extraclass = ' preventjs'; | |
681 | } | |
682 | $output .= html_writer::start_tag('form', array('method' => 'post', | |
683 | 'action' => new moodle_url('/course/togglecompletion.php'), | |
684 | 'class' => 'togglecompletion'. $extraclass)); | |
685 | $output .= html_writer::start_tag('div'); | |
686 | $output .= html_writer::empty_tag('input', array( | |
687 | 'type' => 'hidden', 'name' => 'id', 'value' => $mod->id)); | |
688 | $output .= html_writer::empty_tag('input', array( | |
689 | 'type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey())); | |
690 | $output .= html_writer::empty_tag('input', array( | |
691 | 'type' => 'hidden', 'name' => 'modulename', 'value' => $mod->name)); | |
692 | $output .= html_writer::empty_tag('input', array( | |
693 | 'type' => 'hidden', 'name' => 'completionstate', 'value' => $newstate)); | |
694 | $output .= html_writer::empty_tag('input', array( | |
695 | 'type' => 'image', | |
696 | 'src' => $this->output->pix_url('i/completion-'.$completionicon), | |
f0989c3b RT |
697 | 'alt' => $imgalt, 'title' => $imgtitle, |
698 | 'aria-live' => 'polite')); | |
7e29340f MG |
699 | $output .= html_writer::end_tag('div'); |
700 | $output .= html_writer::end_tag('form'); | |
701 | } else { | |
702 | // In auto mode, or when editing, the icon is just an image | |
703 | $completionpixicon = new pix_icon('i/completion-'.$completionicon, $imgalt, '', | |
704 | array('title' => $imgalt)); | |
705 | $output .= html_writer::tag('span', $this->output->render($completionpixicon), | |
706 | array('class' => 'autocompletion')); | |
707 | } | |
708 | } | |
709 | return $output; | |
710 | } | |
ed513fad MG |
711 | |
712 | /** | |
713 | * Checks if course module has any conditions that may make it unavailable for | |
714 | * all or some of the students | |
715 | * | |
716 | * This function is internal and is only used to create CSS classes for the module name/text | |
717 | * | |
718 | * @param cm_info $mod | |
719 | * @return bool | |
720 | */ | |
721 | protected function is_cm_conditionally_hidden(cm_info $mod) { | |
722 | global $CFG; | |
723 | $conditionalhidden = false; | |
724 | if (!empty($CFG->enableavailability)) { | |
725 | $conditionalhidden = $mod->availablefrom > time() || | |
726 | ($mod->availableuntil && $mod->availableuntil < time()) || | |
727 | count($mod->conditionsgrade) > 0 || | |
728 | count($mod->conditionscompletion) > 0; | |
729 | } | |
730 | return $conditionalhidden; | |
731 | } | |
732 | ||
733 | /** | |
734 | * Renders html to display a name with the link to the course module on a course page | |
735 | * | |
736 | * If module is unavailable for user but still needs to be displayed | |
737 | * in the list, just the name is returned without a link | |
738 | * | |
739 | * Note, that for course modules that never have separate pages (i.e. labels) | |
740 | * this function return an empty string | |
741 | * | |
742 | * @param cm_info $mod | |
743 | * @param array $displayoptions | |
744 | * @return string | |
745 | */ | |
746 | public function course_section_cm_name(cm_info $mod, $displayoptions = array()) { | |
747 | global $CFG; | |
748 | $output = ''; | |
749 | if (!$mod->uservisible && | |
750 | (empty($mod->showavailability) || empty($mod->availableinfo))) { | |
751 | // nothing to be displayed to the user | |
752 | return $output; | |
753 | } | |
754 | $url = $mod->get_url(); | |
755 | if (!$url) { | |
756 | return $output; | |
757 | } | |
758 | ||
759 | //Accessibility: for files get description via icon, this is very ugly hack! | |
760 | $instancename = $mod->get_formatted_name(); | |
761 | $altname = ''; | |
762 | $altname = $mod->modfullname; | |
763 | // Avoid unnecessary duplication: if e.g. a forum name already | |
764 | // includes the word forum (or Forum, etc) then it is unhelpful | |
765 | // to include that in the accessible description that is added. | |
766 | if (false !== strpos(textlib::strtolower($instancename), | |
767 | textlib::strtolower($altname))) { | |
768 | $altname = ''; | |
769 | } | |
770 | // File type after name, for alphabetic lists (screen reader). | |
771 | if ($altname) { | |
772 | $altname = get_accesshide(' '.$altname); | |
773 | } | |
774 | ||
775 | $conditionalhidden = $this->is_cm_conditionally_hidden($mod); | |
776 | $accessiblebutdim = !$mod->visible || $conditionalhidden; | |
777 | ||
778 | $linkclasses = ''; | |
779 | $accesstext = ''; | |
780 | $textclasses = ''; | |
781 | if ($accessiblebutdim) { | |
782 | $linkclasses .= ' dimmed'; | |
783 | $textclasses .= ' dimmed_text'; | |
784 | if ($conditionalhidden) { | |
785 | $linkclasses .= ' conditionalhidden'; | |
786 | $textclasses .= ' conditionalhidden'; | |
787 | } | |
788 | if ($mod->uservisible) { | |
789 | // show accessibility note only if user can access the module himself | |
790 | $accesstext = get_accesshide(get_string('hiddenfromstudents').': '); | |
791 | } | |
792 | } | |
793 | ||
794 | // Get on-click attribute value if specified and decode the onclick - it | |
795 | // has already been encoded for display (puke). | |
796 | $onclick = htmlspecialchars_decode($mod->get_on_click(), ENT_QUOTES); | |
797 | ||
798 | $groupinglabel = ''; | |
799 | if (!empty($mod->groupingid) && has_capability('moodle/course:managegroups', context_course::instance($mod->course))) { | |
800 | $groupings = groups_get_all_groupings($mod->course); | |
801 | $groupinglabel = html_writer::tag('span', '('.format_string($groupings[$mod->groupingid]->name).')', | |
802 | array('class' => 'groupinglabel '.$textclasses)); | |
803 | } | |
804 | ||
805 | // Display link itself. | |
806 | $activitylink = html_writer::empty_tag('img', array('src' => $mod->get_icon_url(), | |
807 | 'class' => 'iconlarge activityicon', 'alt' => $mod->modfullname)) . $accesstext . | |
808 | html_writer::tag('span', $instancename . $altname, array('class' => 'instancename')); | |
809 | if ($mod->uservisible) { | |
810 | $output .= html_writer::link($url, $activitylink, array('class' => $linkclasses, 'onclick' => $onclick)) . | |
811 | $groupinglabel; | |
812 | } else { | |
813 | // We may be displaying this just in order to show information | |
814 | // about visibility, without the actual link ($mod->uservisible) | |
815 | $output .= html_writer::tag('div', $activitylink, array('class' => $textclasses)) . | |
816 | $groupinglabel; | |
817 | } | |
818 | return $output; | |
819 | } | |
820 | ||
821 | /** | |
822 | * Renders html to display the module content on the course page (i.e. text of the labels) | |
823 | * | |
824 | * @param cm_info $mod | |
825 | * @param array $displayoptions | |
826 | * @return string | |
827 | */ | |
828 | public function course_section_cm_text(cm_info $mod, $displayoptions = array()) { | |
829 | $output = ''; | |
830 | if (!$mod->uservisible && | |
831 | (empty($mod->showavailability) || empty($mod->availableinfo))) { | |
832 | // nothing to be displayed to the user | |
833 | return $output; | |
834 | } | |
835 | $content = $mod->get_formatted_content(array('overflowdiv' => true, 'noclean' => true)); | |
836 | $conditionalhidden = $this->is_cm_conditionally_hidden($mod); | |
837 | $accessiblebutdim = !$mod->visible || $conditionalhidden; | |
838 | $textclasses = ''; | |
839 | $accesstext = ''; | |
840 | if ($accessiblebutdim) { | |
841 | $textclasses .= ' dimmed_text'; | |
842 | if ($conditionalhidden) { | |
843 | $textclasses .= ' conditionalhidden'; | |
844 | } | |
845 | if ($mod->uservisible) { | |
846 | // show accessibility note only if user can access the module himself | |
847 | $accesstext = get_accesshide(get_string('hiddenfromstudents').': '); | |
848 | } | |
849 | } | |
850 | if ($mod->get_url()) { | |
851 | if ($content) { | |
852 | // If specified, display extra content after link. | |
853 | $output = html_writer::tag('div', $content, array('class' => | |
854 | trim('contentafterlink ' . $textclasses))); | |
855 | } | |
856 | } else { | |
857 | // No link, so display only content. | |
858 | $output = html_writer::tag('div', $accesstext . $content, array('class' => $textclasses)); | |
859 | } | |
860 | return $output; | |
861 | } | |
862 | ||
863 | /** | |
864 | * Renders HTML to show course module availability information (for someone who isn't allowed | |
865 | * to see the activity itself, or for staff) | |
866 | * | |
867 | * @param cm_info $mod | |
868 | * @param array $displayoptions | |
869 | * @return string | |
870 | */ | |
871 | public function course_section_cm_availability(cm_info $mod, $displayoptions = array()) { | |
872 | global $CFG; | |
873 | if (!$mod->uservisible) { | |
874 | // this is a student who is not allowed to see the module but might be allowed | |
875 | // to see availability info (i.e. "Available from ...") | |
876 | if (!empty($mod->showavailability) && !empty($mod->availableinfo)) { | |
877 | $output = html_writer::tag('div', $mod->availableinfo, array('class' => 'availabilityinfo')); | |
878 | } | |
879 | return $output; | |
880 | } | |
881 | // this is a teacher who is allowed to see module but still should see the | |
882 | // information that module is not available to all/some students | |
883 | $modcontext = context_module::instance($mod->id); | |
884 | $canviewhidden = has_capability('moodle/course:viewhiddenactivities', $modcontext); | |
885 | if ($canviewhidden && !empty($CFG->enableavailability)) { | |
886 | // Don't add availability information if user is not editing and activity is hidden. | |
887 | if ($mod->visible || $this->page->user_is_editing()) { | |
888 | $hidinfoclass = ''; | |
889 | if (!$mod->visible) { | |
890 | $hidinfoclass = 'hide'; | |
891 | } | |
892 | $ci = new condition_info($mod); | |
893 | $fullinfo = $ci->get_full_information(); | |
894 | if($fullinfo) { | |
db82b130 | 895 | return '<div class="availabilityinfo '.$hidinfoclass.'">'.get_string($mod->showavailability |
ed513fad MG |
896 | ? 'userrestriction_visible' |
897 | : 'userrestriction_hidden','condition', | |
898 | $fullinfo).'</div>'; | |
899 | } | |
900 | } | |
901 | } | |
902 | return ''; | |
903 | } | |
c58a25d6 MG |
904 | |
905 | /** | |
906 | * Renders HTML to display one course module in a course section | |
907 | * | |
908 | * This includes link, content, availability, completion info and additional information | |
909 | * that module type wants to display (i.e. number of unread forum posts) | |
910 | * | |
911 | * This function calls: | |
912 | * {@link core_course_renderer::course_section_cm_name()} | |
913 | * {@link cm_info::get_after_link()} | |
914 | * {@link core_course_renderer::course_section_cm_text()} | |
915 | * {@link core_course_renderer::course_section_cm_availability()} | |
916 | * {@link core_course_renderer::course_section_cm_completion()} | |
917 | * {@link course_get_cm_edit_actions()} | |
918 | * {@link core_course_renderer::course_section_cm_edit_actions()} | |
33919cca | 919 | * |
c58a25d6 MG |
920 | * @param stdClass $course |
921 | * @param completion_info $completioninfo | |
922 | * @param cm_info $mod | |
923 | * @param int|null $sectionreturn | |
924 | * @param array $displayoptions | |
925 | * @return string | |
926 | */ | |
927 | public function course_section_cm($course, &$completioninfo, cm_info $mod, $sectionreturn, $displayoptions = array()) { | |
928 | $output = ''; | |
929 | // We return empty string (because course module will not be displayed at all) | |
930 | // if: | |
931 | // 1) The activity is not visible to users | |
932 | // and | |
933 | // 2a) The 'showavailability' option is not set (if that is set, | |
934 | // we need to display the activity so we can show | |
935 | // availability info) | |
936 | // or | |
937 | // 2b) The 'availableinfo' is empty, i.e. the activity was | |
938 | // hidden in a way that leaves no info, such as using the | |
939 | // eye icon. | |
940 | if (!$mod->uservisible && | |
941 | (empty($mod->showavailability) || empty($mod->availableinfo))) { | |
942 | return $output; | |
943 | } | |
944 | ||
945 | $indentclasses = 'mod-indent'; | |
946 | if (!empty($mod->indent)) { | |
947 | $indentclasses .= ' mod-indent-'.$mod->indent; | |
948 | if ($mod->indent > 15) { | |
949 | $indentclasses .= ' mod-indent-huge'; | |
950 | } | |
951 | } | |
952 | $output .= html_writer::start_tag('div', array('class' => $indentclasses)); | |
953 | ||
954 | // Start the div for the activity title, excluding the edit icons. | |
955 | $output .= html_writer::start_tag('div', array('class' => 'activityinstance')); | |
956 | ||
957 | // Display the link to the module (or do nothing if module has no url) | |
958 | $output .= $this->course_section_cm_name($mod, $displayoptions); | |
959 | ||
960 | // Module can put text after the link (e.g. forum unread) | |
961 | $output .= $mod->get_after_link(); | |
962 | ||
963 | // Closing the tag which contains everything but edit icons. Content part of the module should not be part of this. | |
964 | $output .= html_writer::end_tag('div'); // .activityinstance | |
965 | ||
966 | // If there is content but NO link (eg label), then display the | |
967 | // content here (BEFORE any icons). In this case cons must be | |
968 | // displayed after the content so that it makes more sense visually | |
969 | // and for accessibility reasons, e.g. if you have a one-line label | |
970 | // it should work similarly (at least in terms of ordering) to an | |
971 | // activity. | |
972 | $contentpart = $this->course_section_cm_text($mod, $displayoptions); | |
973 | $url = $mod->get_url(); | |
974 | if (empty($url)) { | |
975 | $output .= $contentpart; | |
976 | } | |
977 | ||
978 | if ($this->page->user_is_editing()) { | |
979 | $editactions = course_get_cm_edit_actions($mod, $mod->indent, $sectionreturn); | |
980 | $output .= ' '. $this->course_section_cm_edit_actions($editactions); | |
981 | $output .= $mod->get_after_edit_icons(); | |
982 | } | |
983 | ||
984 | $output .= $this->course_section_cm_completion($course, $completioninfo, $mod, $displayoptions); | |
985 | ||
986 | // If there is content AND a link, then display the content here | |
987 | // (AFTER any icons). Otherwise it was displayed before | |
988 | if (!empty($url)) { | |
989 | $output .= $contentpart; | |
990 | } | |
991 | ||
992 | // show availability info (if module is not available) | |
993 | $output .= $this->course_section_cm_availability($mod, $displayoptions); | |
994 | ||
995 | $output .= html_writer::end_tag('div'); // $indentclasses | |
996 | return $output; | |
997 | } | |
998 | ||
999 | /** | |
1000 | * Renders HTML to display a list of course modules in a course section | |
1001 | * Also displays "move here" controls in Javascript-disabled mode | |
1002 | * | |
1003 | * This function calls {@link core_course_renderer::course_section_cm()} | |
1004 | * | |
1005 | * @param stdClass $course course object | |
1006 | * @param int|stdClass|section_info $section relative section number or section object | |
1007 | * @param int $sectionreturn section number to return to | |
1008 | * @param int $displayoptions | |
1009 | * @return void | |
1010 | */ | |
1011 | public function course_section_cm_list($course, $section, $sectionreturn = null, $displayoptions = array()) { | |
1012 | global $USER; | |
1013 | ||
1014 | $output = ''; | |
1015 | $modinfo = get_fast_modinfo($course); | |
1016 | if (is_object($section)) { | |
1017 | $section = $modinfo->get_section_info($section->section); | |
1018 | } else { | |
1019 | $section = $modinfo->get_section_info($section); | |
1020 | } | |
1021 | $completioninfo = new completion_info($course); | |
1022 | ||
1023 | // check if we are currently in the process of moving a module with JavaScript disabled | |
1024 | $ismoving = $this->page->user_is_editing() && ismoving($course->id); | |
1025 | if ($ismoving) { | |
1026 | $movingpix = new pix_icon('movehere', get_string('movehere'), 'moodle', array('class' => 'movetarget')); | |
1027 | $strmovefull = strip_tags(get_string("movefull", "", "'$USER->activitycopyname'")); | |
1028 | } | |
1029 | ||
1030 | // Get the list of modules visible to user (excluding the module being moved if there is one) | |
1031 | $moduleshtml = array(); | |
1032 | if (!empty($modinfo->sections[$section->section])) { | |
1033 | foreach ($modinfo->sections[$section->section] as $modnumber) { | |
1034 | $mod = $modinfo->cms[$modnumber]; | |
1035 | ||
1036 | if ($ismoving and $mod->id == $USER->activitycopy) { | |
1037 | // do not display moving mod | |
1038 | continue; | |
1039 | } | |
1040 | ||
1041 | if ($modulehtml = $this->course_section_cm($course, | |
1042 | $completioninfo, $mod, $sectionreturn, $displayoptions)) { | |
1043 | $moduleshtml[$modnumber] = $modulehtml; | |
1044 | } | |
1045 | } | |
1046 | } | |
1047 | ||
1048 | if (!empty($moduleshtml) || $ismoving) { | |
1049 | ||
1050 | $output .= html_writer::start_tag('ul', array('class' => 'section img-text')); | |
1051 | ||
1052 | foreach ($moduleshtml as $modnumber => $modulehtml) { | |
1053 | if ($ismoving) { | |
1054 | $movingurl = new moodle_url('/course/mod.php', array('moveto' => $modnumber, 'sesskey' => sesskey())); | |
1055 | $output .= html_writer::tag('li', html_writer::link($movingurl, $this->output->render($movingpix)), | |
1056 | array('class' => 'movehere', 'title' => $strmovefull)); | |
1057 | } | |
1058 | ||
1059 | $mod = $modinfo->cms[$modnumber]; | |
8df0765a | 1060 | $modclasses = 'activity '. $mod->modname. ' modtype_'.$mod->modname. ' '. $mod->get_extra_classes(); |
c58a25d6 MG |
1061 | $output .= html_writer::start_tag('li', array('class' => $modclasses, 'id' => 'module-'. $mod->id)); |
1062 | $output .= $modulehtml; | |
1063 | $output .= html_writer::end_tag('li'); | |
1064 | } | |
1065 | ||
1066 | if ($ismoving) { | |
1067 | $movingurl = new moodle_url('/course/mod.php', array('movetosection' => $section->id, 'sesskey' => sesskey())); | |
1068 | $output .= html_writer::tag('li', html_writer::link($movingurl, $this->output->render($movingpix)), | |
1069 | array('class' => 'movehere', 'title' => $strmovefull)); | |
1070 | } | |
1071 | ||
1072 | $output .= html_writer::end_tag('ul'); // .section | |
1073 | } | |
1074 | ||
1075 | return $output; | |
1076 | } | |
f4c23f03 | 1077 | } |