Differences Between: [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403]
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 * This file contains the definition for the library class for file feedback plugin 19 * 20 * 21 * @package assignfeedback_offline 22 * @copyright 2012 NetSpot {@link http://www.netspot.com.au} 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 require_once($CFG->dirroot.'/grade/grading/lib.php'); 29 30 /** 31 * library class for file feedback plugin extending feedback plugin base class 32 * 33 * @package assignfeedback_offline 34 * @copyright 2012 NetSpot {@link http://www.netspot.com.au} 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 */ 37 class assign_feedback_offline extends assign_feedback_plugin { 38 39 /** @var boolean|null $enabledcache Cached lookup of the is_enabled function */ 40 private $enabledcache = null; 41 42 /** 43 * Get the name of the file feedback plugin 44 * @return string 45 */ 46 public function get_name() { 47 return get_string('pluginname', 'assignfeedback_offline'); 48 } 49 50 /** 51 * Get form elements for grading form 52 * 53 * @param stdClass $grade 54 * @param MoodleQuickForm $mform 55 * @param stdClass $data 56 * @return bool true if elements were added to the form 57 */ 58 public function get_form_elements($grade, MoodleQuickForm $mform, stdClass $data) { 59 return false; 60 } 61 62 /** 63 * Return true if there are no feedback files 64 * @param stdClass $grade 65 */ 66 public function is_empty(stdClass $grade) { 67 return true; 68 } 69 70 /** 71 * This plugin does not save through the normal interface so this returns false. 72 * 73 * @param stdClass $grade The grade. 74 * @param stdClass $data Form data from the feedback form. 75 * @return boolean - False 76 */ 77 public function is_feedback_modified(stdClass $grade, stdClass $data) { 78 return false; 79 } 80 81 /** 82 * Loop through uploaded grades and update the grades for this assignment 83 * 84 * @param int $draftid - The unique draft item id for this import 85 * @param int $importid - The unique import ID for this csv import operation 86 * @param bool $ignoremodified - Ignore the last modified date when checking fields 87 * @param string $encoding - Encoding of the file being processed. 88 * @param string $separator - The character used to separate the information. 89 * @return string - The html response 90 */ 91 public function process_import_grades($draftid, $importid, $ignoremodified, $encoding = 'utf-8', $separator = 'comma') { 92 global $USER, $DB; 93 94 require_sesskey(); 95 require_capability('mod/assign:grade', $this->assignment->get_context()); 96 97 $gradeimporter = new assignfeedback_offline_grade_importer($importid, $this->assignment, $encoding, $separator); 98 99 $context = context_user::instance($USER->id); 100 $fs = get_file_storage(); 101 if (!$files = $fs->get_area_files($context->id, 'user', 'draft', $draftid, 'id DESC', false)) { 102 redirect(new moodle_url('view.php', 103 array('id'=>$this->assignment->get_course_module()->id, 104 'action'=>'grading'))); 105 return; 106 } 107 $file = reset($files); 108 109 $csvdata = $file->get_content(); 110 111 if ($csvdata) { 112 $gradeimporter->parsecsv($csvdata); 113 } 114 if (!$gradeimporter->init()) { 115 $thisurl = new moodle_url('/mod/assign/view.php', array('action'=>'viewpluginpage', 116 'pluginsubtype'=>'assignfeedback', 117 'plugin'=>'offline', 118 'pluginaction'=>'uploadgrades', 119 'id' => $this->assignment->get_course_module()->id)); 120 print_error('invalidgradeimport', 'assignfeedback_offline', $thisurl); 121 return; 122 } 123 // Does this assignment use a scale? 124 $scaleoptions = null; 125 if ($this->assignment->get_instance()->grade < 0) { 126 if ($scale = $DB->get_record('scale', array('id'=>-($this->assignment->get_instance()->grade)))) { 127 $scaleoptions = make_menu_from_list($scale->scale); 128 } 129 } 130 // We may need to upgrade the gradebook comments after this update. 131 $adminconfig = $this->assignment->get_admin_config(); 132 $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook; 133 134 $updategradecount = 0; 135 $updatefeedbackcount = 0; 136 while ($record = $gradeimporter->next()) { 137 $user = $record->user; 138 $modified = $record->modified; 139 $userdesc = fullname($user); 140 $usergrade = $this->assignment->get_user_grade($user->id, false); 141 142 if (!empty($scaleoptions)) { 143 // This is a scale - we need to convert any grades to indexes in the scale. 144 $scaleindex = array_search($record->grade, $scaleoptions); 145 if ($scaleindex !== false) { 146 $record->grade = $scaleindex; 147 } else { 148 $record->grade = ''; 149 } 150 } else { 151 $record->grade = unformat_float($record->grade); 152 } 153 154 // Note: Do not count the seconds when comparing modified dates. 155 $skip = false; 156 $stalemodificationdate = ($usergrade && $usergrade->timemodified > ($modified + 60)); 157 158 if ($usergrade && $usergrade->grade == $record->grade) { 159 // Skip - grade not modified. 160 $skip = true; 161 } else if (!isset($record->grade) || $record->grade === '' || $record->grade < 0) { 162 // Skip - grade has no value. 163 $skip = true; 164 } else if (!$ignoremodified && $stalemodificationdate) { 165 // Skip - grade has been modified. 166 $skip = true; 167 } else if ($this->assignment->grading_disabled($record->user->id)) { 168 // Skip grade is locked. 169 $skip = true; 170 } else if (($this->assignment->get_instance()->grade > -1) && 171 (($record->grade < 0) || ($record->grade > $this->assignment->get_instance()->grade))) { 172 // Out of range. 173 $skip = true; 174 } 175 176 if (!$skip) { 177 $grade = $this->assignment->get_user_grade($record->user->id, true); 178 179 $grade->grade = $record->grade; 180 $grade->grader = $USER->id; 181 if ($this->assignment->update_grade($grade)) { 182 $this->assignment->notify_grade_modified($grade); 183 $updategradecount += 1; 184 } 185 } 186 187 if ($ignoremodified || !$stalemodificationdate) { 188 foreach ($record->feedback as $feedback) { 189 $plugin = $feedback['plugin']; 190 $field = $feedback['field']; 191 $newvalue = $feedback['value']; 192 $description = $feedback['description']; 193 $oldvalue = ''; 194 if ($usergrade) { 195 $oldvalue = $plugin->get_editor_text($field, $usergrade->id); 196 if (empty($oldvalue)) { 197 $oldvalue = ''; 198 } 199 } 200 if ($newvalue != $oldvalue) { 201 $updatefeedbackcount += 1; 202 $grade = $this->assignment->get_user_grade($record->user->id, true); 203 $this->assignment->notify_grade_modified($grade); 204 $plugin->set_editor_text($field, $newvalue, $grade->id); 205 206 // If this is the gradebook comments plugin - post an update to the gradebook. 207 if (($plugin->get_subtype() . '_' . $plugin->get_type()) == $gradebookplugin) { 208 $grade->feedbacktext = $plugin->text_for_gradebook($grade); 209 $grade->feedbackformat = $plugin->format_for_gradebook($grade); 210 $this->assignment->update_grade($grade); 211 } 212 } 213 } 214 } 215 } 216 $gradeimporter->close(true); 217 218 $renderer = $this->assignment->get_renderer(); 219 $o = ''; 220 221 $o .= $renderer->render(new assign_header($this->assignment->get_instance(), 222 $this->assignment->get_context(), 223 false, 224 $this->assignment->get_course_module()->id, 225 get_string('importgrades', 'assignfeedback_offline'))); 226 $strparams = [ 227 'gradeupdatescount' => $updategradecount, 228 'feedbackupdatescount' => $updatefeedbackcount, 229 ]; 230 $o .= $renderer->box(get_string('updatedgrades', 'assignfeedback_offline', $strparams)); 231 $url = new moodle_url('view.php', 232 array('id'=>$this->assignment->get_course_module()->id, 233 'action'=>'grading')); 234 $o .= $renderer->continue_button($url); 235 $o .= $renderer->render_footer(); 236 return $o; 237 } 238 239 /** 240 * Display upload grades form 241 * 242 * @return string The response html 243 */ 244 public function upload_grades() { 245 global $CFG, $USER; 246 247 require_capability('mod/assign:grade', $this->assignment->get_context()); 248 require_once($CFG->dirroot . '/mod/assign/feedback/offline/uploadgradesform.php'); 249 require_once($CFG->dirroot . '/mod/assign/feedback/offline/importgradesform.php'); 250 require_once($CFG->dirroot . '/mod/assign/feedback/offline/importgradeslib.php'); 251 require_once($CFG->libdir . '/csvlib.class.php'); 252 253 $mform = new assignfeedback_offline_upload_grades_form(null, 254 array('context'=>$this->assignment->get_context(), 255 'cm'=>$this->assignment->get_course_module()->id)); 256 257 $o = ''; 258 259 $confirm = optional_param('confirm', 0, PARAM_BOOL); 260 $renderer = $this->assignment->get_renderer(); 261 262 if ($mform->is_cancelled()) { 263 redirect(new moodle_url('view.php', 264 array('id'=>$this->assignment->get_course_module()->id, 265 'action'=>'grading'))); 266 return; 267 } else if (($data = $mform->get_data()) && 268 ($csvdata = $mform->get_file_content('gradesfile'))) { 269 270 $importid = csv_import_reader::get_new_iid('assignfeedback_offline'); 271 $gradeimporter = new assignfeedback_offline_grade_importer($importid, $this->assignment, 272 $data->encoding, $data->separator); 273 // File exists and was valid. 274 $ignoremodified = !empty($data->ignoremodified); 275 276 $draftid = $data->gradesfile; 277 278 // Preview import. 279 280 $mform = new assignfeedback_offline_import_grades_form(null, array('assignment'=>$this->assignment, 281 'csvdata'=>$csvdata, 282 'ignoremodified'=>$ignoremodified, 283 'gradeimporter'=>$gradeimporter, 284 'draftid'=>$draftid)); 285 286 $o .= $renderer->render(new assign_header($this->assignment->get_instance(), 287 $this->assignment->get_context(), 288 false, 289 $this->assignment->get_course_module()->id, 290 get_string('confirmimport', 'assignfeedback_offline'))); 291 $o .= $renderer->render(new assign_form('confirmimport', $mform)); 292 $o .= $renderer->render_footer(); 293 } else if ($confirm) { 294 $importid = optional_param('importid', 0, PARAM_INT); 295 $draftid = optional_param('draftid', 0, PARAM_INT); 296 $encoding = optional_param('encoding', 'utf-8', PARAM_ALPHANUMEXT); 297 $separator = optional_param('separator', 'comma', PARAM_ALPHA); 298 $ignoremodified = optional_param('ignoremodified', 0, PARAM_BOOL); 299 $gradeimporter = new assignfeedback_offline_grade_importer($importid, $this->assignment, $encoding, $separator); 300 $mform = new assignfeedback_offline_import_grades_form(null, array('assignment'=>$this->assignment, 301 'csvdata'=>'', 302 'ignoremodified'=>$ignoremodified, 303 'gradeimporter'=>$gradeimporter, 304 'draftid'=>$draftid)); 305 if ($mform->is_cancelled()) { 306 redirect(new moodle_url('view.php', 307 array('id'=>$this->assignment->get_course_module()->id, 308 'action'=>'grading'))); 309 return; 310 } 311 312 $o .= $this->process_import_grades($draftid, $importid, $ignoremodified, $encoding, $separator); 313 } else { 314 315 $o .= $renderer->render(new assign_header($this->assignment->get_instance(), 316 $this->assignment->get_context(), 317 false, 318 $this->assignment->get_course_module()->id, 319 get_string('uploadgrades', 'assignfeedback_offline'))); 320 $o .= $renderer->render(new assign_form('batchuploadfiles', $mform)); 321 $o .= $renderer->render_footer(); 322 } 323 324 return $o; 325 } 326 327 /** 328 * Download a marking worksheet 329 * 330 * @return string The response html 331 */ 332 public function download_grades() { 333 global $CFG; 334 335 require_capability('mod/assign:grade', $this->assignment->get_context()); 336 require_once($CFG->dirroot . '/mod/assign/gradingtable.php'); 337 338 $groupmode = groups_get_activity_groupmode($this->assignment->get_course_module()); 339 // All users. 340 $groupid = 0; 341 $groupname = ''; 342 if ($groupmode) { 343 $groupid = groups_get_activity_group($this->assignment->get_course_module(), true); 344 $groupname = groups_get_group_name($groupid) . '-'; 345 } 346 $filename = clean_filename(get_string('offlinegradingworksheet', 'assignfeedback_offline') . '-' . 347 $this->assignment->get_course()->shortname . '-' . 348 $this->assignment->get_instance()->name . '-' . 349 $groupname . 350 $this->assignment->get_course_module()->id); 351 352 $table = new assign_grading_table($this->assignment, 0, '', 0, false, $filename); 353 354 $table->out(0, false); 355 return; 356 } 357 358 /** 359 * Print a sub page in this plugin 360 * 361 * @param string $action - The plugin action 362 * @return string The response html 363 */ 364 public function view_page($action) { 365 if ($action == 'downloadgrades') { 366 return $this->download_grades(); 367 } else if ($action == 'uploadgrades') { 368 return $this->upload_grades(); 369 } 370 371 return ''; 372 } 373 374 /** 375 * Return a list of the grading actions performed by this plugin 376 * This plugin supports upload zip 377 * 378 * @return array The list of grading actions 379 */ 380 public function get_grading_actions() { 381 return array('uploadgrades'=>get_string('uploadgrades', 'assignfeedback_offline'), 382 'downloadgrades'=>get_string('downloadgrades', 'assignfeedback_offline')); 383 } 384 385 /** 386 * Override the default is_enabled to disable this plugin if advanced grading is active 387 * 388 * @return bool 389 */ 390 public function is_enabled() { 391 if ($this->enabledcache === null) { 392 $gradingmanager = get_grading_manager($this->assignment->get_context(), 'mod_assign', 'submissions'); 393 $controller = $gradingmanager->get_active_controller(); 394 $active = !empty($controller); 395 396 if ($active) { 397 $this->enabledcache = false; 398 } else { 399 $this->enabledcache = parent::is_enabled(); 400 } 401 } 402 return $this->enabledcache; 403 } 404 405 /** 406 * Do not show this plugin in the grading table or on the front page 407 * 408 * @return bool 409 */ 410 public function has_user_summary() { 411 return false; 412 } 413 414 /** 415 * Return the plugin configs for external functions. 416 * 417 * @return array the list of settings 418 * @since Moodle 3.2 419 */ 420 public function get_config_for_external() { 421 return (array) $this->get_config(); 422 } 423 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body