���ѧۧݧ�ӧ�� �ާ֧ߧ֧էا֧� - ���֧էѧܧ�ڧ��ӧѧ�� - /home3/cpr76684/public_html/import.tar
���ѧ٧ѧ�
direct/db/access.php 0000644 00000002257 15151264176 0010373 0 ustar 00 <?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/>. /** * Capabilities gradeimport plugin. * * @package gradeimport_direct * @copyright 2014 Adrian Greeve <adrian@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $capabilities = array( 'gradeimport/direct:view' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, 'archetypes' => array( 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW ) ) ); direct/index.php 0000644 00000011651 15151264176 0007652 0 ustar 00 <?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/>. require_once(__DIR__ . "/../../../config.php"); require_once($CFG->libdir.'/gradelib.php'); require_once($CFG->dirroot.'/grade/lib.php'); require_once($CFG->dirroot.'/grade/import/lib.php'); require_once($CFG->libdir . '/csvlib.class.php'); $id = required_param('id', PARAM_INT); // Course id. $verbosescales = optional_param('verbosescales', 1, PARAM_BOOL); $iid = optional_param('iid', null, PARAM_INT); $importcode = optional_param('importcode', '', PARAM_FILE); $forceimport = optional_param('forceimport', false, PARAM_BOOL); $url = new moodle_url('/grade/import/direct/index.php', array('id' => $id)); if ($verbosescales !== 1) { $url->param('verbosescales', $verbosescales); } $PAGE->set_url($url); if (!$course = $DB->get_record('course', array('id' => $id))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($id); require_capability('moodle/grade:import', $context); require_capability('gradeimport/direct:view', $context); $separatemode = (groups_get_course_groupmode($COURSE) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)); $currentgroup = groups_get_course_group($course); $actionbar = new \core_grades\output\import_action_bar($context, null, 'direct'); print_grade_page_head($course->id, 'import', 'direct', get_string('pluginname', 'gradeimport_direct'), false, false, true, 'userdata', 'gradeimport_direct', null, $actionbar); $renderer = $PAGE->get_renderer('gradeimport_csv'); // Get the grade items to be matched with the import mapping columns. $gradeitems = gradeimport_csv_load_data::fetch_grade_items($course->id); // If the csv file hasn't been imported yet then look for a form submission or // show the initial submission form. if (!$iid) { // Set up the import form. $mform = new gradeimport_direct_import_form(null, array('includeseparator' => true, 'verbosescales' => true, 'acceptedtypes' => array('.csv', '.txt'))); // If the import form has been submitted. if ($formdata = $mform->get_data()) { $text = $formdata->userdata; $csvimport = new gradeimport_csv_load_data(); $csvimport->load_csv_content($text, $formdata->encoding, 'tab', $formdata->previewrows); $csvimporterror = $csvimport->get_error(); if (!empty($csvimporterror)) { echo $renderer->errors(array($csvimport->get_error())); echo $OUTPUT->footer(); die(); } $iid = $csvimport->get_iid(); echo $renderer->import_preview_page($csvimport->get_headers(), $csvimport->get_previewdata()); } else { // Display the standard upload file form. echo $renderer->standard_upload_file_form($course, $mform); echo $OUTPUT->footer(); die(); } } // Data has already been submitted so we can use the $iid to retrieve it. $csvimport = new csv_import_reader($iid, 'grade'); $header = $csvimport->get_columns(); // Get a new import code for updating to the grade book. if (empty($importcode)) { $importcode = get_new_importcode(); } $mappingformdata = array( 'gradeitems' => $gradeitems, 'header' => $header, 'iid' => $iid, 'id' => $id, 'forceimport' => $forceimport, 'importcode' => $importcode, 'verbosescales' => $verbosescales ); // We create a form to handle mapping data from the file to the database. $mform2 = new gradeimport_direct_mapping_form(null, $mappingformdata); // Here, if we have data, we process the fields and enter the information into the database. if ($formdata = $mform2->get_data()) { $gradeimport = new gradeimport_csv_load_data(); $status = $gradeimport->prepare_import_grade_data($header, $formdata, $csvimport, $course->id, $separatemode, $currentgroup, $verbosescales); // At this stage if things are all ok, we commit the changes from temp table. if ($status) { grade_import_commit($course->id, $importcode); } else { $errors = $gradeimport->get_gradebookerrors(); $errors[] = get_string('importfailed', 'grades'); echo $renderer->errors($errors); } echo $OUTPUT->footer(); } else { // If data hasn't been submitted then display the data mapping form. $mform2->display(); echo $OUTPUT->footer(); } direct/version.php 0000644 00000002411 15151264176 0010222 0 ustar 00 <?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/>. /** * Version details * * @package gradeimport_direct * @copyright 2014 Adrian Greeve <adrian@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $plugin->version = 2022112800; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2022111800; // Requires this Moodle version. $plugin->component = 'gradeimport_direct'; // Full name of the plugin (used for diagnostics). $plugin->dependencies = array('gradeimport_csv' => 2022111800); // Grade import csv is required for this plugin. direct/classes/privacy/provider.php 0000644 00000003003 15151264176 0013477 0 ustar 00 <?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/>. /** * Privacy Subsystem implementation for gradeimport_direct. * * @package gradeimport_direct * @copyright 2018 Sara Arjona <sara@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace gradeimport_direct\privacy; defined('MOODLE_INTERNAL') || die(); /** * Privacy Subsystem for gradeimport_direct implementing null_provider. * * @copyright 2018 Sara Arjona <sara@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class provider implements \core_privacy\local\metadata\null_provider { /** * Get the language string identifier with the component's language * file to explain why this plugin stores no data. * * @return string */ public static function get_reason() : string { return 'privacy:metadata'; } } direct/classes/import_form.php 0000644 00000006545 15151264176 0012543 0 ustar 00 <?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/>. require_once($CFG->libdir.'/formslib.php'); if (!defined('MOODLE_INTERNAL')) { die('Direct access to this script is forbidden.'); // It must be included from a Moodle page. } /** * Form for copying and pasting from a spreadsheet. * * @package gradeimport_direct * @copyright 2014 Adrian Greeve <adrian@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class gradeimport_direct_import_form extends moodleform { /** * Definition method. */ public function definition() { global $COURSE; $mform = $this->_form; if (isset($this->_customdata)) { // Hardcoding plugin names here is hacky. $features = $this->_customdata; } else { $features = array(); } // Course id needs to be passed for auth purposes. $mform->addElement('hidden', 'id', optional_param('id', 0, PARAM_INT)); $mform->setType('id', PARAM_INT); $mform->addElement('header', 'general', get_string('pluginname', 'gradeimport_direct')); // Data upload from copy/paste. $mform->addElement('textarea', 'userdata', get_string('importdata', 'core_grades'), array('rows' => 10, 'class' => 'gradeimport_data_area')); $mform->addHelpButton('userdata', 'importdata', 'core_grades'); $mform->addRule('userdata', null, 'required'); $mform->setType('userdata', PARAM_RAW); $encodings = core_text::get_encodings(); $mform->addElement('select', 'encoding', get_string('encoding', 'grades'), $encodings); $mform->addHelpButton('encoding', 'encoding', 'grades'); if (!empty($features['verbosescales'])) { $options = array(1 => get_string('yes'), 0 => get_string('no')); $mform->addElement('select', 'verbosescales', get_string('verbosescales', 'grades'), $options); $mform->addHelpButton('verbosescales', 'verbosescales', 'grades'); } $options = array('10' => 10, '20' => 20, '100' => 100, '1000' => 1000, '100000' => 100000); $mform->addElement('select', 'previewrows', get_string('rowpreviewnum', 'grades'), $options); $mform->addHelpButton('previewrows', 'rowpreviewnum', 'grades'); $mform->setType('previewrows', PARAM_INT); $mform->addElement('hidden', 'groupid', groups_get_course_group($COURSE)); $mform->setType('groupid', PARAM_INT); $mform->addElement('advcheckbox', 'forceimport', get_string('forceimport', 'grades')); $mform->addHelpButton('forceimport', 'forceimport', 'grades'); $mform->setDefault('forceimport', false); $this->add_action_buttons(false, get_string('uploadgrades', 'grades')); } } direct/classes/mapping_form.php 0000644 00000011600 15151264176 0012650 0 ustar 00 <?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/>. require_once($CFG->libdir.'/formslib.php'); require_once($CFG->libdir.'/gradelib.php'); if (!defined('MOODLE_INTERNAL')) { die('Direct access to this script is forbidden.'); // It must be included from a Moodle page. } /** * Form for mapping columns to the fields in the table. * * @package gradeimport_direct * @copyright 2014 Adrian Greeve <adrian@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class gradeimport_direct_mapping_form extends moodleform { /** * Definition method. */ public function definition() { global $CFG, $COURSE; $mform = $this->_form; // This is an array of headers. $header = $this->_customdata['header']; // Course id. $mform->addElement('header', 'general', get_string('identifier', 'grades')); $mapfromoptions = array(); if ($header) { foreach ($header as $i => $h) { $mapfromoptions[$i] = s($h); } } $mform->addElement('select', 'mapfrom', get_string('mapfrom', 'grades'), $mapfromoptions); $mform->addHelpButton('mapfrom', 'mapfrom', 'grades'); $maptooptions = array( 'userid' => get_string('userid', 'grades'), 'username' => get_string('username'), 'useridnumber' => get_string('idnumber'), 'useremail' => get_string('email'), '0' => get_string('ignore', 'grades') ); $mform->addElement('select', 'mapto', get_string('mapto', 'grades'), $maptooptions); $mform->addHelpButton('mapto', 'mapto', 'grades'); $mform->addElement('header', 'general_map', get_string('mappings', 'grades')); $mform->addHelpButton('general_map', 'mappings', 'grades'); // Add a feedback option. $feedbacks = array(); if ($gradeitems = $this->_customdata['gradeitems']) { foreach ($gradeitems as $itemid => $itemname) { $feedbacks['feedback_'.$itemid] = get_string('feedbackforgradeitems', 'grades', $itemname); } } if ($header) { $i = 0; foreach ($header as $h) { $h = trim($h); // This is what each header maps to. $headermapsto = array( get_string('others', 'grades') => array( '0' => get_string('ignore', 'grades'), 'new' => get_string('newitem', 'grades') ), get_string('gradeitems', 'grades') => $gradeitems, get_string('feedbacks', 'grades') => $feedbacks ); $mform->addElement('selectgroups', 'mapping_'.$i, s($h), $headermapsto); $i++; } } // Course id needs to be passed for auth purposes. $mform->addElement('hidden', 'map', 1); $mform->setType('map', PARAM_INT); $mform->setConstant('map', 1); $mform->addElement('hidden', 'id', $this->_customdata['id']); $mform->setType('id', PARAM_INT); $mform->setConstant('id', $this->_customdata['id']); $mform->addElement('hidden', 'iid', $this->_customdata['iid']); $mform->setType('iid', PARAM_INT); $mform->setConstant('iid', $this->_customdata['iid']); $mform->addElement('hidden', 'importcode', $this->_customdata['importcode']); $mform->setType('importcode', PARAM_FILE); $mform->setConstant('importcode', $this->_customdata['importcode']); $mform->addElement('hidden', 'verbosescales', 1); $mform->setType('verbosescales', PARAM_INT); $mform->setConstant('verbosescales', $this->_customdata['importcode']); $mform->addElement('hidden', 'groupid', groups_get_course_group($COURSE)); $mform->setType('groupid', PARAM_INT); $mform->setConstant('groupid', groups_get_course_group($COURSE)); $mform->addElement('hidden', 'forceimport', $this->_customdata['forceimport']); $mform->setType('forceimport', PARAM_BOOL); $mform->setConstant('forceimport', $this->_customdata['forceimport']); $this->add_action_buttons(false, get_string('uploadgrades', 'grades')); } } direct/lang/en/gradeimport_direct.php 0000644 00000003024 15151264176 0013730 0 ustar 00 <?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/>. /** * Strings for component 'gradeimport_direct', language 'en', branch 'MOODLE_28_STABLE' * * @package gradeimport_direct * @copyright 2014 Adrian Greeve <adrian@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ $string['direct:view'] = 'Import grades from spreadsheet'; $string['pluginname'] = 'Paste from spreadsheet'; $string['privacy:metadata'] = 'The import grades from copied spreadsheed plugin does not store any personal data.'; $string['userdata'] = 'Help copying data into this form.'; $string['userdata_help'] = 'Grades may be copied and pasted from a spreadsheet into the gradebook. The spreadsheet should have a column containing user identity data - either username or ID number or email address. Each column for import should have a column header.'; $string['userdata_link'] = 'grade/import/direct/index'; keymanager.php 0000644 00000005720 15151264176 0007414 0 ustar 00 <?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/>. /** * Grade import key management page. * * @package moodlecore * @copyright 2008 Petr Skoda * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once(__DIR__.'/../../config.php'); require_once($CFG->dirroot.'/grade/lib.php'); $id = required_param('id', PARAM_INT); // course id $PAGE->set_url('/grade/import/keymanager.php', array('id' => $id)); if (!$course = $DB->get_record('course', array('id'=>$id))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($id); require_capability('moodle/grade:import', $context); // Check if the user has at least one grade publishing capability. $plugins = grade_helper::get_plugins_import($course->id); if (!isset($plugins['keymanager'])) { throw new \moodle_exception('nopermissions'); } $actionbar = new \core_grades\output\import_key_manager_action_bar($context); print_grade_page_head($course->id, 'import', 'keymanager', get_string('keymanager', 'grades'), false, false, true, 'importcsv', 'grades', null, $actionbar); $stredit = get_string('edit'); $strdelete = get_string('delete'); $data = array(); $params = array($course->id, $USER->id); if ($keys = $DB->get_records_select('user_private_key', "script='grade/import' AND instance=? AND userid=?", $params)) { foreach($keys as $key) { $line = array(); $line[0] = format_string($key->value); $line[1] = $key->iprestriction; $line[2] = empty($key->validuntil) ? get_string('always') : userdate($key->validuntil); $url = new moodle_url('key.php', array('id' => $key->id)); $buttons = $OUTPUT->action_icon($url, new pix_icon('t/edit', $stredit)); $url->param('delete', 1); $url->param('sesskey', sesskey()); $buttons .= $OUTPUT->action_icon($url, new pix_icon('t/delete', $strdelete)); $line[3] = $buttons; $data[] = $line; } } $table = new html_table(); $table->head = array(get_string('keyvalue', 'userkey'), get_string('keyiprestriction', 'userkey'), get_string('keyvaliduntil', 'userkey'), $stredit); $table->size = array('50%', '30%', '10%', '10%'); $table->align = array('left', 'left', 'left', 'center'); $table->width = '90%'; $table->data = $data; echo html_writer::table($table); echo $OUTPUT->footer(); key.php 0000644 00000011405 15151264176 0006056 0 ustar 00 <?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/>. /** * Import key management. * * @package moodlecore * @copyright 2008 Nicolas Connault * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once('../../config.php'); require_once('key_form.php'); require_once($CFG->dirroot.'/grade/lib.php'); /// get url variables $courseid = optional_param('courseid', 0, PARAM_INT); $id = optional_param('id', 0, PARAM_INT); $delete = optional_param('delete', 0, PARAM_BOOL); $confirm = optional_param('confirm', 0, PARAM_BOOL); $url = new moodle_url('/grade/import/key.php', ['courseid' => $courseid, 'id' => $id]); $PAGE->set_url($url); if ($id) { if (!$key = $DB->get_record('user_private_key', array('id' => $id))) { throw new \moodle_exception('invalidgroupid'); } if (empty($courseid)) { $courseid = $key->instance; } else if ($courseid != $key->instance) { throw new \moodle_exception('invalidcourseid'); } if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } } else { if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } $key = new stdClass(); } $key->courseid = $course->id; require_login($course); $context = context_course::instance($course->id); require_capability('moodle/grade:import', $context); // Check if the user has at least one grade publishing capability. $plugins = grade_helper::get_plugins_import($course->id); if (!isset($plugins['keymanager'])) { throw new \moodle_exception('nopermissions'); } // extra security check if (!empty($key->userid) and $USER->id != $key->userid) { throw new \moodle_exception('notownerofkey'); } $returnurl = $CFG->wwwroot.'/grade/import/keymanager.php?id='.$course->id; $strkeys = get_string('keymanager', 'userkey'); $strimportgrades = get_string('import', 'grades'); $PAGE->navbar->add($strimportgrades, new moodle_url(new moodle_url('/grade/import/index.php', ['id' => $courseid]))); $PAGE->navbar->add($strkeys, new moodle_url('/grade/import/keymanager.php', ['id' => $courseid])); if ($id and $delete) { if (!$confirm) { $PAGE->set_title(get_string('deleteselectedkey')); $PAGE->set_heading($course->fullname); $PAGE->set_secondary_active_tab('grades'); $PAGE->navbar->add(get_string('deleteuserkey', 'userkey')); echo $OUTPUT->header(); $optionsyes = array('id'=>$id, 'delete'=>1, 'courseid'=>$courseid, 'sesskey'=>sesskey(), 'confirm'=>1); $optionsno = array('id'=>$courseid); $formcontinue = new single_button(new moodle_url('key.php', $optionsyes), get_string('yes'), 'get'); $formcancel = new single_button(new moodle_url('keymanager.php', $optionsno), get_string('no'), 'get'); echo $OUTPUT->confirm(get_string('deletekeyconfirm', 'userkey', $key->value), $formcontinue, $formcancel); echo $OUTPUT->footer(); die; } else if (confirm_sesskey()){ $DB->delete_records('user_private_key', array('id' => $id)); redirect('keymanager.php?id='.$course->id); } } /// First create the form $editform = new key_form(); $editform->set_data($key); if ($editform->is_cancelled()) { redirect($returnurl); } elseif ($data = $editform->get_data()) { if ($data->id) { $record = new stdClass(); $record->id = $data->id; $record->iprestriction = $data->iprestriction; $record->validuntil = $data->validuntil; $DB->update_record('user_private_key', $record); } else { create_user_key('grade/import', $USER->id, $course->id, $data->iprestriction, $data->validuntil); } redirect($returnurl); } if ($id) { $strheading = get_string('edituserkey', 'userkey'); } else { $strheading = get_string('createuserkey', 'userkey'); } $PAGE->navbar->add($strheading); /// Print header $PAGE->set_title($strkeys); $PAGE->set_heading($course->fullname); $PAGE->set_secondary_active_tab('grades'); echo $OUTPUT->header(); echo $OUTPUT->heading($strheading); $editform->display(); echo $OUTPUT->footer(); grade_import_form.php 0000644 00000017253 15151264176 0010774 0 ustar 00 <?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/>. if (!defined('MOODLE_INTERNAL')) { die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page } require_once $CFG->libdir.'/formslib.php'; require_once($CFG->libdir.'/gradelib.php'); class grade_import_form extends moodleform { function definition (){ global $COURSE; $mform =& $this->_form; if (isset($this->_customdata)) { // hardcoding plugin names here is hacky $features = $this->_customdata; } else { $features = array(); } // course id needs to be passed for auth purposes $mform->addElement('hidden', 'id', optional_param('id', 0, PARAM_INT)); $mform->setType('id', PARAM_INT); $mform->addElement('header', 'general', get_string('importfile', 'grades')); // Restrict the possible upload file types. if (!empty($features['acceptedtypes'])) { $acceptedtypes = $features['acceptedtypes']; } else { $acceptedtypes = '*'; } // File upload. $mform->addElement('filepicker', 'userfile', get_string('file'), null, array('accepted_types' => $acceptedtypes)); $mform->addRule('userfile', null, 'required'); $encodings = core_text::get_encodings(); $mform->addElement('select', 'encoding', get_string('encoding', 'grades'), $encodings); $mform->addHelpButton('encoding', 'encoding', 'grades'); if (!empty($features['includeseparator'])) { $radio = array(); $radio[] = $mform->createElement('radio', 'separator', null, get_string('septab', 'grades'), 'tab'); $radio[] = $mform->createElement('radio', 'separator', null, get_string('sepcomma', 'grades'), 'comma'); $radio[] = $mform->createElement('radio', 'separator', null, get_string('sepcolon', 'grades'), 'colon'); $radio[] = $mform->createElement('radio', 'separator', null, get_string('sepsemicolon', 'grades'), 'semicolon'); $mform->addGroup($radio, 'separator', get_string('separator', 'grades'), ' ', false); $mform->addHelpButton('separator', 'separator', 'grades'); $mform->setDefault('separator', 'comma'); } if (!empty($features['verbosescales'])) { $options = array(1=>get_string('yes'), 0=>get_string('no')); $mform->addElement('select', 'verbosescales', get_string('verbosescales', 'grades'), $options); $mform->addHelpButton('verbosescales', 'verbosescales', 'grades'); } $options = array('10'=>10, '20'=>20, '100'=>100, '1000'=>1000, '100000'=>100000); $mform->addElement('select', 'previewrows', get_string('rowpreviewnum', 'grades'), $options); // TODO: localize $mform->addHelpButton('previewrows', 'rowpreviewnum', 'grades'); $mform->setType('previewrows', PARAM_INT); $mform->addElement('checkbox', 'forceimport', get_string('forceimport', 'grades')); $mform->addHelpButton('forceimport', 'forceimport', 'grades'); $mform->setDefault('forceimport', false); $mform->setType('forceimport', PARAM_BOOL); $mform->addElement('hidden', 'groupid', groups_get_course_group($COURSE)); $mform->setType('groupid', PARAM_INT); $this->add_action_buttons(false, get_string('uploadgrades', 'grades')); } } class grade_import_mapping_form extends moodleform { function definition () { global $CFG, $COURSE; $mform =& $this->_form; // this is an array of headers $header = $this->_customdata['header']; // course id $mform->addElement('header', 'general', get_string('identifier', 'grades')); $mapfromoptions = array(); if ($header) { foreach ($header as $i=>$h) { $mapfromoptions[$i] = s($h); } } $mform->addElement('select', 'mapfrom', get_string('mapfrom', 'grades'), $mapfromoptions); $mform->addHelpButton('mapfrom', 'mapfrom', 'grades'); $maptooptions = array( 'userid' => get_string('userid', 'grades'), 'username' => get_string('username'), 'useridnumber' => get_string('idnumber'), 'useremail' => get_string('email'), '0' => get_string('ignore', 'grades') ); $mform->addElement('select', 'mapto', get_string('mapto', 'grades'), $maptooptions); $mform->addHelpButton('mapto', 'mapto', 'grades'); $mform->addElement('header', 'general_map', get_string('mappings', 'grades')); $mform->addHelpButton('general_map', 'mappings', 'grades'); // Add a feedback option. $feedbacks = []; $gradeitems = (array) $this->_customdata['gradeitems']; foreach ($gradeitems as $itemid => $itemname) { $feedbacks['feedback_'.$itemid] = get_string('feedbackforgradeitems', 'grades', $itemname); } if ($header) { $i = 0; // index foreach ($header as $h) { $h = trim($h); // This is what each header maps to. $headermapsto = array( get_string('others', 'grades') => array( '0' => get_string('ignore', 'grades'), 'new' => get_string('newitem', 'grades') ), get_string('gradeitems', 'grades') => $gradeitems, get_string('feedbacks', 'grades') => $feedbacks ); $mform->addElement('selectgroups', 'mapping_'.$i, s($h), $headermapsto); $i++; } } // course id needs to be passed for auth purposes $mform->addElement('hidden', 'map', 1); $mform->setType('map', PARAM_INT); $mform->setConstant('map', 1); $mform->addElement('hidden', 'id', $this->_customdata['id']); $mform->setType('id', PARAM_INT); $mform->setConstant('id', $this->_customdata['id']); $mform->addElement('hidden', 'iid', $this->_customdata['iid']); $mform->setType('iid', PARAM_INT); $mform->setConstant('iid', $this->_customdata['iid']); $mform->addElement('hidden', 'importcode', $this->_customdata['importcode']); $mform->setType('importcode', PARAM_FILE); $mform->setConstant('importcode', $this->_customdata['importcode']); $mform->addElement('hidden', 'verbosescales', 1); $mform->setType('verbosescales', PARAM_INT); $mform->setConstant('verbosescales', $this->_customdata['verbosescales']); $mform->addElement('hidden', 'groupid', groups_get_course_group($COURSE)); $mform->setType('groupid', PARAM_INT); $mform->setConstant('groupid', groups_get_course_group($COURSE)); $mform->addElement('hidden', 'forceimport', $this->_customdata['forceimport']); $mform->setType('forceimport', PARAM_BOOL); $mform->setConstant('forceimport', $this->_customdata['forceimport']); $this->add_action_buttons(false, get_string('uploadgrades', 'grades')); } } csv/db/access.php 0000644 00000002233 15151264176 0007706 0 ustar 00 <?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/>. /** * Capabilities gradeimport plugin. * * @package gradeimport_csv * @copyright 2007 Martin Dougiamas * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $capabilities = array( 'gradeimport/csv:view' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, 'archetypes' => array( 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW ) ) ); csv/tests/fixtures/phpunit_gradeimport_csv_load_data.php 0000644 00000010712 15151264176 0020023 0 ustar 00 <?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/>. require_once($CFG->dirroot . '/grade/import/csv/classes/load_data.php'); require_once($CFG->dirroot . '/grade/import/lib.php'); /** * Class to open up private methods in gradeimport_csv_load_data(). */ class phpunit_gradeimport_csv_load_data extends gradeimport_csv_load_data { /** * Method to open up the appropriate method for unit testing. * * @param object $record * @param int $studentid */ public function test_insert_grade_record($record, $studentid) { $this->importcode = 00001; $this->insert_grade_record($record, $studentid); } /** * Method to open up the appropriate method for unit testing. */ public function get_importcode() { return $this->importcode; } /** * Method to open up the appropriate method for unit testing. * * @param array $header The column headers from the CSV file. * @param int $key Current row identifier. * @param string $value The value for this row (final grade). * @return array new grades that are ready for commiting to the gradebook. */ public function test_import_new_grade_item($header, $key, $value) { $this->newgradeitems = null; $this->importcode = 00001; return $this->import_new_grade_item($header, $key, $value); } /** * Method to open up the appropriate method for unit testing. * * @param string $value The value, from the csv file, being mapped to identify the user. * @param array $userfields Contains the field and label being mapped from. * @return int Returns the user ID if it exists, otherwise null. */ public function test_check_user_exists($value, $userfields) { return $this->check_user_exists($value, $userfields); } /** * Method to open up the appropriate method for unit testing. * * @param int $courseid The course ID. * @param int $itemid The ID of the grade item that the feedback relates to. * @param string $value The actual feedback being imported. * @return object Creates a feedback object with the item ID and the feedback value. */ public function test_create_feedback($courseid, $itemid, $value) { return $this->create_feedback($courseid, $itemid, $value); } /** * Method to open up the appropriate method for unit testing. */ public function test_update_grade_item($courseid, $map, $key, $verbosescales, $value) { return $this->update_grade_item($courseid, $map, $key, $verbosescales, $value); } /** * Method to open up the appropriate method for unit testing. * * @param int $courseid The course ID. * @param array $map Mapping information provided by the user. * @param int $key The line that we are currently working on. * @param bool $verbosescales Form setting for grading with scales. * @param string $value The grade value . * @return array grades to be updated. */ public function test_map_user_data_with_value($mappingidentifier, $value, $header, $map, $key, $courseid, $feedbackgradeid, $verbosescales) { // Set an import code. $this->importcode = 00001; $this->map_user_data_with_value($mappingidentifier, $value, $header, $map, $key, $courseid, $feedbackgradeid, $verbosescales); switch ($mappingidentifier) { case 'userid': case 'useridnumber': case 'useremail': case 'username': return $this->studentid; break; case 'new': return $this->newgrades; break; case 'feedback': return $this->newfeedbacks; break; default: return $this->newgrades; break; } } } csv/tests/load_data_test.php 0000644 00000061665 15151264176 0012207 0 ustar 00 <?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/>. namespace gradeimport_csv; defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->dirroot . '/grade/import/csv/tests/fixtures/phpunit_gradeimport_csv_load_data.php'); require_once($CFG->libdir . '/csvlib.class.php'); require_once($CFG->libdir . '/grade/grade_item.php'); require_once($CFG->libdir . '/grade/tests/fixtures/lib.php'); /** * Unit tests for lib.php * * @package gradeimport_csv * @copyright 2014 Adrian Greeve * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class load_data_test extends \grade_base_testcase { /** @var string $oktext Text to be imported. This data should have no issues being imported. */ protected $oktext = '"First name","Last name","ID number",Institution,Department,"Email address","Assignment: Assignment for grape group", "Feedback: Assignment for grape group","Assignment: Second new grade item","Course total" Anne,Able,,"Moodle HQ","Rock on!",student7@example.com,56.00,"We welcome feedback",,56.00 Bobby,Bunce,,"Moodle HQ","Rock on!",student5@example.com,75.00,,45.0,75.00'; /** @var string $badtext Text to be imported. This data has an extra column and should not succeed in being imported. */ protected $badtext = '"First name","Last name","ID number",Institution,Department,"Email address","Assignment: Assignment for grape group","Course total" Anne,Able,,"Moodle HQ","Rock on!",student7@example.com,56.00,56.00,78.00 Bobby,Bunce,,"Moodle HQ","Rock on!",student5@example.com,75.00,75.00'; /** @var string $csvtext CSV data to be imported with Last download from this course column. */ protected $csvtext = '"First name","Last name","ID number",Institution,Department,"Email address","Assignment: Assignment for grape group", "Feedback: Assignment for grape group","Course total","Last downloaded from this course" Anne,Able,,"Moodle HQ","Rock on!",student7@example.com,56.00,"We welcome feedback",56.00,{exportdate} Bobby,Bunce,,"Moodle HQ","Rock on!",student5@example.com,75.00,,75.00,{exportdate}'; /** @var int $iid Import ID. */ protected $iid; /** @var object $csvimport a csv_import_reader object that handles the csv import. */ protected $csvimport; /** @var array $columns The first row of the csv file. These are the columns of the import file.*/ protected $columns; public function tearDown(): void { $this->csvimport = null; } /** * Load up the above text through the csv import. * * @param string $content Text to be imported into the gradebook. * @return array All text separated by commas now in an array. */ protected function csv_load($content) { // Import the csv strings. $this->iid = \csv_import_reader::get_new_iid('grade'); $this->csvimport = new \csv_import_reader($this->iid, 'grade'); $this->csvimport->load_csv_content($content, 'utf8', 'comma'); $this->columns = $this->csvimport->get_columns(); $this->csvimport->init(); while ($line = $this->csvimport->next()) { $testarray[] = $line; } return $testarray; } /** * Test loading data and returning preview content. */ public function test_load_csv_content() { $encoding = 'utf8'; $separator = 'comma'; $previewrows = 5; $csvpreview = new \phpunit_gradeimport_csv_load_data(); $csvpreview->load_csv_content($this->oktext, $encoding, $separator, $previewrows); $expecteddata = array(array( 'Anne', 'Able', '', 'Moodle HQ', 'Rock on!', 'student7@example.com', 56.00, 'We welcome feedback', '', 56.00 ), array( 'Bobby', 'Bunce', '', 'Moodle HQ', 'Rock on!', 'student5@example.com', 75.00, '', 45.0, 75.00 ) ); $expectedheaders = array( 'First name', 'Last name', 'ID number', 'Institution', 'Department', 'Email address', 'Assignment: Assignment for grape group', 'Feedback: Assignment for grape group', 'Assignment: Second new grade item', 'Course total' ); // Check that general data is returned as expected. $this->assertEquals($csvpreview->get_previewdata(), $expecteddata); // Check that headers are returned as expected. $this->assertEquals($csvpreview->get_headers(), $expectedheaders); // Check that errors are being recorded. $csvpreview = new \phpunit_gradeimport_csv_load_data(); $csvpreview->load_csv_content($this->badtext, $encoding, $separator, $previewrows); // Columns shouldn't match. $this->assertEquals($csvpreview->get_error(), get_string('csvweirdcolumns', 'error')); } /** * Test fetching grade items for the course. */ public function test_fetch_grade_items() { $gradeitemsarray = \grade_item::fetch_all(array('courseid' => $this->courseid)); $gradeitems = \phpunit_gradeimport_csv_load_data::fetch_grade_items($this->courseid); // Make sure that each grade item is located in the gradeitemsarray. foreach ($gradeitems as $key => $gradeitem) { $this->assertArrayHasKey($key, $gradeitemsarray); } // Get the key for a specific grade item. $quizkey = null; foreach ($gradeitemsarray as $key => $value) { if ($value->itemname == "Quiz grade item") { $quizkey = $key; } } // Expected modified item name. $testitemname = get_string('modulename', $gradeitemsarray[$quizkey]->itemmodule) . ': ' . $gradeitemsarray[$quizkey]->itemname; // Check that an item that is a module, is concatenated properly. $this->assertEquals($testitemname, $gradeitems[$quizkey]); } /** * Test the inserting of grade record data. */ public function test_insert_grade_record() { global $DB, $USER; $user = $this->getDataGenerator()->create_user(); $this->setAdminUser(); $record = new \stdClass(); $record->itemid = 4; $record->newgradeitem = 25; $record->finalgrade = 62.00; $record->feedback = 'Some test feedback'; $testobject = new \phpunit_gradeimport_csv_load_data(); $testobject->test_insert_grade_record($record, $user->id); $gradeimportvalues = $DB->get_records('grade_import_values'); // Get the insert id. $key = key($gradeimportvalues); $testarray = array(); $testarray[$key] = new \stdClass(); $testarray[$key]->id = $key; $testarray[$key]->itemid = $record->itemid; $testarray[$key]->newgradeitem = $record->newgradeitem; $testarray[$key]->userid = $user->id; $testarray[$key]->finalgrade = $record->finalgrade; $testarray[$key]->feedback = $record->feedback; $testarray[$key]->importcode = $testobject->get_importcode(); $testarray[$key]->importer = $USER->id; $testarray[$key]->importonlyfeedback = 0; // Check that the record was inserted into the database. $this->assertEquals($gradeimportvalues, $testarray); } /** * Test preparing a new grade item for import into the gradebook. */ public function test_import_new_grade_item() { global $DB; $this->setAdminUser(); $this->csv_load($this->oktext); $columns = $this->columns; // The assignment is item 6. $key = 6; $testobject = new \phpunit_gradeimport_csv_load_data(); // Key for this assessment. $this->csvimport->init(); $testarray = array(); while ($line = $this->csvimport->next()) { $testarray[] = $testobject->test_import_new_grade_item($columns, $key, $line[$key]); } // Query the database and check how many results were inserted. $newgradeimportitems = $DB->get_records('grade_import_newitem'); $this->assertEquals(count($testarray), count($newgradeimportitems)); } /** * Data provider for \gradeimport_csv_load_data_testcase::test_check_user_exists(). * * @return array */ public function check_user_exists_provider() { return [ 'Fetch by email' => [ 'email', 's1@example.com', true ], 'Fetch by email, different case' => [ 'email', 'S1@EXAMPLE.COM', true ], 'Fetch data using a non-existent email' => [ 'email', 's2@example.com', false ], 'Multiple accounts with the same email' => [ 'email', 's1@example.com', false, 1 ], 'Fetch data using a valid user ID' => [ 'id', true, true ], 'Fetch data using a non-existent user ID' => [ 'id', false, false ], 'Fetch data using a valid username' => [ 'username', 's1', true ], 'Fetch data using a valid username, different case' => [ 'username', 'S1', true ], 'Fetch data using an invalid username' => [ 'username', 's2', false ], 'Fetch data using a valid ID Number' => [ 'idnumber', 's1', true ], 'Fetch data using an invalid ID Number' => [ 'idnumber', 's2', false ], ]; } /** * Check that the user matches a user in the system. * * @dataProvider check_user_exists_provider * @param string $field The field to use for the query. * @param string|boolean $value The field value. When fetching by ID, set true to fetch valid user ID, false otherwise. * @param boolean $successexpected Whether we expect for a user to be found or not. * @param int $allowaccountssameemail Value for $CFG->allowaccountssameemail */ public function test_check_user_exists($field, $value, $successexpected, $allowaccountssameemail = 0) { $this->resetAfterTest(); $generator = $this->getDataGenerator(); // Need to add one of the users into the system. $user = $generator->create_user([ 'firstname' => 'Anne', 'lastname' => 'Able', 'email' => 's1@example.com', 'idnumber' => 's1', 'username' => 's1', ]); if ($allowaccountssameemail) { // Create another user with the same email address. $generator->create_user(['email' => 's1@example.com']); } // Since the data provider can't know what user ID to use, do a special handling for ID field tests. if ($field === 'id') { if ($value) { // Test for fetching data using a valid user ID. Use the generated user's ID. $value = $user->id; } else { // Test for fetching data using a non-existent user ID. $value = $user->id + 1; } } $userfields = [ 'field' => $field, 'label' => 'Field label: ' . $field ]; $testobject = new \phpunit_gradeimport_csv_load_data(); // Check whether the user exists. If so, then the user id is returned. Otherwise, it returns null. $userid = $testobject->test_check_user_exists($value, $userfields); if ($successexpected) { // Check that the user id returned matches with the user that we created. $this->assertEquals($user->id, $userid); // Check that there are no errors. $this->assertEmpty($testobject->get_gradebookerrors()); } else { // Check that the userid is null. $this->assertNull($userid); // Check that expected error message and actual message match. $gradebookerrors = $testobject->get_gradebookerrors(); $mappingobject = (object)[ 'field' => $userfields['label'], 'value' => $value, ]; if ($allowaccountssameemail) { $expectederrormessage = get_string('usermappingerrormultipleusersfound', 'grades', $mappingobject); } else { $expectederrormessage = get_string('usermappingerror', 'grades', $mappingobject); } $this->assertEquals($expectederrormessage, $gradebookerrors[0]); } } /** * Test preparing feedback for inserting / updating into the gradebook. */ public function test_create_feedback() { $testarray = $this->csv_load($this->oktext); $testobject = new \phpunit_gradeimport_csv_load_data(); // Try to insert some feedback for an assessment. $feedback = $testobject->test_create_feedback($this->courseid, 1, $testarray[0][7]); // Expected result. $expectedfeedback = array('itemid' => 1, 'feedback' => $testarray[0][7]); $this->assertEquals((array)$feedback, $expectedfeedback); } /** * Test preparing grade_items for upgrading into the gradebook. */ public function test_update_grade_item() { $testarray = $this->csv_load($this->oktext); $testobject = new \phpunit_gradeimport_csv_load_data(); // We're not using scales so no to this option. $verbosescales = 0; // Map and key are to retrieve the grade_item that we are updating. $map = array(1); $key = 0; // We return the new grade array for saving. $newgrades = $testobject->test_update_grade_item($this->courseid, $map, $key, $verbosescales, $testarray[0][6]); $expectedresult = array(); $expectedresult[0] = new \stdClass(); $expectedresult[0]->itemid = 1; $expectedresult[0]->finalgrade = $testarray[0][6]; $this->assertEquals($newgrades, $expectedresult); // Try sending a bad grade value (A letter instead of a float / int). $newgrades = $testobject->test_update_grade_item($this->courseid, $map, $key, $verbosescales, 'A'); // The $newgrades variable should be null. $this->assertNull($newgrades); $expectederrormessage = get_string('badgrade', 'grades'); // Check that the error message is what we expect. $gradebookerrors = $testobject->get_gradebookerrors(); $this->assertEquals($expectederrormessage, $gradebookerrors[0]); } /** * Test importing data and mapping it with items in the course. */ public function test_map_user_data_with_value() { // Need to add one of the users into the system. $user = new \stdClass(); $user->firstname = 'Anne'; $user->lastname = 'Able'; $user->email = 'student7@example.com'; $userdetail = $this->getDataGenerator()->create_user($user); $testarray = $this->csv_load($this->oktext); $testobject = new \phpunit_gradeimport_csv_load_data(); // We're not using scales so no to this option. $verbosescales = 0; // Map and key are to retrieve the grade_item that we are updating. $map = array(1); $key = 0; // Test new user mapping. This should return the user id if there were no problems. $userid = $testobject->test_map_user_data_with_value('useremail', $testarray[0][5], $this->columns, $map, $key, $this->courseid, $map[$key], $verbosescales); $this->assertEquals($userid, $userdetail->id); $newgrades = $testobject->test_map_user_data_with_value('new', $testarray[0][6], $this->columns, $map, $key, $this->courseid, $map[$key], $verbosescales); // Check that the final grade is the same as the one inserted. $this->assertEquals($testarray[0][6], $newgrades[0]->finalgrade); $newgrades = $testobject->test_map_user_data_with_value('new', $testarray[0][8], $this->columns, $map, $key, $this->courseid, $map[$key], $verbosescales); // Check that the final grade is the same as the one inserted. // The testobject should now contain 2 new grade items. $this->assertEquals(2, count($newgrades)); // Because this grade item is empty, the value for final grade should be null. $this->assertNull($newgrades[1]->finalgrade); $feedback = $testobject->test_map_user_data_with_value('feedback', $testarray[0][7], $this->columns, $map, $key, $this->courseid, $map[$key], $verbosescales); // Expected result. $resultarray = array(); $resultarray[0] = new \stdClass(); $resultarray[0]->itemid = 1; $resultarray[0]->feedback = $testarray[0][7]; $this->assertEquals($feedback, $resultarray); // Default behaviour (update a grade item). $newgrades = $testobject->test_map_user_data_with_value('default', $testarray[0][6], $this->columns, $map, $key, $this->courseid, $map[$key], $verbosescales); $this->assertEquals($testarray[0][6], $newgrades[0]->finalgrade); } /** * Test importing data into the gradebook. */ public function test_prepare_import_grade_data() { global $DB; // Need to add one of the users into the system. $user = new \stdClass(); $user->firstname = 'Anne'; $user->lastname = 'Able'; $user->email = 'student7@example.com'; // Insert user 1. $this->getDataGenerator()->create_user($user); $user = new \stdClass(); $user->firstname = 'Bobby'; $user->lastname = 'Bunce'; $user->email = 'student5@example.com'; // Insert user 2. $this->getDataGenerator()->create_user($user); $this->csv_load($this->oktext); $importcode = 007; $verbosescales = 0; // Form data object. $formdata = new \stdClass(); $formdata->mapfrom = 5; $formdata->mapto = 'useremail'; $formdata->mapping_0 = 0; $formdata->mapping_1 = 0; $formdata->mapping_2 = 0; $formdata->mapping_3 = 0; $formdata->mapping_4 = 0; $formdata->mapping_5 = 0; $formdata->mapping_6 = 'new'; $formdata->mapping_7 = 'feedback_2'; $formdata->mapping_8 = 0; $formdata->mapping_9 = 0; $formdata->map = 1; $formdata->id = 2; $formdata->iid = $this->iid; $formdata->importcode = $importcode; $formdata->forceimport = false; // Blam go time. $testobject = new \phpunit_gradeimport_csv_load_data(); $dataloaded = $testobject->prepare_import_grade_data($this->columns, $formdata, $this->csvimport, $this->courseid, '', '', $verbosescales); // If everything inserted properly then this should be true. $this->assertTrue($dataloaded); } /* * Test importing csv data into the gradebook using "Last downloaded from this course" column and force import option. */ public function test_force_import_option () { // Need to add users into the system. $user = new \stdClass(); $user->firstname = 'Anne'; $user->lastname = 'Able'; $user->email = 'student7@example.com'; $user->id_number = 1; $user1 = $this->getDataGenerator()->create_user($user); $user = new \stdClass(); $user->firstname = 'Bobby'; $user->lastname = 'Bunce'; $user->email = 'student5@example.com'; $user->id_number = 2; $user2 = $this->getDataGenerator()->create_user($user); // Create a new grade item. $params = array( 'itemtype' => 'manual', 'itemname' => 'Grade item 1', 'gradetype' => GRADE_TYPE_VALUE, 'courseid' => $this->courseid ); $gradeitem = new \grade_item($params, false); $gradeitemid = $gradeitem->insert(); $importcode = 001; $verbosescales = 0; // Form data object. $formdata = new \stdClass(); $formdata->mapfrom = 5; $formdata->mapto = 'useremail'; $formdata->mapping_0 = 0; $formdata->mapping_1 = 0; $formdata->mapping_2 = 0; $formdata->mapping_3 = 0; $formdata->mapping_4 = 0; $formdata->mapping_5 = 0; $formdata->mapping_6 = $gradeitemid; $formdata->mapping_7 = 'feedback_2'; $formdata->mapping_8 = 0; $formdata->mapping_9 = 0; $formdata->map = 1; $formdata->id = 2; $formdata->iid = $this->iid; $formdata->importcode = $importcode; $formdata->forceimport = false; // Add last download from this course column to csv content. $exportdate = time(); $newcsvdata = str_replace('{exportdate}', $exportdate, $this->csvtext); $this->csv_load($newcsvdata); $testobject = new \phpunit_gradeimport_csv_load_data(); $dataloaded = $testobject->prepare_import_grade_data($this->columns, $formdata, $this->csvimport, $this->courseid, '', '', $verbosescales); $this->assertTrue($dataloaded); // We must update the last modified date. grade_import_commit($this->courseid, $importcode, false, false); // Test using force import disabled and a date in the past. $pastdate = strtotime('-1 day', time()); $newcsvdata = str_replace('{exportdate}', $pastdate, $this->csvtext); $this->csv_load($newcsvdata); $testobject = new \phpunit_gradeimport_csv_load_data(); $dataloaded = $testobject->prepare_import_grade_data($this->columns, $formdata, $this->csvimport, $this->courseid, '', '', $verbosescales); $this->assertFalse($dataloaded); $errors = $testobject->get_gradebookerrors(); $this->assertEquals($errors[0], get_string('gradealreadyupdated', 'grades', fullname($user1))); // Test using force import enabled and a date in the past. $formdata->forceimport = true; $testobject = new \phpunit_gradeimport_csv_load_data(); $dataloaded = $testobject->prepare_import_grade_data($this->columns, $formdata, $this->csvimport, $this->courseid, '', '', $verbosescales); $this->assertTrue($dataloaded); // Test importing using an old exported file (2 years ago). $formdata->forceimport = false; $twoyearsago = strtotime('-2 year', time()); $newcsvdata = str_replace('{exportdate}', $twoyearsago, $this->csvtext); $this->csv_load($newcsvdata); $testobject = new \phpunit_gradeimport_csv_load_data(); $dataloaded = $testobject->prepare_import_grade_data($this->columns, $formdata, $this->csvimport, $this->courseid, '', '', $verbosescales); $this->assertFalse($dataloaded); $errors = $testobject->get_gradebookerrors(); $this->assertEquals($errors[0], get_string('invalidgradeexporteddate', 'grades')); // Test importing using invalid exported date. $baddate = '0123A56B89'; $newcsvdata = str_replace('{exportdate}', $baddate, $this->csvtext); $this->csv_load($newcsvdata); $formdata->mapping_6 = $gradeitemid; $testobject = new \phpunit_gradeimport_csv_load_data(); $dataloaded = $testobject->prepare_import_grade_data($this->columns, $formdata, $this->csvimport, $this->courseid, '', '', $verbosescales); $this->assertFalse($dataloaded); $errors = $testobject->get_gradebookerrors(); $this->assertEquals($errors[0], get_string('invalidgradeexporteddate', 'grades')); // Test importing using date in the future. $oneyearahead = strtotime('+1 year', time()); $oldcsv = str_replace('{exportdate}', $oneyearahead, $this->csvtext); $this->csv_load($oldcsv); $formdata->mapping_6 = $gradeitemid; $testobject = new \phpunit_gradeimport_csv_load_data(); $dataloaded = $testobject->prepare_import_grade_data($this->columns, $formdata, $this->csvimport, $this->courseid, '', '', $verbosescales); $this->assertFalse($dataloaded); $errors = $testobject->get_gradebookerrors(); $this->assertEquals($errors[0], get_string('invalidgradeexporteddate', 'grades')); } } csv/index.php 0000644 00000012117 15151264176 0007171 0 ustar 00 <?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/>. require_once("../../../config.php"); require_once($CFG->libdir.'/gradelib.php'); require_once($CFG->dirroot.'/grade/lib.php'); require_once($CFG->dirroot. '/grade/import/grade_import_form.php'); require_once($CFG->dirroot.'/grade/import/lib.php'); require_once($CFG->libdir . '/csvlib.class.php'); $id = required_param('id', PARAM_INT); // Course id. $separator = optional_param('separator', '', PARAM_ALPHA); $verbosescales = optional_param('verbosescales', 1, PARAM_BOOL); $iid = optional_param('iid', null, PARAM_INT); $importcode = optional_param('importcode', '', PARAM_FILE); $forceimport = optional_param('forceimport', false, PARAM_BOOL); $url = new moodle_url('/grade/import/csv/index.php', array('id'=>$id)); if ($separator !== '') { $url->param('separator', $separator); } if ($verbosescales !== 1) { $url->param('verbosescales', $verbosescales); } $PAGE->set_url($url); if (!$course = $DB->get_record('course', array('id'=>$id))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($id); require_capability('moodle/grade:import', $context); require_capability('gradeimport/csv:view', $context); $separatemode = (groups_get_course_groupmode($COURSE) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)); $currentgroup = groups_get_course_group($course); $actionbar = new \core_grades\output\import_action_bar($context, null, 'csv'); print_grade_page_head($course->id, 'import', 'csv', get_string('importcsv', 'grades'), false, false, true, 'importcsv', 'grades', null, $actionbar); $renderer = $PAGE->get_renderer('gradeimport_csv'); // Get the grade items to be matched with the import mapping columns. $gradeitems = gradeimport_csv_load_data::fetch_grade_items($course->id); // If the csv file hasn't been imported yet then look for a form submission or // show the initial submission form. if (!$iid) { // Set up the import form. $mform = new grade_import_form(null, array('includeseparator' => true, 'verbosescales' => $verbosescales, 'acceptedtypes' => array('.csv', '.txt'))); // If the import form has been submitted. if ($formdata = $mform->get_data()) { $text = $mform->get_file_content('userfile'); $csvimport = new gradeimport_csv_load_data(); $csvimport->load_csv_content($text, $formdata->encoding, $separator, $formdata->previewrows); $csvimporterror = $csvimport->get_error(); if (!empty($csvimporterror)) { echo $renderer->errors(array($csvimport->get_error())); echo $OUTPUT->footer(); die(); } $iid = $csvimport->get_iid(); echo $renderer->import_preview_page($csvimport->get_headers(), $csvimport->get_previewdata()); } else { // Display the standard upload file form. echo $renderer->standard_upload_file_form($course, $mform); echo $OUTPUT->footer(); die(); } } // Data has already been submitted so we can use the $iid to retrieve it. $csvimport = new csv_import_reader($iid, 'grade'); $header = $csvimport->get_columns(); // Get a new import code for updating to the grade book. if (empty($importcode)) { $importcode = get_new_importcode(); } $mappingformdata = array( 'gradeitems' => $gradeitems, 'header' => $header, 'iid' => $iid, 'id' => $id, 'importcode' => $importcode, 'forceimport' => $forceimport, 'verbosescales' => $verbosescales ); // we create a form to handle mapping data from the file to the database. $mform2 = new grade_import_mapping_form(null, $mappingformdata); // Here, if we have data, we process the fields and enter the information into the database. if ($formdata = $mform2->get_data()) { $gradeimport = new gradeimport_csv_load_data(); $status = $gradeimport->prepare_import_grade_data($header, $formdata, $csvimport, $course->id, $separatemode, $currentgroup, $verbosescales); // At this stage if things are all ok, we commit the changes from temp table. if ($status) { grade_import_commit($course->id, $importcode); } else { $errors = $gradeimport->get_gradebookerrors(); $errors[] = get_string('importfailed', 'grades'); echo $renderer->errors($errors); } echo $OUTPUT->footer(); } else { // If data hasn't been submitted then display the data mapping form. $mform2->display(); echo $OUTPUT->footer(); } csv/version.php 0000644 00000002256 15151264176 0007552 0 ustar 00 <?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/>. /** * Version details * * @package gradeimport * @subpackage csv * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $plugin->version = 2022112800; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2022111800; // Requires this Moodle version. $plugin->component = 'gradeimport_csv'; // Full name of the plugin (used for diagnostics) csv/classes/output/renderer.php 0000644 00000005507 15151264176 0012672 0 ustar 00 <?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/>. /** * Renderers for the import of CSV files into the gradebook. * * @package gradeimport_csv * @copyright 2014 Adrian Greeve <adrian@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * Renderers for the import of CSV files into the gradebook. * * @package gradeimport_csv * @copyright 2014 Adrian Greeve <adrian@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class gradeimport_csv_renderer extends plugin_renderer_base { /** * A renderer for the standard upload file form. * * @param object $course The course we are doing all of this action in. * @param object $mform The mform for uploading CSV files. * @return string html to be displayed. */ public function standard_upload_file_form($course, $mform) { $output = groups_print_course_menu($course, 'index.php?id=' . $course->id, true); $output .= html_writer::start_tag('div', array('class' => 'clearer')); $output .= html_writer::end_tag('div'); // Form. ob_start(); $mform->display(); $output .= ob_get_contents(); ob_end_clean(); return $output; } /** * A renderer for the CSV file preview. * * @param array $header Column headers from the CSV file. * @param array $data The rest of the data from the CSV file. * @return string html to be displayed. */ public function import_preview_page($header, $data) { $html = $this->output->heading(get_string('importpreview', 'grades')); $table = new html_table(); $table->head = $header; $table->data = $data; $html .= html_writer::table($table); return $html; } /** * A renderer for errors generated trying to import the CSV file. * * @param array $errors Display import errors. * @return string errors as html to be displayed. */ public function errors($errors) { $html = ''; foreach ($errors as $error) { $html .= $this->output->notification($error); } return $html; } } csv/classes/privacy/provider.php 0000644 00000002767 15151264176 0013040 0 ustar 00 <?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/>. /** * Privacy Subsystem implementation for gradeimport_csv. * * @package gradeimport_csv * @copyright 2018 Sara Arjona <sara@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace gradeimport_csv\privacy; defined('MOODLE_INTERNAL') || die(); /** * Privacy Subsystem for gradeimport_csv implementing null_provider. * * @copyright 2018 Sara Arjona <sara@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class provider implements \core_privacy\local\metadata\null_provider { /** * Get the language string identifier with the component's language * file to explain why this plugin stores no data. * * @return string */ public static function get_reason() : string { return 'privacy:metadata'; } } csv/classes/load_data.php 0000644 00000063372 15151264176 0011440 0 ustar 00 <?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/>. /** * A class for loading and preparing grade data from import. * * @package gradeimport_csv * @copyright 2014 Adrian Greeve <adrian@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * A class for loading and preparing grade data from import. * * @package gradeimport_csv * @copyright 2014 Adrian Greeve <adrian@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class gradeimport_csv_load_data { /** @var string $error csv import error. */ protected $error; /** @var int $iid Unique identifier for these csv records. */ protected $iid; /** @var array $headers Column names for the data. */ protected $headers; /** @var array $previewdata A subsection of the csv imported data. */ protected $previewdata; // The map_user_data_with_value variables. /** @var array $newgrades Grades to be inserted into the gradebook. */ protected $newgrades; /** @var array $newfeedbacks Feedback to be inserted into the gradebook. */ protected $newfeedbacks; /** @var int $studentid Student ID*/ protected $studentid; // The prepare_import_grade_data() variables. /** @var bool $status The current status of the import. True = okay, False = errors. */ protected $status; /** @var int $importcode The code for this batch insert. */ protected $importcode; /** @var array $gradebookerrors An array of errors from trying to import into the gradebook. */ protected $gradebookerrors; /** @var array $newgradeitems An array of new grade items to be inserted into the gradebook. */ protected $newgradeitems; /** * Load CSV content for previewing. * * @param string $text The grade data being imported. * @param string $encoding The type of encoding the file uses. * @param string $separator The separator being used to define each field. * @param int $previewrows How many rows are being previewed. */ public function load_csv_content($text, $encoding, $separator, $previewrows) { $this->raise_limits(); $this->iid = csv_import_reader::get_new_iid('grade'); $csvimport = new csv_import_reader($this->iid, 'grade'); $csvimport->load_csv_content($text, $encoding, $separator); $this->error = $csvimport->get_error(); // If there are no import errors then proceed. if (empty($this->error)) { // Get header (field names). $this->headers = $csvimport->get_columns(); $this->trim_headers(); $csvimport->init(); $this->previewdata = array(); for ($numlines = 0; $numlines <= $previewrows; $numlines++) { $lines = $csvimport->next(); if ($lines) { $this->previewdata[] = $lines; } } } } /** * Gets all of the grade items in this course. * * @param int $courseid Course id; * @return array An array of grade items for the course. */ public static function fetch_grade_items($courseid) { $gradeitems = null; if ($allgradeitems = grade_item::fetch_all(array('courseid' => $courseid))) { foreach ($allgradeitems as $gradeitem) { // Skip course type and category type. if ($gradeitem->itemtype == 'course' || $gradeitem->itemtype == 'category') { continue; } $displaystring = null; if (!empty($gradeitem->itemmodule)) { $displaystring = get_string('modulename', $gradeitem->itemmodule).get_string('labelsep', 'langconfig') .$gradeitem->get_name(); } else { $displaystring = $gradeitem->get_name(); } $gradeitems[$gradeitem->id] = $displaystring; } } return $gradeitems; } /** * Cleans the column headers from the CSV file. */ protected function trim_headers() { foreach ($this->headers as $i => $h) { $h = trim($h); // Remove whitespace. $h = clean_param($h, PARAM_RAW); // Clean the header. $this->headers[$i] = $h; } } /** * Raises the php execution time and memory limits for importing the CSV file. */ protected function raise_limits() { // Large files are likely to take their time and memory. Let PHP know // that we'll take longer, and that the process should be recycled soon // to free up memory. core_php_time_limit::raise(); raise_memory_limit(MEMORY_EXTRA); } /** * Inserts a record into the grade_import_values table. This also adds common record information. * * @param object $record The grade record being inserted into the database. * @param int $studentid The student ID. * @return bool|int true or insert id on success. Null if the grade value is too high. */ protected function insert_grade_record($record, $studentid) { global $DB, $USER, $CFG; $record->importcode = $this->importcode; $record->userid = $studentid; $record->importer = $USER->id; // By default the maximum grade is 100. $gradepointmaximum = 100; // If the grade limit has been increased then use the gradepointmax setting. if ($CFG->unlimitedgrades) { $gradepointmaximum = $CFG->gradepointmax; } // If the record final grade is set then check that the grade value isn't too high. // Final grade will not be set if we are inserting feedback. if (!isset($record->finalgrade) || $record->finalgrade <= $gradepointmaximum) { return $DB->insert_record('grade_import_values', $record); } else { $this->cleanup_import(get_string('gradevaluetoobig', 'grades', $gradepointmaximum)); return null; } } /** * Insert the new grade into the grade item buffer table. * * @param array $header The column headers from the CSV file. * @param int $key Current row identifier. * @param string $value The value for this row (final grade). * @return stdClass new grade that is ready for commiting to the gradebook. */ protected function import_new_grade_item($header, $key, $value) { global $DB, $USER; // First check if header is already in temp database. if (empty($this->newgradeitems[$key])) { $newgradeitem = new stdClass(); $newgradeitem->itemname = $header[$key]; $newgradeitem->importcode = $this->importcode; $newgradeitem->importer = $USER->id; // Insert into new grade item buffer. $this->newgradeitems[$key] = $DB->insert_record('grade_import_newitem', $newgradeitem); } $newgrade = new stdClass(); $newgrade->newgradeitem = $this->newgradeitems[$key]; $trimmed = trim($value); if ($trimmed === '' or $trimmed == '-') { // Blank or dash grade means null, ie "no grade". $newgrade->finalgrade = null; } else { // We have an actual grade. $newgrade->finalgrade = $value; } $this->newgrades[] = $newgrade; return $newgrade; } /** * Check that the user is in the system. * * @param string $value The value, from the csv file, being mapped to identify the user. * @param array $userfields Contains the field and label being mapped from. * @return int Returns the user ID if it exists, otherwise null. */ protected function check_user_exists($value, $userfields) { global $DB; $user = null; $errorkey = false; // The user may use the incorrect field to match the user. This could result in an exception. try { $field = $userfields['field']; // Fields that can be queried in a case-insensitive manner. $caseinsensitivefields = [ 'email', 'username', ]; // Build query predicate. if (in_array($field, $caseinsensitivefields)) { // Case-insensitive. $select = $DB->sql_equal($field, ':' . $field, false); } else { // Exact-value. $select = "{$field} = :{$field}"; } // Validate if the user id value is numerical. if ($field === 'id' && !is_numeric($value)) { $errorkey = 'usermappingerror'; } // Make sure the record exists and that there's only one matching record found. $user = $DB->get_record_select('user', $select, array($userfields['field'] => $value), '*', MUST_EXIST); } catch (dml_missing_record_exception $missingex) { $errorkey = 'usermappingerror'; } catch (dml_multiple_records_exception $multiex) { $errorkey = 'usermappingerrormultipleusersfound'; } // Field may be fine, but no records were returned. if ($errorkey) { $usermappingerrorobj = new stdClass(); $usermappingerrorobj->field = $userfields['label']; $usermappingerrorobj->value = $value; $this->cleanup_import(get_string($errorkey, 'grades', $usermappingerrorobj)); unset($usermappingerrorobj); return null; } return $user->id; } /** * Check to see if the feedback matches a grade item. * * @param int $courseid The course ID. * @param int $itemid The ID of the grade item that the feedback relates to. * @param string $value The actual feedback being imported. * @return object Creates a feedback object with the item ID and the feedback value. */ protected function create_feedback($courseid, $itemid, $value) { // Case of an id, only maps id of a grade_item. // This was idnumber. if (!new grade_item(array('id' => $itemid, 'courseid' => $courseid))) { // Supplied bad mapping, should not be possible since user // had to pick mapping. $this->cleanup_import(get_string('importfailed', 'grades')); return null; } // The itemid is the id of the grade item. $feedback = new stdClass(); $feedback->itemid = $itemid; $feedback->feedback = $value; return $feedback; } /** * This updates existing grade items. * * @param int $courseid The course ID. * @param array $map Mapping information provided by the user. * @param int $key The line that we are currently working on. * @param bool $verbosescales Form setting for grading with scales. * @param string $value The grade value. * @return array grades to be updated. */ protected function update_grade_item($courseid, $map, $key, $verbosescales, $value) { // Case of an id, only maps id of a grade_item. // This was idnumber. if (!$gradeitem = new grade_item(array('id' => $map[$key], 'courseid' => $courseid))) { // Supplied bad mapping, should not be possible since user // had to pick mapping. $this->cleanup_import(get_string('importfailed', 'grades')); return null; } // Check if grade item is locked if so, abort. if ($gradeitem->is_locked()) { $this->cleanup_import(get_string('gradeitemlocked', 'grades')); return null; } $newgrade = new stdClass(); $newgrade->itemid = $gradeitem->id; if ($gradeitem->gradetype == GRADE_TYPE_SCALE and $verbosescales) { if ($value === '' or $value == '-') { $value = null; // No grade. } else { $scale = $gradeitem->load_scale(); $scales = explode(',', $scale->scale); $scales = array_map('trim', $scales); // Hack - trim whitespace around scale options. array_unshift($scales, '-'); // Scales start at key 1. $key = array_search($value, $scales); if ($key === false) { $this->cleanup_import(get_string('badgrade', 'grades')); return null; } $value = $key; } $newgrade->finalgrade = $value; } else { if ($value === '' or $value == '-') { $value = null; // No grade. } else { // If the value has a local decimal or can correctly be unformatted, do it. $validvalue = unformat_float($value, true); if ($validvalue !== false) { $value = $validvalue; } else { // Non numeric grade value supplied, possibly mapped wrong column. $this->cleanup_import(get_string('badgrade', 'grades')); return null; } } $newgrade->finalgrade = $value; } $this->newgrades[] = $newgrade; return $this->newgrades; } /** * Clean up failed CSV grade import. Clears the temp table for inserting grades. * * @param string $notification The error message to display from the unsuccessful grade import. */ protected function cleanup_import($notification) { $this->status = false; import_cleanup($this->importcode); $this->gradebookerrors[] = $notification; } /** * Check user mapping. * * @param string $mappingidentifier The user field that we are matching together. * @param string $value The value we are checking / importing. * @param array $header The column headers of the csv file. * @param array $map Mapping information provided by the user. * @param int $key Current row identifier. * @param int $courseid The course ID. * @param int $feedbackgradeid The ID of the grade item that the feedback relates to. * @param bool $verbosescales Form setting for grading with scales. */ protected function map_user_data_with_value($mappingidentifier, $value, $header, $map, $key, $courseid, $feedbackgradeid, $verbosescales) { // Fields that the user can be mapped from. $userfields = array( 'userid' => array( 'field' => 'id', 'label' => 'id', ), 'useridnumber' => array( 'field' => 'idnumber', 'label' => 'idnumber', ), 'useremail' => array( 'field' => 'email', 'label' => 'email address', ), 'username' => array( 'field' => 'username', 'label' => 'username', ), ); switch ($mappingidentifier) { case 'userid': case 'useridnumber': case 'useremail': case 'username': $this->studentid = $this->check_user_exists($value, $userfields[$mappingidentifier]); break; case 'new': $this->import_new_grade_item($header, $key, $value); break; case 'feedback': if ($feedbackgradeid) { $feedback = $this->create_feedback($courseid, $feedbackgradeid, $value); if (isset($feedback)) { $this->newfeedbacks[] = $feedback; } } break; default: // Existing grade items. if (!empty($map[$key])) { $this->newgrades = $this->update_grade_item($courseid, $map, $key, $verbosescales, $value, $mappingidentifier); } // Otherwise, we ignore this column altogether because user has chosen // to ignore them (e.g. institution, address etc). break; } } /** * Checks and prepares grade data for inserting into the gradebook. * * @param array $header Column headers of the CSV file. * @param object $formdata Mapping information from the preview page. * @param object $csvimport csv import reader object for iterating over the imported CSV file. * @param int $courseid The course ID. * @param bool $separatemode If we have groups are they separate? * @param mixed $currentgroup current group information. * @param bool $verbosescales Form setting for grading with scales. * @return bool True if the status for importing is okay, false if there are errors. */ public function prepare_import_grade_data($header, $formdata, $csvimport, $courseid, $separatemode, $currentgroup, $verbosescales) { global $DB, $USER; // The import code is used for inserting data into the grade tables. $this->importcode = $formdata->importcode; $this->status = true; $this->headers = $header; $this->studentid = null; $this->gradebookerrors = null; $forceimport = $formdata->forceimport; // Temporary array to keep track of what new headers are processed. $this->newgradeitems = array(); $this->trim_headers(); $timeexportkey = null; $map = array(); // Loops mapping_0, mapping_1 .. mapping_n and construct $map array. foreach ($header as $i => $head) { if (isset($formdata->{'mapping_'.$i})) { $map[$i] = $formdata->{'mapping_'.$i}; } if ($head == get_string('timeexported', 'gradeexport_txt')) { $timeexportkey = $i; } } // If mapping information is supplied. $map[clean_param($formdata->mapfrom, PARAM_RAW)] = clean_param($formdata->mapto, PARAM_RAW); // Check for mapto collisions. $maperrors = array(); foreach ($map as $i => $j) { if ($j == 0) { // You can have multiple ignores. continue; } else { if (!isset($maperrors[$j])) { $maperrors[$j] = true; } else { // Collision. throw new \moodle_exception('cannotmapfield', '', '', $j); } } } $this->raise_limits(); $csvimport->init(); while ($line = $csvimport->next()) { if (count($line) <= 1) { // There is no data on this line, move on. continue; } // Array to hold all grades to be inserted. $this->newgrades = array(); // Array to hold all feedback. $this->newfeedbacks = array(); // Each line is a student record. foreach ($line as $key => $value) { $value = clean_param($value, PARAM_RAW); $value = trim($value); /* * the options are * 1) userid, useridnumber, usermail, username - used to identify user row * 2) new - new grade item * 3) id - id of the old grade item to map onto * 3) feedback_id - feedback for grade item id */ // Explode the mapping for feedback into a label 'feedback' and the identifying number. $mappingbase = explode("_", $map[$key]); $mappingidentifier = $mappingbase[0]; // Set the feedback identifier if it exists. if (isset($mappingbase[1])) { $feedbackgradeid = (int)$mappingbase[1]; } else { $feedbackgradeid = ''; } $this->map_user_data_with_value($mappingidentifier, $value, $header, $map, $key, $courseid, $feedbackgradeid, $verbosescales); if ($this->status === false) { return $this->status; } } // No user mapping supplied at all, or user mapping failed. if (empty($this->studentid) || !is_numeric($this->studentid)) { // User not found, abort whole import. $this->cleanup_import(get_string('usermappingerrorusernotfound', 'grades')); break; } if ($separatemode and !groups_is_member($currentgroup, $this->studentid)) { // Not allowed to import into this group, abort. $this->cleanup_import(get_string('usermappingerrorcurrentgroup', 'grades')); break; } // Insert results of this students into buffer. if ($this->status and !empty($this->newgrades)) { foreach ($this->newgrades as $newgrade) { // Check if grade_grade is locked and if so, abort. if (!empty($newgrade->itemid) and $gradegrade = new grade_grade(array('itemid' => $newgrade->itemid, 'userid' => $this->studentid))) { if ($gradegrade->is_locked()) { // Individual grade locked. $this->cleanup_import(get_string('gradelocked', 'grades')); return $this->status; } // Check if the force import option is disabled and the last exported date column is present. if (!$forceimport && !empty($timeexportkey)) { $exportedtime = $line[$timeexportkey]; if (clean_param($exportedtime, PARAM_INT) != $exportedtime || $exportedtime > time() || $exportedtime < strtotime("-1 year", time())) { // The date is invalid, or in the future, or more than a year old. $this->cleanup_import(get_string('invalidgradeexporteddate', 'grades')); return $this->status; } $timemodified = $gradegrade->get_dategraded(); if (!empty($timemodified) && ($exportedtime < $timemodified)) { // The item was graded after we exported it, we return here not to override it. $user = core_user::get_user($this->studentid); $this->cleanup_import(get_string('gradealreadyupdated', 'grades', fullname($user))); return $this->status; } } } $insertid = self::insert_grade_record($newgrade, $this->studentid); // Check to see if the insert was successful. if (empty($insertid)) { return null; } } } // Updating/inserting all comments here. if ($this->status and !empty($this->newfeedbacks)) { foreach ($this->newfeedbacks as $newfeedback) { $sql = "SELECT * FROM {grade_import_values} WHERE importcode=? AND userid=? AND itemid=? AND importer=?"; if ($feedback = $DB->get_record_sql($sql, array($this->importcode, $this->studentid, $newfeedback->itemid, $USER->id))) { $newfeedback->id = $feedback->id; $DB->update_record('grade_import_values', $newfeedback); } else { // The grade item for this is not updated. $newfeedback->importonlyfeedback = true; $insertid = self::insert_grade_record($newfeedback, $this->studentid); // Check to see if the insert was successful. if (empty($insertid)) { return null; } } } } } return $this->status; } /** * Returns the headers parameter for this class. * * @return array returns headers parameter for this class. */ public function get_headers() { return $this->headers; } /** * Returns the error parameter for this class. * * @return string returns error parameter for this class. */ public function get_error() { return $this->error; } /** * Returns the iid parameter for this class. * * @return int returns iid parameter for this class. */ public function get_iid() { return $this->iid; } /** * Returns the preview_data parameter for this class. * * @return array returns previewdata parameter for this class. */ public function get_previewdata() { return $this->previewdata; } /** * Returns the gradebookerrors parameter for this class. * * @return array returns gradebookerrors parameter for this class. */ public function get_gradebookerrors() { return $this->gradebookerrors; } } csv/lang/en/gradeimport_csv.php 0000644 00000002171 15151264176 0012574 0 ustar 00 <?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/>. /** * Strings for component 'gradeimport_csv', language 'en', branch 'MOODLE_20_STABLE' * * @package gradeimport_csv * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ $string['csv:view'] = 'Import grades from CSV'; $string['pluginname'] = 'CSV file'; $string['privacy:metadata'] = 'The import grades from CSV plugin does not store any personal data.'; index.php 0000644 00000004132 15151264176 0006374 0 ustar 00 <?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/>. /** * Redirects the user to a default grades import plugin page. * * @package core_grades * @copyright 2021 Mihail Geshoski <mihail@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once(__DIR__ . '/../../config.php'); // Course ID. $courseid = required_param('id', PARAM_INT); $PAGE->set_url(new moodle_url('/grade/import/index.php', ['id' => $courseid])); // Basic access checks. if (!$course = $DB->get_record('course', ['id' => $courseid])) { throw new moodle_exception('invalidcourseid', 'error'); } require_login($course); $context = context_course::instance($courseid); require_capability('moodle/grade:import', $context); $importplugins = core_component::get_plugin_list('gradeimport'); if (!empty($importplugins)) { $importplugin = array_key_first($importplugins); $url = new moodle_url("/grade/import/{$importplugin}/index.php", ['id' => $courseid]); redirect($url); } // Otherwise, output the page with a notification stating that there are no available grade import options. $PAGE->set_title(get_string('import', 'grades')); $PAGE->set_pagelayout('incourse'); $PAGE->set_heading($course->fullname); $PAGE->set_pagetype('course-view-' . $course->format); echo $OUTPUT->header(); echo $OUTPUT->heading(get_string('import', 'grades')); echo html_writer::div($OUTPUT->notification(get_string('nogradeimport', 'grades'), 'error'), 'mt-3'); echo $OUTPUT->footer(); xml/db/access.php 0000644 00000002537 15151264176 0007722 0 ustar 00 <?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/>. /** * Capabilities gradeimport plugin. * * @package gradeimport_xml * @copyright 2007 Martin Dougiamas * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $capabilities = array( 'gradeimport/xml:view' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, 'archetypes' => array( 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW ) ), 'gradeimport/xml:publish' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, 'archetypes' => array( 'manager' => CAP_ALLOW ) ) ); xml/import.php 0000644 00000005177 15151264176 0007411 0 ustar 00 <?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/>. require_once '../../../config.php'; require_once 'lib.php'; require_once $CFG->libdir.'/filelib.php'; $gradesurl = required_param('url', PARAM_URL); // only real urls here $id = required_param('id', PARAM_INT); // course id $feedback = optional_param('feedback', 0, PARAM_BOOL); $url = new moodle_url('/grade/import/xml/import.php', array('id' => $id,'url' => $gradesurl)); if ($feedback !== 0) { $url->param('feedback', $feedback); } $PAGE->set_url($url); if (!$course = $DB->get_record('course', array('id'=>$id))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($id); require_capability('moodle/grade:import', $context); require_capability('gradeimport/xml:view', $context); // Large files are likely to take their time and memory. Let PHP know // that we'll take longer, and that the process should be recycled soon // to free up memory. core_php_time_limit::raise(); raise_memory_limit(MEMORY_EXTRA); $text = download_file_content($gradesurl); if ($text === false) { throw new \moodle_exception('cannotreadfile', 'error', $CFG->wwwroot . '/grade/import/xml/index.php?id=' . $id, $gradesurl); } $error = ''; $importcode = import_xml_grades($text, $course, $error); if ($importcode !== false) { /// commit the code if we are up this far if (defined('USER_KEY_LOGIN')) { if (grade_import_commit($id, $importcode, $feedback, false)) { echo 'ok'; die; } else { throw new \moodle_exception('cannotimportgrade'); // TODO: localize. } } else { print_grade_page_head($course->id, 'import', 'xml', get_string('importxml', 'grades')); grade_import_commit($id, $importcode, $feedback, true); echo $OUTPUT->footer(); die; } } else { throw new \moodle_exception('errorduringimport', 'gradeimport_xml', $CFG->wwwroot . '/grade/import/xml/index.php?id=' . $id, $error); } xml/grade_import_form.php 0000644 00000011667 15151264176 0011577 0 ustar 00 <?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/>. if (!defined('MOODLE_INTERNAL')) { die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page } require_once $CFG->libdir.'/formslib.php'; class grade_import_form extends moodleform { function definition () { global $COURSE, $USER, $CFG, $DB; $mform =& $this->_form; if (isset($this->_customdata)) { $features = $this->_customdata; } else { $features = array(); } // course id needs to be passed for auth purposes $mform->addElement('hidden', 'id', optional_param('id', 0, PARAM_INT)); $mform->setType('id', PARAM_INT); $mform->addElement('header', 'general', get_string('importfile', 'grades')); $mform->addElement('advcheckbox', 'feedback', get_string('importfeedback', 'grades')); $mform->setDefault('feedback', 0); // Restrict the possible upload file types. if (!empty($features['acceptedtypes'])) { $acceptedtypes = $features['acceptedtypes']; } else { $acceptedtypes = '*'; } // File upload. $mform->addElement('filepicker', 'userfile', get_string('file'), null, array('accepted_types' => $acceptedtypes)); $mform->disabledIf('userfile', 'url', 'noteq', ''); $mform->addElement('text', 'url', get_string('fileurl', 'gradeimport_xml'), 'size="80"'); $mform->setType('url', PARAM_URL); $mform->disabledIf('url', 'userfile', 'noteq', ''); $mform->addHelpButton('url', 'fileurl', 'gradeimport_xml'); if (!empty($CFG->gradepublishing)) { $mform->addElement('header', 'publishing', get_string('publishing', 'grades')); $options = array(get_string('nopublish', 'grades'), get_string('createnewkey', 'userkey')); $keys = $DB->get_records_select('user_private_key', "script='grade/import' AND instance=? AND userid=?", array($COURSE->id, $USER->id)); if ($keys) { foreach ($keys as $key) { $options[$key->value] = $key->value; // TODO: add more details - ip restriction, valid until ?? } } $mform->addElement('select', 'key', get_string('userkey', 'userkey'), $options); $mform->addHelpButton('key', 'userkey', 'userkey'); $mform->addElement('static', 'keymanagerlink', get_string('keymanager', 'userkey'), '<a href="'.$CFG->wwwroot.'/grade/import/keymanager.php?id='.$COURSE->id.'">'.get_string('keymanager', 'userkey').'</a>'); $mform->addElement('text', 'iprestriction', get_string('keyiprestriction', 'userkey'), array('size'=>80)); $mform->addHelpButton('iprestriction', 'keyiprestriction', 'userkey'); $mform->setDefault('iprestriction', getremoteaddr()); // own IP - just in case somebody does not know what user key is $mform->addElement('date_time_selector', 'validuntil', get_string('keyvaliduntil', 'userkey'), array('optional'=>true)); $mform->addHelpButton('validuntil', 'keyvaliduntil', 'userkey'); $mform->setDefault('validuntil', time()+3600*24*7); // only 1 week default duration - just in case somebody does not know what user key is $mform->disabledIf('iprestriction', 'key', 'noteq', 1); $mform->disabledIf('validuntil', 'key', 'noteq', 1); $mform->disabledIf('iprestriction', 'url', 'eq', ''); $mform->disabledIf('validuntil', 'url', 'eq', ''); $mform->disabledIf('key', 'url', 'eq', ''); } $this->add_action_buttons(false, get_string('uploadgrades', 'grades')); } function validation($data, $files) { $err = parent::validation($data, $files); if (empty($data['url']) and empty($data['userfile'])) { if (array_key_exists('url', $data)) { $err['url'] = get_string('required'); } if (array_key_exists('userfile', $data)) { $err['userfile'] = get_string('required'); } } else if (array_key_exists('url', $data) and $data['url'] != clean_param($data['url'], PARAM_URL)) { $err['url'] = get_string('error'); } return $err; } } xml/fetch.php 0000644 00000002522 15151264176 0007157 0 ustar 00 <?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/>. define('NO_MOODLE_COOKIES', true); // session not used here require_once '../../../config.php'; $id = required_param('id', PARAM_INT); // course id if (!$course = $DB->get_record('course', array('id'=>$id))) { throw new \moodle_exception('invalidcourseid'); } require_user_key_login('grade/import', $id); // we want different keys for each course if (empty($CFG->gradepublishing)) { throw new \moodle_exception('gradepubdisable'); } $context = context_course::instance($id); require_capability('gradeimport/xml:publish', $context); // use the same page parameters as import.php and append &key=sdhakjsahdksahdkjsahksadjksahdkjsadhksa require 'import.php'; xml/index.php 0000644 00000007202 15151264176 0007175 0 ustar 00 <?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/>. require_once('../../../config.php'); require_once('lib.php'); require_once('grade_import_form.php'); $id = required_param('id', PARAM_INT); // course id $PAGE->set_url(new moodle_url('/grade/import/xml/index.php', array('id'=>$id))); $PAGE->set_pagelayout('admin'); if (!$course = $DB->get_record('course', array('id'=>$id))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($id); require_capability('moodle/grade:import', $context); require_capability('gradeimport/xml:view', $context); // print header $strgrades = get_string('grades', 'grades'); $actionstr = get_string('pluginname', 'gradeimport_xml'); if (!empty($CFG->gradepublishing)) { $CFG->gradepublishing = has_capability('gradeimport/xml:publish', $context); } $mform = new grade_import_form(null, array('acceptedtypes' => array('.xml'))); if ($data = $mform->get_data()) { // Large files are likely to take their time and memory. Let PHP know // that we'll take longer, and that the process should be recycled soon // to free up memory. core_php_time_limit::raise(); raise_memory_limit(MEMORY_EXTRA); if ($text = $mform->get_file_content('userfile')) { print_grade_page_head($COURSE->id, 'import', 'xml', get_string('importxml', 'grades'), false, false, true, 'importxml', 'gradeimport_xml'); $error = ''; $importcode = import_xml_grades($text, $course, $error); if ($importcode) { grade_import_commit($id, $importcode, $data->feedback, true); echo $OUTPUT->footer(); die; } else { echo $OUTPUT->notification($error); echo $OUTPUT->continue_button($CFG->wwwroot.'/grade/index.php?id='.$course->id); echo $OUTPUT->footer(); die; } } else if (empty($data->key)) { redirect('import.php?id='.$id.'&feedback='.(int)($data->feedback).'&url='.urlencode($data->url)); } else { if ($data->key == 1) { $data->key = create_user_key('grade/import', $USER->id, $course->id, $data->iprestriction, $data->validuntil); } print_grade_page_head($COURSE->id, 'import', 'xml', get_string('importxml', 'grades'), false, false, true, 'importxml', 'gradeimport_xml'); echo '<div class="gradeexportlink">'; $link = $CFG->wwwroot.'/grade/import/xml/fetch.php?id='.$id.'&feedback='.(int)($data->feedback).'&url='.urlencode($data->url).'&key='.$data->key; echo get_string('import', 'grades').': <a href="'.$link.'">'.$link.'</a>'; echo '</div>'; echo $OUTPUT->footer(); die; } } $actionbar = new \core_grades\output\import_action_bar($context, null, 'xml'); print_grade_page_head($COURSE->id, 'import', 'xml', get_string('importxml', 'grades'), false, false, true, 'importxml', 'gradeimport_xml', null, $actionbar); $mform->display(); echo $OUTPUT->footer(); xml/lib.php 0000644 00000010740 15151264176 0006635 0 ustar 00 <?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/>. require_once $CFG->libdir.'/gradelib.php'; require_once($CFG->libdir.'/xmlize.php'); require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->dirroot.'/grade/import/lib.php'; function import_xml_grades($text, $course, &$error) { global $USER, $DB; $importcode = get_new_importcode(); $status = true; $content = xmlize($text); if (!empty($content['results']['#']['result'])) { $results = $content['results']['#']['result']; foreach ($results as $i => $result) { $gradeidnumber = $result['#']['assignment'][0]['#']; if (!$grade_items = grade_item::fetch_all(array('idnumber'=>$gradeidnumber, 'courseid'=>$course->id))) { // gradeitem does not exist // no data in temp table so far, abort $status = false; $error = get_string('errincorrectgradeidnumber', 'gradeimport_xml', $gradeidnumber); break; } else if (count($grade_items) != 1) { $status = false; $error = get_string('errduplicategradeidnumber', 'gradeimport_xml', $gradeidnumber); break; } else { $grade_item = reset($grade_items); } // grade item locked, abort if ($grade_item->is_locked()) { $status = false; $error = get_string('gradeitemlocked', 'grades'); break; } // check if user exist and convert idnumber to user id $useridnumber = $result['#']['student'][0]['#']; if (!$user = $DB->get_record('user', array('idnumber' =>$useridnumber))) { // no user found, abort $status = false; $error = get_string('errincorrectuseridnumber', 'gradeimport_xml', $useridnumber); break; } // check if grade_grade is locked and if so, abort if ($grade_grade = new grade_grade(array('itemid'=>$grade_item->id, 'userid'=>$user->id))) { $grade_grade->grade_item =& $grade_item; if ($grade_grade->is_locked()) { // individual grade locked, abort $status = false; $error = get_string('gradelocked', 'grades'); break; } } $newgrade = new stdClass(); $newgrade->itemid = $grade_item->id; $newgrade->userid = $user->id; $newgrade->importcode = $importcode; $newgrade->importer = $USER->id; // check grade value exists and is a numeric grade if (isset($result['#']['score'][0]['#']) && $result['#']['score'][0]['#'] !== '-') { if (is_numeric($result['#']['score'][0]['#'])) { $newgrade->finalgrade = $result['#']['score'][0]['#']; } else { $status = false; $error = get_string('badgrade', 'grades'); break; } } else { $newgrade->finalgrade = NULL; } // check grade feedback exists if (isset($result['#']['feedback'][0]['#'])) { $newgrade->feedback = $result['#']['feedback'][0]['#']; } else { $newgrade->feedback = NULL; } // insert this grade into a temp table $DB->insert_record('grade_import_values', $newgrade); } } else { // no results section found in xml, // assuming bad format, abort import $status = false; $error = get_string('errbadxmlformat', 'gradeimport_xml'); } if ($status) { return $importcode; } else { import_cleanup($importcode); return false; } } xml/version.php 0000644 00000002256 15151264176 0007557 0 ustar 00 <?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/>. /** * Version details * * @package gradeimport * @subpackage xml * @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $plugin->version = 2022112800; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2022111800; // Requires this Moodle version. $plugin->component = 'gradeimport_xml'; // Full name of the plugin (used for diagnostics) xml/classes/privacy/provider.php 0000644 00000002767 15151264176 0013045 0 ustar 00 <?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/>. /** * Privacy Subsystem implementation for gradeimport_xml. * * @package gradeimport_xml * @copyright 2018 Sara Arjona <sara@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace gradeimport_xml\privacy; defined('MOODLE_INTERNAL') || die(); /** * Privacy Subsystem for gradeimport_xml implementing null_provider. * * @copyright 2018 Sara Arjona <sara@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class provider implements \core_privacy\local\metadata\null_provider { /** * Get the language string identifier with the component's language * file to explain why this plugin stores no data. * * @return string */ public static function get_reason() : string { return 'privacy:metadata'; } } xml/lang/en/gradeimport_xml.php 0000644 00000004461 15151264176 0012612 0 ustar 00 <?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/>. /** * Strings for component 'gradeimport_xml', language 'en', branch 'MOODLE_20_STABLE' * * @package gradeimport_xml * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ $string['errbadxmlformat'] = 'Error - bad XML format'; $string['errduplicategradeidnumber'] = 'Error - there are two grade items with idnumber \'{$a}\' in this course. This should be impossible.'; $string['errduplicateidnumber'] = 'Error - duplicate idnumber'; $string['errincorrectgradeidnumber'] = 'Error - idnumber \'{$a}\' from the import file does not match any grade item.'; $string['errincorrectidnumber'] = 'Error - incorrect idnumber'; $string['errincorrectuseridnumber'] = 'Error - idnumber \'{$a}\' from the import file does not match any user.'; $string['error'] = 'Errors occur'; $string['errorduringimport'] = 'An error occurred when trying to import: {$a}'; $string['fileurl'] = 'Remote file URL'; $string['fileurl_help'] = 'The remote file URL field is for fetching data from a remote server, such as a student information system.'; $string['pluginname'] = 'XML file'; $string['privacy:metadata'] = 'The import grades from XML plugin does not store any personal data.'; $string['xml:publish'] = 'Publish import grades from XML'; $string['xml:view'] = 'Import grades from XML'; $string['importxml'] = 'XML import'; $string['importxml_help'] = 'Grades can be imported via an XML file containing user ID numbers and activity ID numbers. To obtain the correct format, first export some grades to XML file then view the file.'; $string['importxml_link'] = 'grade/import/xml/index'; lib.php 0000644 00000023422 15151264176 0006036 0 ustar 00 <?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/>. require_once($CFG->libdir.'/gradelib.php'); /** * Returns new improtcode for current user * @return int importcode */ function get_new_importcode() { global $USER, $DB; $importcode = time(); while ($DB->get_record('grade_import_values', array('importcode' => $importcode, 'importer' => $USER->id))) { $importcode--; } return $importcode; } /** * given an import code, commits all entries in buffer tables * (grade_import_value and grade_import_newitem) * If this function is called, we assume that all data collected * up to this point is fine and we can go ahead and commit * @param int $courseid - ID of the course. * @param int $importcode - Import batch identifier. * @param bool $importfeedback - Whether to import feedback as well. * @param bool $verbose - Print feedback and continue button. * @return bool success */ function grade_import_commit($courseid, $importcode, $importfeedback=true, $verbose=true) { global $CFG, $USER, $DB, $OUTPUT; $failed = false; $executionerrors = false; $commitstart = time(); // start time in case we need to roll back $newitemids = array(); // array to hold new grade_item ids from grade_import_newitem table, mapping array /// first select distinct new grade_items with this batch $params = array($importcode, $USER->id); if ($newitems = $DB->get_records_sql("SELECT * FROM {grade_import_newitem} WHERE importcode = ? AND importer=?", $params)) { // instances of the new grade_items created, cached // in case grade_update fails, so that we can remove them $instances = array(); foreach ($newitems as $newitem) { // get all grades with this item $gradeimportparams = array('newgradeitem' => $newitem->id, 'importcode' => $importcode, 'importer' => $USER->id); if ($grades = $DB->get_records('grade_import_values', $gradeimportparams)) { /// create a new grade item for this - must use false as second param! /// TODO: we need some bounds here too $gradeitem = new grade_item(array('courseid'=>$courseid, 'itemtype'=>'manual', 'itemname'=>$newitem->itemname), false); $gradeitem->insert('import'); $instances[] = $gradeitem; // insert each individual grade to this new grade item foreach ($grades as $grade) { if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import', $grade->feedback, FORMAT_MOODLE, null, null, true)) { $failed = true; break 2; } } } } if ($failed) { foreach ($instances as $instance) { $gradeitem->delete('import'); } import_cleanup($importcode); return false; } } /// then find all existing items if ($gradeitems = $DB->get_records_sql("SELECT DISTINCT (itemid) FROM {grade_import_values} WHERE importcode = ? AND importer=? AND itemid > 0", array($importcode, $USER->id))) { $modifieditems = array(); foreach ($gradeitems as $itemid=>$notused) { if (!$gradeitem = new grade_item(array('id'=>$itemid))) { // not supposed to happen, but just in case import_cleanup($importcode); return false; } // get all grades with this item $gradeimportparams = array('itemid' => $itemid, 'importcode' => $importcode, 'importer' => $USER->id); if ($grades = $DB->get_records('grade_import_values', $gradeimportparams)) { // make the grades array for update_grade foreach ($grades as $grade) { if (!$importfeedback || $grade->feedback === null) { $grade->feedback = false; // ignore it } if ($grade->importonlyfeedback) { // False means do not change. See grade_itme::update_final_grade(). $grade->finalgrade = false; } if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import', $grade->feedback, FORMAT_MOODLE, null, null, true)) { $errordata = new stdClass(); $errordata->itemname = $gradeitem->itemname; $errordata->userid = $grade->userid; $executionerrors[] = get_string('errorsettinggrade', 'grades', $errordata); $failed = true; break 2; } } //$itemdetails -> idnumber = $gradeitem->idnumber; $modifieditems[] = $itemid; } } if ($failed) { if ($executionerrors && $verbose) { echo $OUTPUT->notification(get_string('gradeimportfailed', 'grades')); foreach ($executionerrors as $errorstr) { echo $OUTPUT->notification($errorstr); } } import_cleanup($importcode); return false; } } if ($verbose) { echo $OUTPUT->notification(get_string('importsuccess', 'grades'), 'notifysuccess'); $unenrolledusers = get_unenrolled_users_in_import($importcode, $courseid); if ($unenrolledusers) { $list = array(); foreach ($unenrolledusers as $u) { $u->fullname = fullname($u); $list[] = get_string('usergrade', 'grades', $u); } echo $OUTPUT->notification(get_string('unenrolledusersinimport', 'grades', html_writer::alist($list)), 'notifysuccess'); } echo $OUTPUT->continue_button($CFG->wwwroot.'/grade/index.php?id='.$courseid); } // clean up import_cleanup($importcode); return true; } /** * This function returns an array of grades that were included in the import, * but where the user does not currently have a graded role on the course. These grades * are still stored in the database, but will not be visible in the gradebook unless * this user subsequently enrols on the course in a graded roles. * * The returned objects have fields useridnumber and gradeidnumber, plus enough user name fields to pass to {@see fullname} * * @param integer $importcode import batch identifier * @param integer $courseid the course we are importing to. * @return mixed and array of user objects, or false if none. */ function get_unenrolled_users_in_import($importcode, $courseid) { global $CFG, $DB; $coursecontext = context_course::instance($courseid); // We want to query both the current context and parent contexts. list($relatedctxsql, $relatedctxparams) = $DB->get_in_or_equal($coursecontext->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'relatedctx'); // Users with a gradeable role. list($gradebookrolessql, $gradebookrolesparams) = $DB->get_in_or_equal(explode(',', $CFG->gradebookroles), SQL_PARAMS_NAMED, 'grbr'); $usernamefields = core_user\fields::for_name()->get_sql('u', false, '', '', false); // Enrolled users. $context = context_course::instance($courseid); list($enrolledsql, $enrolledparams) = get_enrolled_sql($context); list($sort, $sortparams) = users_order_by_sql('u'); $sql = "SELECT giv.id, {$usernamefields->selects}, u.idnumber AS useridnumber, COALESCE(gi.idnumber, gin.itemname) AS gradeidnumber FROM {grade_import_values} giv JOIN {user} u ON giv.userid = u.id LEFT JOIN {grade_items} gi ON gi.id = giv.itemid LEFT JOIN {grade_import_newitem} gin ON gin.id = giv.newgradeitem LEFT JOIN ($enrolledsql) je ON je.id = u.id LEFT JOIN {role_assignments} ra ON (giv.userid = ra.userid AND ra.roleid $gradebookrolessql AND ra.contextid $relatedctxsql) WHERE giv.importcode = :importcode AND (ra.id IS NULL OR je.id IS NULL) ORDER BY gradeidnumber, $sort"; $params = array_merge($gradebookrolesparams, $enrolledparams, $sortparams, $relatedctxparams); $params['importcode'] = $importcode; return $DB->get_records_sql($sql, $params); } /** * removes entries from grade import buffer tables grade_import_value and grade_import_newitem * after a successful import, or during an import abort * @param string importcode - import batch identifier */ function import_cleanup($importcode) { global $USER, $DB; // remove entries from buffer table $DB->delete_records('grade_import_values', array('importcode' => $importcode, 'importer' => $USER->id)); $DB->delete_records('grade_import_newitem', array('importcode' => $importcode, 'importer' => $USER->id)); } key_form.php 0000644 00000003702 15151264176 0007102 0 ustar 00 <?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/>. /** * Grade import key management form. * * @package moodlecore * @copyright 2008 Petr Skoda * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ if (!defined('MOODLE_INTERNAL')) { die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page } require_once($CFG->dirroot.'/lib/formslib.php'); class key_form extends moodleform { // Define the form function definition () { global $USER, $CFG, $COURSE; $mform =& $this->_form; $mform->addElement('static', 'value', get_string('keyvalue', 'userkey')); $mform->addElement('text', 'iprestriction', get_string('keyiprestriction', 'userkey'), array('size'=>80)); $mform->addElement('date_time_selector', 'validuntil', get_string('keyvaliduntil', 'userkey'), array('optional'=>true)); $mform->addHelpButton('iprestriction', 'keyiprestriction', 'userkey'); $mform->addHelpButton('validuntil', 'keyvaliduntil', 'userkey'); $mform->setType('iprestriction', PARAM_RAW_TRIMMED); $mform->addElement('hidden','id'); $mform->setType('id', PARAM_INT); $mform->addElement('hidden','courseid'); $mform->setType('courseid', PARAM_INT); $this->add_action_buttons(); } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | ���֧ߧ֧�ѧ�ڧ� ����ѧߧڧ��: 0 |
proxy
|
phpinfo
|
���ѧ����ۧܧ�