62536f65d983577e2627032e582ad42479703bd7
[moodle.git] / grade / edit / tree / grade.php
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/>.
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  */
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';
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);
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);
47 if (!$course = $DB->get_record('course', array('id' => $courseid))) {
48     print_error('nocourseid');
49 }
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 }
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);
62 // security checks!
63 if (!empty($id)) {
64     if (!$grade = $DB->get_record('grade_grades', array('id' => $id))) {
65         print_error('invalidgroupid');
66     }
68     if (!empty($itemid) and $itemid != $grade->itemid) {
69         print_error('invaliditemid');
70     }
71     $itemid = $grade->itemid;
73     if (!empty($userid) and $userid != $grade->userid) {
74         print_error('invaliduser');
75     }
76     $userid = $grade->userid;
78     unset($grade);
80 } else if (empty($userid) or empty($itemid)) {
81     print_error('missinguseranditemid');
82 }
84 if (!$grade_item = grade_item::fetch(array('id'=>$itemid, 'courseid'=>$courseid))) {
85     print_error('cannotfindgradeitem');
86 }
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             print_error('cannotgradeuser');
99         }
100     } else {
101         print_error('cannotgradeuser');
102     }
105 $mform = new edit_grade_form(null, array('grade_item'=>$grade_item, 'gpr'=>$gpr));
107 if ($grade = $DB->get_record('grade_grades', array('itemid' => $grade_item->id, 'userid' => $userid))) {
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->smiley  = false;
115         $options->filter  = false;
116         $options->noclean = false;
117         $options->para    = false;
118         $grade->feedback  = format_text($grade->feedback, $grade->feedbackformat, $options);
119     }
120     $grade->feedbackformat = FORMAT_HTML;
122     $grade->locked      = $grade->locked     > 0 ? 1:0;
123     $grade->overridden  = $grade->overridden > 0 ? 1:0;
124     $grade->excluded    = $grade->excluded   > 0 ? 1:0;
126     if ($grade->hidden > 1) {
127         $grade->hiddenuntil = $grade->hidden;
128         $grade->hidden = 1;
129     } else {
130         $grade->hiddenuntil = 0;
131     }
133     if ($grade_item->is_hidden()) {
134         $grade->hidden = 1;
135     }
137     if ($grade_item->is_locked()) {
138         $grade->locked = 1;
139     }
141     // normalize the final grade value
142     if ($grade_item->gradetype == GRADE_TYPE_SCALE) {
143         if (empty($grade->finalgrade)) {
144             $grade->finalgrade = -1;
145         } else {
146             $grade->finalgrade = (int)$grade->finalgrade;
147         }
148     } else if ($grade_item->gradetype == GRADE_TYPE_VALUE) {
149         $grade->finalgrade = format_float($grade->finalgrade, $grade_item->get_decimals());
150     }
152     $grade->oldgrade    = $grade->finalgrade;
153     $grade->oldfeedback = $grade->feedback;
155     $grade->feedback = array('text'=>$grade->feedback, 'format'=>$grade->feedbackformat);
157     $mform->set_data($grade);
158 } else {
159     $grade = new stdClass();
160     $grade->feedback = array('text'=>'', 'format'=>FORMAT_HTML);
161     $mform->set_data(array('itemid'=>$itemid, 'userid'=>$userid, 'locked'=>$grade_item->locked, 'locktime'=>$grade_item->locktime));
164 if ($mform->is_cancelled()) {
165     redirect($returnurl);
167 // form processing
168 } else if ($data = $mform->get_data(false)) {
170     if (isset($data->feedback) && is_array($data->feedback)) {
171         $data->feedbackformat = $data->feedback['format'];
172         $data->feedback = $data->feedback['text'];
173     }
175     $old_grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true); //might not exist yet
177     // fix no grade for scales
178     if (!isset($data->finalgrade) or $data->finalgrade == $data->oldgrade) {
179         $data->finalgrade = $old_grade_grade->finalgrade;
181     } else if ($grade_item->gradetype == GRADE_TYPE_SCALE) {
182         if ($data->finalgrade < 1) {
183             $data->finalgrade = NULL;
184         }
186     } else if ($grade_item->gradetype == GRADE_TYPE_VALUE) {
187         $data->finalgrade = unformat_float($data->finalgrade);
189     } else {
190         //this should not happen
191         $data->finalgrade = $old_grade_grade->finalgrade;
192     }
194     // the overriding of feedback is tricky - we have to care about external items only
195     if (!property_exists($data, 'feedback') or $data->feedback == $data->oldfeedback) {
196         $data->feedback       = $old_grade_grade->feedback;
197         $data->feedbackformat = $old_grade_grade->feedbackformat;
198     }
200     // update final grade or feedback
201     // when we set override grade the first time, it happens here
202     $grade_item->update_final_grade($data->userid, $data->finalgrade, 'editgrade', $data->feedback, $data->feedbackformat);
204     $grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true);
205     $grade_grade->grade_item =& $grade_item; // no db fetching
207     if (has_capability('moodle/grade:manage', $context) or has_capability('moodle/grade:edit', $context)) {
208         // change overridden flag
209         if (!isset($data->overridden)) {
210             $data->overridden = 0; // checkbox unticked
211         }
212         $grade_grade->set_overridden($data->overridden);
213     }
215     if (has_capability('moodle/grade:manage', $context) or has_capability('moodle/grade:hide', $context)) {
216         $hidden      = empty($data->hidden) ? 0: $data->hidden;
217         $hiddenuntil = empty($data->hiddenuntil) ? 0: $data->hiddenuntil;
219         if ($grade_item->is_hidden()) {
220             if ($old_grade_grade->hidden == 1 and $hiddenuntil == 0) {
221                 //nothing to do - grade was originally hidden, we want to keep it that way
222             } else {
223                 $grade_grade->set_hidden($hiddenuntil);
224             }
225         } else {
226             if ($hiddenuntil) {
227                 $grade_grade->set_hidden($hiddenuntil);
228             } else {
229                 $grade_grade->set_hidden($hidden); // checkbox data might be undefined
230             }
231         }
232     }
234     if (isset($data->locked) and !$grade_item->is_locked()) {
235         if (($old_grade_grade->locked or $old_grade_grade->locktime)
236           and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context))) {
237             //ignore data
239         } else if ((!$old_grade_grade->locked and !$old_grade_grade->locktime)
240           and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context))) {
241             //ignore data
243         } else {
244             $grade_grade->set_locktime($data->locktime); //set_lock may reset locktime
245             $grade_grade->set_locked($data->locked, false, true);
246             // reload grade in case it was regraded from activity
247             $grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true);
248             $grade_grade->grade_item =& $grade_item; // no db fetching
249         }
250     }
252     if (isset($data->excluded) and has_capability('moodle/grade:manage', $context)) {
253         $grade_grade->set_excluded($data->excluded);
254     }
256     // detect cases when we need to do full regrading
257     if ($old_grade_grade->excluded != $grade_grade->excluded) {
258         $parent = $grade_item->get_parent_category();
259         $parent->force_regrading();
261     } else if ($old_grade_grade->overridden != $grade_grade->overridden and empty($grade_grade->overridden)) { // only when unoverridding
262         $grade_item->force_regrading();
264     } else if ($old_grade_grade->locktime != $grade_grade->locktime) {
265         $grade_item->force_regrading();
266     }
268     $grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true);
269     if ($old_grade_grade->finalgrade != $grade_grade->finalgrade
270         or empty($old_grade_grade->overridden) != empty($grade_grade->overridden)
271     ) {
272         $grade_grade->grade_item = $grade_item;
273         \core\event\user_graded::create_from_grade($grade_grade)->trigger();
274     }
276     redirect($returnurl);
279 $strgrades       = get_string('grades');
280 $strgraderreport = get_string('graderreport', 'grades');
281 $strgradeedit    = get_string('editgrade', 'grades');
282 $struser         = get_string('user');
284 grade_build_nav(__FILE__, $strgradeedit, array('courseid' => $courseid));
286 /*********** BEGIN OUTPUT *************/
287 $PAGE->set_title($strgrades . ': ' . $strgraderreport . ': ' . $strgradeedit);
288 $PAGE->set_heading($course->fullname);
290 echo $OUTPUT->header();
291 echo $OUTPUT->heading($strgradeedit);
293 echo $OUTPUT->box_start();
295 // Form if in edit or add modes
296 $mform->display();
298 echo $OUTPUT->box_end();
300 echo $OUTPUT->footer();
301 die;