Splitting white-wood backgroud into two different backgrounds,
[moodle.git] / lib / gradelib.php
CommitLineData
5834dcdb 1<?php // $Id$
2
3///////////////////////////////////////////////////////////////////////////
4// //
5// NOTICE OF COPYRIGHT //
6// //
7// Moodle - Modular Object-Oriented Dynamic Learning Environment //
8// http://moodle.com //
9// //
10// Copyright (C) 2001-2003 Martin Dougiamas http://dougiamas.com //
11// //
12// This program is free software; you can redistribute it and/or modify //
13// it under the terms of the GNU General Public License as published by //
14// the Free Software Foundation; either version 2 of the License, or //
15// (at your option) any later version. //
16// //
17// This program is distributed in the hope that it will be useful, //
18// but WITHOUT ANY WARRANTY; without even the implied warranty of //
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
20// GNU General Public License for more details: //
21// //
22// http://www.gnu.org/copyleft/gpl.html //
23// //
24///////////////////////////////////////////////////////////////////////////
25
26/**
42bbccd7 27 * Library of functions for gradebook
5834dcdb 28 *
29 * @author Moodle HQ developers
30 * @version $Id$
31 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
32 * @package moodlecore
33 */
34
b8ff92b6 35define('GRADE_AGGREGATE_MEAN_ALL', 0);
9580a21f 36define('GRADE_AGGREGATE_MEAN_GRADED', 1);
37define('GRADE_AGGREGATE_MEDIAN', 2);
b8ff92b6 38define('GRADE_AGGREGATE_MIN', 3);
39define('GRADE_AGGREGATE_MAX', 4);
95affb8a 40define('GRADE_AGGREGATE_MODE', 5);
9580a21f 41define('GRADE_AGGREGATE_WEIGHTED_MEAN_ALL', 6);
42define('GRADE_AGGREGATE_WEIGHTED_MEAN_GRADED', 7);
43define('GRADE_AGGREGATE_EXTRACREDIT_MEAN_ALL', 8);
44define('GRADE_AGGREGATE_EXTRACREDIT_MEAN_GRADED', 9);
612607bd 45
27f95e9b 46define('GRADE_CHILDTYPE_ITEM', 0);
47define('GRADE_CHILDTYPE_CAT', 1);
612607bd 48
27f95e9b 49define('GRADE_ITEM', 0); // Used to compare class names with CHILDTYPE values
50define('GRADE_CATEGORY', 1); // Used to compare class names with CHILDTYPE values
612607bd 51
8ace7bf7 52define('GRADE_CATEGORY_CONTRACTED', 0); // The state of a category header in the grader report
53define('GRADE_CATEGORY_EXPANDED', 1); // The state of a category header in the grader report
54
210611f6 55define('GRADE_TYPE_NONE', 0);
56define('GRADE_TYPE_VALUE', 1);
57define('GRADE_TYPE_SCALE', 2);
58define('GRADE_TYPE_TEXT', 3);
42bbccd7 59
612607bd 60define('GRADE_UPDATE_OK', 0);
61define('GRADE_UPDATE_FAILED', 1);
62define('GRADE_UPDATE_MULTIPLE', 2);
63define('GRADE_UPDATE_ITEM_DELETED', 3);
4cf1b9be 64define('GRADE_UPDATE_ITEM_LOCKED', 4);
612607bd 65
aaff71da 66// Grate teables history tracking actions
67define('GRADE_HISTORY_INSERT', 1);
68define('GRADE_HISTORY_UPDATE', 2);
69define('GRADE_HISTORY_DELETE', 3);
70
936f1350 71// Common directories
72define('GRADE_EDIT_DIR', $CFG->dirroot . '/grade/edit');
8ba894e0 73define('GRADE_EDIT_URL', $CFG->wwwroot . '/grade/edit');
612607bd 74
eea6690a 75// Grader reports
bb384a8e 76define('GRADE_REPORT_AGGREGATION_POSITION_LEFT', 0);
77define('GRADE_REPORT_AGGREGATION_POSITION_RIGHT', 1);
78define('GRADE_REPORT_AGGREGATION_VIEW_FULL', 0);
79define('GRADE_REPORT_AGGREGATION_VIEW_COMPACT', 1);
db4c7968 80define('GRADE_REPORT_GRADE_DISPLAY_TYPE_REAL', 0);
bb384a8e 81define('GRADE_REPORT_GRADE_DISPLAY_TYPE_PERCENTAGE', 1);
db4c7968 82define('GRADE_REPORT_GRADE_DISPLAY_TYPE_LETTER', 2);
e50ce569 83define('GRADE_REPORT_PREFERENCE_DEFAULT', 'default');
84define('GRADE_REPORT_PREFERENCE_INHERIT', 'inherit');
32b97bb2 85define('GRADE_REPORT_PREFERENCE_UNUSED', -1);
eea6690a 86
3058964f 87require_once($CFG->libdir . '/grade/grade_category.php');
88require_once($CFG->libdir . '/grade/grade_item.php');
3ee5c201 89require_once($CFG->libdir . '/grade/grade_grade.php');
d5bdb228 90require_once($CFG->libdir . '/grade/grade_scale.php');
5501446d 91require_once($CFG->libdir . '/grade/grade_outcome.php');
3ee5c201 92require_once($CFG->libdir . '/grade/grade_grade_text.php');
8ff4550a 93require_once($CFG->libdir . '/grade/grade_tree.php');
60cf7430 94
612607bd 95/***** PUBLIC GRADE API *****/
96
c5b5f18d 97/**
98 * Submit new or update grade; update/create grade_item definition. Grade must have userid specified,
ac9b0805 99 * rawgrade and feedback with format are optional. rawgrade NULL means 'Not graded', missing property
c5b5f18d 100 * or key means do not change existing.
4cf1b9be 101 *
c5b5f18d 102 * Only following grade item properties can be changed 'itemname', 'idnumber', 'gradetype', 'grademax',
e648f890 103 * 'grademin', 'scaleid', 'multfactor', 'plusfactor', 'deleted'.
4cf1b9be 104 *
c5b5f18d 105 * @param string $source source of the grade such as 'mod/assignment', often used to prevent infinite loops when processing grade_updated events
106 * @param int $courseid id of course
107 * @param string $itemtype type of grade item - mod, block, gradecategory, calculated
108 * @param string $itemmodule more specific then $itemtype - assignment, forum, etc.; maybe NULL for some item types
109 * @param int $iteminstance instance it of graded subject
110 * @param int $itemnumber most probably 0, modules can use other numbers when having more than one grades for each user
111 * @param mixed $grades grade (object, array) or several grades (arrays of arrays or objects), NULL if updating rgade_item definition only\
112 * @param mixed $itemdetails object or array describing the grading item, NULL if no change
113 */
b67ec72f 114function grade_update($source, $courseid, $itemtype, $itemmodule, $iteminstance, $itemnumber, $grades=NULL, $itemdetails=NULL) {
aaff71da 115 global $USER;
612607bd 116
c5b5f18d 117 // only following grade_item properties can be changed in this function
e648f890 118 $allowed = array('itemname', 'idnumber', 'gradetype', 'grademax', 'grademin', 'scaleid', 'multfactor', 'plusfactor', 'deleted');
612607bd 119
c4e4068f 120 // grade item identification
121 $params = compact('courseid', 'itemtype', 'itemmodule', 'iteminstance', 'itemnumber');
122
612607bd 123 if (is_null($courseid) or is_null($itemtype)) {
124 debugging('Missing courseid or itemtype');
125 return GRADE_UPDATE_FAILED;
126 }
127
c4e4068f 128 if (!$grade_items = grade_item::fetch_all($params)) {
612607bd 129 // create a new one
130 $grade_item = false;
131
132 } else if (count($grade_items) == 1){
133 $grade_item = reset($grade_items);
134 unset($grade_items); //release memory
135
136 } else {
34e67f76 137 debugging('Found more than one grade item');
612607bd 138 return GRADE_UPDATE_MULTIPLE;
139 }
140
aaff71da 141 if (!empty($itemdetails['deleted'])) {
142 if ($grade_item) {
143 if ($grade_item->delete($source)) {
144 return GRADE_UPDATE_OK;
145 } else {
146 return GRADE_UPDATE_FAILED;
147 }
148 }
149 return GRADE_UPDATE_OK;
150 }
151
612607bd 152/// Create or update the grade_item if needed
153 if (!$grade_item) {
612607bd 154 if ($itemdetails) {
155 $itemdetails = (array)$itemdetails;
2e53372c 156
772ddfbf 157 // grademin and grademax ignored when scale specified
2e53372c 158 if (array_key_exists('scaleid', $itemdetails)) {
159 if ($itemdetails['scaleid']) {
160 unset($itemdetails['grademin']);
161 unset($itemdetails['grademax']);
162 }
163 }
164
612607bd 165 foreach ($itemdetails as $k=>$v) {
166 if (!in_array($k, $allowed)) {
167 // ignore it
168 continue;
169 }
170 if ($k == 'gradetype' and $v == GRADE_TYPE_NONE) {
171 // no grade item needed!
172 return GRADE_UPDATE_OK;
173 }
174 $params[$k] = $v;
175 }
176 }
f70152b7 177 $grade_item = new grade_item($params);
178 $grade_item->insert();
612607bd 179
180 } else {
2cc4b0f9 181 if ($grade_item->is_locked()) {
612607bd 182 debugging('Grading item is locked!');
4cf1b9be 183 return GRADE_UPDATE_ITEM_LOCKED;
612607bd 184 }
185
186 if ($itemdetails) {
187 $itemdetails = (array)$itemdetails;
188 $update = false;
189 foreach ($itemdetails as $k=>$v) {
190 if (!in_array($k, $allowed)) {
191 // ignore it
192 continue;
193 }
194 if ($grade_item->{$k} != $v) {
195 $grade_item->{$k} = $v;
196 $update = true;
197 }
198 }
199 if ($update) {
200 $grade_item->update();
201 }
202 }
203 }
204
205/// Some extra checks
206 // do we use grading?
207 if ($grade_item->gradetype == GRADE_TYPE_NONE) {
208 return GRADE_UPDATE_OK;
209 }
210
211 // no grade submitted
b67ec72f 212 if (empty($grades)) {
612607bd 213 return GRADE_UPDATE_OK;
214 }
215
612607bd 216/// Finally start processing of grades
b67ec72f 217 if (is_object($grades)) {
218 $grades = array($grades);
612607bd 219 } else {
b67ec72f 220 if (array_key_exists('userid', $grades)) {
221 $grades = array($grades);
612607bd 222 }
223 }
224
4cf1b9be 225 $failed = false;
612607bd 226 foreach ($grades as $grade) {
227 $grade = (array)$grade;
228 if (empty($grade['userid'])) {
4cf1b9be 229 $failed = true;
230 debugging('Invalid userid in grade submitted');
231 continue;
ac9b0805 232 } else {
233 $userid = $grade['userid'];
612607bd 234 }
235
2cc4b0f9 236 $rawgrade = false;
ac9b0805 237 $feedback = false;
238 $feedbackformat = FORMAT_MOODLE;
772ddfbf 239
ac9b0805 240 if (array_key_exists('rawgrade', $grade)) {
241 $rawgrade = $grade['rawgrade'];
242 }
612607bd 243
4cf1b9be 244 if (array_key_exists('feedback', $grade)) {
ac9b0805 245 $feedback = $grade['feedback'];
612607bd 246 }
247
ac9b0805 248 if (array_key_exists('feedbackformat', $grade)) {
249 $feedbackformat = $grade['feedbackformat'];
612607bd 250 }
251
aaff71da 252 if (array_key_exists('usermodified', $grade)) {
253 $usermodified = $grade['usermodified'];
254 } else {
255 $usermodified = $USER->id;
256 }
257
ac9b0805 258 // update or insert the grade
aaff71da 259 if (!$grade_item->update_raw_grade($userid, $rawgrade, $source, null, $feedback, $feedbackformat, $usermodified)) {
4cf1b9be 260 $failed = true;
4cf1b9be 261 }
612607bd 262 }
263
4cf1b9be 264 if (!$failed) {
265 return GRADE_UPDATE_OK;
266 } else {
267 return GRADE_UPDATE_FAILED;
268 }
612607bd 269}
270
b67ec72f 271
272/**
273* Tells a module whether a grade (or grade_item if $userid is not given) is currently locked or not.
274* This is a combination of the actual settings in the grade tables and a check on moodle/course:editgradeswhenlocked.
275* If it's locked to the current use then the module can print a nice message or prevent editing in the module.
276* If no $userid is given, the method will always return the grade_item's locked state.
277* If a $userid is given, the method will first check the grade_item's locked state (the column). If it is locked,
278* the method will return true no matter the locked state of the specific grade being checked. If unlocked, it will
279* return the locked state of the specific grade.
280*
34e67f76 281* @param int $courseid id of course
b67ec72f 282* @param string $itemtype 'mod', 'blocks', 'import', 'calculated' etc
283* @param string $itemmodule 'forum, 'quiz', 'csv' etc
284* @param int $iteminstance id of the item module
34e67f76 285* @param int $itemnumber most probably 0, modules can use other numbers when having more than one grades for each user
286* @param int $userid ID of the graded user
b67ec72f 287* @return boolean Whether the grade is locked or not
288*/
34e67f76 289function grade_is_locked($courseid, $itemtype, $itemmodule, $iteminstance, $itemnumber, $userid=NULL) {
b67ec72f 290
f92dcad8 291 if (!$grade_items = grade_item::fetch_all(compact('courseid', 'itemtype', 'itemmodule', 'iteminstance', 'itemnumber'))) {
34e67f76 292 return false;
293
294 } else if (count($grade_items) == 1){
295 $grade_item = reset($grade_items);
296 return $grade_item->is_locked($userid);
297
298 } else {
299 debugging('Found more than one grade item');
300 foreach ($grade_items as $grade_item) {
301 if ($grade_item->is_locked($userid)) {
302 return true;
303 }
304 }
305 return false;
306 }
307}
b67ec72f 308
612607bd 309/***** END OF PUBLIC API *****/
310
f8e6e4db 311function grade_force_full_regrading($courseid) {
312 set_field('grade_items', 'needsupdate', 1, 'courseid', $courseid);
313}
34e67f76 314
5834dcdb 315/**
ac9b0805 316 * Updates all final grades in course.
a8995b34 317 *
318 * @param int $courseid
f8e6e4db 319 * @param int $userid if specified, try to do a quick regrading of grades of this user only
320 * @param object $updated_item the item in which
321 * @return boolean true if ok, array of errors if problems found (item id is used as key)
a8995b34 322 */
c86caae7 323function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null) {
a8995b34 324
f8e6e4db 325 $course_item = grade_item::fetch_course_item($courseid);
b8ff92b6 326
f8e6e4db 327 if ($userid) {
328 // one raw grade updated for one user
329 if (empty($updated_item)) {
330 error("updated_item_id can not be null!");
331 }
332 if ($course_item->needsupdate) {
333 $updated_item->force_regrading();
334 return 'Can not do fast regrading after updating of raw grades';
a8995b34 335 }
772ddfbf 336
f8e6e4db 337 } else {
338 if (!$course_item->needsupdate) {
339 // nothing to do :-)
b8ff92b6 340 return true;
b8ff92b6 341 }
a8995b34 342 }
343
f8e6e4db 344 $grade_items = grade_item::fetch_all(array('courseid'=>$courseid));
345 $depends_on = array();
346
347 // first mark all category and calculated items as needing regrading
348 // this is slower, but 100% accurate - this function is called only when there is
349 // a change in grading setup, update of individual grade does not trigger this function
350 foreach ($grade_items as $gid=>$gitem) {
fb46b5b6 351 if (!empty($updated_item) and $updated_item->id == $gid) {
f8e6e4db 352 $grade_items[$gid]->needsupdate = 1;
353
354 } else if ($grade_items[$gid]->is_category_item() or $grade_items[$gid]->is_calculated()) {
355 $grade_items[$gid]->needsupdate = 1;
356 }
2e53372c 357
f8e6e4db 358 // construct depends_on lookup array
359 $depends_on[$gid] = $grade_items[$gid]->depends_on();
360 }
2e53372c 361 $errors = array();
362
b8ff92b6 363 $finalitems = array();
364 $finalids = array();
365 while (count($grade_items) > 0) {
f8e6e4db 366 $count = 0; // count how many items were updated in this cycle
b8ff92b6 367 foreach ($grade_items as $gid=>$gitem) {
368 $grade_item =& $grade_items[$gid];
2e53372c 369 if (!$grade_item->needsupdate) {
b8ff92b6 370 $finalitems[$gid] = $grade_item;
371 $finalids[] = $gid;
372 unset($grade_items[$gid]);
373 continue;
374 }
375
b8ff92b6 376 $doupdate = true;
f8e6e4db 377 foreach ($depends_on[$gid] as $did) {
b8ff92b6 378 if (!in_array($did, $finalids)) {
379 $doupdate = false;
f8e6e4db 380 break;
b8ff92b6 381 }
382 }
383
384 //oki - let's update, calculate or aggregate :-)
385 if ($doupdate) {
c86caae7 386 $result = $grade_item->regrade_final_grades($userid);
f8e6e4db 387
388 if ($result === true) {
389 $grade_item->regrading_finished();
390 $count++;
b8ff92b6 391 $finalitems[$gid] = $grade_item;
392 $finalids[] = $gid;
393 unset($grade_items[$gid]);
f8e6e4db 394 } else {
395 $grade_item->force_regrading();
396 $errors[$gid] = $result;
b8ff92b6 397 }
398 }
399 }
400
401 if ($count == 0) {
402 foreach($grade_items as $grade_item) {
f8e6e4db 403 $grade_item->force_regrading();
404 $errors[$grade_item->id] = 'Probably circular reference or broken calculation formula'; // TODO: localize
b8ff92b6 405 }
406 break;
407 }
408 }
409
410 if (count($errors) == 0) {
411 return true;
412 } else {
413 return $errors;
414 }
a8995b34 415}
967f222f 416
de420c11 417/**
d185c3ee 418 * For backwards compatibility with old third-party modules, this function can
419 * be used to import all grades from activities with legacy grading.
739196ba 420 * @param int $courseid or null if all courses
967f222f 421 */
739196ba 422function grade_grab_legacy_grades($courseid=null) {
612607bd 423
ac9b0805 424 global $CFG;
967f222f 425
426 if (!$mods = get_list_of_plugins('mod') ) {
427 error('No modules installed!');
428 }
429
739196ba 430 if ($courseid) {
431 $course_sql = " AND cm.course=$courseid";
432 } else {
433 $course_sql = "";
434 }
435
967f222f 436 foreach ($mods as $mod) {
437
438 if ($mod == 'NEWMODULE') { // Someone has unzipped the template, ignore it
439 continue;
440 }
441
d185c3ee 442 if (!$module = get_record('modules', 'name', $mod)) {
443 //not installed
444 continue;
445 }
446
447 if (!$module->visible) {
448 //disabled module
449 continue;
450 }
451
452 $fullmod = $CFG->dirroot.'/mod/'.$mod;
967f222f 453
454 // include the module lib once
455 if (file_exists($fullmod.'/lib.php')) {
456 include_once($fullmod.'/lib.php');
de420c11 457 // look for modname_grades() function - old gradebook pulling function
458 // if present sync the grades with new grading system
967f222f 459 $gradefunc = $mod.'_grades';
de420c11 460 if (function_exists($gradefunc)) {
461
462 // get all instance of the activity
d185c3ee 463 $sql = "SELECT a.*, cm.idnumber as cmidnumber, m.name as modname
464 FROM {$CFG->prefix}$mod a, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m
739196ba 465 WHERE m.name='$mod' AND m.id=cm.module AND cm.instance=a.id $course_sql";
de420c11 466
467 if ($modinstances = get_records_sql($sql)) {
967f222f 468 foreach ($modinstances as $modinstance) {
d185c3ee 469 grade_update_mod_grades($modinstance);
967f222f 470 }
471 }
472 }
473 }
474 }
475}
476
ac9b0805 477/**
478 * For testing purposes mainly, reloads grades from all non legacy modules into gradebook.
479 */
480function grade_grab_grades() {
481
482 global $CFG;
483
484 if (!$mods = get_list_of_plugins('mod') ) {
485 error('No modules installed!');
486 }
487
488 foreach ($mods as $mod) {
489
490 if ($mod == 'NEWMODULE') { // Someone has unzipped the template, ignore it
491 continue;
492 }
493
494 if (!$module = get_record('modules', 'name', $mod)) {
495 //not installed
496 continue;
497 }
498
499 if (!$module->visible) {
500 //disabled module
501 continue;
502 }
503
504 $fullmod = $CFG->dirroot.'/mod/'.$mod;
505
506 // include the module lib once
507 if (file_exists($fullmod.'/lib.php')) {
508 include_once($fullmod.'/lib.php');
509 // look for modname_grades() function - old gradebook pulling function
510 // if present sync the grades with new grading system
511 $gradefunc = $mod.'_update_grades';
512 if (function_exists($gradefunc)) {
513 $gradefunc();
514 }
515 }
516 }
517}
518
d185c3ee 519/**
520 * Force full update of module grades in central gradebook - works for both legacy and converted activities.
521 * @param object $modinstance object with extra cmidnumber and modname property
522 * @return boolean success
523 */
524function grade_update_mod_grades($modinstance) {
525 global $CFG;
526
527 $fullmod = $CFG->dirroot.'/mod/'.$modinstance->modname;
528 if (!file_exists($fullmod.'/lib.php')) {
529 debugging('missing lib.php file in module');
530 return false;
531 }
532 include_once($fullmod.'/lib.php');
533
534 // does it use legacy grading?
535 $gradefunc = $modinstance->modname.'_grades';
536 $updategradesfunc = $modinstance->modname.'_update_grades';
537 $updateitemfunc = $modinstance->modname.'_grade_item_update';
538
539 if (function_exists($gradefunc)) {
540 if ($oldgrades = $gradefunc($modinstance->id)) {
541
542 $grademax = $oldgrades->maxgrade;
543 $scaleid = NULL;
544 if (!is_numeric($grademax)) {
545 // scale name is provided as a string, try to find it
546 if (!$scale = get_record('scale', 'name', $grademax)) {
547 debugging('Incorrect scale name! name:'.$grademax);
548 return false;
549 }
550 $scaleid = $scale->id;
551 }
552
553 if (!$grade_item = grade_get_legacy_grade_item($modinstance, $grademax, $scaleid)) {
554 debugging('Can not get/create legacy grade item!');
555 return false;
556 }
557
558 $grades = array();
559 foreach ($oldgrades->grades as $userid=>$usergrade) {
560 $grade = new object();
561 $grade->userid = $userid;
562
563 if ($usergrade == '-') {
564 // no grade
ac9b0805 565 $grade->rawgrade = null;
d185c3ee 566
567 } else if ($scaleid) {
568 // scale in use, words used
569 $gradescale = explode(",", $scale->scale);
ac9b0805 570 $grade->rawgrade = array_search($usergrade, $gradescale) + 1;
d185c3ee 571
572 } else {
573 // good old numeric value
ac9b0805 574 $grade->rawgrade = $usergrade;
d185c3ee 575 }
576 $grades[] = $grade;
577 }
578
579 grade_update('legacygrab', $grade_item->courseid, $grade_item->itemtype, $grade_item->itemmodule,
580 $grade_item->iteminstance, $grade_item->itemnumber, $grades);
581 }
582
583 } else if (function_exists($updategradesfunc) and function_exists($updateitemfunc)) {
584 //new grading supported, force updating of grades
585 $updateitemfunc($modinstance);
586 $updategradesfunc($modinstance);
587
588 } else {
589 // mudule does not support grading
590 }
591
592 return true;
593}
de420c11 594
595/**
d185c3ee 596 * Get and update/create grade item for legacy modules.
de420c11 597 */
598function grade_get_legacy_grade_item($modinstance, $grademax, $scaleid) {
599
600 // does it already exist?
3ee5c201 601 if ($grade_items = grade_grade::fetch_all(array('courseid'=>$modinstance->course, 'itemtype'=>'mod', 'itemmodule'=>$modinstance->modname, 'iteminstance'=>$modinstance->id, 'itemnumber'=>0))) {
de420c11 602 if (count($grade_items) > 1) {
d185c3ee 603 debugging('Multiple legacy grade_items found.');
de420c11 604 return false;
605 }
606
607 $grade_item = reset($grade_items);
de420c11 608
d185c3ee 609 if (is_null($grademax) and is_null($scaleid)) {
610 $grade_item->gradetype = GRADE_TYPE_NONE;
de420c11 611
d185c3ee 612 } else if ($scaleid) {
613 $grade_item->gradetype = GRADE_TYPE_SCALE;
614 $grade_item->scaleid = $scaleid;
97d608ba 615 $grade_item->grademin = 1;
de420c11 616
d185c3ee 617 } else {
97d608ba 618 $grade_item->gradetype = GRADE_TYPE_VALUE;
619 $grade_item->grademax = $grademax;
620 $grade_item->grademin = 0;
de420c11 621 }
622
d185c3ee 623 $grade_item->itemname = $modinstance->name;
624 $grade_item->idnumber = $modinstance->cmidnumber;
de420c11 625
d185c3ee 626 $grade_item->update();
de420c11 627
628 return $grade_item;
629 }
612607bd 630
de420c11 631 // create new one
d185c3ee 632 $params = array('courseid' =>$modinstance->course,
de420c11 633 'itemtype' =>'mod',
634 'itemmodule' =>$modinstance->modname,
635 'iteminstance'=>$modinstance->id,
d185c3ee 636 'itemnumber' =>0,
de420c11 637 'itemname' =>$modinstance->name,
638 'idnumber' =>$modinstance->cmidnumber);
639
d185c3ee 640 if (is_null($grademax) and is_null($scaleid)) {
641 $params['gradetype'] = GRADE_TYPE_NONE;
642
643 } else if ($scaleid) {
612607bd 644 $params['gradetype'] = GRADE_TYPE_SCALE;
de420c11 645 $params['scaleid'] = $scaleid;
b3ac6c3e 646 $grade_item->grademin = 1;
de420c11 647 } else {
612607bd 648 $params['gradetype'] = GRADE_TYPE_VALUE;
de420c11 649 $params['grademax'] = $grademax;
650 $params['grademin'] = 0;
651 }
652
f70152b7 653 $grade_item = new grade_item($params);
654 $grade_item->insert();
de420c11 655
f70152b7 656 return $grade_item;
de420c11 657}
658
b8ff92b6 659/**
660 * This function is used to migrade old date and settings from old gradebook into new grading system.
661 *
662 * TODO:
663 * - category weight not used - we would have to create extra top course grade calculated category
664 * - exta_credit item flag not used - does not fit all our aggregation types, could be used in SUM only
665 */
666function grade_oldgradebook_upgrade($courseid) {
667 global $CFG;
668
669 $categories = array();
670 if ($oldcats = get_records('grade_category', 'courseid', $courseid)) {
671 foreach ($oldcats as $oldcat) {
672 $newcat = new grade_category(array('courseid'=>$courseid, 'fullname'=>$oldcat->name));
673 $newcat->droplow = $oldcat->drop_x_lowest;
674 $newcat->aggregation = GRADE_AGGREGATE_MEAN_GRADED;
675
676 if (empty($newcat->id)) {
677 $newcat->insert();
678 } else {
679 $newcat->update();
680 }
681
682 $categories[$oldcat->id] = $newcat;
683
684 $catitem = $newcat->get_grade_item();
685 $catitem->gradetype = GRADE_TYPE_VALUE;
686 $catitem->plusfactor = $oldcat->bonus_points;
687 $catitem->hidden = $oldcat->hidden;
688 $catitem->update();
689 }
690 }
691
692 // get all grade items with mod details
693 $sql = "SELECT gi.*, cm.idnumber as cmidnumber, m.name as modname
694 FROM {$CFG->prefix}grade_item gi, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m
695 WHERE gi.courseid=$courseid AND m.id=gi.modid AND cm.instance=gi.cminstance
696 ORDER BY gi.sortorder ASC";
697
698 if ($olditems = get_records_sql($sql)) {
699 foreach ($olditems as $olditem) {
700 $newitem = new grade_item(array('courseid'=>$olditem->courseid, 'itemtype'=>'mod', 'itemmodule'=>$olditem->modname, 'iteminstance'=>$olditem->cminstance, 'itemnumber'=>0));
701 if (!empty($olditem->category)) {
702 // we do this low level stuff to get some speedup during upgrade
f13002d5 703 $newitem->set_parent($categories[$olditem->category]->id);
b8ff92b6 704 }
705 $newitem->gradetype = GRADE_TYPE_NONE;
706 $newitem->multfactor = $olditem->scale_grade;
707 if (empty($newitem->id)) {
708 $newitem->insert();
709 } else {
710 $newitem->update();
711 }
712 }
713 }
714}
bfe7297e 715
32b97bb2 716/**
717 * Builds an array of percentages indexed by integers for the purpose of building a select drop-down element.
718 * @param int $steps The value between each level.
719 * @param string $order 'asc' for 0-100 and 'desc' for 100-0
720 * @param int $lowest The lowest value to include
721 * @param int $highest The highest value to include
722 */
723function build_percentages_array($steps=1, $order='desc', $lowest=0, $highest=100) {
724 // TODO reject or implement
725}
60cf7430 726?>