MDL-58428 renderer: Move renderer override from course management
[moodle.git] / theme / bootstrapbase / classes / output / core_course / management / renderer.php
CommitLineData
3ec69c2e
BB
1<?php
2// This file is part of The Bootstrap Moodle theme
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 * Renderers to align Moodle's HTML with that expected by Bootstrap
19 *
9f0595c4 20 * @package theme_bootstrapbase
3ec69c2e
BB
21 * @copyright 2018 Bas Brands
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
9f0595c4 25namespace theme_bootstrapbase\output\core_course\management;
3ec69c2e
BB
26defined('MOODLE_INTERNAL') || die();
27
28require_once($CFG->dirroot . "/course/classes/management_renderer.php");
29
30use html_writer;
442f12f8 31use core_course_category;
3ec69c2e 32use moodle_url;
442f12f8 33use core_course_list_element;
3ec69c2e
BB
34use lang_string;
35use context_system;
36use stdClass;
37use action_menu;
38use action_menu_link_secondary;
39
40/**
41 * Main renderer for the course management pages.
42 *
9f0595c4 43 * @package theme_bootstrapbase
3ec69c2e
BB
44 * @copyright 2013 Sam Hemelryk
45 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
46 */
47class renderer extends \core_course_management_renderer {
48
49 /**
50 * Opens a grid.
51 *
52 * Call {@link core_course_management_renderer::grid_column_start()} to create columns.
53 *
54 * @param string $id An id to give this grid.
55 * @param string $class A class to give this grid.
56 * @return string
57 */
58 public function grid_start($id = null, $class = null) {
9f0595c4 59 $gridclass = 'grid-row-r row-fluid';
3ec69c2e
BB
60 if (is_null($class)) {
61 $class = $gridclass;
62 } else {
63 $class .= ' ' . $gridclass;
64 }
65 $attributes = array();
66 if (!is_null($id)) {
67 $attributes['id'] = $id;
68 }
69 return html_writer::start_div($class, $attributes);
70 }
71
72 /**
73 * Opens a grid column
74 *
75 * @param int $size The number of segments this column should span.
76 * @param string $id An id to give the column.
77 * @param string $class A class to give the column.
78 * @return string
79 */
80 public function grid_column_start($size, $id = null, $class = null) {
81
9f0595c4
MM
82 // Calculate Bootstrap grid sizing.
83 $bootstrapclass = 'span'.$size.' col-md-'.$size;
84
85 // Calculate YUI grid sizing.
86 if ($size === 12) {
87 $maxsize = 1;
88 $size = 1;
3ec69c2e 89 } else {
9f0595c4
MM
90 $maxsize = 12;
91 $divisors = array(8, 6, 5, 4, 3, 2);
92 foreach ($divisors as $divisor) {
93 if (($maxsize % $divisor === 0) && ($size % $divisor === 0)) {
94 $maxsize = $maxsize / $divisor;
95 $size = $size / $divisor;
96 break;
97 }
98 }
99 }
100 if ($maxsize > 1) {
101 $yuigridclass = "grid-col-{$size}-{$maxsize} grid-col";
102 } else {
103 $yuigridclass = "grid-col-1 grid-col";
3ec69c2e 104 }
3ec69c2e
BB
105
106 if (is_null($class)) {
107 $class = $yuigridclass . ' ' . $bootstrapclass;
108 } else {
109 $class .= ' ' . $yuigridclass . ' ' . $bootstrapclass;
110 }
111 $attributes = array();
112 if (!is_null($id)) {
113 $attributes['id'] = $id;
114 }
9f0595c4 115 return html_writer::start_div($class, $attributes);
3ec69c2e
BB
116 }
117
118 /**
119 * Renderers detailed course information.
120 *
9f0595c4 121 * @param core_course_list_element $course The course to display details for.
3ec69c2e
BB
122 * @return string
123 */
442f12f8 124 public function course_detail(core_course_list_element $course) {
3ec69c2e
BB
125 $details = \core_course\management\helper::get_course_detail_array($course);
126 $fullname = $details['fullname']['value'];
127
9f0595c4
MM
128 $html = html_writer::start_div('course-detail');
129 $html .= html_writer::tag('h3', $fullname, array('id' => 'course-detail-title', 'tabindex' => '0'));
3ec69c2e
BB
130 $html .= $this->course_detail_actions($course);
131 foreach ($details as $class => $data) {
132 $html .= $this->detail_pair($data['key'], $data['value'], $class);
133 }
134 $html .= html_writer::end_div();
3ec69c2e
BB
135 return $html;
136 }
137
138 /**
139 * Renders html to display a course search form
140 *
141 * @param string $value default value to populate the search field
142 * @param string $format display format - 'plain' (default), 'short' or 'navbar'
143 * @return string
144 */
145 public function course_search_form($value = '', $format = 'plain') {
146 static $count = 0;
147 $formid = 'coursesearch';
148 if ((++$count) > 1) {
149 $formid .= $count;
150 }
151
152 switch ($format) {
153 case 'navbar' :
154 $formid = 'coursesearchnavbar';
155 $inputid = 'navsearchbox';
156 $inputsize = 20;
157 break;
158 case 'short' :
159 $inputid = 'shortsearchbox';
160 $inputsize = 12;
161 break;
162 default :
163 $inputid = 'coursesearchbox';
164 $inputsize = 30;
165 }
166
167 $strsearchcourses = get_string("searchcourses");
168 $searchurl = new moodle_url('/course/management.php');
169
9f0595c4
MM
170 $output = html_writer::start_tag('form', array('id' => $formid, 'action' => $searchurl, 'method' => 'get',
171 'class' => 'form-inline'));
172 $output .= html_writer::start_tag('fieldset', array('class' => 'coursesearchbox invisiblefieldset m-y-1'));
173 $output .= html_writer::tag('label', $strsearchcourses, array('for' => $inputid));
174 $output .= html_writer::empty_tag('input', array('type' => 'text', 'id' => $inputid, 'size' => $inputsize,
175 'name' => 'search', 'value' => s($value), 'class' => 'form-control m-x-1'));
176 $output .= html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('go'),
177 'class' => 'btn btn-secondary'));
3ec69c2e
BB
178 $output .= html_writer::end_tag('fieldset');
179 $output .= html_writer::end_tag('form');
3ec69c2e
BB
180
181 return $output;
182 }
183
184 /**
185 * Presents a course category listing.
186 *
442f12f8 187 * @param core_course_category $category The currently selected category. Also the category to highlight in the listing.
3ec69c2e
BB
188 * @return string
189 */
442f12f8 190 public function category_listing(core_course_category $category = null) {
3ec69c2e
BB
191
192 if ($category === null) {
193 $selectedparents = array();
194 $selectedcategory = null;
195 } else {
196 $selectedparents = $category->get_parents();
197 $selectedparents[] = $category->id;
198 $selectedcategory = $category->id;
199 }
200 $catatlevel = \core_course\management\helper::get_expanded_categories('');
201 $catatlevel[] = array_shift($selectedparents);
202 $catatlevel = array_unique($catatlevel);
203
442f12f8 204 $listing = core_course_category::get(0)->get_children();
3ec69c2e
BB
205
206 $attributes = array(
9f0595c4
MM
207 'class' => 'ml',
208 'role' => 'tree',
209 'aria-labelledby' => 'category-listing-title'
3ec69c2e
BB
210 );
211
9f0595c4
MM
212 $html = html_writer::start_div('category-listing');
213 $html .= html_writer::tag('h3', get_string('categories'), array('id' => 'category-listing-title'));
3ec69c2e
BB
214 $html .= $this->category_listing_actions($category);
215 $html .= html_writer::start_tag('ul', $attributes);
216 foreach ($listing as $listitem) {
217 // Render each category in the listing.
218 $subcategories = array();
219 if (in_array($listitem->id, $catatlevel)) {
220 $subcategories = $listitem->get_children();
221 }
222 $html .= $this->category_listitem(
9f0595c4
MM
223 $listitem,
224 $subcategories,
225 $listitem->get_children_count(),
226 $selectedcategory,
227 $selectedparents
3ec69c2e
BB
228 );
229 }
230 $html .= html_writer::end_tag('ul');
231 $html .= $this->category_bulk_actions($category);
232 $html .= html_writer::end_div();
3ec69c2e
BB
233 return $html;
234 }
235
236 /**
237 * Renders a category list item.
238 *
239 * This function gets called recursively to render sub categories.
240 *
442f12f8
MG
241 * @param core_course_category $category The category to render as listitem.
242 * @param core_course_category[] $subcategories The subcategories belonging to the category being rented.
3ec69c2e
BB
243 * @param int $totalsubcategories The total number of sub categories.
244 * @param int $selectedcategory The currently selected category
245 * @param int[] $selectedcategories The path to the selected category and its ID.
246 * @return string
247 */
442f12f8 248 public function category_listitem(core_course_category $category, array $subcategories, $totalsubcategories,
9f0595c4 249 $selectedcategory = null, $selectedcategories = array()) {
3ec69c2e
BB
250
251 $isexpandable = ($totalsubcategories > 0);
252 $isexpanded = (!empty($subcategories));
253 $activecategory = ($selectedcategory === $category->id);
254 $attributes = array(
9f0595c4
MM
255 'class' => 'listitem listitem-category',
256 'data-id' => $category->id,
257 'data-expandable' => $isexpandable ? '1' : '0',
258 'data-expanded' => $isexpanded ? '1' : '0',
259 'data-selected' => $activecategory ? '1' : '0',
260 'data-visible' => $category->visible ? '1' : '0',
261 'role' => 'treeitem',
262 'aria-expanded' => $isexpanded ? 'true' : 'false'
3ec69c2e
BB
263 );
264 $text = $category->get_formatted_name();
265 if ($category->parent) {
266 $a = new stdClass;
267 $a->category = $text;
268 $a->parentcategory = $category->get_parent_coursecat()->get_formatted_name();
269 $textlabel = get_string('categorysubcategoryof', 'moodle', $a);
270 }
271 $courseicon = $this->output->pix_icon('i/course', get_string('courses'));
272 $bcatinput = array(
9f0595c4
MM
273 'type' => 'checkbox',
274 'name' => 'bcat[]',
275 'value' => $category->id,
276 'class' => 'bulk-action-checkbox',
277 'aria-label' => get_string('bulkactionselect', 'moodle', $text),
278 'data-action' => 'select'
3ec69c2e
BB
279 );
280
281 if (!$category->can_resort_subcategories() && !$category->has_manage_capability()) {
282 // Very very hardcoded here.
283 $bcatinput['style'] = 'visibility:hidden';
284 }
285
286 $viewcaturl = new moodle_url('/course/management.php', array('categoryid' => $category->id));
287 if ($isexpanded) {
9f0595c4 288 $icon = $this->output->pix_icon('t/switch_minus', get_string('collapse'), 'moodle', array('class' => 'tree-icon', 'title' => ''));
3ec69c2e 289 $icon = html_writer::link(
9f0595c4
MM
290 $viewcaturl,
291 $icon,
292 array(
293 'class' => 'float-left',
294 'data-action' => 'collapse',
295 'title' => get_string('collapsecategory', 'moodle', $text),
296 'aria-controls' => 'subcategoryof'.$category->id
297 )
3ec69c2e
BB
298 );
299 } else if ($isexpandable) {
9f0595c4 300 $icon = $this->output->pix_icon('t/switch_plus', get_string('expand'), 'moodle', array('class' => 'tree-icon', 'title' => ''));
3ec69c2e 301 $icon = html_writer::link(
9f0595c4
MM
302 $viewcaturl,
303 $icon,
304 array(
305 'class' => 'float-left',
306 'data-action' => 'expand',
307 'title' => get_string('expandcategory', 'moodle', $text)
308 )
3ec69c2e
BB
309 );
310 } else {
311 $icon = $this->output->pix_icon(
9f0595c4
MM
312 'i/empty',
313 '',
314 'moodle',
315 array('class' => 'tree-icon'));
3ec69c2e
BB
316 $icon = html_writer::span($icon, 'float-left');
317 }
318 $actions = \core_course\management\helper::get_category_listitem_actions($category);
319 $hasactions = !empty($actions) || $category->can_create_course();
320
321 $html = html_writer::start_tag('li', $attributes);
322 $html .= html_writer::start_div('clearfix');
323 $html .= html_writer::start_div('float-left ba-checkbox');
324 $html .= html_writer::empty_tag('input', $bcatinput).'&nbsp;';
325 $html .= html_writer::end_div();
326 $html .= $icon;
327 if ($hasactions) {
328 $textattributes = array('class' => 'float-left categoryname');
329 } else {
330 $textattributes = array('class' => 'float-left categoryname without-actions');
331 }
332 if (isset($textlabel)) {
333 $textattributes['aria-label'] = $textlabel;
334 }
335 $html .= html_writer::link($viewcaturl, $text, $textattributes);
9f0595c4 336 $html .= html_writer::start_div('float-right');
3ec69c2e
BB
337 if ($category->idnumber) {
338 $html .= html_writer::tag('span', s($category->idnumber), array('class' => 'dimmed idnumber'));
339 }
340 if ($hasactions) {
341 $html .= $this->category_listitem_actions($category, $actions);
342 }
343 $countid = 'course-count-'.$category->id;
344 $html .= html_writer::span(
9f0595c4
MM
345 html_writer::span($category->get_courses_count()) .
346 html_writer::span(get_string('courses'), 'accesshide', array('id' => $countid)) .
347 $courseicon,
348 'course-count dimmed',
349 array('aria-labelledby' => $countid)
3ec69c2e
BB
350 );
351 $html .= html_writer::end_div();
352 $html .= html_writer::end_div();
353 if ($isexpanded) {
354 $html .= html_writer::start_tag('ul',
9f0595c4 355 array('class' => 'ml', 'role' => 'group', 'id' => 'subcategoryof'.$category->id));
3ec69c2e
BB
356 $catatlevel = \core_course\management\helper::get_expanded_categories($category->path);
357 $catatlevel[] = array_shift($selectedcategories);
358 $catatlevel = array_unique($catatlevel);
359 foreach ($subcategories as $listitem) {
360 $childcategories = (in_array($listitem->id, $catatlevel)) ? $listitem->get_children() : array();
361 $html .= $this->category_listitem(
9f0595c4
MM
362 $listitem,
363 $childcategories,
364 $listitem->get_children_count(),
365 $selectedcategory,
366 $selectedcategories
3ec69c2e
BB
367 );
368 }
369 $html .= html_writer::end_tag('ul');
370 }
371 $html .= html_writer::end_tag('li');
372 return $html;
373 }
374
375 /**
376 * Renderers the actions that are possible for the course category listing.
377 *
378 * These are not the actions associated with an individual category listing.
379 * That happens through category_listitem_actions.
380 *
442f12f8 381 * @param core_course_category $category
3ec69c2e
BB
382 * @return string
383 */
442f12f8 384 public function category_listing_actions(core_course_category $category = null) {
3ec69c2e
BB
385 $actions = array();
386
387 $cancreatecategory = $category && $category->can_create_subcategory();
442f12f8 388 $cancreatecategory = $cancreatecategory || core_course_category::can_create_top_level_category();
3ec69c2e 389 if ($category === null) {
442f12f8 390 $category = core_course_category::get(0);
3ec69c2e
BB
391 }
392
393 if ($cancreatecategory) {
394 $url = new moodle_url('/course/editcategory.php', array('parent' => $category->id));
9f0595c4 395 $actions[] = html_writer::link($url, get_string('createnewcategory'));
3ec69c2e 396 }
442f12f8 397 if (core_course_category::can_approve_course_requests()) {
3ec69c2e
BB
398 $actions[] = html_writer::link(new moodle_url('/course/pending.php'), get_string('coursespending'));
399 }
400 if (count($actions) === 0) {
401 return '';
402 }
9f0595c4 403 return html_writer::div(join(' | ', $actions), 'listing-actions category-listing-actions');
3ec69c2e
BB
404 }
405
406 /**
407 * Renders a course listing.
408 *
442f12f8 409 * @param core_course_category $category The currently selected category. This is what the listing is focused on.
9f0595c4 410 * @param core_course_list_element $course The currently selected course.
3ec69c2e
BB
411 * @param int $page The page being displayed.
412 * @param int $perpage The number of courses to display per page.
d29bde59 413 * @param string|null $viewmode The view mode the page is in, one out of 'default', 'combined', 'courses' or 'categories'.
3ec69c2e
BB
414 * @return string
415 */
442f12f8 416 public function course_listing(core_course_category $category = null, core_course_list_element $course = null,
9f0595c4
MM
417 $page = 0, $perpage = 20,
418 $viewmode = 'default') {
3ec69c2e
BB
419
420 if ($category === null) {
421 $html = html_writer::start_div('select-a-category');
422 $html .= html_writer::tag('h3', get_string('courses'),
9f0595c4 423 array('id' => 'course-listing-title', 'tabindex' => '0'));
3ec69c2e
BB
424 $html .= $this->output->notification(get_string('selectacategory'), 'notifymessage');
425 $html .= html_writer::end_div();
426 return $html;
427 }
428
429 $page = max($page, 0);
430 $perpage = max($perpage, 2);
431 $totalcourses = $category->coursecount;
432 $totalpages = ceil($totalcourses / $perpage);
433 if ($page > $totalpages - 1) {
434 $page = $totalpages - 1;
435 }
436 $options = array(
9f0595c4
MM
437 'offset' => $page * $perpage,
438 'limit' => $perpage
3ec69c2e
BB
439 );
440 $courseid = isset($course) ? $course->id : null;
441 $class = '';
442 if ($page === 0) {
443 $class .= ' firstpage';
444 }
445 if ($page + 1 === (int)$totalpages) {
446 $class .= ' lastpage';
447 }
448
9f0595c4
MM
449 $html = html_writer::start_div('course-listing'.$class, array(
450 'data-category' => $category->id,
451 'data-page' => $page,
452 'data-totalpages' => $totalpages,
453 'data-totalcourses' => $totalcourses,
454 'data-canmoveoutof' => $category->can_move_courses_out_of() && $category->can_move_courses_into()
3ec69c2e
BB
455 ));
456 $html .= html_writer::tag('h3', $category->get_formatted_name(),
9f0595c4 457 array('id' => 'course-listing-title', 'tabindex' => '0'));
3ec69c2e 458 $html .= $this->course_listing_actions($category, $course, $perpage);
d29bde59 459 $html .= $this->listing_pagination($category, $page, $perpage, false, $viewmode);
1801b905 460 $html .= html_writer::start_tag('ul', array('class' => 'ml course-list', 'role' => 'group'));
3ec69c2e
BB
461 foreach ($category->get_courses($options) as $listitem) {
462 $html .= $this->course_listitem($category, $listitem, $courseid);
463 }
464 $html .= html_writer::end_tag('ul');
d29bde59 465 $html .= $this->listing_pagination($category, $page, $perpage, true, $viewmode);
3ec69c2e
BB
466 $html .= $this->course_bulk_actions($category);
467 $html .= html_writer::end_div();
3ec69c2e
BB
468 return $html;
469 }
470
471 /**
472 * Renderers a course list item.
473 *
474 * This function will be called for every course being displayed by course_listing.
475 *
442f12f8 476 * @param core_course_category $category The currently selected category and the category the course belongs to.
9f0595c4 477 * @param core_course_list_element $course The course to produce HTML for.
3ec69c2e
BB
478 * @param int $selectedcourse The id of the currently selected course.
479 * @return string
480 */
442f12f8 481 public function course_listitem(core_course_category $category, core_course_list_element $course, $selectedcourse) {
3ec69c2e
BB
482
483 $text = $course->get_formatted_name();
484 $attributes = array(
9f0595c4
MM
485 'class' => 'listitem listitem-course',
486 'data-id' => $course->id,
487 'data-selected' => ($selectedcourse == $course->id) ? '1' : '0',
488 'data-visible' => $course->visible ? '1' : '0'
3ec69c2e
BB
489 );
490
491 $bulkcourseinput = array(
9f0595c4
MM
492 'type' => 'checkbox',
493 'name' => 'bc[]',
494 'value' => $course->id,
495 'class' => 'bulk-action-checkbox',
496 'aria-label' => get_string('bulkactionselect', 'moodle', $text),
497 'data-action' => 'select'
3ec69c2e
BB
498 );
499 if (!$category->has_manage_capability()) {
500 // Very very hardcoded here.
501 $bulkcourseinput['style'] = 'visibility:hidden';
502 }
503
504 $viewcourseurl = new moodle_url($this->page->url, array('courseid' => $course->id));
505
506 $html = html_writer::start_tag('li', $attributes);
507 $html .= html_writer::start_div('clearfix');
508
509 if ($category->can_resort_courses()) {
510 // In order for dnd to be available the user must be able to resort the category children..
511 $html .= html_writer::div($this->output->pix_icon('i/move_2d', get_string('dndcourse')), 'float-left drag-handle');
512 }
513
514 $html .= html_writer::start_div('ba-checkbox float-left');
515 $html .= html_writer::empty_tag('input', $bulkcourseinput).'&nbsp;';
516 $html .= html_writer::end_div();
517 $html .= html_writer::link($viewcourseurl, $text, array('class' => 'float-left coursename'));
518 $html .= html_writer::start_div('float-right');
519 if ($course->idnumber) {
520 $html .= html_writer::tag('span', s($course->idnumber), array('class' => 'dimmed idnumber'));
521 }
522 $html .= $this->course_listitem_actions($category, $course);
523 $html .= html_writer::end_div();
524 $html .= html_writer::end_div();
525 $html .= html_writer::end_tag('li');
526 return $html;
527 }
528
529 /**
530 * Renderers actions for the course listing.
531 *
532 * Not to be confused with course_listitem_actions which renderers the actions for individual courses.
533 *
442f12f8
MG
534 * @param core_course_category $category
535 * @param core_course_list_element $course The currently selected course.
3ec69c2e
BB
536 * @param int $perpage
537 * @return string
538 */
442f12f8 539 public function course_listing_actions(core_course_category $category, core_course_list_element $course = null, $perpage = 20) {
3ec69c2e
BB
540 $actions = array();
541 if ($category->can_create_course()) {
542 $url = new moodle_url('/course/edit.php', array('category' => $category->id, 'returnto' => 'catmanage'));
9f0595c4 543 $actions[] = html_writer::link($url, get_string('createnewcourse'));
3ec69c2e
BB
544 }
545 if ($category->can_request_course()) {
546 // Request a new course.
547 $url = new moodle_url('/course/request.php', array('return' => 'management'));
548 $actions[] = html_writer::link($url, get_string('requestcourse'));
549 }
550 if ($category->can_resort_courses()) {
551 $params = $this->page->url->params();
552 $params['action'] = 'resortcourses';
553 $params['sesskey'] = sesskey();
554 $baseurl = new moodle_url('/course/management.php', $params);
555 $fullnameurl = new moodle_url($baseurl, array('resort' => 'fullname'));
556 $fullnameurldesc = new moodle_url($baseurl, array('resort' => 'fullnamedesc'));
557 $shortnameurl = new moodle_url($baseurl, array('resort' => 'shortname'));
558 $shortnameurldesc = new moodle_url($baseurl, array('resort' => 'shortnamedesc'));
559 $idnumberurl = new moodle_url($baseurl, array('resort' => 'idnumber'));
560 $idnumberdescurl = new moodle_url($baseurl, array('resort' => 'idnumberdesc'));
561 $timecreatedurl = new moodle_url($baseurl, array('resort' => 'timecreated'));
562 $timecreateddescurl = new moodle_url($baseurl, array('resort' => 'timecreateddesc'));
563 $menu = new action_menu(array(
9f0595c4
MM
564 new action_menu_link_secondary($fullnameurl,
565 null,
566 get_string('sortbyx', 'moodle', get_string('fullnamecourse'))),
567 new action_menu_link_secondary($fullnameurldesc,
568 null,
569 get_string('sortbyxreverse', 'moodle', get_string('fullnamecourse'))),
570 new action_menu_link_secondary($shortnameurl,
571 null,
572 get_string('sortbyx', 'moodle', get_string('shortnamecourse'))),
573 new action_menu_link_secondary($shortnameurldesc,
574 null,
575 get_string('sortbyxreverse', 'moodle', get_string('shortnamecourse'))),
576 new action_menu_link_secondary($idnumberurl,
577 null,
578 get_string('sortbyx', 'moodle', get_string('idnumbercourse'))),
579 new action_menu_link_secondary($idnumberdescurl,
580 null,
581 get_string('sortbyxreverse', 'moodle', get_string('idnumbercourse'))),
582 new action_menu_link_secondary($timecreatedurl,
583 null,
584 get_string('sortbyx', 'moodle', get_string('timecreatedcourse'))),
585 new action_menu_link_secondary($timecreateddescurl,
586 null,
587 get_string('sortbyxreverse', 'moodle', get_string('timecreatedcourse')))
3ec69c2e
BB
588 ));
589 $menu->set_menu_trigger(get_string('resortcourses'));
590 $actions[] = $this->render($menu);
591 }
592 $strall = get_string('all');
593 $menu = new action_menu(array(
9f0595c4
MM
594 new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 5)), null, 5),
595 new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 10)), null, 10),
596 new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 20)), null, 20),
597 new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 50)), null, 50),
598 new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 100)), null, 100),
599 new action_menu_link_secondary(new moodle_url($this->page->url, array('perpage' => 999)), null, $strall),
3ec69c2e
BB
600 ));
601 if ((int)$perpage === 999) {
602 $perpage = $strall;
603 }
604 $menu->attributes['class'] .= ' courses-per-page';
605 $menu->set_menu_trigger(get_string('perpagea', 'moodle', $perpage));
606 $actions[] = $this->render($menu);
9f0595c4 607 return html_writer::div(join(' | ', $actions), 'listing-actions course-listing-actions');
3ec69c2e
BB
608 }
609
610 /**
611 * Displays a search result listing.
612 *
613 * @param array $courses The courses to display.
614 * @param int $totalcourses The total number of courses to display.
9f0595c4 615 * @param core_course_list_element $course The currently selected course if there is one.
3ec69c2e
BB
616 * @param int $page The current page, starting at 0.
617 * @param int $perpage The number of courses to display per page.
618 * @param string $search The string we are searching for.
619 * @return string
620 */
442f12f8 621 public function search_listing(array $courses, $totalcourses, core_course_list_element $course = null, $page = 0, $perpage = 20,
9f0595c4 622 $search = '') {
3ec69c2e
BB
623 $page = max($page, 0);
624 $perpage = max($perpage, 2);
625 $totalpages = ceil($totalcourses / $perpage);
626 if ($page > $totalpages - 1) {
627 $page = $totalpages - 1;
628 }
629 $courseid = isset($course) ? $course->id : null;
630 $first = true;
631 $last = false;
632 $i = $page * $perpage;
633
9f0595c4
MM
634 $html = html_writer::start_div('course-listing', array(
635 'data-category' => 'search',
636 'data-page' => $page,
637 'data-totalpages' => $totalpages,
638 'data-totalcourses' => $totalcourses
3ec69c2e
BB
639 ));
640 $html .= html_writer::tag('h3', get_string('courses'));
641 $html .= $this->search_pagination($totalcourses, $page, $perpage);
642 $html .= html_writer::start_tag('ul', array('class' => 'ml'));
643 foreach ($courses as $listitem) {
644 $i++;
645 if ($i == $totalcourses) {
646 $last = true;
647 }
648 $html .= $this->search_listitem($listitem, $courseid, $first, $last);
649 $first = false;
650 }
651 $html .= html_writer::end_tag('ul');
652 $html .= $this->search_pagination($totalcourses, $page, $perpage, true, $search);
653 $html .= $this->course_search_bulk_actions();
654 $html .= html_writer::end_div();
655 return $html;
656 }
657
658 /**
659 * Renderers a search result course list item.
660 *
661 * This function will be called for every course being displayed by course_listing.
662 *
9f0595c4 663 * @param core_course_list_element $course The course to produce HTML for.
3ec69c2e
BB
664 * @param int $selectedcourse The id of the currently selected course.
665 * @return string
666 */
442f12f8 667 public function search_listitem(core_course_list_element $course, $selectedcourse) {
3ec69c2e
BB
668
669 $text = $course->get_formatted_name();
670 $attributes = array(
9f0595c4
MM
671 'class' => 'listitem listitem-course',
672 'data-id' => $course->id,
673 'data-selected' => ($selectedcourse == $course->id) ? '1' : '0',
674 'data-visible' => $course->visible ? '1' : '0'
3ec69c2e
BB
675 );
676 $bulkcourseinput = '';
442f12f8 677 if (core_course_category::get($course->category)->can_move_courses_out_of()) {
3ec69c2e 678 $bulkcourseinput = array(
9f0595c4
MM
679 'type' => 'checkbox',
680 'name' => 'bc[]',
681 'value' => $course->id,
682 'class' => 'bulk-action-checkbox',
683 'aria-label' => get_string('bulkactionselect', 'moodle', $text),
684 'data-action' => 'select'
3ec69c2e
BB
685 );
686 }
687 $viewcourseurl = new moodle_url($this->page->url, array('courseid' => $course->id));
442f12f8 688 $categoryname = core_course_category::get($course->category)->get_formatted_name();
3ec69c2e
BB
689
690 $html = html_writer::start_tag('li', $attributes);
691 $html .= html_writer::start_div('clearfix');
692 $html .= html_writer::start_div('float-left');
693 if ($bulkcourseinput) {
694 $html .= html_writer::empty_tag('input', $bulkcourseinput).'&nbsp;';
695 }
696 $html .= html_writer::end_div();
697 $html .= html_writer::link($viewcourseurl, $text, array('class' => 'float-left coursename'));
698 $html .= html_writer::tag('span', $categoryname, array('class' => 'float-left categoryname'));
699 $html .= html_writer::start_div('float-right');
700 $html .= $this->search_listitem_actions($course);
701 $html .= html_writer::tag('span', s($course->idnumber), array('class' => 'dimmed idnumber'));
702 $html .= html_writer::end_div();
703 $html .= html_writer::end_div();
704 $html .= html_writer::end_tag('li');
705 return $html;
706 }
707
708 /**
709 * Renderers a key value pair of information for display.
710 *
711 * @param string $key
712 * @param string $value
713 * @param string $class
714 * @return string
715 */
716 protected function detail_pair($key, $value, $class ='') {
717 $html = html_writer::start_div('detail-pair row yui3-g '.preg_replace('#[^a-zA-Z0-9_\-]#', '-', $class));
9f0595c4
MM
718 $html .= html_writer::div(html_writer::span($key), 'pair-key span3 col-md-3 yui3-u-1-4');
719 $html .= html_writer::div(html_writer::span($value), 'pair-value span9 col-md-9 m-b-1 yui3-u-3-4 form-inline');
3ec69c2e
BB
720 $html .= html_writer::end_div();
721 return $html;
722 }
723
724 /**
725 * A collection of actions for a course.
726 *
9f0595c4 727 * @param core_course_list_element $course The course to display actions for.
3ec69c2e
BB
728 * @return string
729 */
442f12f8 730 public function course_detail_actions(core_course_list_element $course) {
3ec69c2e
BB
731 $actions = \core_course\management\helper::get_course_detail_actions($course);
732 if (empty($actions)) {
733 return '';
734 }
735 $options = array();
736 foreach ($actions as $action) {
9f0595c4 737 $options[] = $this->action_link($action['url'], $action['string']);
3ec69c2e 738 }
9f0595c4 739 return html_writer::div(join(' | ', $options), 'listing-actions course-detail-listing-actions');
3ec69c2e
BB
740 }
741
742}