Merge branch 'MDL-69993-310' of git://github.com/paulholden/moodle into MOODLE_310_STABLE
[moodle.git] / grade / querylib.php
CommitLineData
e060e33d 1<?php
e060e33d 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/>.
b9f49659 16
17/**
a153c9f2
AD
18 * Functions used to retrieve grades objects
19 *
20 * @package core_grades
21 * @category grade
22 * @copyright 2008 Petr Skoda and Nicolas Connault
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26/**
27 * Returns the aggregated or calculated course grade(s) for a single course for one or more users
28 *
29 * @param int $courseid The ID of course
30 * @param int|array $userid_or_ids Optional ID of the graded user or array of user IDs; if userid not used, returns only information about grade_item
31 * @return stdClass Returns an object containing information about course grade item. scaleid, name, grade
32 * and locked status etc and user course grades: $item->grades[$userid] => $usercoursegrade
b9f49659 33 */
34function grade_get_course_grades($courseid, $userid_or_ids=null) {
35
36 $grade_item = grade_item::fetch_course_item($courseid);
37
38 if ($grade_item->needsupdate) {
39 grade_regrade_final_grades($courseid);
40 }
41
ace9051c 42 $item = new stdClass();
b9f49659 43 $item->scaleid = $grade_item->scaleid;
44 $item->name = $grade_item->get_name();
45 $item->grademin = $grade_item->grademin;
46 $item->grademax = $grade_item->grademax;
47 $item->gradepass = $grade_item->gradepass;
48 $item->locked = $grade_item->is_locked();
49 $item->hidden = $grade_item->is_hidden();
50 $item->grades = array();
51
52 switch ($grade_item->gradetype) {
53 case GRADE_TYPE_NONE:
bd5fdcfc 54 break;
b9f49659 55
56 case GRADE_TYPE_VALUE:
57 $item->scaleid = 0;
58 break;
59
60 case GRADE_TYPE_TEXT:
61 $item->scaleid = 0;
62 $item->grademin = 0;
63 $item->grademax = 0;
64 $item->gradepass = 0;
65 break;
66 }
67
68 if (empty($userid_or_ids)) {
69 $userids = array();
70
71 } else if (is_array($userid_or_ids)) {
72 $userids = $userid_or_ids;
73
74 } else {
75 $userids = array($userid_or_ids);
76 }
77
78 if ($userids) {
79 $grade_grades = grade_grade::fetch_users_grades($grade_item, $userids, true);
80 foreach ($userids as $userid) {
81 $grade_grades[$userid]->grade_item =& $grade_item;
82
ace9051c 83 $grade = new stdClass();
b9f49659 84 $grade->grade = $grade_grades[$userid]->finalgrade;
85 $grade->locked = $grade_grades[$userid]->is_locked();
86 $grade->hidden = $grade_grades[$userid]->is_hidden();
87 $grade->overridden = $grade_grades[$userid]->overridden;
88 $grade->feedback = $grade_grades[$userid]->feedback;
89 $grade->feedbackformat = $grade_grades[$userid]->feedbackformat;
90 $grade->usermodified = $grade_grades[$userid]->usermodified;
b9f49659 91 $grade->dategraded = $grade_grades[$userid]->get_dategraded();
a7888487 92 $grade->datesubmitted = $grade_grades[$userid]->get_datesubmitted();
b9f49659 93
94 // create text representation of grade
95 if ($grade_item->needsupdate) {
85a0a69f 96 $grade->grade = false;
97 $grade->str_grade = get_string('error');
98 $grade->str_long_grade = $grade->str_grade;
b9f49659 99
100 } else if (is_null($grade->grade)) {
85a0a69f 101 $grade->str_grade = '-';
102 $grade->str_long_grade = $grade->str_grade;
b9f49659 103
104 } else {
105 $grade->str_grade = grade_format_gradevalue($grade->grade, $grade_item);
85a0a69f 106 if ($grade_item->gradetype == GRADE_TYPE_SCALE or $grade_item->get_displaytype() != GRADE_DISPLAY_TYPE_REAL) {
107 $grade->str_long_grade = $grade->str_grade;
108 } else {
ace9051c 109 $a = new stdClass();
85a0a69f 110 $a->grade = $grade->str_grade;
111 $a->max = grade_format_gradevalue($grade_item->grademax, $grade_item);
112 $grade->str_long_grade = get_string('gradelong', 'grades', $a);
113 }
b9f49659 114 }
115
116 // create html representation of feedback
117 if (is_null($grade->feedback)) {
118 $grade->str_feedback = '';
119 } else {
120 $grade->str_feedback = format_text($grade->feedback, $grade->feedbackformat);
121 }
122
123 $item->grades[$userid] = $grade;
124 }
125 }
126
127 return $item;
128}
129
028553e7 130/**
a153c9f2
AD
131 * Returns the aggregated or calculated course grade for a single user for one or more courses
132 *
133 * @param int $userid The ID of the single user
134 * @param int|array $courseid_or_ids Optional ID of course or array of IDs, empty means all of the user's courses
028553e7 135 * @return mixed grade info or grades array including item info, false if error
136 */
137function grade_get_course_grade($userid, $courseid_or_ids=null) {
138
139 if (!is_array($courseid_or_ids)) {
140 if (empty($courseid_or_ids)) {
df997f84 141 if (!$courses = enrol_get_users_courses($userid)) {
028553e7 142 return false;
143 }
144 $courseids = array_keys($courses);
145 return grade_get_course_grade($userid, $courseids);
146 }
147 if (!is_numeric($courseid_or_ids)) {
148 return false;
149 }
150 if (!$grades = grade_get_course_grade($userid, array($courseid_or_ids))) {
151 return false;
152 } else {
153 // only one grade - not array
154 $grade = reset($grades);
155 return $grade;
156 }
157 }
158
159 foreach ($courseid_or_ids as $courseid) {
160 $grade_item = grade_item::fetch_course_item($courseid);
161 $course_items[$grade_item->courseid] = $grade_item;
162 }
163
164 $grades = array();
165 foreach ($course_items as $grade_item) {
166 if ($grade_item->needsupdate) {
167 grade_regrade_final_grades($courseid);
168 }
169
ace9051c 170 $item = new stdClass();
028553e7 171 $item->scaleid = $grade_item->scaleid;
172 $item->name = $grade_item->get_name();
173 $item->grademin = $grade_item->grademin;
174 $item->grademax = $grade_item->grademax;
175 $item->gradepass = $grade_item->gradepass;
176 $item->locked = $grade_item->is_locked();
177 $item->hidden = $grade_item->is_hidden();
178
179 switch ($grade_item->gradetype) {
180 case GRADE_TYPE_NONE:
bd5fdcfc 181 break;
028553e7 182
183 case GRADE_TYPE_VALUE:
184 $item->scaleid = 0;
185 break;
186
187 case GRADE_TYPE_TEXT:
188 $item->scaleid = 0;
189 $item->grademin = 0;
190 $item->grademax = 0;
191 $item->gradepass = 0;
192 break;
193 }
194 $grade_grade = new grade_grade(array('userid'=>$userid, 'itemid'=>$grade_item->id));
195 $grade_grade->grade_item =& $grade_item;
196
ace9051c 197 $grade = new stdClass();
028553e7 198 $grade->grade = $grade_grade->finalgrade;
199 $grade->locked = $grade_grade->is_locked();
200 $grade->hidden = $grade_grade->is_hidden();
201 $grade->overridden = $grade_grade->overridden;
202 $grade->feedback = $grade_grade->feedback;
203 $grade->feedbackformat = $grade_grade->feedbackformat;
204 $grade->usermodified = $grade_grade->usermodified;
205 $grade->dategraded = $grade_grade->get_dategraded();
206 $grade->item = $item;
207
208 // create text representation of grade
209 if ($grade_item->needsupdate) {
85a0a69f 210 $grade->grade = false;
211 $grade->str_grade = get_string('error');
212 $grade->str_long_grade = $grade->str_grade;
028553e7 213
214 } else if (is_null($grade->grade)) {
85a0a69f 215 $grade->str_grade = '-';
216 $grade->str_long_grade = $grade->str_grade;
028553e7 217
218 } else {
219 $grade->str_grade = grade_format_gradevalue($grade->grade, $grade_item);
85a0a69f 220 if ($grade_item->gradetype == GRADE_TYPE_SCALE or $grade_item->get_displaytype() != GRADE_DISPLAY_TYPE_REAL) {
221 $grade->str_long_grade = $grade->str_grade;
222 } else {
ace9051c 223 $a = new stdClass();
85a0a69f 224 $a->grade = $grade->str_grade;
225 $a->max = grade_format_gradevalue($grade_item->grademax, $grade_item);
226 $grade->str_long_grade = get_string('gradelong', 'grades', $a);
227 }
028553e7 228 }
229
230 // create html representation of feedback
231 if (is_null($grade->feedback)) {
232 $grade->str_feedback = '';
233 } else {
234 $grade->str_feedback = format_text($grade->feedback, $grade->feedbackformat);
235 }
236
237 $grades[$grade_item->courseid] = $grade;
238 }
239
240 return $grades;
241}
242
b9f49659 243/**
244 * Returns all grade items (including outcomes) or main item for a given activity identified by $cm object.
245 *
a153c9f2
AD
246 * @param cm_info $cm A course module object (preferably with modname property)
247 * @param bool $only_main_item Limit the search to the primary grade item for the activity, 'itemnumber'==0
248 * @return mixed An array of grade item instances, one grade item if $only_main_item == true, false if error or not found
b9f49659 249 */
250function grade_get_grade_items_for_activity($cm, $only_main_item=false) {
d24832f9 251 global $CFG, $DB;
b9f49659 252
253 if (!isset($cm->modname)) {
d24832f9 254 $params = array($cm->id);
3a346592 255 $cm = $DB->get_record_sql("SELECT cm.*, md.name as modname
d24832f9 256 FROM {course_modules} cm,
3a346592 257 {modules} md
d24832f9 258 WHERE cm.id = ? AND md.id = cm.module", $params);
b9f49659 259 }
260
261
262 if (empty($cm) or empty($cm->instance) or empty($cm->course)) {
263 debugging("Incorrect cm parameter in grade_get_grade_items_for_activity()!");
264 return false;
265 }
266
267 if ($only_main_item) {
268 return grade_item::fetch_all(array('itemtype'=>'mod', 'itemmodule'=>$cm->modname, 'iteminstance'=>$cm->instance, 'courseid'=>$cm->course, 'itemnumber'=>0));
269 } else {
270 return grade_item::fetch_all(array('itemtype'=>'mod', 'itemmodule'=>$cm->modname, 'iteminstance'=>$cm->instance, 'courseid'=>$cm->course));
271 }
272}
273
274/**
a153c9f2 275 * Returns whether or not a user received grades in main grade item for given activity
b9f49659 276 *
a153c9f2
AD
277 * @param cm_info $cm The activity context module
278 * @param int $userid The user ID
279 * @return bool True if graded, false if user not graded yet
b9f49659 280 */
281function grade_is_user_graded_in_activity($cm, $userid) {
282
283 $grade_items = grade_get_grade_items_for_activity($cm, true);
284 if (empty($grade_items)) {
285 return false;
286 }
287
288 $grade_item = reset($grade_items);
289
290 if ($grade_item->gradetype == GRADE_TYPE_NONE) {
291 return false;
292 }
293
294 if ($grade_item->needsupdate) {
295 // activity items should never fail to regrade
296 grade_regrade_final_grades($grade_item->courseid);
297 }
298
299 if (!$grade = $grade_item->get_final($userid)) {
300 return false;
301 }
302
303 if (is_null($grade->finalgrade)) {
304 return false;
305 }
306
307 return true;
308}
309
310/**
311 * Returns an array of activities (defined as $cm objects) which are gradeable from gradebook, outcomes are ignored.
312 *
313 * @param int $courseid If provided then restrict to one course.
314 * @param string $modulename If defined (could be 'forum', 'assignment' etc) then only that type are returned.
315 * @return array $cm objects
316 */
317function grade_get_gradable_activities($courseid, $modulename='') {
d24832f9 318 global $CFG, $DB;
b9f49659 319
320 if (empty($modulename)) {
d24832f9 321 if (!$modules = $DB->get_records('modules', array('visible' => '1'))) {
b9f49659 322 return false;
323 }
324 $result = array();
325 foreach ($modules as $module) {
326 if ($cms = grade_get_gradable_activities($courseid, $module->name)) {
327 $result = $result + $cms;
328 }
329 }
330 if (empty($result)) {
331 return false;
332 } else {
333 return $result;
334 }
335 }
336
d24832f9 337 $params = array($courseid, $modulename, GRADE_TYPE_NONE, $modulename);
b9f49659 338 $sql = "SELECT cm.*, m.name, md.name as modname
f41741e7 339 FROM {grade_items} gi, {course_modules} cm, {modules} md, {{$modulename}} m
d24832f9 340 WHERE gi.courseid = ? AND
b9f49659 341 gi.itemtype = 'mod' AND
d24832f9 342 gi.itemmodule = ? AND
b9f49659 343 gi.itemnumber = 0 AND
d24832f9 344 gi.gradetype != ? AND
b9f49659 345 gi.iteminstance = cm.instance AND
346 cm.instance = m.id AND
d24832f9 347 md.name = ? AND
b9f49659 348 md.id = cm.module";
349
d24832f9 350 return $DB->get_records_sql($sql, $params);
b9f49659 351}
6c3ef410 352