MDL-29529 Assignment: Fix regression (order by status) caused by MDL-27638
[moodle.git] / grade / querylib.php
blob0a18e0a68484f46816bba277eccd35a9b51aea5f
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
19 /**
20 * Returns the aggregated or calculated course grade(s) in given course.
21 * @public
22 * @param int $courseid id of course
23 * @param int $userid_or_ids optional id of the graded user or array of ids; if userid not used, returns only information about grade_item
24 * @return information about course grade item scaleid, name, grade and locked status, etc. + user grades
26 function grade_get_course_grades($courseid, $userid_or_ids=null) {
28 $grade_item = grade_item::fetch_course_item($courseid);
30 if ($grade_item->needsupdate) {
31 grade_regrade_final_grades($courseid);
34 $item = new object();
35 $item->scaleid = $grade_item->scaleid;
36 $item->name = $grade_item->get_name();
37 $item->grademin = $grade_item->grademin;
38 $item->grademax = $grade_item->grademax;
39 $item->gradepass = $grade_item->gradepass;
40 $item->locked = $grade_item->is_locked();
41 $item->hidden = $grade_item->is_hidden();
42 $item->grades = array();
44 switch ($grade_item->gradetype) {
45 case GRADE_TYPE_NONE:
46 continue;
48 case GRADE_TYPE_VALUE:
49 $item->scaleid = 0;
50 break;
52 case GRADE_TYPE_TEXT:
53 $item->scaleid = 0;
54 $item->grademin = 0;
55 $item->grademax = 0;
56 $item->gradepass = 0;
57 break;
60 if (empty($userid_or_ids)) {
61 $userids = array();
63 } else if (is_array($userid_or_ids)) {
64 $userids = $userid_or_ids;
66 } else {
67 $userids = array($userid_or_ids);
70 if ($userids) {
71 $grade_grades = grade_grade::fetch_users_grades($grade_item, $userids, true);
72 foreach ($userids as $userid) {
73 $grade_grades[$userid]->grade_item =& $grade_item;
75 $grade = new object();
76 $grade->grade = $grade_grades[$userid]->finalgrade;
77 $grade->locked = $grade_grades[$userid]->is_locked();
78 $grade->hidden = $grade_grades[$userid]->is_hidden();
79 $grade->overridden = $grade_grades[$userid]->overridden;
80 $grade->feedback = $grade_grades[$userid]->feedback;
81 $grade->feedbackformat = $grade_grades[$userid]->feedbackformat;
82 $grade->usermodified = $grade_grades[$userid]->usermodified;
83 $grade->dategraded = $grade_grades[$userid]->get_dategraded();
85 // create text representation of grade
86 if ($grade_item->needsupdate) {
87 $grade->grade = false;
88 $grade->str_grade = get_string('error');
89 $grade->str_long_grade = $grade->str_grade;
91 } else if (is_null($grade->grade)) {
92 $grade->str_grade = '-';
93 $grade->str_long_grade = $grade->str_grade;
95 } else {
96 $grade->str_grade = grade_format_gradevalue($grade->grade, $grade_item);
97 if ($grade_item->gradetype == GRADE_TYPE_SCALE or $grade_item->get_displaytype() != GRADE_DISPLAY_TYPE_REAL) {
98 $grade->str_long_grade = $grade->str_grade;
99 } else {
100 $a = new object();
101 $a->grade = $grade->str_grade;
102 $a->max = grade_format_gradevalue($grade_item->grademax, $grade_item);
103 $grade->str_long_grade = get_string('gradelong', 'grades', $a);
107 // create html representation of feedback
108 if (is_null($grade->feedback)) {
109 $grade->str_feedback = '';
110 } else {
111 $grade->str_feedback = format_text($grade->feedback, $grade->feedbackformat);
114 $item->grades[$userid] = $grade;
118 return $item;
122 * Returns the aggregated or calculated course grade for the given user(s).
123 * @public
124 * @param int $userid
125 * @param int $courseid optional id of course or array of ids, empty means all uses courses (returns array if not present)
126 * @return mixed grade info or grades array including item info, false if error
128 function grade_get_course_grade($userid, $courseid_or_ids=null) {
130 if (!is_array($courseid_or_ids)) {
131 if (empty($courseid_or_ids)) {
132 if (!$courses = get_my_courses($userid, $sort='visible DESC,sortorder ASC', 'id')) {
133 return false;
135 $courseids = array_keys($courses);
136 return grade_get_course_grade($userid, $courseids);
138 if (!is_numeric($courseid_or_ids)) {
139 return false;
141 if (!$grades = grade_get_course_grade($userid, array($courseid_or_ids))) {
142 return false;
143 } else {
144 // only one grade - not array
145 $grade = reset($grades);
146 return $grade;
150 foreach ($courseid_or_ids as $courseid) {
151 $grade_item = grade_item::fetch_course_item($courseid);
152 $course_items[$grade_item->courseid] = $grade_item;
155 $grades = array();
156 foreach ($course_items as $grade_item) {
157 if ($grade_item->needsupdate) {
158 grade_regrade_final_grades($courseid);
161 $item = new object();
162 $item->scaleid = $grade_item->scaleid;
163 $item->name = $grade_item->get_name();
164 $item->grademin = $grade_item->grademin;
165 $item->grademax = $grade_item->grademax;
166 $item->gradepass = $grade_item->gradepass;
167 $item->locked = $grade_item->is_locked();
168 $item->hidden = $grade_item->is_hidden();
170 switch ($grade_item->gradetype) {
171 case GRADE_TYPE_NONE:
172 continue;
174 case GRADE_TYPE_VALUE:
175 $item->scaleid = 0;
176 break;
178 case GRADE_TYPE_TEXT:
179 $item->scaleid = 0;
180 $item->grademin = 0;
181 $item->grademax = 0;
182 $item->gradepass = 0;
183 break;
185 $grade_grade = new grade_grade(array('userid'=>$userid, 'itemid'=>$grade_item->id));
186 $grade_grade->grade_item =& $grade_item;
188 $grade = new object();
189 $grade->grade = $grade_grade->finalgrade;
190 $grade->locked = $grade_grade->is_locked();
191 $grade->hidden = $grade_grade->is_hidden();
192 $grade->overridden = $grade_grade->overridden;
193 $grade->feedback = $grade_grade->feedback;
194 $grade->feedbackformat = $grade_grade->feedbackformat;
195 $grade->usermodified = $grade_grade->usermodified;
196 $grade->dategraded = $grade_grade->get_dategraded();
197 $grade->item = $item;
199 // create text representation of grade
200 if ($grade_item->needsupdate) {
201 $grade->grade = false;
202 $grade->str_grade = get_string('error');
203 $grade->str_long_grade = $grade->str_grade;
205 } else if (is_null($grade->grade)) {
206 $grade->str_grade = '-';
207 $grade->str_long_grade = $grade->str_grade;
209 } else {
210 $grade->str_grade = grade_format_gradevalue($grade->grade, $grade_item);
211 if ($grade_item->gradetype == GRADE_TYPE_SCALE or $grade_item->get_displaytype() != GRADE_DISPLAY_TYPE_REAL) {
212 $grade->str_long_grade = $grade->str_grade;
213 } else {
214 $a = new object();
215 $a->grade = $grade->str_grade;
216 $a->max = grade_format_gradevalue($grade_item->grademax, $grade_item);
217 $grade->str_long_grade = get_string('gradelong', 'grades', $a);
221 // create html representation of feedback
222 if (is_null($grade->feedback)) {
223 $grade->str_feedback = '';
224 } else {
225 $grade->str_feedback = format_text($grade->feedback, $grade->feedbackformat);
228 $grades[$grade_item->courseid] = $grade;
231 return $grades;
235 * Returns all grade items (including outcomes) or main item for a given activity identified by $cm object.
237 * @param object $cm A course module object (preferably with modname property)
238 * @return mixed - array of grade item instances (one if $only_main_item true), false if error or not found
240 function grade_get_grade_items_for_activity($cm, $only_main_item=false) {
241 global $CFG;
243 if (!isset($cm->modname)) {
244 $cm = get_record_sql("SELECT cm.*, m.name, md.name as modname
245 FROM {$CFG->prefix}course_modules cm,
246 {$CFG->prefix}modules md,
247 WHERE cm.id = {$cm->id} AND md.id = cm.module");
251 if (empty($cm) or empty($cm->instance) or empty($cm->course)) {
252 debugging("Incorrect cm parameter in grade_get_grade_items_for_activity()!");
253 return false;
256 if ($only_main_item) {
257 return grade_item::fetch_all(array('itemtype'=>'mod', 'itemmodule'=>$cm->modname, 'iteminstance'=>$cm->instance, 'courseid'=>$cm->course, 'itemnumber'=>0));
258 } else {
259 return grade_item::fetch_all(array('itemtype'=>'mod', 'itemmodule'=>$cm->modname, 'iteminstance'=>$cm->instance, 'courseid'=>$cm->course));
264 * Returns whether or not user received grades in main grade item for given activity.
266 * @param object $cm
267 * @param int $userid
268 * @return bool True if graded false if user not graded yet
270 function grade_is_user_graded_in_activity($cm, $userid) {
272 $grade_items = grade_get_grade_items_for_activity($cm, true);
273 if (empty($grade_items)) {
274 return false;
277 $grade_item = reset($grade_items);
279 if ($grade_item->gradetype == GRADE_TYPE_NONE) {
280 return false;
283 if ($grade_item->needsupdate) {
284 // activity items should never fail to regrade
285 grade_regrade_final_grades($grade_item->courseid);
288 if (!$grade = $grade_item->get_final($userid)) {
289 return false;
292 if (is_null($grade->finalgrade)) {
293 return false;
296 return true;
300 * Returns an array of activities (defined as $cm objects) which are gradeable from gradebook, outcomes are ignored.
302 * @param int $courseid If provided then restrict to one course.
303 * @param string $modulename If defined (could be 'forum', 'assignment' etc) then only that type are returned.
304 * @return array $cm objects
306 function grade_get_gradable_activities($courseid, $modulename='') {
307 global $CFG;
309 if (empty($modulename)) {
310 if (!$modules = get_records('modules', 'visible', '1')) {
311 return false;
313 $result = array();
314 foreach ($modules as $module) {
315 if ($cms = grade_get_gradable_activities($courseid, $module->name)) {
316 $result = $result + $cms;
319 if (empty($result)) {
320 return false;
321 } else {
322 return $result;
326 $sql = "SELECT cm.*, m.name, md.name as modname
327 FROM {$CFG->prefix}grade_items gi, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules md, {$CFG->prefix}$modulename m
328 WHERE gi.courseid = $courseid AND
329 gi.itemtype = 'mod' AND
330 gi.itemmodule = '$modulename' AND
331 gi.itemnumber = 0 AND
332 gi.gradetype != ".GRADE_TYPE_NONE." AND
333 gi.iteminstance = cm.instance AND
334 cm.instance = m.id AND
335 md.name = '$modulename' AND
336 md.id = cm.module";
338 return get_records_sql($sql);