| 1 | efrain | 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/>.
 | 
        
           |  |  | 16 |   | 
        
           |  |  | 17 | /**
 | 
        
           |  |  | 18 |  * Edit a user's grade for a particular activity
 | 
        
           |  |  | 19 |  *
 | 
        
           |  |  | 20 |  * @package   core_grades
 | 
        
           |  |  | 21 |  * @copyright 2007 Petr Skoda
 | 
        
           |  |  | 22 |  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 23 |  */
 | 
        
           |  |  | 24 |   | 
        
           |  |  | 25 | require_once '../../../config.php';
 | 
        
           |  |  | 26 | require_once $CFG->dirroot.'/grade/lib.php';
 | 
        
           |  |  | 27 | require_once $CFG->dirroot.'/grade/report/lib.php';
 | 
        
           |  |  | 28 | require_once 'grade_form.php';
 | 
        
           |  |  | 29 |   | 
        
           |  |  | 30 | $courseid = required_param('courseid', PARAM_INT);
 | 
        
           |  |  | 31 | $id       = optional_param('id', 0, PARAM_INT);
 | 
        
           |  |  | 32 | $itemid   = optional_param('itemid', 0, PARAM_INT);
 | 
        
           |  |  | 33 | $userid   = optional_param('userid', 0, PARAM_INT);
 | 
        
           |  |  | 34 |   | 
        
           |  |  | 35 | $url = new moodle_url('/grade/edit/tree/grade.php', array('courseid'=>$courseid));
 | 
        
           |  |  | 36 | if ($id !== 0) {
 | 
        
           |  |  | 37 |     $url->param('id', $id);
 | 
        
           |  |  | 38 | }
 | 
        
           |  |  | 39 | if ($itemid !== 0) {
 | 
        
           |  |  | 40 |     $url->param('itemid', $itemid);
 | 
        
           |  |  | 41 | }
 | 
        
           |  |  | 42 | if ($userid !== 0) {
 | 
        
           |  |  | 43 |     $url->param('userid', $userid);
 | 
        
           |  |  | 44 | }
 | 
        
           |  |  | 45 | $PAGE->set_url($url);
 | 
        
           |  |  | 46 |   | 
        
           |  |  | 47 | if (!$course = $DB->get_record('course', array('id' => $courseid))) {
 | 
        
           |  |  | 48 |     throw new \moodle_exception('invalidcourseid');
 | 
        
           |  |  | 49 | }
 | 
        
           |  |  | 50 |   | 
        
           |  |  | 51 | $PAGE->set_pagelayout('incourse');
 | 
        
           |  |  | 52 | require_login($course);
 | 
        
           |  |  | 53 | $context = context_course::instance($course->id);
 | 
        
           |  |  | 54 | if (!has_capability('moodle/grade:manage', $context)) {
 | 
        
           |  |  | 55 |     require_capability('moodle/grade:edit', $context);
 | 
        
           |  |  | 56 | }
 | 
        
           |  |  | 57 |   | 
        
           |  |  | 58 | // default return url
 | 
        
           |  |  | 59 | $gpr = new grade_plugin_return();
 | 
        
           |  |  | 60 | $returnurl = $gpr->get_return_url($CFG->wwwroot.'/grade/report/index.php?id='.$course->id);
 | 
        
           |  |  | 61 |   | 
        
           |  |  | 62 | // security checks!
 | 
        
           |  |  | 63 | if (!empty($id)) {
 | 
        
           |  |  | 64 |     if (!$grade = $DB->get_record('grade_grades', array('id' => $id))) {
 | 
        
           |  |  | 65 |         throw new \moodle_exception('invalidgroupid');
 | 
        
           |  |  | 66 |     }
 | 
        
           |  |  | 67 |   | 
        
           |  |  | 68 |     if (!empty($itemid) and $itemid != $grade->itemid) {
 | 
        
           |  |  | 69 |         throw new \moodle_exception('invaliditemid');
 | 
        
           |  |  | 70 |     }
 | 
        
           |  |  | 71 |     $itemid = $grade->itemid;
 | 
        
           |  |  | 72 |   | 
        
           |  |  | 73 |     if (!empty($userid) and $userid != $grade->userid) {
 | 
        
           |  |  | 74 |         throw new \moodle_exception('invaliduser');
 | 
        
           |  |  | 75 |     }
 | 
        
           |  |  | 76 |     $userid = $grade->userid;
 | 
        
           |  |  | 77 |   | 
        
           |  |  | 78 |     unset($grade);
 | 
        
           |  |  | 79 |   | 
        
           |  |  | 80 | } else if (empty($userid) or empty($itemid)) {
 | 
        
           |  |  | 81 |     throw new \moodle_exception('missinguseranditemid');
 | 
        
           |  |  | 82 | }
 | 
        
           |  |  | 83 |   | 
        
           |  |  | 84 | if (!$grade_item = grade_item::fetch(array('id'=>$itemid, 'courseid'=>$courseid))) {
 | 
        
           |  |  | 85 |     throw new \moodle_exception('cannotfindgradeitem');
 | 
        
           |  |  | 86 | }
 | 
        
           |  |  | 87 |   | 
        
           |  |  | 88 | // now verify grading user has access to all groups or is member of the same group when separate groups used in course
 | 
        
           |  |  | 89 | if (groups_get_course_groupmode($COURSE) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) {
 | 
        
           |  |  | 90 |     if ($groups = groups_get_all_groups($COURSE->id, $userid)) {
 | 
        
           |  |  | 91 |         $ok = false;
 | 
        
           |  |  | 92 |         foreach ($groups as $group) {
 | 
        
           |  |  | 93 |             if (groups_is_member($group->id, $USER->id)) {
 | 
        
           |  |  | 94 |                 $ok = true;
 | 
        
           |  |  | 95 |             }
 | 
        
           |  |  | 96 |         }
 | 
        
           |  |  | 97 |         if (!$ok) {
 | 
        
           |  |  | 98 |             throw new \moodle_exception('cannotgradeuser');
 | 
        
           |  |  | 99 |         }
 | 
        
           |  |  | 100 |     } else {
 | 
        
           |  |  | 101 |         throw new \moodle_exception('cannotgradeuser');
 | 
        
           |  |  | 102 |     }
 | 
        
           |  |  | 103 | }
 | 
        
           |  |  | 104 |   | 
        
           |  |  | 105 | $mform = new edit_grade_form(null, array('grade_item'=>$grade_item, 'gpr'=>$gpr));
 | 
        
           |  |  | 106 |   | 
        
           |  |  | 107 | if ($grade = $DB->get_record('grade_grades', array('itemid' => $grade_item->id, 'userid' => $userid))) {
 | 
        
           |  |  | 108 |   | 
        
           |  |  | 109 |     // always clean existing feedback - grading should not have XSS risk
 | 
        
           |  |  | 110 |     if (empty($grade->feedback)) {
 | 
        
           |  |  | 111 |         $grade->feedback  = '';
 | 
        
           |  |  | 112 |     } else {
 | 
        
           |  |  | 113 |         $options = new stdClass();
 | 
        
           |  |  | 114 |         $options->filter  = false;
 | 
        
           |  |  | 115 |         $options->noclean = false;
 | 
        
           |  |  | 116 |         $options->para    = false;
 | 
        
           |  |  | 117 |         $grade->feedback  = format_text($grade->feedback, $grade->feedbackformat, $options);
 | 
        
           |  |  | 118 |     }
 | 
        
           |  |  | 119 |     $grade->feedbackformat = FORMAT_HTML;
 | 
        
           |  |  | 120 |   | 
        
           |  |  | 121 |     $grade->locked      = $grade->locked     > 0 ? 1:0;
 | 
        
           |  |  | 122 |     $grade->overridden  = $grade->overridden > 0 ? 1:0;
 | 
        
           |  |  | 123 |     $grade->excluded    = $grade->excluded   > 0 ? 1:0;
 | 
        
           |  |  | 124 |   | 
        
           |  |  | 125 |     if ($grade->hidden > 1) {
 | 
        
           |  |  | 126 |         $grade->hiddenuntil = $grade->hidden;
 | 
        
           |  |  | 127 |         $grade->hidden = 1;
 | 
        
           |  |  | 128 |     } else {
 | 
        
           |  |  | 129 |         $grade->hiddenuntil = 0;
 | 
        
           |  |  | 130 |     }
 | 
        
           |  |  | 131 |   | 
        
           |  |  | 132 |     if ($grade_item->is_hidden()) {
 | 
        
           |  |  | 133 |         $grade->hidden = 1;
 | 
        
           |  |  | 134 |     }
 | 
        
           |  |  | 135 |   | 
        
           |  |  | 136 |     if ($grade_item->is_locked()) {
 | 
        
           |  |  | 137 |         $grade->locked = 1;
 | 
        
           |  |  | 138 |     }
 | 
        
           |  |  | 139 |   | 
        
           |  |  | 140 |     // normalize the final grade value
 | 
        
           |  |  | 141 |     if ($grade_item->gradetype == GRADE_TYPE_SCALE) {
 | 
        
           |  |  | 142 |         if (empty($grade->finalgrade)) {
 | 
        
           |  |  | 143 |             $grade->finalgrade = -1;
 | 
        
           |  |  | 144 |         } else {
 | 
        
           |  |  | 145 |             $grade->finalgrade = (int)$grade->finalgrade;
 | 
        
           |  |  | 146 |         }
 | 
        
           |  |  | 147 |     } else if ($grade_item->gradetype == GRADE_TYPE_VALUE) {
 | 
        
           |  |  | 148 |         $grade->finalgrade = format_float($grade->finalgrade, $grade_item->get_decimals());
 | 
        
           |  |  | 149 |     }
 | 
        
           |  |  | 150 |   | 
        
           |  |  | 151 |     $grade->oldgrade    = $grade->finalgrade;
 | 
        
           |  |  | 152 |     $grade->oldfeedback = $grade->feedback;
 | 
        
           |  |  | 153 |   | 
        
           |  |  | 154 |     $grade->feedback = array('text'=>$grade->feedback, 'format'=>$grade->feedbackformat);
 | 
        
           |  |  | 155 |   | 
        
           |  |  | 156 |     $mform->set_data($grade);
 | 
        
           |  |  | 157 | } else {
 | 
        
           |  |  | 158 |     $grade = new stdClass();
 | 
        
           |  |  | 159 |     $grade->feedback = array('text'=>'', 'format'=>FORMAT_HTML);
 | 
        
           |  |  | 160 |     $mform->set_data(array('itemid'=>$itemid, 'userid'=>$userid, 'locked'=>$grade_item->locked, 'locktime'=>$grade_item->locktime));
 | 
        
           |  |  | 161 | }
 | 
        
           |  |  | 162 |   | 
        
           |  |  | 163 | if ($mform->is_cancelled()) {
 | 
        
           |  |  | 164 |     redirect($returnurl);
 | 
        
           |  |  | 165 |   | 
        
           |  |  | 166 | // form processing
 | 
        
           |  |  | 167 | } else if ($data = $mform->get_data(false)) {
 | 
        
           |  |  | 168 |   | 
        
           |  |  | 169 |     if (isset($data->feedback) && is_array($data->feedback)) {
 | 
        
           |  |  | 170 |         $data->feedbackformat = $data->feedback['format'];
 | 
        
           | 1441 | ariadna | 171 |         $data->feedback = $data->feedback['text'] ?? null;
 | 
        
           | 1 | efrain | 172 |     }
 | 
        
           |  |  | 173 |   | 
        
           |  |  | 174 |     $old_grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true); //might not exist yet
 | 
        
           |  |  | 175 |   | 
        
           |  |  | 176 |     // fix no grade for scales
 | 
        
           |  |  | 177 |     if (!isset($data->finalgrade) or $data->finalgrade == $data->oldgrade) {
 | 
        
           |  |  | 178 |         $data->finalgrade = $old_grade_grade->finalgrade;
 | 
        
           |  |  | 179 |   | 
        
           |  |  | 180 |     } else if ($grade_item->gradetype == GRADE_TYPE_SCALE) {
 | 
        
           |  |  | 181 |         if ($data->finalgrade < 1) {
 | 
        
           |  |  | 182 |             $data->finalgrade = NULL;
 | 
        
           |  |  | 183 |         }
 | 
        
           |  |  | 184 |   | 
        
           |  |  | 185 |     } else if ($grade_item->gradetype == GRADE_TYPE_VALUE) {
 | 
        
           |  |  | 186 |         $data->finalgrade = unformat_float($data->finalgrade);
 | 
        
           |  |  | 187 |   | 
        
           |  |  | 188 |     } else {
 | 
        
           |  |  | 189 |         //this should not happen
 | 
        
           |  |  | 190 |         $data->finalgrade = $old_grade_grade->finalgrade;
 | 
        
           |  |  | 191 |     }
 | 
        
           |  |  | 192 |   | 
        
           |  |  | 193 |     // the overriding of feedback is tricky - we have to care about external items only
 | 
        
           |  |  | 194 |     if (!property_exists($data, 'feedback') or $data->feedback == $data->oldfeedback) {
 | 
        
           |  |  | 195 |         $data->feedback       = $old_grade_grade->feedback;
 | 
        
           |  |  | 196 |         $data->feedbackformat = $old_grade_grade->feedbackformat;
 | 
        
           |  |  | 197 |     }
 | 
        
           |  |  | 198 |   | 
        
           |  |  | 199 |     // update final grade or feedback
 | 
        
           |  |  | 200 |     // when we set override grade the first time, it happens here
 | 
        
           |  |  | 201 |     $grade_item->update_final_grade($data->userid, $data->finalgrade, 'editgrade', $data->feedback, $data->feedbackformat);
 | 
        
           |  |  | 202 |   | 
        
           |  |  | 203 |     $grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true);
 | 
        
           |  |  | 204 |     $grade_grade->grade_item =& $grade_item; // no db fetching
 | 
        
           |  |  | 205 |   | 
        
           |  |  | 206 |     if (has_capability('moodle/grade:manage', $context) or has_capability('moodle/grade:edit', $context)) {
 | 
        
           |  |  | 207 |         // change overridden flag
 | 
        
           |  |  | 208 |         if (!isset($data->overridden)) {
 | 
        
           |  |  | 209 |             $data->overridden = 0; // checkbox unticked
 | 
        
           |  |  | 210 |         }
 | 
        
           |  |  | 211 |         $grade_grade->set_overridden($data->overridden);
 | 
        
           |  |  | 212 |     }
 | 
        
           |  |  | 213 |   | 
        
           |  |  | 214 |     if (has_capability('moodle/grade:manage', $context) or has_capability('moodle/grade:hide', $context)) {
 | 
        
           |  |  | 215 |         $hidden      = empty($data->hidden) ? 0: $data->hidden;
 | 
        
           |  |  | 216 |         $hiddenuntil = empty($data->hiddenuntil) ? 0: $data->hiddenuntil;
 | 
        
           |  |  | 217 |   | 
        
           |  |  | 218 |         if ($grade_item->is_hidden()) {
 | 
        
           |  |  | 219 |             if ($old_grade_grade->hidden == 1 and $hiddenuntil == 0) {
 | 
        
           |  |  | 220 |                 //nothing to do - grade was originally hidden, we want to keep it that way
 | 
        
           |  |  | 221 |             } else {
 | 
        
           |  |  | 222 |                 $grade_grade->set_hidden($hiddenuntil);
 | 
        
           |  |  | 223 |             }
 | 
        
           |  |  | 224 |         } else {
 | 
        
           |  |  | 225 |             if ($hiddenuntil) {
 | 
        
           |  |  | 226 |                 $grade_grade->set_hidden($hiddenuntil);
 | 
        
           |  |  | 227 |             } else {
 | 
        
           |  |  | 228 |                 $grade_grade->set_hidden($hidden); // checkbox data might be undefined
 | 
        
           |  |  | 229 |             }
 | 
        
           |  |  | 230 |         }
 | 
        
           |  |  | 231 |     }
 | 
        
           |  |  | 232 |   | 
        
           |  |  | 233 |     if (isset($data->locked) and !$grade_item->is_locked()) {
 | 
        
           |  |  | 234 |         if (($old_grade_grade->locked or $old_grade_grade->locktime)
 | 
        
           |  |  | 235 |           and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context))) {
 | 
        
           |  |  | 236 |             //ignore data
 | 
        
           |  |  | 237 |   | 
        
           |  |  | 238 |         } else if ((!$old_grade_grade->locked and !$old_grade_grade->locktime)
 | 
        
           |  |  | 239 |           and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context))) {
 | 
        
           |  |  | 240 |             //ignore data
 | 
        
           |  |  | 241 |   | 
        
           |  |  | 242 |         } else {
 | 
        
           |  |  | 243 |             $grade_grade->set_locktime($data->locktime); //set_lock may reset locktime
 | 
        
           |  |  | 244 |             $grade_grade->set_locked($data->locked, false, true);
 | 
        
           |  |  | 245 |             // reload grade in case it was regraded from activity
 | 
        
           |  |  | 246 |             $grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true);
 | 
        
           |  |  | 247 |             $grade_grade->grade_item =& $grade_item; // no db fetching
 | 
        
           |  |  | 248 |         }
 | 
        
           |  |  | 249 |     }
 | 
        
           |  |  | 250 |   | 
        
           |  |  | 251 |     if (isset($data->excluded) and has_capability('moodle/grade:manage', $context)) {
 | 
        
           |  |  | 252 |         $grade_grade->set_excluded($data->excluded);
 | 
        
           |  |  | 253 |     }
 | 
        
           |  |  | 254 |   | 
        
           |  |  | 255 |     // detect cases when we need to do full regrading
 | 
        
           |  |  | 256 |     if ($old_grade_grade->excluded != $grade_grade->excluded) {
 | 
        
           |  |  | 257 |         $parent = $grade_item->get_parent_category();
 | 
        
           |  |  | 258 |         $parent->force_regrading();
 | 
        
           |  |  | 259 |   | 
        
           |  |  | 260 |     } else if ($old_grade_grade->overridden != $grade_grade->overridden and empty($grade_grade->overridden)) { // only when unoverridding
 | 
        
           |  |  | 261 |         $grade_item->force_regrading();
 | 
        
           |  |  | 262 |   | 
        
           |  |  | 263 |     } else if ($old_grade_grade->locktime != $grade_grade->locktime) {
 | 
        
           |  |  | 264 |         $grade_item->force_regrading();
 | 
        
           |  |  | 265 |     }
 | 
        
           |  |  | 266 |   | 
        
           |  |  | 267 |     redirect($returnurl);
 | 
        
           |  |  | 268 | }
 | 
        
           |  |  | 269 |   | 
        
           |  |  | 270 | $strgrades       = get_string('grades');
 | 
        
           |  |  | 271 | $strgraderreport = get_string('graderreport', 'grades');
 | 
        
           |  |  | 272 | $strgradeedit    = get_string('editgrade', 'grades');
 | 
        
           |  |  | 273 | $struser         = get_string('user');
 | 
        
           |  |  | 274 |   | 
        
           |  |  | 275 | grade_build_nav(__FILE__, $strgradeedit, array('courseid' => $courseid));
 | 
        
           |  |  | 276 |   | 
        
           |  |  | 277 | /*********** BEGIN OUTPUT *************/
 | 
        
           |  |  | 278 | $PAGE->set_title($strgrades . ': ' . $strgraderreport . ': ' . $strgradeedit);
 | 
        
           |  |  | 279 | $PAGE->set_heading($course->fullname);
 | 
        
           |  |  | 280 |   | 
        
           |  |  | 281 | echo $OUTPUT->header();
 | 
        
           |  |  | 282 | echo $OUTPUT->heading($strgradeedit);
 | 
        
           |  |  | 283 |   | 
        
           |  |  | 284 | echo $OUTPUT->box_start();
 | 
        
           |  |  | 285 |   | 
        
           |  |  | 286 | // Form if in edit or add modes
 | 
        
           |  |  | 287 | $mform->display();
 | 
        
           |  |  | 288 |   | 
        
           |  |  | 289 | echo $OUTPUT->box_end();
 | 
        
           |  |  | 290 |   | 
        
           |  |  | 291 | echo $OUTPUT->footer();
 | 
        
           |  |  | 292 | die;
 |