Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
<?php// This file is part of Moodle - http://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <http://www.gnu.org/licenses/>./*** Course renderer.** @package theme_universe* @copyright 2023 Marcin Czaja (https://rosea.io)* @license Commercial https://themeforest.net/licenses*/namespace theme_universe\output\core;use moodle_url;use html_writer;use core_course_category;use coursecat_helper;use stdClass;use core_course_list_element;use single_select;use lang_string;use cm_info;use core_text;use completion_info;use course_handler;use context_course;use theme_universe\util\course;/*** @package theme_universe* @copyright 2023 Marcin Czaja - Rosea Themes - rosea.io* @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** @param string $value default value to populate the search field* @return string*/public function course_search_form($value = '') {$data = ['action' => \core_search\manager::get_course_search_url(),'btnclass' => 'btn-primary','inputname' => 'q','searchstring' => get_string('searchcourses'),'hiddenfields' => (object) ['name' => 'areaids', 'value' => 'core_course-course'],'query' => $value];return $this->render_from_template('core/search_input_fw', $data);}/*** Renders the list of courses** This is internal function, please use core_course_renderer::courses_list() or another public* method from outside of the class** 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** @throws \coding_exception* @throws \dml_exception* @throws \moodle_exception*/protected function coursecat_courses(coursecat_helper $chelper, $courses, $totalcount = null) {global $CFG, $COURSE;$theme = \theme_config::load('universe');if ($totalcount === null) {$totalcount = count($courses);}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 (($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;if ($theme->settings->courselistview == 1) {$content .= html_writer::start_tag('div', array('class' => 'rui-course--list mt-2'));} else {$content .= html_writer::start_tag('div', array('class' => 'rui-course-card-deck mt-2'));}foreach ($courses as $course) {$content .= $this->coursecat_coursebox($chelper, $course);$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;}protected function coursecat_subcategories(coursecat_helper $chelper, $coursecat, $depth) {global $CFG;$subcategories = array();if (!$chelper->get_categories_display_option('nodisplay')) {$subcategories = $coursecat->get_children($chelper->get_categories_display_options());}$totalcount = $coursecat->get_children_count();if (!$totalcount) {// Note that we call core_course_category::get_children_count() AFTER core_course_category::get_children().// To avoid extra DB requests.// Categories count is cached during children categories retrieval.return '';}// Prepare content of paging bar or more link if it is needed.$paginationurl = $chelper->get_categories_display_option('paginationurl');$paginationallowall = $chelper->get_categories_display_option('paginationallowall');if ($totalcount > count($subcategories)) {if ($paginationurl) {// The option 'paginationurl was specified, display pagingbar.$perpage = $chelper->get_categories_display_option('limit', $CFG->coursesperpage);$page = $chelper->get_categories_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_categories_display_option('viewmoreurl')) {// The option 'viewmoreurl' was specified, display more link (if it is link to category view page, add category id).if ($viewmoreurl->compare(new moodle_url('/course/index.php'), URL_MATCH_BASE)) {$viewmoreurl->param('categoryid', $coursecat->id);}$viewmoretext = $chelper->get_categories_display_option('viewmoretext', new lang_string('viewmore'));$morelink = html_writer::tag('div',html_writer::link($viewmoreurl, $viewmoretext, array('class' => 'btn btn-secondary w-100')),array('class' => 'paging paging-morelink wrapper-fw'));}} 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 subcategories.$content = html_writer::start_tag('div', array('class' => 'subcategories'));if (!empty($pagingbar)) {$content .= $pagingbar;}foreach ($subcategories as $subcategory) {$content .= $this->coursecat_category($chelper, $subcategory, $depth);}if (!empty($pagingbar)) {$content .= $pagingbar;}if (!empty($morelink)) {$content .= $morelink;}$content .= html_writer::end_tag('div');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** @throws \coding_exception* @throws \dml_exception* @throws \moodle_exception*/protected function coursecat_coursebox_content(coursecat_helper $chelper, $course) {global $DB, $COURSE;$theme = \theme_config::load('universe');if ($course instanceof stdClass) {$course = new core_course_list_element($course);}$cccteachers = $theme->settings->cccteachers;$cccsummary = $theme->settings->cccsummary;$coursecarddesclimit = $theme->settings->coursecarddesclimit;$courseprogressbar = $theme->settings->courseprogressbar;$courseutil = new course($course);$coursecontacts = $courseutil->get_course_contacts();$courseenrolmenticons = $courseutil->get_enrolment_icons();$courseenrolmenticons = !empty($courseenrolmenticons) ? $this->render_enrolment_icons($courseenrolmenticons) : false;$courseprogress = $courseutil->get_progress();$hasprogress = $courseprogress != null;if ($theme->settings->courselangbadge == 1) {$forcedlanguage = strval($course->lang);} else {$forcedlanguage = null;}if ($theme->settings->showcustomfields == 1) {$showcustomfields = true;} else {$showcustomfields = false;}$data = ['id' => $course->id,'fullname' => $chelper->get_course_formatted_name($course),'visible' => $course->visible,'image' => $courseutil->get_summary_image(),'summary' => $courseutil->get_summary($chelper),'category' => $courseutil->get_category(),'customfields' => $courseutil->course_get_taux(),'showcustomfields' => $showcustomfields,'hasprogress' => $hasprogress,'progress' => (int) $courseprogress,'hasenrolmenticons' => $courseenrolmenticons != false,'enrolmenticons' => $courseenrolmenticons,'hascontacts' => !empty($coursecontacts),'contacts' => $coursecontacts,'courseprogressbar' => $courseprogressbar,'cccteachers' => $cccteachers,'cccsummary' => $cccsummary,'coursecarddesclimit' => $coursecarddesclimit,'forcedlanguage' => $forcedlanguage];if ($theme->settings->courselistview == 1) {return $this->render_from_template('theme_universe/custom_courselist', $data);} else {return $this->render_from_template('theme_universe/custom_coursecard', $data);}}/*** Displays one course in the list of courses.** This is an internal function, to display an information about just one course* please use 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 <div> tag (usually* depend on the course position in list - first/last/even/odd)* @return string*/protected function coursecat_coursebox(coursecat_helper $chelper, $course, $additionalclasses = '') {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);}return $this->coursecat_coursebox_content($chelper, $course);}/*** Returns HTML to display a tree of subcategories and courses in the given category** @param coursecat_helper $chelper various display options* @param core_course_category $coursecat top category (this category's name and description will NOT be added to the tree)* @return string*/protected function coursecat_tree(coursecat_helper $chelper, $coursecat) {// Reset the category expanded flag for this course category tree first.$this->categoryexpandedonload = false;$categorycontent = $this->coursecat_category_content($chelper, $coursecat, 1);if (empty($categorycontent)) {return '';}// Start content generation.$content = '';$attributes = $chelper->get_and_erase_attributes('course_category_tree clearfix');$content .= html_writer::start_tag('div', $attributes);if ($coursecat->get_children_count()) {$classes = array('collapseexpand', 'aabtn');// Check if the category content contains subcategories with children's content loaded.if ($this->categoryexpandedonload) {$classes[] = 'collapse-all';$linkname = get_string('collapseall');} else {$linkname = get_string('expandall');}// Only show the collapse/expand if there are children to expand.$content .= html_writer::start_tag('div', array('class' => 'wrapper-fw collapsible-actions position-relative'));$content .= html_writer::link('#', $linkname, array('class' => implode(' ', $classes)));$content .= html_writer::end_tag('div');$this->page->requires->strings_for_js(array('collapseall', 'expandall'), 'moodle');}$content .= html_writer::tag('div', $categorycontent, array('class' => 'content'));$content .= html_writer::end_tag('div'); // End course_category_tree.return $content;}/*** Returns HTML to display a course category as a part of a tree** This is an internal function, to display a particular category and all its contents* use {@link core_course_renderer::course_category()}** @param coursecat_helper $chelper various display options* @param core_course_category $coursecat* @param int $depth depth of this category in the current tree* @return string*/protected function coursecat_category(coursecat_helper $chelper, $coursecat, $depth) {// Open category tag.$classes = array('category');if (empty($coursecat->visible)) {$classes[] = 'dimmed_category';}if ($chelper->get_subcat_depth() > 0 && $depth >= $chelper->get_subcat_depth()) {// Do not load content.$categorycontent = '';$classes[] = 'notloaded';if ($coursecat->get_children_count() ||($chelper->get_show_courses() >= self::COURSECAT_SHOW_COURSES_COLLAPSED && $coursecat->get_courses_count())) {$classes[] = 'with_children';$classes[] = 'collapsed';}} else {// Load category content.$categorycontent = $this->coursecat_category_content($chelper, $coursecat, $depth);$classes[] = 'loaded';if (!empty($categorycontent)) {$classes[] = 'with_children';// Category content loaded with children.$this->categoryexpandedonload = true;}}// Make sure JS file to expand category content is included.$this->coursecat_include_js();$content = html_writer::start_tag('div', array('class' => join(' ', $classes),'data-categoryid' => $coursecat->id,'data-depth' => $depth,'data-showcourses' => $chelper->get_show_courses(),'data-type' => self::COURSECAT_TYPE_CATEGORY,));// Category name.$categoryname = html_writer::link(new moodle_url('/course/index.php',array('categoryid' => $coursecat->id)),$coursecat->get_formatted_name(),array('class' => 'rui-category-link'));$icon = '<svg class="mr-1" width="18" height="18" fill="none" viewBox="0 0 24 24"><path stroke="currentColor"stroke-linecap="round"stroke-linejoin="round"stroke-width="2"d="M19.25 5.75C19.25 5.19772 18.8023 4.75 18.25 4.75H14C12.8954 4.7512 5.64543 12 6.75V19.25L12.8284 18.4216C13.5786 17.6714 14.596 17.25 15.656917.25H18.25C18.8023 17.25 19.25 16.8023 19.25 16.25V5.75Z"></path><path stroke="currentColor"stroke-linecap="round"stroke-linejoin="round"stroke-width="2"d="M4.75 5.75C4.75 5.19772 5.19772 4.75 5.75 4.75H10C11.1046 4.75 125.64543 12 6.75V19.25L11.1716 18.4216C10.421417.6714 9.40401 17.25 8.34315 17.25H5.75C5.19772 17.25 4.75 16.80234.75 16.25V5.75Z"></path></svg>';$a = $coursecat->get_courses_count();$b = $coursecat->get_children_count();$coursesum = $a + $b;$coursescount = $icon . $coursesum;$content .= html_writer::start_tag('div', array('class' => 'wrapper-fw info'));$content .= html_writer::start_tag('h5', array('class' => 'categoryname aabtn'));$content .= $categoryname;$acontent = '';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'));// The option 'viewmoreurl' was specified, display more link (if it is link to category view page, add category id).if ($viewmoreurl->compare(new moodle_url('/course/index.php'), URL_MATCH_BASE)) {$viewmoreurl->param('categoryid', $coursecat->id);}$acontent .= html_writer::tag('div', html_writer::link($viewmoreurl,$viewmoretext,array('class' => 'btn btn-sm btn-light ml-2')));}$content .= '<div class="rui-number-of-courses d-inline-flex">' .html_writer::tag('span', $coursescount, array('class' => 'badge badge-sq badge-primary')) . $acontent . '</div>';$content .= html_writer::end_tag('h5');$content .= html_writer::end_tag('div'); // End .info.// Add category content to the output.$content .= html_writer::tag('div', $categorycontent, array('class' => 'content'));$content .= html_writer::end_tag('div'); // End .category.// Return the course category tree HTML.return $content;}/*** Returns the first course's summary issue** @param \core_course_list_element $course* @param string $courselink** @return string*/public static function get_course_summary_image($course, $courselink) {global $CFG;$contentimage = '';foreach ($course->get_course_overviewfiles() as $file) {$isimage = $file->is_valid_image();$url = moodle_url::make_file_url("$CFG->wwwroot/pluginfile.php",'/' . $file->get_contextid() . '/' . $file->get_component() . '/' .$file->get_filearea() . $file->get_filepath() . $file->get_filename(),!$isimage);if ($isimage) {$contentimage .= '<a href="' . $courselink . '"><figure class="rui-course-card-img-top" style="background-image: url(' . $url . ');"></figure></a>';break;}}if (empty($contentimage)) {$contentimage = '';}return $contentimage;}/*** Returns enrolment icons** @param array $icons** @return array*/protected function render_enrolment_icons(array $icons): array {$data = [];foreach ($icons as $icon) {$data[] = $this->render($icon);}return $data;}}