forked from moodle/moodle
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgrade_outcome.php
426 lines (375 loc) · 13.1 KB
/
grade_outcome.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
<?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/>.
/**
* Definition of grade outcome class
*
* @package core_grades
* @category grade
* @copyright 2006 Nicolas Connault
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once('grade_object.php');
/**
* Class representing a grade outcome.
*
* It is responsible for handling its DB representation, modifying and returning its metadata.
*
* @package core_grades
* @category grade
* @copyright 2006 Nicolas Connault
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class grade_outcome extends grade_object {
/**
* DB Table (used by grade_object).
* @var string $table
*/
public $table = 'grade_outcomes';
/**
* Array of required table fields, must start with 'id'.
* @var array $required_fields
*/
public $required_fields = array('id', 'courseid', 'shortname', 'fullname', 'scaleid','description',
'descriptionformat', 'timecreated', 'timemodified', 'usermodified');
/**
* The course this outcome belongs to.
* @var int $courseid
*/
public $courseid;
/**
* The shortname of the outcome.
* @var string $shortname
*/
public $shortname;
/**
* The fullname of the outcome.
* @var string $fullname
*/
public $fullname;
/**
* A full grade_scale object referenced by $this->scaleid.
* @var object $scale
*/
public $scale;
/**
* The id of the scale referenced by this outcome.
* @var int $scaleid
*/
public $scaleid;
/**
* The description of this outcome - FORMAT_MOODLE.
* @var string $description
*/
public $description;
/**
* The userid of the person who last modified this outcome.
*
* @var int $usermodified
*/
public $usermodified;
/**
* Deletes this outcome from the database.
*
* @param string $source from where was the object deleted (mod/forum, manual, etc.)
* @return bool success
*/
public function delete($source=null) {
global $DB;
if (!empty($this->courseid)) {
$DB->delete_records('grade_outcomes_courses', array('outcomeid' => $this->id, 'courseid' => $this->courseid));
}
if (parent::delete($source)) {
$context = context_system::instance();
$fs = get_file_storage();
$files = $fs->get_area_files($context->id, 'grade', 'outcome', $this->id);
foreach ($files as $file) {
$file->delete();
}
return true;
}
return false;
}
/**
* Records this object in the Database, sets its id to the returned value, and returns that value.
* If successful this function also fetches the new object data from database and stores it
* in object properties.
*
* @param string $source from where was the object inserted (mod/forum, manual, etc.)
* @param bool $isbulkupdate If bulk grade update is happening.
* @return int PK ID if successful, false otherwise
*/
public function insert($source = null, $isbulkupdate = false) {
global $DB;
$this->timecreated = $this->timemodified = time();
if ($result = parent::insert($source)) {
if (!empty($this->courseid)) {
$goc = new stdClass();
$goc->courseid = $this->courseid;
$goc->outcomeid = $this->id;
$DB->insert_record('grade_outcomes_courses', $goc);
}
}
return $result;
}
/**
* In addition to update() it also updates grade_outcomes_courses if needed
*
* @param string $source from where was the object inserted
* @param bool $isbulkupdate If bulk grade update is happening.
* @return bool success
*/
public function update($source = null, $isbulkupdate = false) {
$this->timemodified = time();
if ($result = parent::update($source)) {
if (!empty($this->courseid)) {
$this->use_in($this->courseid);
}
}
return $result;
}
/**
* Mark outcome as used in a course
*
* @param int $courseid
* @return False if invalid courseid requested
*/
public function use_in($courseid) {
global $DB;
if (!empty($this->courseid) and $courseid != $this->courseid) {
return false;
}
if (!$DB->record_exists('grade_outcomes_courses', array('courseid' => $courseid, 'outcomeid' => $this->id))) {
$goc = new stdClass();
$goc->courseid = $courseid;
$goc->outcomeid = $this->id;
$DB->insert_record('grade_outcomes_courses', $goc);
}
return true;
}
/**
* Finds and returns a grade_outcome instance based on params.
*
* @static
* @param array $params associative arrays varname=>value
* @return object grade_outcome instance or false if none found.
*/
public static function fetch($params) {
return grade_object::fetch_helper('grade_outcomes', 'grade_outcome', $params);
}
/**
* Finds and returns all grade_outcome instances based on params.
*
* @static
* @param array $params associative arrays varname=>value
* @return array array of grade_outcome insatnces or false if none found.
*/
public static function fetch_all($params) {
return grade_object::fetch_all_helper('grade_outcomes', 'grade_outcome', $params);
}
/**
* Instantiates a grade_scale object whose data is retrieved from the database
*
* @return grade_scale
*/
public function load_scale() {
if (empty($this->scale->id) or $this->scale->id != $this->scaleid) {
$this->scale = grade_scale::fetch(array('id'=>$this->scaleid));
$this->scale->load_items();
}
return $this->scale;
}
/**
* Static function returning all global outcomes
*
* @static
* @return array
*/
public static function fetch_all_global() {
if (!$outcomes = grade_outcome::fetch_all(array('courseid'=>null))) {
$outcomes = array();
}
return $outcomes;
}
/**
* Static function returning all local course outcomes
*
* @static
* @param int $courseid
* @return array
*/
public static function fetch_all_local($courseid) {
if (!$outcomes =grade_outcome::fetch_all(array('courseid'=>$courseid))) {
$outcomes = array();
}
return $outcomes;
}
/**
* Static method that returns all outcomes available in course
*
* @static
* @param int $courseid
* @return array
*/
public static function fetch_all_available($courseid) {
global $CFG, $DB;
$result = array();
$params = array($courseid);
$sql = "SELECT go.*
FROM {grade_outcomes} go, {grade_outcomes_courses} goc
WHERE go.id = goc.outcomeid AND goc.courseid = ?
ORDER BY go.id ASC";
if ($datas = $DB->get_records_sql($sql, $params)) {
foreach($datas as $data) {
$instance = new grade_outcome();
grade_object::set_properties($instance, $data);
$result[$instance->id] = $instance;
}
}
return $result;
}
/**
* Returns the most descriptive field for this object. This is a standard method used
* when we do not know the exact type of an object.
*
* @return string name
*/
public function get_name() {
// Grade outcomes can be created at site or course context, so set the filter context appropriately.
$context = empty($this->courseid) ? context_system::instance() : context_course::instance($this->courseid);
return format_string($this->fullname, false, ["context" => $context]);
}
/**
* Returns unique outcome short name.
*
* @return string name
*/
public function get_shortname() {
return $this->shortname;
}
/**
* Returns the formatted grade description with URLs converted
*
* @return string
*/
public function get_description() {
global $CFG;
require_once($CFG->libdir . '/filelib.php');
$options = new stdClass;
$options->noclean = true;
$systemcontext = context_system::instance();
$description = file_rewrite_pluginfile_urls($this->description, 'pluginfile.php', $systemcontext->id, 'grade', 'outcome', $this->id);
return format_text($description, $this->descriptionformat, $options);
}
/**
* Checks if outcome can be deleted.
*
* @return bool
*/
public function can_delete() {
if ($this->get_item_uses_count()) {
return false;
}
if (empty($this->courseid)) {
if ($this->get_course_uses_count()) {
return false;
}
}
return true;
}
/**
* Returns the number of places where outcome is used.
*
* @return int
*/
public function get_course_uses_count() {
global $DB;
if (!empty($this->courseid)) {
return 1;
}
return $DB->count_records('grade_outcomes_courses', array('outcomeid' => $this->id));
}
/**
* Returns the number of grade items that use this grade outcome
*
* @return int
*/
public function get_item_uses_count() {
global $DB;
return $DB->count_records('grade_items', array('outcomeid' => $this->id));
}
/**
* Computes then returns extra information about this outcome and other objects that are linked to it.
* The average of all grades that use this outcome, for all courses (or 1 course if courseid is given) can
* be requested, and is returned as a float if requested alone. If the list of items that use this outcome
* is also requested, then a single array is returned, which contains the grade_items AND the average grade
* if such is still requested (array('items' => array(...), 'avg' => 2.30)). This combining of two
* methods into one is to save on DB queries, since both queries are similar and can be performed together.
*
* @param int $courseid An optional courseid to narrow down the average to 1 course only
* @param bool $average Whether or not to return the average grade for this outcome
* @param bool $items Whether or not to return the list of items using this outcome
* @return float
*/
public function get_grade_info($courseid=null, $average=true, $items=false) {
global $CFG, $DB;
if (!isset($this->id)) {
debugging("You must setup the outcome's id before calling its get_grade_info() method!");
return false; // id must be defined for this to work
}
if ($average === false && $items === false) {
debugging('Either the 1st or 2nd param of grade_outcome::get_grade_info() must be true, or both, but not both false!');
return false;
}
$params = array($this->id);
$wheresql = '';
if (!is_null($courseid)) {
$wheresql = " AND {grade_items}.courseid = ? ";
$params[] = $courseid;
}
$selectadd = '';
if ($items !== false) {
$selectadd = ", {grade_items}.* ";
}
$sql = "SELECT finalgrade $selectadd
FROM {grade_grades}, {grade_items}, {grade_outcomes}
WHERE {grade_outcomes}.id = {grade_items}.outcomeid
AND {grade_items}.id = {grade_grades}.itemid
AND {grade_outcomes}.id = ?
$wheresql";
$grades = $DB->get_records_sql($sql, $params);
$retval = array();
if ($average !== false && count($grades) > 0) {
$count = 0;
$total = 0;
foreach ($grades as $k => $grade) {
// Skip null finalgrades
if (!is_null($grade->finalgrade)) {
$total += $grade->finalgrade;
$count++;
}
unset($grades[$k]->finalgrade);
}
$retval['avg'] = $total / $count;
}
if ($items !== false) {
foreach ($grades as $grade) {
$retval['items'][$grade->id] = new grade_item($grade);
}
}
return $retval;
}
}