MDL-34785 performance improvement with big list of courses
[moodle.git] / blocks / course_overview / locallib.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * Helper functions for course_overview block
19  *
20  * @package    block_course_overview
21  * @copyright  2012 Adam Olley <adam.olley@netspot.com.au>
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 /**
26  * Display overview for courses
27  *
28  * @param array $courses courses for which overview needs to be shown
29  * @return array html overview
30  */
31 function block_course_overview_get_overviews($courses) {
32     $htmlarray = array();
33     if ($modules = get_plugin_list_with_function('mod', 'print_overview')) {
34         // Split courses list into batches with no more than MAX_MODINFO_CACHE_SIZE courses in one batch.
35         // Otherwise we exceed the cache limit in get_fast_modinfo() and rebuild it too often.
36         if (defined('MAX_MODINFO_CACHE_SIZE') && MAX_MODINFO_CACHE_SIZE > 0 && count($courses) > MAX_MODINFO_CACHE_SIZE) {
37             $batches = array_chunk($courses, MAX_MODINFO_CACHE_SIZE, true);
38         } else {
39             $batches = array($courses);
40         }
41         foreach ($batches as $courses) {
42             foreach ($modules as $fname) {
43                 $fname($courses, $htmlarray);
44             }
45         }
46     }
47     return $htmlarray;
48 }
50 /**
51  * Sets user preference for maximum courses to be displayed in course_overview block
52  *
53  * @param int $number maximum courses which should be visible
54  */
55 function block_course_overview_update_mynumber($number) {
56     set_user_preference('course_overview_number_of_courses', $number);
57 }
59 /**
60  * Sets user course sorting preference in course_overview block
61  *
62  * @param array $sortorder sort order of course
63  */
64 function block_course_overview_update_myorder($sortorder) {
65     set_user_preference('course_overview_course_order', serialize($sortorder));
66 }
68 /**
69  * Returns shortname of activities in course
70  *
71  * @param int $courseid id of course for which activity shortname is needed
72  * @return string|bool list of child shortname
73  */
74 function block_course_overview_get_child_shortnames($courseid) {
75     global $DB;
76     $ctxselect = context_helper::get_preload_record_columns_sql('ctx');
77     $sql = "SELECT c.id, c.shortname, $ctxselect
78             FROM {enrol} e
79             JOIN {course} c ON (c.id = e.customint1)
80             JOIN {context} ctx ON (ctx.instanceid = e.customint1)
81             WHERE e.courseid = :courseid AND e.enrol = :method AND ctx.contextlevel = :contextlevel ORDER BY e.sortorder";
82     $params = array('method' => 'meta', 'courseid' => $courseid, 'contextlevel' => CONTEXT_COURSE);
84     if ($results = $DB->get_records_sql($sql, $params)) {
85         $shortnames = array();
86         // Preload the context we will need it to format the category name shortly.
87         foreach ($results as $res) {
88             context_helper::preload_from_record($res);
89             $context = context_course::instance($res->id);
90             $shortnames[] = format_string($res->shortname, true, $context);
91         }
92         $total = count($shortnames);
93         $suffix = '';
94         if ($total > 10) {
95             $shortnames = array_slice($shortnames, 0, 10);
96             $diff = $total - count($shortnames);
97             if ($diff > 1) {
98                 $suffix = get_string('shortnamesufixprural', 'block_course_overview', $diff);
99             } else {
100                 $suffix = get_string('shortnamesufixsingular', 'block_course_overview', $diff);
101             }
102         }
103         $shortnames = get_string('shortnameprefix', 'block_course_overview', implode('; ', $shortnames));
104         $shortnames .= $suffix;
105     }
107     return isset($shortnames) ? $shortnames : false;
110 /**
111  * Returns maximum number of courses which will be displayed in course_overview block
112  *
113  * @return int maximum number of courses
114  */
115 function block_course_overview_get_max_user_courses() {
116     // Get block configuration
117     $config = get_config('block_course_overview');
118     $limit = $config->defaultmaxcourses;
120     // If max course is not set then try get user preference
121     if (empty($config->forcedefaultmaxcourses)) {
122         $limit = get_user_preferences('course_overview_number_of_courses', $limit);
123     }
124     return $limit;
127 /**
128  * Return sorted list of user courses
129  *
130  * @return array list of sorted courses and count of courses.
131  */
132 function block_course_overview_get_sorted_courses() {
133     global $USER;
135     $limit = block_course_overview_get_max_user_courses();
137     $courses = enrol_get_my_courses('id, shortname, fullname, modinfo, sectioncache');
138     $site = get_site();
140     if (array_key_exists($site->id,$courses)) {
141         unset($courses[$site->id]);
142     }
144     foreach ($courses as $c) {
145         if (isset($USER->lastcourseaccess[$c->id])) {
146             $courses[$c->id]->lastaccess = $USER->lastcourseaccess[$c->id];
147         } else {
148             $courses[$c->id]->lastaccess = 0;
149         }
150     }
152     // Get remote courses.
153     $remotecourses = array();
154     if (is_enabled_auth('mnet')) {
155         $remotecourses = get_my_remotecourses();
156     }
157     // Remote courses will have -ve remoteid as key, so it can be differentiated from normal courses
158     foreach ($remotecourses as $id => $val) {
159         $remoteid = $val->remoteid * -1;
160         $val->id = $remoteid;
161         $courses[$remoteid] = $val;
162     }
164     $order = array();
165     if (!is_null($usersortorder = get_user_preferences('course_overview_course_order'))) {
166         $order = unserialize($usersortorder);
167     }
169     $sortedcourses = array();
170     $counter = 0;
171     // Get courses in sort order into list.
172     foreach ($order as $key => $cid) {
173         if (($counter >= $limit) && ($limit != 0)) {
174             break;
175         }
177         // Make sure user is still enroled.
178         if (isset($courses[$cid])) {
179             $sortedcourses[$cid] = $courses[$cid];
180             $counter++;
181         }
182     }
183     // Append unsorted courses if limit allows
184     foreach ($courses as $c) {
185         if (($limit != 0) && ($counter >= $limit)) {
186             break;
187         }
188         if (!in_array($c->id, $order)) {
189             $sortedcourses[$c->id] = $c;
190             $counter++;
191         }
192     }
194     // From list extract site courses for overview
195     $sitecourses = array();
196     foreach ($sortedcourses as $key => $course) {
197         if ($course->id > 0) {
198             $sitecourses[$key] = $course;
199         }
200     }
201     return array($sortedcourses, $sitecourses, count($courses));