diff --git a/classes/output/core/course_renderer.php b/classes/output/core/course_renderer.php index 5c8551d..6c00e3f 100644 --- a/classes/output/core/course_renderer.php +++ b/classes/output/core/course_renderer.php @@ -26,6 +26,11 @@ namespace theme_ilb\output\core; defined('MOODLE_INTERNAL') || die(); use moodle_url; +use core_course_category; +use core_course_list_element; +use html_writer; +use coursecat_helper; +use stdClass; require_once($CFG->dirroot . '/course/renderer.php'); @@ -36,50 +41,312 @@ require_once($CFG->dirroot . '/course/renderer.php'); * @copyright 2016 Frédéric Massart - FMCorz.net * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class course_renderer extends \core_course_renderer { +/** + * Class course_renderer + * @package theme_trema + * @copyright 2019 Trema - {@link https://trema.tech/} + * @author Rodrigo Mady + * @author Trevor Furtado + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class course_renderer extends \core_course_renderer { /** - * Renders html to display a course search form. + * Renders the list of courses for frontpage and /course * - * @param string $value default value to populate the search field - * @param string $format display format - 'plain' (default), 'short' or 'navbar' + * If list of courses is specified in $courses; the argument $chelper is only used + * to retrieve display options and attributes, only methods get_show_courses(), + * get_courses_display_option() and get_and_erase_attributes() are called. + * + * @param coursecat_helper $chelper various display options + * @param array $courses the list of courses to display + * @param int|null $totalcount total number of courses (affects display mode if it is AUTO or pagination if applicable), + * defaulted to count($courses) * @return string */ - public function course_search_form($value = '', $format = 'plain') { - static $count = 0; - $formid = 'coursesearch'; - if ((++$count) > 1) { - $formid .= $count; + protected function coursecat_courses(coursecat_helper $chelper, $courses, $totalcount = null) { + global $CFG; + if ($totalcount === null) { + $totalcount = count($courses); } - - switch ($format) { - case 'navbar' : - $formid = 'coursesearchnavbar'; - $inputid = 'navsearchbox'; - $inputsize = 20; - break; - case 'short' : - $inputid = 'shortsearchbox'; - $inputsize = 12; + if (!$totalcount) { + // Courses count is cached during courses retrieval. + return ''; + } + if ($chelper->get_show_courses() == self::COURSECAT_SHOW_COURSES_AUTO) { + // In 'auto' course display mode we analyse if number of courses is more or less than $CFG->courseswithsummarieslimit. + if ($totalcount <= $CFG->courseswithsummarieslimit) { + $chelper->set_show_courses(self::COURSECAT_SHOW_COURSES_EXPANDED); + } else { + $chelper->set_show_courses(self::COURSECAT_SHOW_COURSES_COLLAPSED); + } + } + // Prepare content of paging bar if it is needed. + $paginationurl = $chelper->get_courses_display_option('paginationurl'); + $paginationallowall = $chelper->get_courses_display_option('paginationallowall'); + if ($totalcount > count($courses)) { + // There are more results that can fit on one page. + if ($paginationurl) { + // The option paginationurl was specified, display pagingbar. + $perpage = $chelper->get_courses_display_option('limit', $CFG->coursesperpage); + $page = $chelper->get_courses_display_option('offset') / $perpage; + $pagingbar = $this->paging_bar($totalcount, $page, $perpage, + $paginationurl->out(false, array('perpage' => $perpage))); + if ($paginationallowall) { + $pagingbar .= html_writer::tag('div', html_writer::link($paginationurl->out(false, array('perpage' => 'all')), + get_string('showall', '', $totalcount)), array('class' => 'paging paging-showall')); + } + } else if ($viewmoreurl = $chelper->get_courses_display_option('viewmoreurl')) { + // The option for 'View more' link was specified, display more link. + $viewmoretext = $chelper->get_courses_display_option('viewmoretext', new \lang_string('viewmore')); + $morelink = html_writer::tag('div', html_writer::link($viewmoreurl, $viewmoretext), + array('class' => 'paging paging-morelink')); + } + } else if (($totalcount > $CFG->coursesperpage) && $paginationurl && $paginationallowall) { + // There are more than one page of results and we are in 'view all' mode, suggest to go back to paginated view mode. + $pagingbar = html_writer::tag( + 'div', + html_writer::link( + $paginationurl->out( + false, + array('perpage' => $CFG->coursesperpage) + ), + get_string('showperpage', '', $CFG->coursesperpage) + ), + array('class' => 'paging paging-showperpage') + ); + } + // Display list of courses. + $attributes = $chelper->get_and_erase_attributes('courses'); + $content = html_writer::start_tag('div', $attributes); + if (!empty($pagingbar)) { + $content .= $pagingbar; + } + $coursecount = 1; + $content .= html_writer::start_tag('div', array('class' => ' row card-deck my-4')); + foreach ($courses as $course) { + $content .= $this->coursecat_coursebox($chelper, $course, 'card mb-3 course-card-view'); + $coursecount ++; + } + $content .= html_writer::end_tag('div'); + if (!empty($pagingbar)) { + $content .= $pagingbar; + } + if (!empty($morelink)) { + $content .= $morelink; + } + $content .= html_writer::end_tag('div'); // End courses. + + return $content; + } + /** + * Displays one course in the list of courses. + * + * This is an internal function, to display an information about just one course + * please use {@link core_course_renderer::course_info_box()} + * + * @param coursecat_helper $chelper various display options + * @param core_course_list_element|stdClass $course + * @param string $additionalclasses additional classes to add to the main
tag (usually + * depend on the course position in list - first/last/even/odd) + * @return string + */ + protected function coursecat_coursebox(coursecat_helper $chelper, $course, $additionalclasses = '') { + global $CFG; + if (!isset($this->strings->summary)) { + $this->strings->summary = get_string('summary'); + } + if ($chelper->get_show_courses() <= self::COURSECAT_SHOW_COURSES_COUNT) { + return ''; + } + if ($course instanceof stdClass) { + $course = new core_course_list_element($course); + } + $content = html_writer::start_tag('div', array('class' => $additionalclasses)); + $classes = ''; + if ($chelper->get_show_courses() >= self::COURSECAT_SHOW_COURSES_EXPANDED) { + $nametag = 'h5'; + } else { + $classes .= ' collapsed'; + $nametag = 'div'; + } + // End coursebox. + $content .= html_writer::start_tag('div', array( + 'class' => $classes, + 'data-courseid' => $course->id, + 'data-type' => self::COURSECAT_TYPE_COURSE, + )); + $content .= $this->coursecat_coursebox_content($chelper, $course); + $content .= html_writer::end_tag('div'); + // End coursebox. + $content .= html_writer::end_tag('div'); + // End col-md-4. + return $content; + } + /** + * Returns HTML to display course content (summary, course contacts and optionally category name) + * + * This method is called from coursecat_coursebox() and may be re-used in AJAX + * + * @param coursecat_helper $chelper various display options + * @param stdClass|core_course_list_element $course + * @return string + */ + protected function coursecat_coursebox_content(coursecat_helper $chelper, $course) { + if ($course instanceof stdClass) { + $course = new core_course_list_element($course); + } + // Course name. + $coursename = $chelper->get_course_formatted_name($course); + $courseurl = new moodle_url('/course/view.php', array('id' => $course->id)); + $coursenamelink = html_writer::link($courseurl, + $coursename, array('class' => $course->visible ? '' : 'dimmed')); + $content = html_writer::start_tag('a', array ('href' => $courseurl, 'class' => 'course-card-img')); + $content .= $this->get_course_summary_image($course); + $content .= html_writer::end_tag('a'); + $content .= html_writer::start_tag('div', array('class' => 'card-body')); + $content .= "
". $coursenamelink ."
"; + $content .= html_writer::end_tag('div'); + $content .= html_writer::start_tag('div', array('class' => 'card-block text-center')); + // Print enrolmenticons. + if ($icons = enrol_get_course_info_icons($course)) { + foreach ($icons as $pixicon) { + $content .= $this->render($pixicon); + } + } + $content .= html_writer::start_tag('div', array('class' => 'pull-right')); + $content .= html_writer::end_tag('div'); // End pull-right. + $content .= html_writer::end_tag('div'); // End card-block. + // Display course contacts. See core_course_list_element::get_course_contacts(). + if ($course->has_course_contacts()) { + $content .= html_writer::start_tag('div', array('class' => 'card-footer teachers')); + $content .= html_writer::start_tag('ul'); + foreach ($course->get_course_contacts() as $userid => $coursecontact) { + $name = $coursecontact['rolename'].': '. + html_writer::link(new moodle_url('/user/view.php', + array('id' => $userid, 'course' => SITEID)), + $coursecontact['username']); + $content .= html_writer::tag('li', $name); + } + $content .= html_writer::end_tag('ul'); // End teachers. + $content .= html_writer::end_tag('div'); // End teachers. + } + // Display course category if necessary (for example in search results). + if ($chelper->get_show_courses() == self::COURSECAT_SHOW_COURSES_EXPANDED_WITH_CAT) { + if ($cat = core_course_category::get($course->category, IGNORE_MISSING)) { + $content .= html_writer::start_tag('div', array('class' => 'coursecat text-center')); + $content .= get_string('category').': '. + html_writer::link(new moodle_url('/course/index.php', array('categoryid' => $cat->id)), + $cat->get_formatted_name(), array('class' => $cat->visible ? '' : 'dimmed')); + $content .= html_writer::end_tag('div'); // End coursecat. + } + } + // Display course summary. + if ($course->has_summary()) { + $content .= html_writer::start_tag('div', array('class' => 'card-see-more text-center')); + $content .= html_writer::start_tag('div', array('class' => 'btn btn-secondary m-2', + 'id' => "course-popover-{$course->id}", 'role' => 'button', 'data-region' => 'popover-region-toggle', + 'data-toggle' => 'popover', 'data-placement' => 'right', + 'data-content' => $chelper->get_course_formatted_summary($course, + array('noclean' => true, 'para' => false)), 'data-html' => 'true', 'tabindex' => '0', 'data-trigger' => 'focus')); + $content .= get_string('seemore', 'theme_trema'); + $content .= html_writer::end_tag('div'); + $content .= html_writer::end_tag('div'); // End summary. + } + return $content; + } + /** + * Returns the first course's summary issue + * + * @param stdClass $course the course object + * @return string + */ + protected function get_course_summary_image($course) { + global $CFG; + $contentimage = ''; + foreach ($course->get_course_overviewfiles() as $file) { + $isimage = $file->is_valid_image(); + $url = file_encode_url("$CFG->wwwroot/pluginfile.php", + '/'. $file->get_contextid(). '/'. $file->get_component(). '/'. + $file->get_filearea(). $file->get_filepath(). $file->get_filename(), !$isimage); + if ($isimage) { + $contentimage = html_writer::start_tag('div', array('style' => "background-image:url('$url')", + 'class' => 'card-img-top')); + $contentimage .= html_writer::end_tag('div'); break; - default : - $inputid = 'coursesearchbox'; - $inputsize = 30; + } } - - $data = (object) [ - 'searchurl' => (new moodle_url('/course/search.php'))->out(false), - 'id' => $formid, - 'inputid' => $inputid, - 'inputsize' => $inputsize, - 'value' => $value - ]; - if ($format != 'navbar') { - $helpicon = new \help_icon('coursesearch', 'core'); - $data->helpicon = $helpicon->export_for_template($this); + if (empty($contentimage)) { + $pattern = new \core_geopattern(); + $pattern->setColor($this->coursecolor($course->id)); + $pattern->patternbyid($course->id); + $contentimage = html_writer::start_tag('div', array('style' => "background-image:url('{$pattern->datauri()}')", + 'class' => 'card-img-top')); + $contentimage .= html_writer::end_tag('div'); } - - return $this->render_from_template('theme_ilb/course_search_form', $data); + return $contentimage; + } + /** + * Generate a semi-random color based on the courseid number (so it will always return + * the same color for a course) + * + * @param int $courseid + * @return string $color, hexvalue color code. + */ + protected function coursecolor($courseid) { + // The colour palette is hardcoded for now. It would make sense to combine it with theme settings. + $basecolors = ['#81ecec', '#74b9ff', '#a29bfe', '#dfe6e9', '#00b894', '#0984e3', '#b2bec3', + '#fdcb6e', '#fd79a8', '#6c5ce7']; + $color = $basecolors[$courseid % 10]; + return $color; } - } + + +// class course_renderer extends \core_course_renderer { + +// /** +// * Renders html to display a course search form. +// * +// * @param string $value default value to populate the search field +// * @param string $format display format - 'plain' (default), 'short' or 'navbar' +// * @return string +// */ +// public function course_search_form($value = '', $format = 'plain') { +// static $count = 0; +// $formid = 'coursesearch'; +// if ((++$count) > 1) { +// $formid .= $count; +// } + +// switch ($format) { +// case 'navbar' : +// $formid = 'coursesearchnavbar'; +// $inputid = 'navsearchbox'; +// $inputsize = 20; +// break; +// case 'short' : +// $inputid = 'shortsearchbox'; +// $inputsize = 12; +// break; +// default : +// $inputid = 'coursesearchbox'; +// $inputsize = 30; +// } + +// $data = (object) [ +// 'searchurl' => (new moodle_url('/course/search.php'))->out(false), +// 'id' => $formid, +// 'inputid' => $inputid, +// 'inputsize' => $inputsize, +// 'value' => $value +// ]; +// if ($format != 'navbar') { +// $helpicon = new \help_icon('coursesearch', 'core'); +// $data->helpicon = $helpicon->export_for_template($this); +// } + +// return $this->render_from_template('theme_ilb/course_search_form', $data); +// } + +// }