weekly release 2.8dev
[moodle.git] / course / classes / management_renderer.php
CommitLineData
5dc361e1
SH
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/>.
16
17/**
18 * Contains renderers for the course management pages.
19 *
20 * @package core_course
21 * @copyright 2013 Sam Hemelryk
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die;
26
27require_once($CFG->dirroot.'/course/renderer.php');
28
29/**
30 * Main renderer for the course management pages.
31 *
32 * @package core_course
33 * @copyright 2013 Sam Hemelryk
34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 */
36class core_course_management_renderer extends plugin_renderer_base {
37
38 /**
39 * Initialises the JS required to enhance the management interface.
40 *
41 * Thunderbirds are go, this function kicks into gear the JS that makes the
42 * course management pages that much cooler.
43 */
44 public function enhance_management_interface() {
484c4c6c 45 $this->page->requires->yui_module('moodle-course-management', 'M.course.management.init');
5dc361e1 46 $this->page->requires->strings_for_js(
d0647301
SH
47 array(
48 'show',
49 'showcategory',
50 'hide',
51 'expand',
52 'expandcategory',
53 'collapse',
54 'collapsecategory',
55 'confirmcoursemove',
56 'move',
57 'cancel',
58 'confirm'
59 ),
5dc361e1
SH
60 'moodle'
61 );
62 }
63
64 /**
65 * Displays a heading for the management pages.
66 *
67 * @param string $heading The heading to display
68 * @param string|null $viewmode The current view mode if there are options.
69 * @param int|null $categoryid The currently selected category if there is one.
70 * @return string
71 */
72 public function management_heading($heading, $viewmode = null, $categoryid = null) {
73 $html = html_writer::start_div('coursecat-management-header clearfix');
74 if (!empty($heading)) {
75 $html .= $this->heading($heading);
76 }
77 if ($viewmode !== null) {
d0647301
SH
78 $html .= html_writer::start_div();
79 $html .= $this->view_mode_selector(\core_course\management\helper::get_management_viewmodes(), $viewmode);
5dc361e1 80 if ($viewmode === 'courses') {
484c4c6c 81 $categories = coursecat::make_categories_list(array('moodle/category:manage', 'moodle/course:create'));
5dc361e1
SH
82 $nothing = false;
83 if ($categoryid === null) {
84 $nothing = array('' => get_string('selectacategory'));
85 $categoryid = '';
86 }
87 $select = new single_select($this->page->url, 'categoryid', $categories, $categoryid, $nothing);
88 $html .= $this->render($select);
89 }
d0647301 90 $html .= html_writer::end_div();
5dc361e1
SH
91 }
92 $html .= html_writer::end_div();
93 return $html;
94 }
95
96 /**
97 * Prepares the form element for the course category listing bulk actions.
98 *
99 * @return string
100 */
101 public function management_form_start() {
102 $form = array('action' => $this->page->url->out(), 'method' => 'POST', 'id' => 'coursecat-management');
103
104 $html = html_writer::start_tag('form', $form);
105 $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
106 $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'action', 'value' => 'bulkaction'));
107 return $html;
108 }
109
110 /**
111 * Closes the course category bulk management form.
112 *
113 * @return string
114 */
115 public function management_form_end() {
116 return html_writer::end_tag('form');
117 }
118
119 /**
120 * Presents a course category listing.
121 *
122 * @param coursecat $category The currently selected category. Also the category to highlight in the listing.
123 * @return string
124 */
125 public function category_listing(coursecat $category = null) {
126
127 if ($category === null) {
5dc361e1 128 $selectedparents = array();
f454e324 129 $selectedcategory = null;
5dc361e1
SH
130 } else {
131 $selectedparents = $category->get_parents();
132 $selectedparents[] = $category->id;
f454e324 133 $selectedcategory = $category->id;
5dc361e1 134 }
d5de8747
SH
135 $catatlevel = \core_course\management\helper::get_expanded_categories('');
136 $catatlevel[] = array_shift($selectedparents);
137 $catatlevel = array_unique($catatlevel);
5dc361e1 138
67e1f268 139 $listing = coursecat::get(0)->get_children();
5dc361e1 140
7fd307b1
SH
141 $attributes = array(
142 'class' => 'ml',
143 'role' => 'tree',
144 'aria-labelledby' => 'category-listing-title'
145 );
146
5dc361e1 147 $html = html_writer::start_div('category-listing');
7fd307b1 148 $html .= html_writer::tag('h3', get_string('categories'), array('id' => 'category-listing-title'));
b488058f 149 $html .= $this->category_listing_actions($category);
7fd307b1 150 $html .= html_writer::start_tag('ul', $attributes);
5dc361e1
SH
151 foreach ($listing as $listitem) {
152 // Render each category in the listing.
153 $subcategories = array();
d5de8747 154 if (in_array($listitem->id, $catatlevel)) {
5dc361e1
SH
155 $subcategories = $listitem->get_children();
156 }
157 $html .= $this->category_listitem(
158 $listitem,
159 $subcategories,
160 $listitem->get_children_count(),
f454e324 161 $selectedcategory,
5dc361e1
SH
162 $selectedparents
163 );
164 }
165 $html .= html_writer::end_tag('ul');
c7a2291f 166 $html .= $this->category_bulk_actions($category);
5dc361e1
SH
167 $html .= html_writer::end_div();
168 return $html;
169 }
170
171 /**
172 * Renders a category list item.
173 *
174 * This function gets called recursively to render sub categories.
175 *
176 * @param coursecat $category The category to render as listitem.
177 * @param coursecat[] $subcategories The subcategories belonging to the category being rented.
178 * @param int $totalsubcategories The total number of sub categories.
179 * @param int $selectedcategory The currently selected category
180 * @param int[] $selectedcategories The path to the selected category and its ID.
181 * @return string
182 */
183 public function category_listitem(coursecat $category, array $subcategories, $totalsubcategories,
184 $selectedcategory = null, $selectedcategories = array()) {
d5de8747 185
5dc361e1
SH
186 $isexpandable = ($totalsubcategories > 0);
187 $isexpanded = (!empty($subcategories));
f454e324 188 $activecategory = ($selectedcategory === $category->id);
5dc361e1
SH
189 $attributes = array(
190 'class' => 'listitem listitem-category',
191 'data-id' => $category->id,
192 'data-expandable' => $isexpandable ? '1' : '0',
193 'data-expanded' => $isexpanded ? '1' : '0',
194 'data-selected' => $activecategory ? '1' : '0',
7fd307b1
SH
195 'data-visible' => $category->visible ? '1' : '0',
196 'role' => 'treeitem',
197 'aria-expanded' => $isexpanded ? 'true' : 'false'
5dc361e1
SH
198 );
199 $text = $category->get_formatted_name();
d0647301
SH
200 if ($category->parent) {
201 $a = new stdClass;
202 $a->category = $text;
203 $a->parentcategory = $category->get_parent_coursecat()->get_formatted_name();
204 $textlabel = get_string('categorysubcategoryof', 'moodle', $a);
205 }
5dc361e1 206 $courseicon = $this->output->pix_icon('i/course', get_string('courses'));
cd96b7d3
SH
207 $bcatinput = array(
208 'type' => 'checkbox',
209 'name' => 'bcat[]',
210 'value' => $category->id,
211 'class' => 'bulk-action-checkbox',
a5888fb5
RT
212 'aria-label' => get_string('bulkactionselect', 'moodle', $text),
213 'data-action' => 'select'
cd96b7d3 214 );
b488058f
SH
215
216 if (!$category->can_resort_subcategories() && !$category->has_manage_capability()) {
217 // Very very hardcoded here.
218 $bcatinput['style'] = 'visibility:hidden';
219 }
220
5dc361e1
SH
221 $viewcaturl = new moodle_url('/course/management.php', array('categoryid' => $category->id));
222 if ($isexpanded) {
d0647301
SH
223 $icon = $this->output->pix_icon('t/switch_minus', get_string('collapse'), 'moodle', array('class' => 'tree-icon', 'title' => ''));
224 $icon = html_writer::link(
225 $viewcaturl,
226 $icon,
227 array(
228 'class' => 'float-left',
229 'data-action' => 'collapse',
230 'title' => get_string('collapsecategory', 'moodle', $text),
231 'aria-controls' => 'subcategoryof'.$category->id
232 )
233 );
5dc361e1 234 } else if ($isexpandable) {
d0647301
SH
235 $icon = $this->output->pix_icon('t/switch_plus', get_string('expand'), 'moodle', array('class' => 'tree-icon', 'title' => ''));
236 $icon = html_writer::link(
237 $viewcaturl,
238 $icon,
239 array(
240 'class' => 'float-left',
241 'data-action' => 'expand',
242 'title' => get_string('expandcategory', 'moodle', $text)
243 )
244 );
5dc361e1 245 } else {
d0647301
SH
246 $icon = $this->output->pix_icon(
247 'i/navigationitem',
248 '',
249 'moodle',
250 array('class' => 'tree-icon', 'title' => get_string('showcategory', 'moodle', $text))
251 );
252 $icon = html_writer::span($icon, 'float-left');
5dc361e1 253 }
b488058f 254 $actions = \core_course\management\helper::get_category_listitem_actions($category);
484c4c6c 255 $hasactions = !empty($actions) || $category->can_create_course();
5dc361e1
SH
256
257 $html = html_writer::start_tag('li', $attributes);
258 $html .= html_writer::start_div('clearfix');
3b681e6c 259 $html .= html_writer::start_div('float-left ba-checkbox');
5dc361e1
SH
260 $html .= html_writer::empty_tag('input', $bcatinput).'&nbsp;';
261 $html .= html_writer::end_div();
262 $html .= $icon;
b488058f 263 if ($hasactions) {
d0647301 264 $textattributes = array('class' => 'float-left categoryname');
b488058f 265 } else {
d0647301
SH
266 $textattributes = array('class' => 'float-left categoryname without-actions');
267 }
268 if (isset($textlabel)) {
269 $textattributes['aria-label'] = $textlabel;
b488058f 270 }
d0647301 271 $html .= html_writer::link($viewcaturl, $text, $textattributes);
5dc361e1 272 $html .= html_writer::start_div('float-right');
c7a2291f
SH
273 if ($category->idnumber) {
274 $html .= html_writer::tag('span', s($category->idnumber), array('class' => 'dimmed idnumber'));
275 }
b488058f
SH
276 if ($hasactions) {
277 $html .= $this->category_listitem_actions($category, $actions);
278 }
7fd307b1 279 $countid = 'course-count-'.$category->id;
38a15200 280 $html .= html_writer::span(
d0647301
SH
281 html_writer::span($category->get_courses_count()) .
282 html_writer::span(get_string('courses'), 'accesshide', array('id' => $countid)) .
283 $courseicon,
38a15200
SH
284 'course-count dimmed',
285 array('aria-labelledby' => $countid)
286 );
5dc361e1
SH
287 $html .= html_writer::end_div();
288 $html .= html_writer::end_div();
289 if ($isexpanded) {
d0647301
SH
290 $html .= html_writer::start_tag('ul',
291 array('class' => 'ml', 'role' => 'group', 'id' => 'subcategoryof'.$category->id));
d5de8747
SH
292 $catatlevel = \core_course\management\helper::get_expanded_categories($category->path);
293 $catatlevel[] = array_shift($selectedcategories);
294 $catatlevel = array_unique($catatlevel);
5dc361e1 295 foreach ($subcategories as $listitem) {
d5de8747 296 $childcategories = (in_array($listitem->id, $catatlevel)) ? $listitem->get_children() : array();
5dc361e1
SH
297 $html .= $this->category_listitem(
298 $listitem,
299 $childcategories,
300 $listitem->get_children_count(),
301 $selectedcategory,
302 $selectedcategories
303 );
304 }
305 $html .= html_writer::end_tag('ul');
306 }
307 $html .= html_writer::end_tag('li');
308 return $html;
309 }
310
311 /**
312 * Renderers the actions that are possible for the course category listing.
313 *
314 * These are not the actions associated with an individual category listing.
315 * That happens through category_listitem_actions.
316 *
317 * @param coursecat $category
318 * @return string
319 */
b488058f 320 public function category_listing_actions(coursecat $category = null) {
5dc361e1 321 $actions = array();
017518d4
SH
322
323 $cancreatecategory = $category && $category->can_create_subcategory();
324 $cancreatecategory = $cancreatecategory || coursecat::can_create_top_level_category();
b488058f
SH
325 if ($category === null) {
326 $category = coursecat::get(0);
327 }
5dc361e1 328
017518d4
SH
329 if ($cancreatecategory) {
330 $url = new moodle_url('/course/editcategory.php', array('parent' => $category->id));
331 $actions[] = html_writer::link($url, get_string('createnewcategory'));
5dc361e1 332 }
484c4c6c
SH
333 if (coursecat::can_approve_course_requests()) {
334 $actions[] = html_writer::link(new moodle_url('/course/pending.php'), get_string('coursespending'));
335 }
c7a2291f 336 if (count($actions) === 0) {
5dc361e1
SH
337 return '';
338 }
339 return html_writer::div(join(' | ', $actions), 'listing-actions category-listing-actions');
340 }
341
342 /**
343 * Renderers the actions for individual category list items.
344 *
345 * @param coursecat $category
c7a2291f 346 * @param array $actions
5dc361e1
SH
347 * @return string
348 */
b488058f
SH
349 public function category_listitem_actions(coursecat $category, array $actions = null) {
350 if ($actions === null) {
351 $actions = \core_course\management\helper::get_category_listitem_actions($category);
352 }
5dc361e1
SH
353 $menu = new action_menu();
354 $menu->attributes['class'] .= ' category-item-actions item-actions';
355 $hasitems = false;
b488058f 356 foreach ($actions as $key => $action) {
5dc361e1
SH
357 $hasitems = true;
358 $menu->add(new action_menu_link(
359 $action['url'],
360 $action['icon'],
361 $action['string'],
362 in_array($key, array('show', 'hide', 'moveup', 'movedown')),
363 array('data-action' => $key, 'class' => 'action-'.$key)
364 ));
365 }
366 if (!$hasitems) {
367 return '';
368 }
369 return $this->render($menu);
370 }
371
372 /**
373 * Renders bulk actions for categories.
374 *
c7a2291f 375 * @param coursecat $category The currently selected category if there is one.
5dc361e1
SH
376 * @return string
377 */
c7a2291f 378 public function category_bulk_actions(coursecat $category = null) {
5dc361e1
SH
379 // Resort courses.
380 // Change parent.
cd96b7d3
SH
381 if (!coursecat::can_resort_any() && !coursecat::can_change_parent_any()) {
382 return '';
383 }
5dc361e1
SH
384 $strgo = new lang_string('go');
385
386 $html = html_writer::start_div('category-bulk-actions bulk-actions');
cd96b7d3 387 $html .= html_writer::div(get_string('categorybulkaction'), 'accesshide', array('tabindex' => '0'));
5dc361e1 388 if (coursecat::can_resort_any()) {
c7a2291f
SH
389 $selectoptions = array(
390 'selectedcategories' => get_string('selectedcategories'),
391 'allcategories' => get_string('allcategories')
5dc361e1 392 );
c7a2291f
SH
393 $form = html_writer::start_div();
394 if ($category) {
395 $selectoptions = array('thiscategory' => get_string('thiscategory')) + $selectoptions;
396 $form .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'currentcategoryid', 'value' => $category->id));
397 }
398 $form .= html_writer::div(
c7a2291f
SH
399 html_writer::select(
400 $selectoptions,
401 'selectsortby',
e69a0251 402 'selectedcategories',
d0647301
SH
403 false,
404 array('aria-label' => get_string('selectcategorysort'))
c7a2291f 405 )
7fd307b1 406 );
c7a2291f 407 $form .= html_writer::div(
c7a2291f
SH
408 html_writer::select(
409 array(
9a4231e9
S
410 'name' => get_string('sortbyx', 'moodle', get_string('categoryname')),
411 'namedesc' => get_string('sortbyxreverse', 'moodle', get_string('categoryname')),
412 'idnumber' => get_string('sortbyx', 'moodle', get_string('idnumbercoursecategory')),
413 'idnumberdesc' => get_string('sortbyxreverse' , 'moodle' , get_string('idnumbercoursecategory')),
c7a2291f
SH
414 'none' => get_string('dontsortcategories')
415 ),
416 'resortcategoriesby',
e69a0251 417 'name',
d0647301
SH
418 false,
419 array('aria-label' => get_string('selectcategorysortby'))
c7a2291f
SH
420 )
421 );
422 $form .= html_writer::div(
c7a2291f
SH
423 html_writer::select(
424 array(
9a4231e9
S
425 'fullname' => get_string('sortbyx', 'moodle', get_string('fullnamecourse')),
426 'fullnamedesc' => get_string('sortbyxreverse', 'moodle', get_string('fullnamecourse')),
427 'shortname' => get_string('sortbyx', 'moodle', get_string('shortnamecourse')),
428 'shortnamedesc' => get_string('sortbyxreverse', 'moodle', get_string('shortnamecourse')),
429 'idnumber' => get_string('sortbyx', 'moodle', get_string('idnumbercourse')),
430 'idnumberdesc' => get_string('sortbyxreverse', 'moodle', get_string('idnumbercourse')),
431 'timecreated' => get_string('sortbyx', 'moodle', get_string('timecreatedcourse')),
432 'timecreateddesc' => get_string('sortbyxreverse', 'moodle', get_string('timecreatedcourse')),
c7a2291f
SH
433 'none' => get_string('dontsortcourses')
434 ),
435 'resortcoursesby',
e69a0251 436 'fullname',
d0647301
SH
437 false,
438 array('aria-label' => get_string('selectcoursesortby'))
c7a2291f 439 )
7fd307b1 440 );
e69a0251 441 $form .= html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'bulksort', 'value' => get_string('sort')));
c7a2291f 442 $form .= html_writer::end_div();
d0647301
SH
443
444 $html .= html_writer::start_div('detail-pair row yui3-g');
445 $html .= html_writer::div(html_writer::span(get_string('sorting')), 'pair-key span3 yui3-u-1-4');
446 $html .= html_writer::div($form, 'pair-value span9 yui3-u-3-4');
447 $html .= html_writer::end_div();
5dc361e1
SH
448 }
449 if (coursecat::can_change_parent_any()) {
3b732cd6
RT
450 $options = array();
451 if (has_capability('moodle/category:manage', context_system::instance())) {
452 $options[0] = coursecat::get(0)->get_formatted_name();
453 }
454 $options += coursecat::make_categories_list('moodle/category:manage');
7fd307b1
SH
455 $select = html_writer::select(
456 $options,
457 'movecategoriesto',
458 '',
459 array('' => 'choosedots'),
460 array('aria-labelledby' => 'moveselectedcategoriesto')
461 );
e69a0251 462 $submit = array('type' => 'submit', 'name' => 'bulkmovecategories', 'value' => get_string('move'));
5dc361e1 463 $html .= $this->detail_pair(
7fd307b1 464 html_writer::span(get_string('moveselectedcategoriesto'), '', array('id' => 'moveselectedcategoriesto')),
5dc361e1
SH
465 $select . html_writer::empty_tag('input', $submit)
466 );
467 }
468 $html .= html_writer::end_div();
469 return $html;
470 }
471
472 /**
473 * Renders a course listing.
474 *
475 * @param coursecat $category The currently selected category. This is what the listing is focused on.
476 * @param course_in_list $course The currently selected course.
477 * @param int $page The page being displayed.
478 * @param int $perpage The number of courses to display per page.
479 * @return string
480 */
481 public function course_listing(coursecat $category = null, course_in_list $course = null, $page = 0, $perpage = 20) {
482
483 if ($category === null) {
484 $html = html_writer::start_div('select-a-category');
d0647301
SH
485 $html .= html_writer::tag('h3', get_string('courses'),
486 array('id' => 'course-listing-title', 'tabindex' => '0'));
5dc361e1
SH
487 $html .= $this->output->notification(get_string('selectacategory'), 'notifymessage');
488 $html .= html_writer::end_div();
489 return $html;
490 }
491
492 $page = max($page, 0);
493 $perpage = max($perpage, 2);
494 $totalcourses = $category->coursecount;
495 $totalpages = ceil($totalcourses / $perpage);
496 if ($page > $totalpages - 1) {
497 $page = $totalpages - 1;
498 }
499 $options = array(
500 'offset' => $page * $perpage,
501 'limit' => $perpage
502 );
503 $courseid = isset($course) ? $course->id : null;
484c4c6c
SH
504 $class = '';
505 if ($page === 0) {
506 $class .= ' firstpage';
507 }
508 if ($page + 1 === (int)$totalpages) {
509 $class .= ' lastpage';
510 }
5dc361e1 511
484c4c6c 512 $html = html_writer::start_div('course-listing'.$class, array(
5dc361e1
SH
513 'data-category' => $category->id,
514 'data-page' => $page,
515 'data-totalpages' => $totalpages,
516 'data-totalcourses' => $totalcourses,
517 'data-canmoveoutof' => $category->can_move_courses_out_of() && $category->can_move_courses_into()
518 ));
d0647301
SH
519 $html .= html_writer::tag('h3', $category->get_formatted_name(),
520 array('id' => 'course-listing-title', 'tabindex' => '0'));
5dc361e1
SH
521 $html .= $this->course_listing_actions($category, $course, $perpage);
522 $html .= $this->listing_pagination($category, $page, $perpage);
d0647301 523 $html .= html_writer::start_tag('ul', array('class' => 'ml', 'role' => 'group'));
5dc361e1 524 foreach ($category->get_courses($options) as $listitem) {
f454e324 525 $html .= $this->course_listitem($category, $listitem, $courseid);
5dc361e1
SH
526 }
527 $html .= html_writer::end_tag('ul');
528 $html .= $this->listing_pagination($category, $page, $perpage, true);
529 $html .= $this->course_bulk_actions($category);
530 $html .= html_writer::end_div();
531 return $html;
532 }
533
534 /**
535 * Renders pagination for a course listing.
536 *
537 * @param coursecat $category The category to produce pagination for.
538 * @param int $page The current page.
539 * @param int $perpage The number of courses to display per page.
540 * @param bool $showtotals Set to true to show the total number of courses and what is being displayed.
541 * @return string
542 */
543 protected function listing_pagination(coursecat $category, $page, $perpage, $showtotals = false) {
544 $html = '';
d61d3163 545 $totalcourses = $category->get_courses_count();
5dc361e1
SH
546 $totalpages = ceil($totalcourses / $perpage);
547 if ($showtotals) {
548 if ($totalpages == 0) {
549 $str = get_string('nocoursesyet');
550 } else if ($totalpages == 1) {
551 $str = get_string('showingacourses', 'moodle', $totalcourses);
552 } else {
553 $a = new stdClass;
554 $a->start = ($page * $perpage) + 1;
555 $a->end = min((($page + 1) * $perpage), $totalcourses);
556 $a->total = $totalcourses;
557 $str = get_string('showingxofycourses', 'moodle', $a);
558 }
559 $html .= html_writer::div($str, 'listing-pagination-totals dimmed');
560 }
561
7c033254 562 if ($totalcourses <= $perpage) {
5dc361e1
SH
563 return $html;
564 }
565 $aside = 2;
566 $span = $aside * 2 + 1;
567 $start = max($page - $aside, 0);
568 $end = min($page + $aside, $totalpages - 1);
569 if (($end - $start) < $span) {
570 if ($start == 0) {
571 $end = min($totalpages - 1, $span - 1);
572 } else if ($end == ($totalpages - 1)) {
573 $start = max(0, $end - $span + 1);
574 }
575 }
576 $items = array();
577 $baseurl = new moodle_url('/course/management.php', array('categoryid' => $category->id));
578 if ($page > 0) {
579 $items[] = $this->action_button(new moodle_url($baseurl, array('page' => 0)), get_string('first'));
580 $items[] = $this->action_button(new moodle_url($baseurl, array('page' => $page - 1)), get_string('prev'));
581 $items[] = '...';
582 }
583 for ($i = $start; $i <= $end; $i++) {
584 $class = '';
585 if ($page == $i) {
586 $class = 'active-page';
587 }
7fd307b1
SH
588 $pageurl = new moodle_url($baseurl, array('page' => $i));
589 $items[] = $this->action_button($pageurl, $i + 1, null, $class, get_string('pagea', 'moodle', $i+1));
5dc361e1
SH
590 }
591 if ($page < ($totalpages - 1)) {
592 $items[] = '...';
593 $items[] = $this->action_button(new moodle_url($baseurl, array('page' => $page + 1)), get_string('next'));
594 $items[] = $this->action_button(new moodle_url($baseurl, array('page' => $totalpages - 1)), get_string('last'));
595 }
596
597 $html .= html_writer::div(join('', $items), 'listing-pagination');
598 return $html;
599 }
600
601 /**
602 * Renderers a course list item.
603 *
604 * This function will be called for every course being displayed by course_listing.
605 *
606 * @param coursecat $category The currently selected category and the category the course belongs to.
607 * @param course_in_list $course The course to produce HTML for.
608 * @param int $selectedcourse The id of the currently selected course.
5dc361e1
SH
609 * @return string
610 */
f454e324 611 public function course_listitem(coursecat $category, course_in_list $course, $selectedcourse) {
5dc361e1
SH
612
613 $text = $course->get_formatted_name();
614 $attributes = array(
615 'class' => 'listitem listitem-course',
616 'data-id' => $course->id,
617 'data-selected' => ($selectedcourse == $course->id) ? '1' : '0',
618 'data-visible' => $course->visible ? '1' : '0'
619 );
620
d0647301
SH
621 $bulkcourseinput = array(
622 'type' => 'checkbox',
623 'name' => 'bc[]',
624 'value' => $course->id,
625 'class' => 'bulk-action-checkbox',
a5888fb5
RT
626 'aria-label' => get_string('bulkactionselect', 'moodle', $text),
627 'data-action' => 'select'
d0647301 628 );
484c4c6c
SH
629 if (!$category->has_manage_capability()) {
630 // Very very hardcoded here.
631 $bulkcourseinput['style'] = 'visibility:hidden';
632 }
633
5dc361e1
SH
634 $viewcourseurl = new moodle_url($this->page->url, array('courseid' => $course->id));
635
636 $html = html_writer::start_tag('li', $attributes);
637 $html .= html_writer::start_div('clearfix');
638
67e1f268 639 if ($category->can_resort_courses()) {
5dc361e1 640 // In order for dnd to be available the user must be able to resort the category children..
10a2bf46 641 $html .= html_writer::div($this->output->pix_icon('i/move_2d', get_string('dndcourse')), 'float-left drag-handle');
5dc361e1
SH
642 }
643
3b681e6c 644 $html .= html_writer::start_div('ba-checkbox float-left');
7fd307b1 645 $html .= html_writer::empty_tag('input', $bulkcourseinput).'&nbsp;';
5dc361e1
SH
646 $html .= html_writer::end_div();
647 $html .= html_writer::link($viewcourseurl, $text, array('class' => 'float-left coursename'));
648 $html .= html_writer::start_div('float-right');
c7a2291f
SH
649 if ($course->idnumber) {
650 $html .= html_writer::tag('span', s($course->idnumber), array('class' => 'dimmed idnumber'));
651 }
f454e324 652 $html .= $this->course_listitem_actions($category, $course);
5dc361e1
SH
653 $html .= html_writer::end_div();
654 $html .= html_writer::end_div();
655 $html .= html_writer::end_tag('li');
656 return $html;
657 }
658
659 /**
660 * Renderers actions for the course listing.
661 *
662 * Not to be confused with course_listitem_actions which renderers the actions for individual courses.
663 *
664 * @param coursecat $category
665 * @param course_in_list $course The currently selected course.
666 * @param int $perpage
667 * @return string
668 */
669 public function course_listing_actions(coursecat $category, course_in_list $course = null, $perpage = 20) {
670 $actions = array();
671 if ($category->can_create_course()) {
672 $url = new moodle_url('/course/edit.php', array('category' => $category->id, 'returnto' => 'catmanage'));
d3670843 673 $actions[] = html_writer::link($url, get_string('createnewcourse'));
5dc361e1 674 }
484c4c6c
SH
675 if ($category->can_request_course()) {
676 // Request a new course.
677 $url = new moodle_url('/course/request.php', array('return' => 'management'));
678 $actions[] = html_writer::link($url, get_string('requestcourse'));
679 }
67e1f268 680 if ($category->can_resort_courses()) {
5dc361e1
SH
681 $params = $this->page->url->params();
682 $params['action'] = 'resortcourses';
683 $params['sesskey'] = sesskey();
684 $baseurl = new moodle_url('/course/management.php', $params);
685 $fullnameurl = new moodle_url($baseurl, array('resort' => 'fullname'));
9a4231e9 686 $fullnameurldesc = new moodle_url($baseurl, array('resort' => 'fullnamedesc'));
5dc361e1 687 $shortnameurl = new moodle_url($baseurl, array('resort' => 'shortname'));
9a4231e9 688 $shortnameurldesc = new moodle_url($baseurl, array('resort' => 'shortnamedesc'));
5dc361e1 689 $idnumberurl = new moodle_url($baseurl, array('resort' => 'idnumber'));
9a4231e9
S
690 $idnumberdescurl = new moodle_url($baseurl, array('resort' => 'idnumberdesc'));
691 $timecreatedurl = new moodle_url($baseurl, array('resort' => 'timecreated'));
692 $timecreateddescurl = new moodle_url($baseurl, array('resort' => 'timecreateddesc'));
5dc361e1 693 $menu = new action_menu(array(
9a4231e9
S
694 new action_menu_link_secondary($fullnameurl,
695 null,
696 get_string('sortbyx', 'moodle', get_string('fullnamecourse'))),
697 new action_menu_link_secondary($fullnameurldesc,
698 null,
699 get_string('sortbyxreverse', 'moodle', get_string('fullnamecourse'))),
700 new action_menu_link_secondary($shortnameurl,
701 null,
702 get_string('sortbyx', 'moodle', get_string('shortnamecourse'))),
703 new action_menu_link_secondary($shortnameurldesc,
704 null,
705 get_string('sortbyxreverse', 'moodle', get_string('shortnamecourse'))),
706 new action_menu_link_secondary($idnumberurl,
707 null,
708 get_string('sortbyx', 'moodle', get_string('idnumbercourse'))),
709 new action_menu_link_secondary($idnumberdescurl,
710 null,
711 get_string('sortbyxreverse', 'moodle', get_string('idnumbercourse'))),
712 new action_menu_link_secondary($timecreatedurl,
713 null,
714 get_string('sortbyx', 'moodle', get_string('timecreatedcourse'))),
715 new action_menu_link_secondary($timecreateddescurl,
716 null,
717 get_string('sortbyxreverse', 'moodle', get_string('timecreatedcourse')))
5dc361e1 718 ));
f5b33487 719 $menu->set_menu_trigger(get_string('resortcourses'));
5dc361e1
SH
720 $actions[] = $this->render($menu);
721 }
722 $strall = get_string('all');
723 $menu = new action_menu(array(
724 new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 5)), null, 5),
725 new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 10)), null, 10),
726 new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 20)), null, 20),
727 new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 50)), null, 50),
728 new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 100)), null, 100),
729 new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 999)), null, $strall),
730 ));
7fd307b1 731 if ((int)$perpage === 999) {
5dc361e1
SH
732 $perpage = $strall;
733 }
734 $menu->attributes['class'] .= ' courses-per-page';
f5b33487 735 $menu->set_menu_trigger(get_string('perpagea', 'moodle', $perpage));
5dc361e1
SH
736 $actions[] = $this->render($menu);
737 return html_writer::div(join(' | ', $actions), 'listing-actions course-listing-actions');
738 }
739
740 /**
741 * Renderers actions for individual course actions.
742 *
743 * @param coursecat $category The currently selected category.
744 * @param course_in_list $course The course to renderer actions for.
5dc361e1
SH
745 * @return string
746 */
f454e324 747 public function course_listitem_actions(coursecat $category, course_in_list $course) {
484c4c6c 748 $actions = \core_course\management\helper::get_course_listitem_actions($category, $course);
5dc361e1
SH
749 if (empty($actions)) {
750 return '';
751 }
484c4c6c
SH
752 $actionshtml = array();
753 foreach ($actions as $action) {
7fd307b1 754 $action['attributes']['role'] = 'button';
484c4c6c
SH
755 $actionshtml[] = $this->output->action_icon($action['url'], $action['icon'], null, $action['attributes']);
756 }
757 return html_writer::span(join('', $actionshtml), 'course-item-actions item-actions');
5dc361e1
SH
758 }
759
760 /**
761 * Renderers bulk actions that can be performed on courses.
762 *
763 * @param coursecat $category The currently selected category and the category in which courses that
764 * are selectable belong.
765 * @return string
766 */
767 public function course_bulk_actions(coursecat $category) {
768 $html = html_writer::start_div('course-bulk-actions bulk-actions');
769 if ($category->can_move_courses_out_of()) {
cd96b7d3 770 $html .= html_writer::div(get_string('coursebulkaction'), 'accesshide', array('tabindex' => '0'));
5dc361e1 771 $options = coursecat::make_categories_list('moodle/category:manage');
7fd307b1
SH
772 $select = html_writer::select(
773 $options,
774 'movecoursesto',
775 '',
776 array('' => 'choosedots'),
777 array('aria-labelledby' => 'moveselectedcoursesto')
778 );
e69a0251 779 $submit = array('type' => 'submit', 'name' => 'bulkmovecourses', 'value' => get_string('move'));
5dc361e1 780 $html .= $this->detail_pair(
7fd307b1 781 html_writer::span(get_string('moveselectedcoursesto'), '', array('id' => 'moveselectedcoursesto')),
5dc361e1
SH
782 $select . html_writer::empty_tag('input', $submit)
783 );
784 }
785 $html .= html_writer::end_div();
786 return $html;
787 }
788
789 /**
790 * Renderers detailed course information.
791 *
792 * @param course_in_list $course The course to display details for.
793 * @return string
794 */
795 public function course_detail(course_in_list $course) {
796 $details = \core_course\management\helper::get_course_detail_array($course);
797 $fullname = $details['fullname']['value'];
798
799 $html = html_writer::start_div('course-detail');
d0647301 800 $html .= html_writer::tag('h3', $fullname, array('id' => 'course-detail-title', 'tabindex' => '0'));
5dc361e1
SH
801 $html .= $this->course_detail_actions($course);
802 foreach ($details as $class => $data) {
803 $html .= $this->detail_pair($data['key'], $data['value'], $class);
804 }
805 $html .= html_writer::end_div();
806 return $html;
807 }
808
809 /**
810 * Renderers a key value pair of information for display.
811 *
812 * @param string $key
813 * @param string $value
814 * @param string $class
815 * @return string
816 */
817 protected function detail_pair($key, $value, $class ='') {
484c4c6c
SH
818 $html = html_writer::start_div('detail-pair row yui3-g '.preg_replace('#[^a-zA-Z0-9_\-]#', '-', $class));
819 $html .= html_writer::div(html_writer::span($key), 'pair-key span3 yui3-u-1-4');
820 $html .= html_writer::div(html_writer::span($value), 'pair-value span9 yui3-u-3-4');
5dc361e1
SH
821 $html .= html_writer::end_div();
822 return $html;
823 }
824
825 /**
826 * A collection of actions for a course.
827 *
828 * @param course_in_list $course The course to display actions for.
829 * @return string
830 */
831 public function course_detail_actions(course_in_list $course) {
832 $actions = \core_course\management\helper::get_course_detail_actions($course);
833 if (empty($actions)) {
834 return '';
835 }
836 $options = array();
837 foreach ($actions as $action) {
484c4c6c 838 $options[] = $this->action_link($action['url'], $action['string']);
5dc361e1 839 }
484c4c6c 840 return html_writer::div(join(' | ', $options), 'listing-actions course-detail-listing-actions');
5dc361e1
SH
841 }
842
843 /**
844 * Creates an action button (styled link)
845 *
846 * @param moodle_url $url The URL to go to when clicked.
847 * @param string $text The text for the button.
848 * @param string $id An id to give the button.
849 * @param string $class A class to give the button.
d0647301 850 * @param array $attributes Any additional attributes
5dc361e1
SH
851 * @return string
852 */
d0647301
SH
853 protected function action_button(moodle_url $url, $text, $id = null, $class = null, $title = null, array $attributes = array()) {
854 if (isset($attributes['class'])) {
855 $attributes['class'] .= ' yui3-button';
856 } else {
857 $attributes['class'] = 'yui3-button';
858 }
5dc361e1
SH
859 if (!is_null($id)) {
860 $attributes['id'] = $id;
861 }
862 if (!is_null($class)) {
863 $attributes['class'] .= ' '.$class;
864 }
7fd307b1
SH
865 if (is_null($title)) {
866 $title = $text;
867 }
868 $attributes['title'] = $title;
d0647301
SH
869 if (!isset($attributes['role'])) {
870 $attributes['role'] = 'button';
871 }
5dc361e1
SH
872 return html_writer::link($url, $text, $attributes);
873 }
874
875 /**
876 * Opens a grid.
877 *
878 * Call {@link core_course_management_renderer::grid_column_start()} to create columns.
879 *
880 * @param string $id An id to give this grid.
881 * @param string $class A class to give this grid.
882 * @return string
883 */
884 public function grid_start($id = null, $class = null) {
885 $gridclass = 'grid-row-r row-fluid';
886 if (is_null($class)) {
887 $class = $gridclass;
888 } else {
889 $class .= ' ' . $gridclass;
890 }
891 $attributes = array();
892 if (!is_null($id)) {
893 $attributes['id'] = $id;
894 }
895 return html_writer::start_div($class, $attributes);
896 }
897
898 /**
899 * Closes the grid.
900 *
901 * @return string
902 */
903 public function grid_end() {
904 return html_writer::end_div();
905 }
906
907 /**
908 * Opens a grid column
909 *
910 * @param int $size The number of segments this column should span.
911 * @param string $id An id to give the column.
912 * @param string $class A class to give the column.
913 * @return string
914 */
915 public function grid_column_start($size, $id = null, $class = null) {
916
917 // Calculate Bootstrap grid sizing.
918 $bootstrapclass = 'span'.$size;
919
920 // Calculate YUI grid sizing.
921 if ($size === 12) {
922 $maxsize = 1;
923 $size = 1;
924 } else {
925 $maxsize = 12;
926 $divisors = array(8, 6, 5, 4, 3, 2);
927 foreach ($divisors as $divisor) {
928 if (($maxsize % $divisor === 0) && ($size % $divisor === 0)) {
929 $maxsize = $maxsize / $divisor;
930 $size = $size / $divisor;
931 break;
932 }
933 }
934 }
935 if ($maxsize > 1) {
936 $yuigridclass = "grid-col-{$size}-{$maxsize} grid-col";
937 } else {
938 $yuigridclass = "grid-col-1 grid-col";
939 }
940
941 if (is_null($class)) {
942 $class = $yuigridclass . ' ' . $bootstrapclass;
943 } else {
944 $class .= ' ' . $yuigridclass . ' ' . $bootstrapclass;
945 }
946 $attributes = array();
947 if (!is_null($id)) {
948 $attributes['id'] = $id;
949 }
950 return html_writer::start_div($class, $attributes);
951 }
952
953 /**
954 * Closes a grid column.
955 *
956 * @return string
957 */
958 public function grid_column_end() {
959 return html_writer::end_div();
960 }
961
962 /**
963 * Renders an action_icon.
964 *
965 * This function uses the {@link core_renderer::action_link()} method for the
966 * most part. What it does different is prepare the icon as HTML and use it
967 * as the link text.
968 *
969 * @param string|moodle_url $url A string URL or moodel_url
970 * @param pix_icon $pixicon
971 * @param component_action $action
972 * @param array $attributes associative array of html link attributes + disabled
973 * @param bool $linktext show title next to image in link
974 * @return string HTML fragment
975 */
976 public function action_icon($url, pix_icon $pixicon, component_action $action = null,
977 array $attributes = null, $linktext = false) {
978 if (!($url instanceof moodle_url)) {
979 $url = new moodle_url($url);
980 }
981 $attributes = (array)$attributes;
982
983 if (empty($attributes['class'])) {
984 // Let devs override the class via $attributes.
985 $attributes['class'] = 'action-icon';
986 }
987
988 $icon = $this->render($pixicon);
989
990 if ($linktext) {
991 $text = $pixicon->attributes['alt'];
992 } else {
993 $text = '';
994 }
995
996 return $this->action_link($url, $icon.$text, $action, $attributes);
997 }
998
999 /**
1000 * Displays a view mode selector.
1001 *
1002 * @param array $modes An array of view modes.
1003 * @param string $currentmode The current view mode.
1004 * @param moodle_url $url The URL to use when changing actions. Defaults to the page URL.
1005 * @param string $param The param name.
1006 * @return string
1007 */
1008 public function view_mode_selector(array $modes, $currentmode, moodle_url $url = null, $param = 'view') {
1009 if ($url === null) {
1010 $url = $this->page->url;
1011 }
1012
1013 $menu = new action_menu;
1014 $menu->attributes['class'] .= ' view-mode-selector vms';
1015
1016 $selected = null;
1017 foreach ($modes as $mode => $modestr) {
1018 $attributes = array(
1019 'class' => 'vms-mode',
1020 'data-mode' => $mode
1021 );
1022 if ($currentmode === $mode) {
1023 $attributes['class'] .= ' currentmode';
1024 $selected = $modestr;
1025 }
1026 if ($selected === null) {
1027 $selected = $modestr;
1028 }
1029 $modeurl = new moodle_url($url, array($param => $mode));
1030 if ($mode === 'default') {
1031 $modeurl->remove_params($param);
1032 }
1033 $menu->add(new action_menu_link_secondary($modeurl, null, $modestr, $attributes));
1034 }
1035
aa861f62 1036 $menu->set_menu_trigger($selected);
5dc361e1
SH
1037
1038 $html = html_writer::start_div('view-mode-selector vms');
aa861f62 1039 $html .= get_string('viewing').' '.$this->render($menu);
5dc361e1
SH
1040 $html .= html_writer::end_div();
1041
1042 return $html;
1043 }
1044
1045 /**
1046 * Displays a search result listing.
1047 *
1048 * @param array $courses The courses to display.
1049 * @param int $totalcourses The total number of courses to display.
1050 * @param course_in_list $course The currently selected course if there is one.
1051 * @param int $page The current page, starting at 0.
1052 * @param int $perpage The number of courses to display per page.
09fef88c 1053 * @param string $search The string we are searching for.
5dc361e1
SH
1054 * @return string
1055 */
09fef88c
MN
1056 public function search_listing(array $courses, $totalcourses, course_in_list $course = null, $page = 0, $perpage = 20,
1057 $search = '') {
5dc361e1
SH
1058 $page = max($page, 0);
1059 $perpage = max($perpage, 2);
1060 $totalpages = ceil($totalcourses / $perpage);
1061 if ($page > $totalpages - 1) {
1062 $page = $totalpages - 1;
1063 }
1064 $courseid = isset($course) ? $course->id : null;
1065 $first = true;
1066 $last = false;
1067 $i = $page * $perpage;
1068
1069 $html = html_writer::start_div('course-listing', array(
1070 'data-category' => 'search',
1071 'data-page' => $page,
1072 'data-totalpages' => $totalpages,
1073 'data-totalcourses' => $totalcourses
1074 ));
1075 $html .= html_writer::tag('h3', get_string('courses'));
1076 $html .= $this->search_pagination($totalcourses, $page, $perpage);
1077 $html .= html_writer::start_tag('ul', array('class' => 'ml'));
1078 foreach ($courses as $listitem) {
1079 $i++;
1080 if ($i == $totalcourses) {
1081 $last = true;
1082 }
1083 $html .= $this->search_listitem($listitem, $courseid, $first, $last);
1084 $first = false;
1085 }
1086 $html .= html_writer::end_tag('ul');
09fef88c 1087 $html .= $this->search_pagination($totalcourses, $page, $perpage, true, $search);
5dc361e1
SH
1088 $html .= html_writer::end_div();
1089 return $html;
1090 }
1091
1092 /**
1093 * Displays pagination for search results.
1094 *
1095 * @param int $totalcourses The total number of courses to be displayed.
1096 * @param int $page The current page.
1097 * @param int $perpage The number of courses being displayed.
1098 * @param bool $showtotals Whether or not to print total information.
09fef88c 1099 * @param string $search The string we are searching for.
5dc361e1
SH
1100 * @return string
1101 */
09fef88c 1102 protected function search_pagination($totalcourses, $page, $perpage, $showtotals = false, $search = '') {
5dc361e1
SH
1103 $html = '';
1104 $totalpages = ceil($totalcourses / $perpage);
1105 if ($showtotals) {
09fef88c
MN
1106 if ($totalpages == 0) {
1107 $str = get_string('nocoursesfound', 'moodle', $search);
1108 } else if ($totalpages == 1) {
5dc361e1
SH
1109 $str = get_string('showingacourses', 'moodle', $totalcourses);
1110 } else {
1111 $a = new stdClass;
1112 $a->start = ($page * $perpage) + 1;
1113 $a->end = min((($page + 1) * $perpage), $totalcourses);
1114 $a->total = $totalcourses;
1115 $str = get_string('showingxofycourses', 'moodle', $a);
1116 }
1117 $html .= html_writer::div($str, 'listing-pagination-totals dimmed');
1118 }
1119
1120 if ($totalcourses < $perpage) {
1121 return $html;
1122 }
1123 $aside = 2;
1124 $span = $aside * 2 + 1;
1125 $start = max($page - $aside, 0);
1126 $end = min($page + $aside, $totalpages - 1);
1127 if (($end - $start) < $span) {
1128 if ($start == 0) {
1129 $end = min($totalpages - 1, $span - 1);
1130 } else if ($end == ($totalpages - 1)) {
1131 $start = max(0, $end - $span + 1);
1132 }
1133 }
1134 $items = array();
1135 $baseurl = $this->page->url;
1136 if ($page > 0) {
1137 $items[] = $this->action_button(new moodle_url($baseurl, array('page' => 0)), get_string('first'));
1138 $items[] = $this->action_button(new moodle_url($baseurl, array('page' => $page - 1)), get_string('prev'));
1139 $items[] = '...';
1140 }
1141 for ($i = $start; $i <= $end; $i++) {
1142 $class = '';
1143 if ($page == $i) {
1144 $class = 'active-page';
1145 }
1146 $items[] = $this->action_button(new moodle_url($baseurl, array('page' => $i)), $i + 1, null, $class);
1147 }
1148 if ($page < ($totalpages - 1)) {
1149 $items[] = '...';
1150 $items[] = $this->action_button(new moodle_url($baseurl, array('page' => $page + 1)), get_string('next'));
1151 $items[] = $this->action_button(new moodle_url($baseurl, array('page' => $totalpages - 1)), get_string('last'));
1152 }
1153
1154 $html .= html_writer::div(join('', $items), 'listing-pagination');
1155 return $html;
1156 }
1157
1158 /**
1159 * Renderers a search result course list item.
1160 *
1161 * This function will be called for every course being displayed by course_listing.
1162 *
1163 * @param course_in_list $course The course to produce HTML for.
1164 * @param int $selectedcourse The id of the currently selected course.
1165 * @return string
1166 */
1167 public function search_listitem(course_in_list $course, $selectedcourse) {
1168
1169 $text = $course->get_formatted_name();
1170 $attributes = array(
1171 'class' => 'listitem listitem-course',
1172 'data-id' => $course->id,
1173 'data-selected' => ($selectedcourse == $course->id) ? '1' : '0',
1174 'data-visible' => $course->visible ? '1' : '0'
1175 );
1176
1177 $bulkcourseinput = array('type' => 'checkbox', 'name' => 'bc[]', 'value' => $course->id, 'class' => 'bulk-action-checkbox');
1178 $viewcourseurl = new moodle_url($this->page->url, array('courseid' => $course->id));
1179 $categoryname = coursecat::get($course->category)->get_formatted_name();
1180
1181 $html = html_writer::start_tag('li', $attributes);
1182 $html .= html_writer::start_div('clearfix');
1183 $html .= html_writer::start_div('float-left');
7fd307b1 1184 $html .= html_writer::empty_tag('input', $bulkcourseinput).'&nbsp;';
5dc361e1
SH
1185 $html .= html_writer::end_div();
1186 $html .= html_writer::link($viewcourseurl, $text, array('class' => 'float-left coursename'));
1187 $html .= html_writer::tag('span', $categoryname, array('class' => 'float-left categoryname'));
1188 $html .= html_writer::start_div('float-right');
1189 $html .= $this->search_listitem_actions($course);
1190 $html .= html_writer::tag('span', s($course->idnumber), array('class' => 'dimmed idnumber'));
1191 $html .= html_writer::end_div();
1192 $html .= html_writer::end_div();
1193 $html .= html_writer::end_tag('li');
1194 return $html;
1195 }
1196
1197 /**
1198 * Renderers actions for individual course actions.
1199 *
1200 * @param course_in_list $course The course to renderer actions for.
1201 * @return string
1202 */
1203 public function search_listitem_actions(course_in_list $course) {
1204 $baseurl = new moodle_url(
1205 '/course/managementsearch.php',
1206 array('courseid' => $course->id, 'categoryid' => $course->category, 'sesskey' => sesskey())
1207 );
1208 $actions = array();
1209 // Edit.
484c4c6c
SH
1210 if ($course->can_access()) {
1211 if ($course->can_edit()) {
5dc361e1 1212 $actions[] = $this->output->action_icon(
484c4c6c
SH
1213 new moodle_url('/course/edit.php', array('id' => $course->id)),
1214 new pix_icon('t/edit', get_string('edit')),
5dc361e1 1215 null,
484c4c6c 1216 array('class' => 'action-edit')
5dc361e1
SH
1217 );
1218 }
14cea316
WL
1219 // Delete.
1220 if ($course->can_delete()) {
1221 $actions[] = $this->output->action_icon(
1222 new moodle_url('/course/delete.php', array('id' => $course->id)),
1223 new pix_icon('t/delete', get_string('delete')),
1224 null,
1225 array('class' => 'action-delete')
1226 );
1227 }
484c4c6c
SH
1228 // Show/Hide.
1229 if ($course->can_change_visibility()) {
484c4c6c
SH
1230 $actions[] = $this->output->action_icon(
1231 new moodle_url($baseurl, array('action' => 'hidecourse')),
617dbe49 1232 new pix_icon('t/hide', get_string('hide')),
484c4c6c
SH
1233 null,
1234 array('data-action' => 'hide', 'class' => 'action-hide')
1235 );
484c4c6c
SH
1236 $actions[] = $this->output->action_icon(
1237 new moodle_url($baseurl, array('action' => 'showcourse')),
617dbe49 1238 new pix_icon('t/show', get_string('show')),
484c4c6c
SH
1239 null,
1240 array('data-action' => 'show', 'class' => 'action-show')
1241 );
484c4c6c 1242 }
5dc361e1
SH
1243 }
1244 if (empty($actions)) {
1245 return '';
1246 }
1247 return html_writer::span(join('', $actions), 'course-item-actions item-actions');
1248 }
1249
4b07116a
WL
1250 /**
1251 * Renders html to display a course search form
1252 *
1253 * @param string $value default value to populate the search field
1254 * @param string $format display format - 'plain' (default), 'short' or 'navbar'
1255 * @return string
1256 */
1257 public function course_search_form($value = '', $format = 'plain') {
1258 static $count = 0;
1259 $formid = 'coursesearch';
1260 if ((++$count) > 1) {
1261 $formid .= $count;
1262 }
1263
1264 switch ($format) {
1265 case 'navbar' :
1266 $formid = 'coursesearchnavbar';
1267 $inputid = 'navsearchbox';
1268 $inputsize = 20;
1269 break;
1270 case 'short' :
1271 $inputid = 'shortsearchbox';
1272 $inputsize = 12;
1273 break;
1274 default :
1275 $inputid = 'coursesearchbox';
1276 $inputsize = 30;
1277 }
1278
1279 $strsearchcourses = get_string("searchcourses");
1280 $searchurl = new moodle_url('/course/management.php');
1281
1282 $output = html_writer::start_tag('form', array('id' => $formid, 'action' => $searchurl, 'method' => 'get'));
1283 $output .= html_writer::start_tag('fieldset', array('class' => 'coursesearchbox invisiblefieldset'));
1284 $output .= html_writer::tag('label', $strsearchcourses.': ', array('for' => $inputid));
1285 $output .= html_writer::empty_tag('input', array('type' => 'text', 'id' => $inputid,
1286 'size' => $inputsize, 'name' => 'search', 'value' => s($value)));
1287 $output .= html_writer::empty_tag('input', array('type' => 'submit',
1288 'value' => get_string('go')));
1289 $output .= html_writer::end_tag('fieldset');
1290 $output .= html_writer::end_tag('form');
1291
1292 return $output;
1293 }
1294
d0647301
SH
1295 /**
1296 * Creates access hidden skip to links for the displayed sections.
1297 *
1298 * @param bool $displaycategorylisting
1299 * @param bool $displaycourselisting
1300 * @param bool $displaycoursedetail
1301 * @return string
1302 */
1303 public function accessible_skipto_links($displaycategorylisting, $displaycourselisting, $displaycoursedetail) {
1304 $html = html_writer::start_div('skiplinks accesshide');
1305 $url = new moodle_url($this->page->url);
1306 if ($displaycategorylisting) {
1307 $url->set_anchor('category-listing');
1308 $html .= html_writer::link($url, get_string('skiptocategorylisting'), array('class' => 'skip'));
1309 }
cd96b7d3 1310 if ($displaycourselisting) {
d0647301
SH
1311 $url->set_anchor('course-listing');
1312 $html .= html_writer::link($url, get_string('skiptocourselisting'), array('class' => 'skip'));
1313 }
cd96b7d3 1314 if ($displaycoursedetail) {
d0647301
SH
1315 $url->set_anchor('course-detail');
1316 $html .= html_writer::link($url, get_string('skiptocoursedetails'), array('class' => 'skip'));
1317 }
1318 $html .= html_writer::end_div();
1319 return $html;
1320 }
1321
9e164027 1322}