MDL-37009 Created functions in core_course_renderer to display courses and categories...
authorMarina Glancy <marina@moodle.com>
Tue, 19 Mar 2013 04:07:40 +0000 (15:07 +1100)
committerMarina Glancy <marina@moodle.com>
Mon, 1 Apr 2013 23:54:48 +0000 (10:54 +1100)
course/renderer.php
lang/en/moodle.php
lib/moodlelib.php

index 41ddb3f..2f84213 100644 (file)
  * $renderer = $PAGE->get_renderer('core','course');
  */
 class core_course_renderer extends plugin_renderer_base {
+    const COURSECAT_SHOW_COURSES_NONE = 0; /* do not show courses at all */
+    const COURSECAT_SHOW_COURSES_COUNT = 5; /* do not show courses but show number of courses next to category name */
+    const COURSECAT_SHOW_COURSES_COLLAPSED = 10;
+    const COURSECAT_SHOW_COURSES_AUTO = 15; /* will choose between collapsed and expanded automatically */
+    const COURSECAT_SHOW_COURSES_EXPANDED = 20;
+    const COURSECAT_SHOW_COURSES_EXPANDED_WITH_CAT = 30;
 
     /**
      * A cache of strings
@@ -1074,4 +1080,758 @@ class core_course_renderer extends plugin_renderer_base {
 
         return $output;
     }
+
+    /**
+     * 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 course_in_list|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 = '') {
+        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) {
+            require_once($CFG->libdir. '/coursecatlib.php');
+            $course = new course_in_list($course);
+        }
+        $content = '';
+        $classes = trim('coursebox clearfix '. $additionalclasses);
+        if ($chelper->get_show_courses() >= self::COURSECAT_SHOW_COURSES_EXPANDED) {
+            $nametag = 'h3';
+        } else {
+            $classes .= ' collapsed';
+            $nametag = 'div';
+        }
+        $content .= html_writer::start_tag('div', array('class' => $classes)); // .coursebox
+
+        $content .= html_writer::start_tag('div', array('class' => 'info'));
+
+        // course name
+        $coursename = $chelper->get_course_formatted_name($course);
+        $coursenamelink = html_writer::link(new moodle_url('/course/view.php', array('id' => $course->id)),
+                $coursename, array('class' => $course->visible ? '' : 'dimmed'));
+        $content .= html_writer::tag($nametag, $coursenamelink, array('class' => 'name'));
+
+        // If we display course in collapsed form but the course has summary or course contacts, display the link to the info page.
+        $content .= html_writer::start_tag('div', array('class' => 'moreinfo'));
+        if ($course->has_summary() || $course->has_course_contacts()) {
+            if ($chelper->get_show_courses() < self::COURSECAT_SHOW_COURSES_EXPANDED) {
+                $url = new moodle_url('/course/info.php', array('id' => $course->id));
+                $image = html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/info'),
+                    'alt' => $this->strings->summary));
+                $content .= $this->action_link($url, $image, new popup_action('click', $url, 'courseinfo'),
+                        array('title' => $this->strings->summary));
+            }
+        }
+        $content .= html_writer::end_tag('div'); // .moreinfo
+
+        // print enrolmenticons
+        if ($icons = enrol_get_course_info_icons($course)) {
+            $content .= html_writer::start_tag('div', array('class' => 'enrolmenticons'));
+            foreach ($icons as $pix_icon) {
+                $content .= $this->render($pix_icon);
+            }
+            $content .= html_writer::end_tag('div'); // .enrolmenticons
+        }
+
+        $content .= html_writer::end_tag('div'); // .info
+
+        $content .= html_writer::start_tag('div', array('class' => 'content'));
+        $content .= $this->coursecat_coursebox_content($chelper, $course);
+        $content .= html_writer::end_tag('div'); // .content
+
+        $content .= html_writer::end_tag('div'); // .coursebox
+        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|course_in_list $course
+     * @return string
+     */
+    protected function coursecat_coursebox_content(coursecat_helper $chelper, $course) {
+        global $CFG;
+        if ($chelper->get_show_courses() < self::COURSECAT_SHOW_COURSES_EXPANDED) {
+            return '';
+        }
+        if ($course instanceof stdClass) {
+            require_once($CFG->libdir. '/coursecatlib.php');
+            $course = new course_in_list($course);
+        }
+        $content = '';
+
+        // display course summary
+        if ($course->has_summary()) {
+            $content .= html_writer::start_tag('div', array('class' => 'summary'));
+            $content .= $chelper->get_course_formatted_summary($course,
+                    array('overflowdiv' => true, 'noclean' => true, 'para' => false));
+            $content .= html_writer::end_tag('div'); // .summary
+        }
+
+        // display course contacts. See course_in_list::get_course_contacts()
+        if ($course->has_course_contacts()) {
+            $content .= html_writer::start_tag('ul', array('class' => 'teachers'));
+            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'); // .teachers
+        }
+
+        // display course category if necessary (for example in search results)
+        if ($chelper->get_show_courses() == self::COURSECAT_SHOW_COURSES_EXPANDED_WITH_CAT
+                && ($cat = coursecat::get($course->category, IGNORE_MISSING))) {
+            $content .= html_writer::start_tag('div', array('class' => 'coursecat'));
+            $content .= get_string('category').': '.
+                    html_writer::link(new moodle_url('/course/category.php', array('id' => $cat->id)),
+                            $cat->get_formatted_name(), array('class' => $cat->visible ? '' : 'dimmed'));
+            $content .= html_writer::end_tag('div'); // .coursecat
+        }
+
+        return $content;
+    }
+
+    /**
+     * Renders the list of courses
+     *
+     * This is internal function, please use {@link 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
+     */
+    protected function coursecat_courses(coursecat_helper $chelper, $courses, $totalcount = null) {
+        global $CFG;
+        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 ($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 = 0;
+        foreach ($courses as $course) {
+            $coursecount ++;
+            $classes = ($coursecount%2) ? 'odd' : 'even';
+            if ($coursecount == 1) {
+                $classes .= ' first';
+            }
+            if ($coursecount >= count($courses)) {
+                $classes .= ' last';
+            }
+            $content .= $this->coursecat_coursebox($chelper, $course, $classes);
+        }
+
+        if (!empty($pagingbar)) {
+            $content .= $pagingbar;
+        }
+        if (!empty($morelink)) {
+            $content .= $morelink;
+        }
+
+        $content .= html_writer::end_tag('div'); // .courses
+        return $content;
+    }
+
+    /**
+     * Renders the list of subcategories in a category
+     *
+     * @param coursecat_helper $chelper various display options
+     * @param coursecat $coursecat
+     * @param int $depth depth of the category in the current tree
+     * @return string
+     */
+    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 get_child_categories_count() AFTER get_child_categories() 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/category.php'), URL_MATCH_BASE)) {
+                    if ($coursecat->id) {
+                        $viewmoreurl->param('id', $coursecat->id);
+                    } else {
+                        $viewmoreurl = new moodle_url('/course/index.php', $viewmoreurl->params());
+                    }
+                }
+                $viewmoretext = $chelper->get_categories_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 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 + 1);
+        }
+
+        if (!empty($pagingbar)) {
+            $content .= $pagingbar;
+        }
+        if (!empty($morelink)) {
+            $content .= $morelink;
+        }
+
+        $content .= html_writer::end_tag('div');
+        return $content;
+    }
+
+    /**
+     * Returns HTML to display the subcategories and courses in the given category
+     *
+     * This method is re-used by AJAX to expand content of not loaded category
+     *
+     * @param coursecat_helper $chelper various display options
+     * @param coursecat $coursecat
+     * @param int $depth depth of the category in the current tree
+     * @return string
+     */
+    protected function coursecat_category_content(coursecat_helper $chelper, $coursecat, $depth) {
+        $content = '';
+        // Subcategories
+        $content .= $this->coursecat_subcategories($chelper, $coursecat, $depth);
+
+        // AUTO show courses: Courses will be shown expanded if this is not nested category,
+        // and number of courses no bigger than $CFG->courseswithsummarieslimit.
+        $showcoursesauto = $chelper->get_show_courses() == self::COURSECAT_SHOW_COURSES_AUTO;
+        if ($showcoursesauto && $depth) {
+            // this is definitely collapsed mode
+            $chelper->set_show_courses(self::COURSECAT_SHOW_COURSES_COLLAPSED);
+        }
+
+        // Courses
+        if ($chelper->get_show_courses() > core_course_renderer::COURSECAT_SHOW_COURSES_COUNT) {
+            $courses = $coursecat->get_courses($chelper->get_courses_display_options());
+            if ($viewmoreurl = $chelper->get_courses_display_option('viewmoreurl')) {
+                // the option for 'View more' link was specified, display more link (if it is link to category view page, add category id)
+                if ($viewmoreurl->compare(new moodle_url('/course/category.php'), URL_MATCH_BASE)) {
+                    $chelper->set_courses_display_option('viewmoreurl', new moodle_url($viewmoreurl, array('id' => $coursecat->id)));
+                }
+            }
+            $content .= $this->coursecat_courses($chelper, $courses, $coursecat->get_courses_count());
+        }
+
+        if ($showcoursesauto) {
+            // restore the show_courses back to AUTO
+            $chelper->set_show_courses(self::COURSECAT_SHOW_COURSES_AUTO);
+        }
+
+        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 coursecat $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';
+            }
+        }
+        $content = html_writer::start_tag('div', array('class' => join(' ', $classes),
+            'data-categoryid' => $coursecat->id,
+            'data-depth' => $depth));
+
+        // category name
+        $categoryname = $coursecat->get_formatted_name();
+        $categoryname = html_writer::link(new moodle_url('/course/category.php',
+                array('id' => $coursecat->id)),
+                $categoryname);
+        if ($chelper->get_show_courses() == self::COURSECAT_SHOW_COURSES_COUNT
+                && ($coursescount = $coursecat->get_courses_count())) {
+            $categoryname .= html_writer::tag('span', ' ('. $coursescount.')',
+                    array('title' => get_string('numberofcourses'), 'class' => 'numberofcourse'));
+        }
+        $content .= html_writer::start_tag('div', array('class' => 'info'));
+        $content .= html_writer::tag(($depth > 1) ? 'h4' : 'h3', $categoryname, array('class' => 'name'));
+        $content .= html_writer::end_tag('div'); // .info
+
+        // add category content to the output
+        $content .= html_writer::tag('div', $categorycontent, array('class' => 'content'));
+
+        $content .= html_writer::end_tag('div'); // .category
+
+        // Return the course category tree HTML
+        return $content;
+    }
+
+    /**
+     * Returns HTML to display a tree of subcategories and courses in the given category
+     *
+     * @param coursecat_helper $chelper various display options
+     * @param coursecat $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) {
+        $categorycontent = $this->coursecat_category_content($chelper, $coursecat, 0);
+        if (empty($categorycontent)) {
+            return '';
+        }
+
+        // Generate an id and the required JS call to make this a nice widget
+        $id = html_writer::random_id('course_category_tree');
+        $this->page->requires->js_init_call('M.util.init_toggle_class_on_click',
+                array($id, '.category.with_children.loaded > .info .name', 'collapsed', '.category.with_children.loaded'));
+
+        // Start content generation
+        $content = '';
+        $attributes = $chelper->get_and_erase_attributes('course_category_tree clearfix');
+        $content .= html_writer::start_tag('div',
+                array('id' => $id, 'data-showcourses' => $chelper->get_show_courses()) + $attributes);
+
+        $content .= html_writer::tag('div', $categorycontent, array('class' => 'content'));
+
+        if ($coursecat->get_children_count() && $chelper->get_subcat_depth() != 1) {
+            // We don't need to display "Expand all"/"Collapse all" buttons if there are no
+            // subcategories or there is only one level of subcategories loaded
+            // TODO if subcategories are loaded by AJAX this might still be needed!
+            $content .= html_writer::start_tag('div', array('class' => 'controls'));
+            $content .= html_writer::tag('div', get_string('collapseall'), array('class' => 'addtoall expandall'));
+            $content .= html_writer::tag('div', get_string('expandall'), array('class' => 'removefromall collapseall'));
+            $content .= html_writer::end_tag('div');
+        }
+
+        $content .= html_writer::end_tag('div'); // .course_category_tree
+
+        return $content;
+    }
+}
+
+/**
+ * Class storing display options and functions to help display course category and/or courses lists
+ *
+ * This is a wrapper for coursecat objects that also stores display options
+ * and functions to retrieve sorted and paginated lists of categories/courses.
+ *
+ * If theme overrides methods in core_course_renderers that access this class
+ * it may as well not use this class at all or extend it.
+ *
+ * @package   core
+ * @copyright 2013 Marina Glancy
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class coursecat_helper {
+    /** @var string [none, collapsed, expanded] how (if) display courses list */
+    protected $showcourses = 10; /* core_course_renderer::COURSECAT_SHOW_COURSES_COLLAPSED */
+    /** @var int depth to expand subcategories in the tree (deeper subcategories will be loaded by AJAX or proceed to category page by clicking on category name) */
+    protected $subcatdepth = 1;
+    /** @var array options to display courses list */
+    protected $coursesdisplayoptions = array();
+    /** @var array options to display subcategories list */
+    protected $categoriesdisplayoptions = array();
+    /** @var array additional HTML attributes */
+    protected $attributes = array();
+    /** @var array search criteria if the list is a search result */
+    protected $searchcriteria = null;
+
+    /**
+     * Sets how (if) to show the courses - none, collapsed, expanded, etc.
+     *
+     * @param int $showcourses SHOW_COURSES_NONE, SHOW_COURSES_COLLAPSED, SHOW_COURSES_EXPANDED, etc.
+     * @return coursecat_helper
+     */
+    public function set_show_courses($showcourses) {
+        $this->showcourses = $showcourses;
+        // Automatically set the options to preload summary and coursecontacts for coursecat::get_courses() and coursecat::search_courses()
+        $this->coursesdisplayoptions['summary'] = $showcourses >= core_course_renderer::COURSECAT_SHOW_COURSES_AUTO;
+        $this->coursesdisplayoptions['coursecontacts'] = $showcourses >= core_course_renderer::COURSECAT_SHOW_COURSES_EXPANDED;
+        return $this;
+    }
+
+    /**
+     * Returns how (if) to show the courses - none, collapsed, expanded, etc.
+     *
+     * @return int - COURSECAT_SHOW_COURSES_NONE, COURSECAT_SHOW_COURSES_COLLAPSED, COURSECAT_SHOW_COURSES_EXPANDED, etc.
+     */
+    public function get_show_courses() {
+        return $this->showcourses;
+    }
+
+    /**
+     * Sets the maximum depth to expand subcategories in the tree
+     *
+     * deeper subcategories may be loaded by AJAX or proceed to category page by clicking on category name
+     *
+     * @param int $subcatdepth
+     * @return coursecat_helper
+     */
+    public function set_subcat_depth($subcatdepth) {
+        $this->subcatdepth = $subcatdepth;
+        return $this;
+    }
+
+    /**
+     * Returns the maximum depth to expand subcategories in the tree
+     *
+     * deeper subcategories may be loaded by AJAX or proceed to category page by clicking on category name
+     *
+     * @return int
+     */
+    public function get_subcat_depth() {
+        return $this->subcatdepth;
+    }
+
+    /**
+     * Sets options to display list of courses
+     *
+     * Options are later submitted as argument to coursecat::get_courses() and/or coursecat::search_courses()
+     *
+     * Options that coursecat::get_courses() accept:
+     *    - recursive - return courses from subcategories as well. Use with care,
+     *      this may be a huge list!
+     *    - summary - preloads fields 'summary' and 'summaryformat'
+     *    - coursecontacts - preloads course contacts
+     *    - isenrolled - preloads indication whether this user is enrolled in the course
+     *    - sort - list of fields to sort. Example
+     *             array('idnumber' => 1, 'shortname' => 1, 'id' => -1)
+     *             will sort by idnumber asc, shortname asc and id desc.
+     *             Default: array('sortorder' => 1)
+     *             Only cached fields may be used for sorting!
+     *    - offset
+     *    - limit - maximum number of children to return, 0 or null for no limit
+     *
+     * Options summary and coursecontacts are filled automatically in the set_show_courses()
+     *
+     * Also renderer can set here any additional options it wants to pass between renderer functions.
+     *
+     * @param array $options
+     * @return coursecat_helper
+     */
+    public function set_courses_display_options($options) {
+        $this->coursesdisplayoptions = $options;
+        $this->set_show_courses($this->showcourses); // this will calculate special display options
+        return $this;
+    }
+
+    /**
+     * Sets one option to display list of courses
+     *
+     * @see coursecat_helper::set_courses_display_options()
+     *
+     * @param string $key
+     * @param mixed $value
+     * @return coursecat_helper
+     */
+    public function set_courses_display_option($key, $value) {
+        $this->coursesdisplayoptions[$key] = $value;
+        return $this;
+    }
+
+    /**
+     * Return the specified option to display list of courses
+     *
+     * @param string $optionname option name
+     * @param mixed $defaultvalue default value for option if it is not specified
+     * @return mixed
+     */
+    public function get_courses_display_option($optionname, $defaultvalue = null) {
+        if (array_key_exists($optionname, $this->coursesdisplayoptions)) {
+            return $this->coursesdisplayoptions[$optionname];
+        } else {
+            return $defaultvalue;
+        }
+    }
+
+    /**
+     * Returns all options to display the courses
+     *
+     * This array is usually passed to {@link coursecat::get_courses()} or
+     * {@link coursecat::search_courses()}
+     *
+     * @return array
+     */
+    public function get_courses_display_options() {
+        return $this->coursesdisplayoptions;
+    }
+
+    /**
+     * Sets options to display list of subcategories
+     *
+     * Options 'sort', 'offset' and 'limit' are passed to coursecat::get_children().
+     * Any other options may be used by renderer functions
+     *
+     * @param array $options
+     * @return coursecat_helper
+     */
+    public function set_categories_display_options($options) {
+        $this->categoriesdisplayoptions = $options;
+        return $this;
+    }
+
+    /**
+     * Return the specified option to display list of subcategories
+     *
+     * @param string $optionname option name
+     * @param mixed $defaultvalue default value for option if it is not specified
+     * @return mixed
+     */
+    public function get_categories_display_option($optionname, $defaultvalue = null) {
+        if (array_key_exists($optionname, $this->categoriesdisplayoptions)) {
+            return $this->categoriesdisplayoptions[$optionname];
+        } else {
+            return $defaultvalue;
+        }
+    }
+
+    /**
+     * Returns all options to display list of subcategories
+     *
+     * This array is usually passed to {@link coursecat::get_children()}
+     *
+     * @return array
+     */
+    public function get_categories_display_options() {
+        return $this->categoriesdisplayoptions;
+    }
+
+    /**
+     * Sets additional general options to pass between renderer functions, usually HTML attributes
+     *
+     * @param array $attributes
+     * @return coursecat_helper
+     */
+    public function set_attributes($attributes) {
+        $this->attributes = $attributes;
+        return $this;
+    }
+
+    /**
+     * Return all attributes and erases them so they are not applied again
+     *
+     * @param string $classname adds additional class name to the beginning of $attributes['class']
+     * @return array
+     */
+    public function get_and_erase_attributes($classname) {
+        $attributes = $this->attributes;
+        $this->attributes = array();
+        if (empty($attributes['class'])) {
+            $attributes['class'] = '';
+        }
+        $attributes['class'] = $classname . ' '. $attributes['class'];
+        return $attributes;
+    }
+
+    /**
+     * Sets the search criteria if the course is a search result
+     *
+     * Search string will be used to highlight terms in course name and description
+     *
+     * @param array $searchcriteria
+     * @return coursecat_helper
+     */
+    public function set_search_criteria($searchcriteria) {
+        $this->searchcriteria = $searchcriteria;
+        return $this;
+    }
+
+    /**
+     * Returns formatted and filtered description of the given category
+     *
+     * @param coursecat $coursecat category
+     * @param stdClass|array $options format options, by default [noclean,overflowdiv],
+     *     if context is not specified it will be added automatically
+     * @return string|null
+     */
+    public function get_category_formatted_description($coursecat, $options = null) {
+        if ($coursecat->id && !empty($coursecat->description)) {
+            if (!isset($coursecat->descriptionformat)) {
+                $descriptionformat = FORMAT_MOODLE;
+            } else {
+                $descriptionformat = $coursecat->descriptionformat;
+            }
+            if ($options === null) {
+                $options = array('noclean' => true, 'overflowdiv' => true);
+            } else {
+                $options = (array)$options;
+            }
+            $context = context_coursecat::instance($coursecat->id);
+            if (!isset($options['context'])) {
+                $options['context'] = $context;
+            }
+            $text = file_rewrite_pluginfile_urls($coursecat->description,
+                    'pluginfile.php', $context->id, 'coursecat', 'description', null);
+            return format_text($text, $descriptionformat, $options);
+        }
+        return null;
+    }
+
+    /**
+     * Returns given course's summary with proper embedded files urls and formatted
+     *
+     * @param course_in_list $course
+     * @param array|stdClass $options additional formatting options
+     * @return string
+     */
+    public function get_course_formatted_summary($course, $options = array()) {
+        global $CFG;
+        require_once($CFG->libdir. '/filelib.php');
+        if (!$course->has_summary()) {
+            return '';
+        }
+        $options = (array)$options;
+        $context = context_course::instance($course->id);
+        if (!isset($options['context'])) {
+            // TODO see MDL-38521
+            // option 1 (current), page context - no code required
+            // option 2, system context
+            // $options['context'] = context_system::instance();
+            // option 3, course context:
+            // $options['context'] = $context;
+            // option 4, course category context:
+            // $options['context'] = $context->get_parent_context();
+        }
+        $summary = file_rewrite_pluginfile_urls($course->summary, 'pluginfile.php', $context->id, 'course', 'summary', null);
+        $summary = format_text($summary, $course->summaryformat, $options, $course->id);
+        if (!empty($this->searchcriteria['search'])) {
+            $summary = highlight($this->searchcriteria['search'], $summary);
+        }
+        return $summary;
+    }
+
+    /**
+     * Returns course name as it is configured to appear in courses lists formatted to course context
+     *
+     * @param course_in_list $course
+     * @param array|stdClass $options additional formatting options
+     * @return string
+     */
+    public function get_course_formatted_name($course, $options = array()) {
+        $options = (array)$options;
+        if (!isset($options['context'])) {
+            $options['context'] = context_course::instance($course->id);
+        }
+        $name = format_string(get_course_display_name_for_list($course), true, $options);
+        if (!empty($this->searchcriteria['search'])) {
+            $name = highlight($this->searchcriteria['search'], $name);
+        }
+        return $name;
+    }
 }
index a2248ed..0827c31 100644 (file)
@@ -1763,6 +1763,7 @@ $string['version'] = 'Version';
 $string['view'] = 'View';
 $string['viewallcourses'] = 'View all courses';
 $string['viewallcoursescategories'] = 'View all courses and categories';
+$string['viewmore'] = 'View more';
 $string['viewfileinpopup'] = 'View file in a popup window';
 $string['viewprofile'] = 'View profile';
 $string['views'] = 'Views';
index c484094..25a502e 100644 (file)
@@ -11197,12 +11197,15 @@ function get_home_page() {
  * Gets the name of a course to be displayed when showing a list of courses.
  * By default this is just $course->fullname but user can configure it. The
  * result of this function should be passed through print_string.
- * @param object $course Moodle course object
+ * @param stdClass|course_in_list $course Moodle course object
  * @return string Display name of course (either fullname or short + fullname)
  */
 function get_course_display_name_for_list($course) {
     global $CFG;
     if (!empty($CFG->courselistshortnames)) {
+        if (!($course instanceof stdClass)) {
+            $course = (object)convert_to_array($course);
+        }
         return get_string('courseextendednamedisplay', '', $course);
     } else {
         return $course->fullname;