���ѧۧݧ�ӧ�� �ާ֧ߧ֧էا֧� - ���֧էѧܧ�ڧ��ӧѧ�� - /home3/cpr76684/public_html/edit.tar
���ѧ٧ѧ�
letter/edit_form.php 0000644 00000006353 15151222054 0010530 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 moodleform for editing grade letters * * @package core_grades * @copyright 2007 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->libdir.'/formslib.php'; class edit_letter_form extends moodleform { public function definition() { $mform =& $this->_form; [ 'lettercount' => $lettercount, 'admin' => $admin, ] = $this->_customdata; $mform->addElement('header', 'gradeletters', get_string('gradeletters', 'grades')); // Only show "override site defaults" checkbox if editing the course grade letters if (!$admin) { $mform->addElement('checkbox', 'override', get_string('overridesitedefaultgradedisplaytype', 'grades')); $mform->addHelpButton('override', 'overridesitedefaultgradedisplaytype', 'grades'); } $gradeletter = get_string('gradeletter', 'grades'); $gradeboundary = get_string('gradeboundary', 'grades'); // The fields to create the grade letter/boundary. $elements = []; $elements[] = $mform->createElement('text', 'gradeletter', "{$gradeletter} {no}"); $elements[] = $mform->createElement('static', '', '', '≥'); $elements[] = $mform->createElement('float', 'gradeboundary', "{$gradeboundary} {no}"); $elements[] = $mform->createElement('static', '', '', '%'); // Element options/rules, fields should be disabled unless "Override" is checked for course grade letters. $options = []; $options['gradeletter']['type'] = PARAM_TEXT; if (!$admin) { $options['gradeletter']['disabledif'] = ['override', 'notchecked']; $options['gradeboundary']['disabledif'] = ['override', 'notchecked']; } // Create our repeatable elements, each one a group comprised of the fields defined previously. $this->repeat_elements([ $mform->createElement('group', 'gradeentry', "{$gradeletter} {no}", $elements, [' '], false) ], $lettercount, $options, 'gradeentrycount', 'gradeentryadd', 3); // Add a help icon to first element group, if it exists. if ($mform->elementExists('gradeentry[0]')) { $mform->addHelpButton('gradeentry[0]', 'gradeletter', 'grades'); } $mform->addElement('hidden', 'id'); $mform->setType('id', PARAM_INT); $this->add_action_buttons(); } } letter/tabs.php 0000644 00000002731 15151222054 0007505 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/>. /** * Prints navigation tabs for viewing and editing grade letters * * @package core_grades * @copyright 2007 Petr Skoda * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ $row = $tabs = array(); $row[] = new tabobject('lettersview', $CFG->wwwroot.'/grade/edit/letter/index.php?id='.$COURSE->id, get_string('letters', 'grades')); if (has_capability('moodle/grade:manageletters', $context)) { $row[] = new tabobject('lettersedit', $CFG->wwwroot.'/grade/edit/letter/edit.php?id='.$context->id, get_string('edit')); } $tabs[] = $row; echo '<div class="letterdisplay">'; print_tabs($tabs, $currenttab); echo '</div>'; letter/index.php 0000644 00000023047 15151222054 0007666 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/>. /** * List of grade letters. * * @package core_grades * @copyright 2008 Nicolas Connault * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once '../../../config.php'; require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->libdir.'/gradelib.php'; $contextid = optional_param('id', SYSCONTEXTID, PARAM_INT); $action = optional_param('action', '', PARAM_ALPHA); $edit = optional_param('edit', false, PARAM_BOOL); //are we editing? $url = new moodle_url('/grade/edit/letter/index.php', array('id' => $contextid)); list($context, $course, $cm) = get_context_info_array($contextid); $contextid = null;//now we have a context object throw away the $contextid from the params //if viewing if (!$edit) { if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:manageletters', $context)) { throw new \moodle_exception('nopermissiontoviewletergrade'); } } else {//else we're editing require_capability('moodle/grade:manageletters', $context); navigation_node::override_active_url($url); $url->param('edit', 1); $PAGE->navbar->add(get_string('editgradeletters', 'grades'), $url); } $PAGE->set_url($url); $returnurl = null; $editparam = null; if ($context->contextlevel == CONTEXT_SYSTEM or $context->contextlevel == CONTEXT_COURSECAT) { require_once $CFG->libdir.'/adminlib.php'; admin_externalpage_setup('letters'); $admin = true; $returnurl = "$CFG->wwwroot/grade/edit/letter/index.php"; $editparam = '?edit=1'; $PAGE->set_primary_active_tab('siteadminnode'); } else if ($context->contextlevel == CONTEXT_COURSE) { $PAGE->set_pagelayout('standard');//calling this here to make blocks display require_login($context->instanceid, false, $cm); $admin = false; $returnurl = $CFG->wwwroot.'/grade/edit/letter/index.php?id='.$context->id; $editparam = '&edit=1'; $gpr = new grade_plugin_return(array('type'=>'edit', 'plugin'=>'letter', 'courseid'=>$course->id)); } else { throw new \moodle_exception('invalidcourselevel'); } $strgrades = get_string('grades'); $pagename = get_string('letters', 'grades'); $letters = grade_get_letters($context); $override = $DB->record_exists('grade_letters', array('contextid' => $context->id)); //if were viewing the letters if (!$edit) { $heading = get_string('gradeletters', 'grades'); $actionbar = new \core_grades\output\grade_letters_action_bar($context); if ($admin) { echo $OUTPUT->header(); $renderer = $PAGE->get_renderer('core_grades'); echo $renderer->render_action_bar($actionbar); echo $OUTPUT->heading($heading); } else { print_grade_page_head($course->id, 'letter', 'view', $heading, false, false, true, null, null, null, $actionbar); } $data = array(); $max = 100; foreach($letters as $boundary=>$letter) { $line = array(); $line[] = format_float($max,2).' %'; $line[] = format_float($boundary,2).' %'; $line[] = format_string($letter); $data[] = $line; $max = $boundary - 0.01; } if (!empty($override)) { echo $OUTPUT->notification(get_string('gradeletteroverridden', 'grades'), 'notifymessage'); } $table = new html_table(); $table->id = 'grade-letters-view'; $table->head = array(get_string('max', 'grades'), get_string('min', 'grades'), get_string('letter', 'grades')); $table->size = array('30%', '30%', '40%'); $table->align = array('left', 'left', 'left'); $table->width = '30%'; $table->data = $data; $table->tablealign = 'center'; echo html_writer::table($table); } else { //else we're editing require_once('edit_form.php'); $data = new stdClass(); $data->id = $context->id; $i = 0; foreach ($letters as $boundary=>$letter) { $data->gradeletter[$i] = $letter; $data->gradeboundary[$i] = $boundary; $i++; } $data->override = $override; // Count number of letters, used to build the repeated elements of the form. $lettercount = count($letters); $mform = new edit_letter_form($returnurl.$editparam, ['lettercount' => $lettercount, 'admin' => $admin]); $mform->set_data($data); if ($mform->is_cancelled()) { redirect($returnurl); } else if ($data = $mform->get_data()) { // Make sure we are updating the cache. $cache = cache::make('core', 'grade_letters'); if (!$admin and empty($data->override)) { $records = $DB->get_records('grade_letters', array('contextid' => $context->id)); foreach ($records as $record) { $DB->delete_records('grade_letters', array('id' => $record->id)); // Trigger the letter grade deleted event. $event = \core\event\grade_letter_deleted::create(array( 'objectid' => $record->id, 'context' => $context, )); $event->trigger(); } // Make sure we clear the cache for this context. $cache->delete($context->id); redirect($returnurl); } $letters = array(); for ($i = 0; $i < $data->gradeentrycount; $i++) { $letter = $data->gradeletter[$i]; if ($letter === '') { continue; } $boundary = floatval($data->gradeboundary[$i]); if ($boundary < 0 || $boundary > 100) { continue; // Skip if out of range. } // The keys need to be strings so floats are not truncated. $letters[number_format($boundary, 5)] = $letter; } $pool = array(); if ($records = $DB->get_records('grade_letters', array('contextid' => $context->id), 'lowerboundary ASC')) { foreach ($records as $r) { // Will re-use the lowerboundary to avoid duplicate during the update process. $pool[number_format($r->lowerboundary, 5)] = $r; } } foreach ($letters as $boundary => $letter) { $record = new stdClass(); $record->letter = $letter; $record->lowerboundary = $boundary; $record->contextid = $context->id; if (isset($pool[$boundary])) { // Re-use the existing boundary to avoid key constraint. if ($letter != $pool[$boundary]->letter) { // The letter has been assigned to another boundary, we update it. $record->id = $pool[$boundary]->id; $DB->update_record('grade_letters', $record); // Trigger the letter grade updated event. $event = \core\event\grade_letter_updated::create(array( 'objectid' => $record->id, 'context' => $context, )); $event->trigger(); } unset($pool[$boundary]); // Remove the letter from the pool. } else if ($candidate = array_pop($pool)) { // The boundary is new, we update a random record from the pool. $record->id = $candidate->id; $DB->update_record('grade_letters', $record); // Trigger the letter grade updated event. $event = \core\event\grade_letter_updated::create(array( 'objectid' => $record->id, 'context' => $context, )); $event->trigger(); } else { // No records were found, this must be a new letter. $newid = $DB->insert_record('grade_letters', $record); // Trigger the letter grade added event. $event = \core\event\grade_letter_created::create(array( 'objectid' => $newid, 'context' => $context, )); $event->trigger(); } } // Cache the changed letters. if (!empty($letters)) { // For some reason, the cache saves it in the order in which they were entered // but we really want to order them in descending order so we sort it here. krsort($letters); $cache->set($context->id, $letters); } // Delete the unused records. foreach($pool as $leftover) { $DB->delete_records('grade_letters', array('id' => $leftover->id)); // Trigger the letter grade deleted event. $event = \core\event\grade_letter_deleted::create(array( 'objectid' => $leftover->id, 'context' => $context, )); $event->trigger(); } redirect($returnurl); } print_grade_page_head($COURSE->id, 'letter', 'edit', get_string('editgradeletters', 'grades'), false, false, false); $mform->display(); } echo $OUTPUT->footer(); scale/edit_form.php 0000644 00000013710 15151222054 0010313 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/>. /** * Edit form for grade scales * * @package core_grades * @copyright 2007 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->libdir.'/formslib.php'; class edit_scale_form extends moodleform { function definition() { global $CFG; $mform =& $this->_form; // visible elements $mform->addElement('header', 'general', get_string('scale')); $mform->addElement('text', 'name', get_string('name'), 'size="40"'); $mform->addRule('name', get_string('required'), 'required', null, 'client'); $mform->setType('name', PARAM_TEXT); $mform->addElement('advcheckbox', 'standard', get_string('scalestandard')); $mform->addHelpButton('standard', 'scalestandard'); $mform->addElement('static', 'used', get_string('used')); $mform->addElement('textarea', 'scale', get_string('scale'), array('cols'=>50, 'rows'=>2)); $mform->addHelpButton('scale', 'scale'); $mform->addRule('scale', get_string('required'), 'required', null, 'client'); $mform->setType('scale', PARAM_TEXT); $mform->addElement('editor', 'description_editor', get_string('description'), null, $this->_customdata['editoroptions']); // hidden params $mform->addElement('hidden', 'id', 0); $mform->setType('id', PARAM_INT); $mform->addElement('hidden', 'courseid', 0); $mform->setType('courseid', PARAM_INT); /// add return tracking info $gpr = $this->_customdata['gpr']; $gpr->add_mform_elements($mform); //------------------------------------------------------------------------------- // buttons $this->add_action_buttons(); } /// tweak the form - depending on existing data function definition_after_data() { global $CFG; $mform =& $this->_form; $courseid = $mform->getElementValue('courseid'); if ($id = $mform->getElementValue('id')) { $scale = grade_scale::fetch(array('id'=>$id)); $used = $scale->is_used(); if ($used) { $mform->hardFreeze('scale'); } if (empty($courseid)) { $mform->hardFreeze('standard'); } else if (!has_capability('moodle/course:managescales', context_system::instance())) { //if they dont have managescales at system level the shouldnt be allowed to make scales standard (or not standard) $mform->hardFreeze('standard'); } else if ($used and !empty($scale->courseid)) { $mform->hardFreeze('standard'); } $usedstr = $scale->is_used() ? get_string('yes') : get_string('no'); $used_el =& $mform->getElement('used'); $used_el->setValue($usedstr); } else { $mform->removeElement('used'); if (empty($courseid) or !has_capability('moodle/course:managescales', context_system::instance())) { $mform->hardFreeze('standard'); } } } /// perform extra validation before submission function validation($data, $files) { global $CFG, $COURSE, $DB; $errors = parent::validation($data, $files); // we can not allow 2 scales with the same exact scale as this creates // problems for backup/restore $old = grade_scale::fetch(array('id'=>$data['id'])); if (array_key_exists('standard', $data)) { if (empty($data['standard'])) { $courseid = $COURSE->id; } else { $courseid = 0; } } else { $courseid = $old->courseid; } if (array_key_exists('scale', $data)) { $scalearray = explode(',', $data['scale']); $scalearray = array_map('trim', $scalearray); $scaleoptioncount = count($scalearray); if (count($scalearray) < 1) { $errors['scale'] = get_string('badlyformattedscale', 'grades'); } else { $thescale = implode(',',$scalearray); //this check strips out whitespace from the scale we're validating but not from those already in the DB $count = $DB->count_records_select('scale', "courseid=:courseid AND ".$DB->sql_compare_text('scale', core_text::strlen($thescale)).'=:scale', array('courseid'=>$courseid, 'scale'=>$thescale)); if ($count) { //if this is a new scale but we found a duplice in the DB //or we found a duplicate in another course report the error if (empty($old->id) or $old->courseid != $courseid) { $errors['scale'] = get_string('duplicatescale', 'grades'); } else if ($old->scale !== $thescale and $old->scale !== $data['scale']) { //if the old scale from DB is different but we found a duplicate then we're trying to modify a scale to be a duplicate $errors['scale'] = get_string('duplicatescale', 'grades'); } } } } return $errors; } } scale/edit.php 0000644 00000013046 15151222054 0007272 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/>. /** * Edit page for grade scales * * @package core_grades * @copyright 2007 Petr Skoda * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once '../../../config.php'; require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->dirroot.'/grade/report/lib.php'; require_once 'edit_form.php'; $courseid = optional_param('courseid', 0, PARAM_INT); $id = optional_param('id', 0, PARAM_INT); $PAGE->set_url('/grade/edit/scale/edit.php', array('id' => $id, 'courseid' => $courseid)); $PAGE->set_pagelayout('admin'); navigation_node::override_active_url(new moodle_url('/grade/edit/scale/index.php', array('id' => $courseid))); $systemcontext = context_system::instance(); // a bit complex access control :-O if ($id) { /// editing existing scale if (!$scale_rec = $DB->get_record('scale', array('id' => $id))) { throw new \moodle_exception('invalidscaleid'); } if ($scale_rec->courseid) { $scale_rec->standard = 0; if (!$course = $DB->get_record('course', array('id' => $scale_rec->courseid))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($course->id); require_capability('moodle/course:managescales', $context); $courseid = $course->id; } else { if ($courseid) { if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } } $scale_rec->standard = 1; $scale_rec->courseid = $courseid; require_login($courseid); require_capability('moodle/course:managescales', $systemcontext); } } else if ($courseid){ /// adding new scale from course if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } $scale_rec = new stdClass(); $scale_rec->standard = 0; $scale_rec->courseid = $courseid; require_login($course); $context = context_course::instance($course->id); require_capability('moodle/course:managescales', $context); } else { /// adding new scale from admin section $scale_rec = new stdClass(); $scale_rec->standard = 1; $scale_rec->courseid = 0; require_login(); require_capability('moodle/course:managescales', $systemcontext); } if (!$courseid) { require_once $CFG->libdir.'/adminlib.php'; admin_externalpage_setup('scales'); $PAGE->set_primary_active_tab('siteadminnode'); } // default return url $gpr = new grade_plugin_return(); $returnurl = $gpr->get_return_url('index.php?id='.$courseid); $editoroptions = array( 'maxfiles' => EDITOR_UNLIMITED_FILES, 'maxbytes' => $CFG->maxbytes, 'trusttext' => false, 'noclean' => true, 'context' => $systemcontext ); if (!empty($scale_rec->id)) { $editoroptions['subdirs'] = file_area_contains_subdirs($systemcontext, 'grade', 'scale', $scale_rec->id); $scale_rec = file_prepare_standard_editor($scale_rec, 'description', $editoroptions, $systemcontext, 'grade', 'scale', $scale_rec->id); } else { $editoroptions['subdirs'] = false; $scale_rec = file_prepare_standard_editor($scale_rec, 'description', $editoroptions, $systemcontext, 'grade', 'scale', null); } $mform = new edit_scale_form(null, compact('gpr', 'editoroptions')); $mform->set_data($scale_rec); if ($mform->is_cancelled()) { redirect($returnurl); } else if ($data = $mform->get_data()) { $scale = new grade_scale(array('id'=>$id)); $data->userid = $USER->id; if (empty($scale->id)) { $data->description = $data->description_editor['text']; $data->descriptionformat = $data->description_editor['format']; grade_scale::set_properties($scale, $data); if (!has_capability('moodle/grade:manage', $systemcontext)) { $data->standard = 0; } $scale->courseid = !empty($data->standard) ? 0 : $courseid; $scale->insert(); $data = file_postupdate_standard_editor($data, 'description', $editoroptions, $systemcontext, 'grade', 'scale', $scale->id); $DB->set_field($scale->table, 'description', $data->description, array('id'=>$scale->id)); } else { $data = file_postupdate_standard_editor($data, 'description', $editoroptions, $systemcontext, 'grade', 'scale', $id); grade_scale::set_properties($scale, $data); if (isset($data->standard)) { $scale->courseid = !empty($data->standard) ? 0 : $courseid; } else { unset($scale->courseid); // keep previous } $scale->update(); } redirect($returnurl); } $heading = $id ? get_string('editscale', 'grades') : get_string('addscale', 'grades'); $PAGE->navbar->add($heading); print_grade_page_head($COURSE->id, 'scale', null, $heading, false, false, false); $mform->display(); echo $OUTPUT->footer(); scale/index.php 0000644 00000016005 15151222054 0007452 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 page for managing custom and standard scales * * @package core_grades * @copyright 2007 Petr Skoda * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once '../../../config.php'; require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->libdir.'/gradelib.php'; $courseid = optional_param('id', 0, PARAM_INT); $action = optional_param('action', '', PARAM_ALPHA); $PAGE->set_url('/grade/edit/scale/index.php', array('id' => $courseid)); /// Make sure they can even access this course if ($courseid) { if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($course->id); require_capability('moodle/course:managescales', $context); $PAGE->set_pagelayout('admin'); } else { require_once $CFG->libdir.'/adminlib.php'; admin_externalpage_setup('scales'); $context = context_system::instance(); $PAGE->set_primary_active_tab('siteadminnode'); } /// return tracking object $gpr = new grade_plugin_return(array('type'=>'edit', 'plugin'=>'scale', 'courseid'=>$courseid)); $strscale = get_string('scale'); $strstandardscale = get_string('scalesstandard'); $strcustomscales = get_string('scalescustom'); $strname = get_string('name'); $strdelete = get_string('delete'); $stredit = get_string('edit'); $strused = get_string('used'); $stredit = get_string('edit'); switch ($action) { case 'delete': if (!confirm_sesskey()) { break; } $scaleid = required_param('scaleid', PARAM_INT); if (!$scale = grade_scale::fetch(array('id'=>$scaleid))) { break; } if (empty($scale->courseid)) { require_capability('moodle/course:managescales', context_system::instance()); } else if ($scale->courseid != $courseid) { throw new \moodle_exception('invalidcourseid'); } if (!$scale->can_delete()) { break; } $deleteconfirmed = optional_param('deleteconfirmed', 0, PARAM_BOOL); if (!$deleteconfirmed) { if ($courseid) { $PAGE->navbar->add(get_string('scales'), new moodle_url('/grade/edit/scale/index.php', ['id' => $courseid])); } $strdeletescale = get_string('deletescale', 'grades'); $PAGE->navbar->add($strdeletescale); $PAGE->set_title($strdeletescale); $PAGE->set_heading($COURSE->fullname); echo $OUTPUT->header(); $confirmurl = new moodle_url('index.php', array( 'id' => $courseid, 'scaleid' => $scale->id, 'action'=> 'delete', 'sesskey' => sesskey(), 'deleteconfirmed'=> 1)); echo $OUTPUT->confirm(get_string('scaleconfirmdelete', 'grades', $scale->get_name()), $confirmurl, "index.php?id={$courseid}"); echo $OUTPUT->footer(); die; } else { $scale->delete(); } break; } if (!$courseid) { echo $OUTPUT->header(); } $table = new html_table(); $table2 = new html_table(); $heading = ''; if ($courseid and $scales = grade_scale::fetch_all_local($courseid)) { $heading = $strcustomscales; $data = array(); foreach($scales as $scale) { $line = array(); $line[] = $scale->get_name() .'<div class="scale_options">'.str_replace(",", ", ", $scale->scale).'</div>'; $used = $scale->is_used(); $line[] = $used ? get_string('yes') : get_string('no'); $buttons = ""; $buttons .= grade_button('edit', $courseid, $scale); if (!$used) { $buttons .= grade_button('delete', $courseid, $scale); } $line[] = $buttons; $data[] = $line; } $table->head = array($strscale, $strused, $stredit); $table->size = array('70%', '20%', '10%'); $table->align = array('left', 'center', 'center'); $table->attributes['class'] = 'scaletable localscales generaltable'; $table->data = $data; } if ($scales = grade_scale::fetch_all_global()) { $heading = $strstandardscale; $data = array(); foreach($scales as $scale) { $line = array(); $line[] = $scale->get_name().'<div class="scale_options">'.str_replace(",", ", ", $scale->scale).'</div>'; $used = $scale->is_used(); $line[] = $used ? get_string('yes') : get_string('no'); $buttons = ""; if (has_capability('moodle/course:managescales', context_system::instance())) { $buttons .= grade_button('edit', $courseid, $scale); } if (!$used and has_capability('moodle/course:managescales', context_system::instance())) { $buttons .= grade_button('delete', $courseid, $scale); } $line[] = $buttons; $data[] = $line; } $table2->head = array($strscale, $strused, $stredit); $table->attributes['class'] = 'scaletable globalscales generaltable'; $table2->size = array('70%', '20%', '10%'); $table2->align = array('left', 'center', 'center'); $table2->data = $data; } $actionbar = new \core_grades\output\scales_action_bar($context); if ($courseid) { print_grade_page_head($courseid, 'scale', 'scale', get_string('coursescales', 'grades'), false, false, true, null, null, null, $actionbar); } else { $renderer = $PAGE->get_renderer('core_grades'); echo $renderer->render_action_bar($actionbar); echo $OUTPUT->heading(get_string('scales', 'core')); } $hascustomscales = !empty($table->data); $hasstandardscales = !empty($table2->data); // If there are custom scales available in this context, output the custom scales table and a heading. if ($hascustomscales) { echo $OUTPUT->heading($strcustomscales, 3, 'main mt-3'); echo html_writer::table($table); } // If there are standard scales available in this context, output the standard scales table and a heading. if ($hasstandardscales) { echo $OUTPUT->heading($strstandardscale, 3, 'main mt-3'); echo html_writer::table($table2); } // If the are no available scales, display a notification. if (!$hascustomscales && !$hasstandardscales) { echo $OUTPUT->notification(get_string('noexistingscales', 'grades'), 'info', false); } echo $OUTPUT->footer(); outcome/course_form.html 0000644 00000005606 15151222054 0011434 0 ustar 00 <?php $maxlength=70; ?> <form action="course.php" method="post"> <div> <table class="courseoutcomes"> <tr> <td> <label for="removeoutcomes"><?php print_string('outcomescourse', 'grades'); ?></label> <br /> <select id="removeoutcomes" size="20" name="removeoutcomes[]" multiple="multiple" class="form-control input-block-level"> <?php if ($co_standard_notused) { echo '<optgroup label="'.get_string('outcomescoursenotused', 'grades').'">'; foreach ($co_standard_notused as $outcome) { echo '<option value="'.$outcome->id.'">'.shorten_text($outcome->get_name(), $maxlength).'</option>'; } echo '</optgroup>'; } if ($co_standard_used) { echo '<optgroup label="'.get_string('outcomescourseused', 'grades').'">'; foreach ($co_standard_used as $outcome) { echo '<option value="'.$outcome->id.'">'.shorten_text($outcome->get_name(), $maxlength).'</option>'; } echo '</optgroup>'; } if ($co_custom) { echo '<optgroup label="'.get_string('outcomescoursecustom', 'grades').'">'; foreach ($co_custom as $outcome) { echo '<option value="'.$outcome->id.'">'.shorten_text($outcome->get_name(), $maxlength).'</option>'; } echo '</optgroup>'; } ?> </select> </td> <?php if (has_capability('moodle/grade:manageoutcomes', $context)) { ?> <td class="pl-3 pr-3"> <div class="my-3"> <input name="add" class="btn btn-secondary" id="add" type="submit" value="<?php echo $OUTPUT->larrow() . ' ' . get_string('add'); ?>" title="<?php print_string('add'); ?>" /> </div> <div class="my-3"> <input name="remove" class="btn btn-secondary" id="remove" type="submit" value="<?php echo get_string('remove') . ' ' . $OUTPUT->rarrow(); ?>" title="<?php print_string('remove'); ?>" /> </div> </td> <?php } ?> <td> <label for="addoutcomes"><?php print_string('outcomesstandardavailable', 'grades'); ?></label> <br /> <select id="addoutcomes" size="20" name="addoutcomes[]" multiple="multiple" class="form-control input-block-level"> <?php foreach ($standardoutcomes as $outcome) { echo '<option value="'.$outcome->id.'">'.shorten_text($outcome->get_name(), $maxlength).'</option>'; } ?> </select> </td> </tr> </table> <input name="id" type="hidden" value="<?php echo $courseid?>"/> <input type="hidden" name="sesskey" value="<?php echo sesskey() ?>" /> </div> </form> outcome/edit_form.php 0000644 00000013037 15151222054 0010701 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/>. /** * Edit form for grade outcomes * * @package core_grades * @copyright 2007 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->libdir.'/formslib.php'; class edit_outcome_form extends moodleform { public function definition() { global $CFG, $COURSE; $mform =& $this->_form; // visible elements $mform->addElement('header', 'general', get_string('outcomes', 'grades')); $mform->addElement('text', 'fullname', get_string('outcomefullname', 'grades'), 'size="40"'); $mform->addRule('fullname', get_string('required'), 'required'); $mform->setType('fullname', PARAM_TEXT); $mform->addElement('text', 'shortname', get_string('outcomeshortname', 'grades'), 'size="20"'); $mform->addRule('shortname', get_string('required'), 'required'); $mform->setType('shortname', PARAM_NOTAGS); $mform->addElement('advcheckbox', 'standard', get_string('outcomestandard', 'grades')); $mform->addHelpButton('standard', 'outcomestandard', 'grades'); $options = array(); $mform->addElement('selectwithlink', 'scaleid', get_string('scale'), $options, null, array('link' => $CFG->wwwroot.'/grade/edit/scale/edit.php?courseid='.$COURSE->id, 'label' => get_string('scalescustomcreate'))); $mform->addHelpButton('scaleid', 'typescale', 'grades'); $mform->addRule('scaleid', get_string('required'), 'required'); $mform->addElement('editor', 'description_editor', get_string('description'), null, $this->_customdata['editoroptions']); // hidden params $mform->addElement('hidden', 'id', 0); $mform->setType('id', PARAM_INT); $mform->addElement('hidden', 'courseid', 0); $mform->setType('courseid', PARAM_INT); /// add return tracking info $gpr = $this->_customdata['gpr']; $gpr->add_mform_elements($mform); //------------------------------------------------------------------------------- // buttons $this->add_action_buttons(); } /// tweak the form - depending on existing data function definition_after_data() { global $CFG; $mform =& $this->_form; // first load proper scales if ($courseid = $mform->getElementValue('courseid')) { $options = array(); if ($scales = grade_scale::fetch_all_local($courseid)) { $options[-1] = '--'.get_string('scalescustom'); foreach($scales as $scale) { $options[$scale->id] = $scale->get_name(); } } if ($scales = grade_scale::fetch_all_global()) { $options[-2] = '--'.get_string('scalesstandard'); foreach($scales as $scale) { $options[$scale->id] = $scale->get_name(); } } $scale_el =& $mform->getElement('scaleid'); $scale_el->load($options); } else { $options = array(); if ($scales = grade_scale::fetch_all_global()) { foreach($scales as $scale) { $options[$scale->id] = $scale->get_name(); } } $scale_el =& $mform->getElement('scaleid'); $scale_el->load($options); } if ($id = $mform->getElementValue('id')) { $outcome = grade_outcome::fetch(array('id'=>$id)); $itemcount = $outcome->get_item_uses_count(); $coursecount = $outcome->get_course_uses_count(); if ($itemcount) { $mform->hardFreeze('scaleid'); } if (empty($courseid)) { $mform->hardFreeze('standard'); } else if (!has_capability('moodle/grade:manage', context_system::instance())) { $mform->hardFreeze('standard'); } else if ($coursecount and empty($outcome->courseid)) { $mform->hardFreeze('standard'); } } else { if (empty($courseid) or !has_capability('moodle/grade:manage', context_system::instance())) { $mform->hardFreeze('standard'); } } } /// perform extra validation before submission function validation($data, $files) { $errors = parent::validation($data, $files); if ($data['scaleid'] < 1) { $errors['scaleid'] = get_string('required'); } if (!empty($data['standard']) and $scale = grade_scale::fetch(array('id'=>$data['scaleid']))) { if (!empty($scale->courseid)) { //TODO: localize $errors['scaleid'] = 'Can not use custom scale in global outcome!'; } } return $errors; } } outcome/edit.php 0000644 00000014315 15151222054 0007656 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/>. /** * Edit page for grade outcomes. * * @package core_grades * @copyright 2008 Nicolas Connault * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once '../../../config.php'; require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->dirroot.'/grade/report/lib.php'; require_once 'edit_form.php'; $courseid = optional_param('courseid', 0, PARAM_INT); $id = optional_param('id', 0, PARAM_INT); $url = new moodle_url('/grade/edit/outcome/edit.php'); if ($courseid !== 0) { $url->param('courseid', $courseid); } if ($id !== 0) { $url->param('id', $id); } $PAGE->set_url($url); $PAGE->set_pagelayout('admin'); $systemcontext = context_system::instance(); $heading = get_string('addoutcome', 'grades'); // a bit complex access control :-O if ($id) { $heading = get_string('editoutcome', 'grades'); /// editing existing outcome if (!$outcome_rec = $DB->get_record('grade_outcomes', array('id' => $id))) { throw new \moodle_exception('invalidoutcome'); } if ($outcome_rec->courseid) { $outcome_rec->standard = 0; if (!$course = $DB->get_record('course', array('id' => $outcome_rec->courseid))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($course->id); require_capability('moodle/grade:manage', $context); $courseid = $course->id; } else { if ($courseid) { if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } } $outcome_rec->standard = 1; $outcome_rec->courseid = $courseid; require_login(); require_capability('moodle/grade:manage', $systemcontext); $PAGE->set_context($systemcontext); } } else if ($courseid){ /// adding new outcome from course $course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST); require_login($course); $context = context_course::instance($course->id); require_capability('moodle/grade:manage', $context); $outcome_rec = new stdClass(); $outcome_rec->standard = 0; $outcome_rec->courseid = $courseid; } else { require_login(); require_capability('moodle/grade:manage', $systemcontext); $PAGE->set_context($systemcontext); /// adding new outcome from admin section $outcome_rec = new stdClass(); $outcome_rec->standard = 1; $outcome_rec->courseid = 0; } if (!$courseid) { require_once $CFG->libdir.'/adminlib.php'; admin_externalpage_setup('outcomes'); $PAGE->set_primary_active_tab('siteadminnode'); } else { navigation_node::override_active_url(new moodle_url('/grade/edit/outcome/course.php', ['id' => $courseid])); $PAGE->navbar->add(get_string('manageoutcomes', 'grades'), new moodle_url('/grade/edit/outcome/index.php', ['id' => $courseid])); } // default return url $gpr = new grade_plugin_return(); $returnurl = $gpr->get_return_url('index.php?id='.$courseid); $editoroptions = array( 'maxfiles' => EDITOR_UNLIMITED_FILES, 'maxbytes' => $CFG->maxbytes, 'trusttext' => false, 'noclean' => true, 'context' => $systemcontext ); if (!empty($outcome_rec->id)) { $editoroptions['subdirs'] = file_area_contains_subdirs($systemcontext, 'grade', 'outcome', $outcome_rec->id); $outcome_rec = file_prepare_standard_editor($outcome_rec, 'description', $editoroptions, $systemcontext, 'grade', 'outcome', $outcome_rec->id); } else { $editoroptions['subdirs'] = false; $outcome_rec = file_prepare_standard_editor($outcome_rec, 'description', $editoroptions, $systemcontext, 'grade', 'outcome', null); } $mform = new edit_outcome_form(null, compact('gpr', 'editoroptions')); $mform->set_data($outcome_rec); if ($mform->is_cancelled()) { redirect($returnurl); } else if ($data = $mform->get_data()) { $outcome = new grade_outcome(array('id'=>$id)); $data->usermodified = $USER->id; if (empty($outcome->id)) { $data->description = $data->description_editor['text']; grade_outcome::set_properties($outcome, $data); if (!has_capability('moodle/grade:manage', $systemcontext)) { $data->standard = 0; } $outcome->courseid = !empty($data->standard) ? null : $courseid; if (empty($outcome->courseid)) { $outcome->courseid = null; } $outcome->insert(); $data = file_postupdate_standard_editor($data, 'description', $editoroptions, $systemcontext, 'grade', 'outcome', $outcome->id); $DB->set_field($outcome->table, 'description', $data->description, array('id'=>$outcome->id)); } else { $data = file_postupdate_standard_editor($data, 'description', $editoroptions, $systemcontext, 'grade', 'outcome', $id); grade_outcome::set_properties($outcome, $data); if (isset($data->standard)) { $outcome->courseid = !empty($data->standard) ? null : $courseid; } else { unset($outcome->courseid); // keep previous } $outcome->update(); } redirect($returnurl); } $PAGE->navbar->add($heading, $url); print_grade_page_head($courseid ?: SITEID, 'outcome', 'edit', $heading, false, false, false); if (!grade_scale::fetch_all_local($courseid) && !grade_scale::fetch_all_global()) { echo $OUTPUT->confirm(get_string('noscales', 'grades'), $CFG->wwwroot.'/grade/edit/scale/edit.php?courseid='.$courseid, $returnurl); echo $OUTPUT->footer(); die(); } $mform->display(); echo $OUTPUT->footer(); outcome/course.php 0000644 00000011764 15151222054 0010236 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 page for selecting outcomes for use in a course * * @package core_grades * @copyright 2007 Petr Skoda * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once '../../../config.php'; require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->libdir.'/gradelib.php'; $courseid = required_param('id', PARAM_INT); $PAGE->set_url('/grade/edit/outcome/course.php', array('id'=>$courseid)); $course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST); /// Make sure they can even access this course require_login($course); $context = context_course::instance($course->id); require_capability('moodle/course:update', $context); /// return tracking object $gpr = new grade_plugin_return(array('type'=>'edit', 'plugin'=>'outcomes', 'courseid'=>$courseid)); // first of all fix the state of outcomes_course table $standardoutcomes = grade_outcome::fetch_all_global(); $co_custom = grade_outcome::fetch_all_local($courseid); $co_standard_used = array(); $co_standard_notused = array(); if ($courseused = $DB->get_records('grade_outcomes_courses', array('courseid' => $courseid), '', 'outcomeid')) { $courseused = array_keys($courseused); } else { $courseused = array(); } // fix wrong entries in outcomes_courses foreach ($courseused as $oid) { if (!array_key_exists($oid, $standardoutcomes) and !array_key_exists($oid, $co_custom)) { $DB->delete_records('grade_outcomes_courses', array('outcomeid' => $oid, 'courseid' => $courseid)); } } // fix local custom outcomes missing in outcomes_course foreach($co_custom as $oid=>$outcome) { if (!in_array($oid, $courseused)) { $courseused[$oid] = $oid; $goc = new stdClass(); $goc->courseid = $courseid; $goc->outcomeid = $oid; $DB->insert_record('grade_outcomes_courses', $goc); } } // now check all used standard outcomes are in outcomes_course too $params = array($courseid); $sql = "SELECT DISTINCT outcomeid FROM {grade_items} WHERE courseid=? and outcomeid IS NOT NULL"; if ($realused = $DB->get_records_sql($sql, $params)) { $realused = array_keys($realused); foreach ($realused as $oid) { if (array_key_exists($oid, $standardoutcomes)) { $co_standard_used[$oid] = $standardoutcomes[$oid]; unset($standardoutcomes[$oid]); if (!in_array($oid, $courseused)) { $courseused[$oid] = $oid; $goc = new stdClass(); $goc->courseid = $courseid; $goc->outcomeid = $oid; $DB->insert_record('grade_outcomes_courses', $goc); } } } } // find all unused standard course outcomes - candidates for removal foreach ($standardoutcomes as $oid=>$outcome) { if (in_array($oid, $courseused)) { $co_standard_notused[$oid] = $standardoutcomes[$oid]; unset($standardoutcomes[$oid]); } } /// form processing if ($data = data_submitted() and confirm_sesskey()) { require_capability('moodle/grade:manageoutcomes', $context); if (!empty($data->add) && !empty($data->addoutcomes)) { /// add all selected to course list foreach ($data->addoutcomes as $add) { $add = clean_param($add, PARAM_INT); if (!array_key_exists($add, $standardoutcomes)) { continue; } $goc = new stdClass(); $goc->courseid = $courseid; $goc->outcomeid = $add; $DB->insert_record('grade_outcomes_courses', $goc); } } else if (!empty($data->remove) && !empty($data->removeoutcomes)) { /// remove all selected from course outcomes list foreach ($data->removeoutcomes as $remove) { $remove = clean_param($remove, PARAM_INT); if (!array_key_exists($remove, $co_standard_notused)) { continue; } $DB->delete_records('grade_outcomes_courses', array('courseid' => $courseid, 'outcomeid' => $remove)); } } redirect('course.php?id='.$courseid); // we must redirect to get fresh data } $actionbar = new \core_grades\output\course_outcomes_action_bar($context); // Print header. print_grade_page_head($COURSE->id, 'outcome', 'course', false, false, false, true, null, null, null, $actionbar); require('course_form.html'); echo $OUTPUT->footer(); outcome/export.php 0000644 00000010243 15151222054 0010246 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/>. /** * Exports selected outcomes in CSV format * * @package core_grades * @copyright 2008 Moodle Pty Ltd (http://moodle.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once '../../../config.php'; require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->libdir.'/gradelib.php'; $courseid = optional_param('id', 0, PARAM_INT); $action = optional_param('action', '', PARAM_ALPHA); /// Make sure they can even access this course if ($courseid) { if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($course->id); require_capability('moodle/grade:manage', $context); if (empty($CFG->enableoutcomes)) { redirect('../../index.php?id='.$courseid); } } else { require_once $CFG->libdir.'/adminlib.php'; admin_externalpage_setup('outcomes'); } require_sesskey(); header("Content-Type: text/csv; charset=utf-8"); // TODO: make the filename more useful, include a date, a specific name, something... header('Content-Disposition: attachment; filename=outcomes.csv'); // sending header with clear names, to make 'what is what' as easy as possible to understand $header = array('outcome_name', 'outcome_shortname', 'outcome_description', 'scale_name', 'scale_items', 'scale_description'); echo format_csv($header, ';', '"'); $outcomes = array(); if ( $courseid ) { $outcomes = array_merge(grade_outcome::fetch_all_global(), grade_outcome::fetch_all_local($courseid)); } else { $outcomes = grade_outcome::fetch_all_global(); } foreach($outcomes as $outcome) { $line = array(); $line[] = $outcome->get_name(); $line[] = $outcome->get_shortname(); $line[] = $outcome->get_description(); $scale = $outcome->load_scale(); $line[] = $scale->get_name(); $line[] = $scale->compact_items(); $line[] = $scale->get_description(); echo format_csv($line, ';', '"'); } /** * Formats and returns a line of data, in CSV format. This code * is from http://au2.php.net/manual/en/function.fputcsv.php#77866 * * @param string[] $fields data to be exported * @param string $delimiter char to be used to separate fields * @param string $enclosure char used to enclose strings that contains newlines, spaces, tabs or the delimiter char itself * @returns string one line of csv data */ function format_csv($fields = array(), $delimiter = ';', $enclosure = '"') { $str = ''; $escape_char = '\\'; foreach ($fields as $value) { if (strpos($value, $delimiter) !== false || strpos($value, $enclosure) !== false || strpos($value, "\n") !== false || strpos($value, "\r") !== false || strpos($value, "\t") !== false || strpos($value, ' ') !== false) { $str2 = $enclosure; $escaped = 0; $len = strlen($value); for ($i=0;$i<$len;$i++) { if ($value[$i] == $escape_char) { $escaped = 1; } else if (!$escaped && $value[$i] == $enclosure) { $str2 .= $enclosure; } else { $escaped = 0; } $str2 .= $value[$i]; } $str2 .= $enclosure; $str .= $str2.$delimiter; } else { $str .= $value.$delimiter; } } $str = substr($str,0,-1); $str .= "\n"; return $str; } outcome/tabs.php 0000644 00000003041 15151222054 0007654 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/>. /** * Prints navigation tabs for viewing and editing grade outcomes * * @package core_grades * @copyright 2009 Petr Skoda * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ $row = $tabs = array(); $context = context_course::instance($courseid); $row[] = new tabobject('courseoutcomes', $CFG->wwwroot.'/grade/edit/outcome/course.php?id='.$courseid, get_string('outcomescourse', 'grades')); if (has_capability('moodle/grade:manage', $context)) { $row[] = new tabobject('outcomes', $CFG->wwwroot.'/grade/edit/outcome/index.php?id='.$courseid, get_string('editoutcomes', 'grades')); } $tabs[] = $row; echo '<div class="outcomedisplay">'; print_tabs($tabs, $currenttab); echo '</div>'; outcome/import_outcomes_form.php 0000644 00000004504 15151222054 0013203 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 form to allow importing outcomes from a file * * @package core_grades * @copyright 2008 Moodle Pty Ltd (http://moodle.com) * @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 import_outcomes_form extends moodleform { public function definition() { global $PAGE, $USER; $mform =& $this->_form; $mform->addElement('hidden', 'action', 'upload'); $mform->setType('action', PARAM_ALPHANUMEXT); $mform->addElement('hidden', 'courseid', $PAGE->course->id); $mform->setType('courseid', PARAM_INT); $scope = array(); if (($PAGE->course->id > 1) && has_capability('moodle/grade:manage', context_system::instance())) { $mform->addElement('radio', 'scope', get_string('importcustom', 'grades'), null, 'custom'); $mform->addElement('radio', 'scope', get_string('importstandard', 'grades'), null, 'global'); $mform->setDefault('scope', 'custom'); } $mform->addElement('filepicker', 'userfile', get_string('importoutcomes', 'grades')); $mform->addRule('userfile', get_string('required'), 'required', null, 'server'); $mform->addHelpButton('userfile', 'importoutcomes', 'grades'); $buttonarray = [ $mform->createElement('submit', 'save', get_string('uploadthisfile')), $mform->createElement('cancel') ]; $mform->addGroup($buttonarray, 'buttonar', '', ' ', false); } } outcome/import.php 0000644 00000024376 15151222054 0010253 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 outcomes from a file * * @package core_grades * @copyright 2008 Moodle Pty Ltd (http://moodle.com) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once(__DIR__.'/../../../config.php'); require_once($CFG->dirroot.'/lib/formslib.php'); require_once($CFG->dirroot.'/grade/lib.php'); require_once($CFG->libdir.'/gradelib.php'); require_once('import_outcomes_form.php'); $courseid = optional_param('courseid', 0, PARAM_INT); $action = optional_param('action', '', PARAM_ALPHA); $scope = optional_param('scope', 'custom', PARAM_ALPHA); $url = new moodle_url('/grade/edit/outcome/import.php', array('courseid' => $courseid)); $PAGE->set_url($url); $PAGE->set_pagelayout('admin'); /// Make sure they can even access this course if ($courseid) { if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($course->id); if (empty($CFG->enableoutcomes)) { redirect('../../index.php?id='.$courseid); } navigation_node::override_active_url(new moodle_url('/grade/edit/outcome/course.php', ['id' => $courseid])); $PAGE->navbar->add(get_string('manageoutcomes', 'grades'), new moodle_url('/grade/edit/outcome/index.php', ['id' => $courseid])); $PAGE->navbar->add(get_string('importoutcomes', 'grades'), new moodle_url('/grade/edit/outcome/import.php', ['courseid' => $courseid])); } else { require_once $CFG->libdir.'/adminlib.php'; admin_externalpage_setup('outcomes'); $context = context_system::instance(); } require_capability('moodle/grade:manageoutcomes', $context); $upload_form = new import_outcomes_form(); if ($upload_form->is_cancelled()) { redirect(new moodle_url('/grade/edit/outcome/index.php', ['id' => $courseid])); die; } print_grade_page_head($courseid, 'outcome', 'import', get_string('importoutcomes', 'grades'), false, false, false); if (!$upload_form->get_data()) { // Display the import form. $upload_form->display(); echo $OUTPUT->footer(); die; } $imported_file = $CFG->tempdir . '/outcomeimport/importedfile_'.time().'.csv'; make_temp_directory('outcomeimport'); // copying imported file if (!$upload_form->save_file('userfile', $imported_file, true)) { redirect('import.php'. ($courseid ? "?courseid=$courseid" : ''), get_string('importfilemissing', 'grades')); } /// which scope are we importing the outcomes in? if (isset($courseid) && ($scope == 'custom')) { // custom scale $local_scope = true; } elseif (($scope == 'global') && has_capability('moodle/grade:manage', context_system::instance())) { // global scale $local_scope = false; } else { // shouldn't happen .. user might be trying to access this script without the right permissions. redirect('index.php', get_string('importerror', 'grades')); } // open the file, start importing data if ($handle = fopen($imported_file, 'r')) { $line = 0; // will keep track of current line, to give better error messages. $file_headers = ''; // $csv_data needs to have at least these columns, the value is the default position in the data file. $headers = array('outcome_name' => 0, 'outcome_shortname' => 1, 'scale_name' => 3, 'scale_items' => 4); $optional_headers = array('outcome_description'=>2, 'scale_description' => 5); $imported_headers = array(); // will later be initialized with the values found in the file $fatal_error = false; $errormessage = ''; // data should be separated by a ';'. *NOT* by a comma! TODO: version 2.0 // or whenever we can depend on PHP5, set the second parameter (8192) to 0 (unlimited line length) : the database can store over 128k per line. while ( $csv_data = fgetcsv($handle, 8192, ';', '"')) { // if the line is over 8k, it won't work... $line++; // be tolerant on input, as fgetcsv returns "an array comprising a single null field" on blank lines if ($csv_data == array(null)) { continue; } // on first run, grab and analyse the header if ($file_headers == '') { $file_headers = array_flip($csv_data); // save the header line ... TODO: use the header line to let import work with columns in arbitrary order $error = false; foreach($headers as $key => $value) { // sanity check #1: make sure the file contains all the mandatory headers if (!array_key_exists($key, $file_headers)) { $error = true; break; } } if ($error) { $fatal_error = true; $errormessage = get_string('importoutcomenofile', 'grades', $line); break; } foreach(array_merge($headers, $optional_headers) as $header => $position) { // match given columns to expected columns *into* $headers $imported_headers[$header] = $file_headers[$header]; } continue; // we don't import headers } // sanity check #2: every line must have the same number of columns as there are // headers. If not, processing stops. if ( count($csv_data) != count($file_headers) ) { $fatal_error = true; $errormessage = get_string('importoutcomenofile', 'grades', $line); break; } // sanity check #3: all required fields must be present on the current line. foreach ($headers as $header => $position) { if ($csv_data[$imported_headers[$header]] == '') { $fatal_error = true; $errormessage = get_string('importoutcomenofile', 'grades', $line); break; } } // MDL-17273 errors in csv are not preventing import from happening. We break from the while loop here if ($fatal_error) { break; } $params = array($csv_data[$imported_headers['outcome_shortname']]); $wheresql = 'shortname = ? '; if ($local_scope) { $params[] = $courseid; $wheresql .= ' AND courseid = ?'; } else { $wheresql .= ' AND courseid IS NULL'; } $outcome = $DB->get_records_select('grade_outcomes', $wheresql, $params); if ($outcome) { // already exists, print a message and skip. echo $OUTPUT->notification(get_string('importskippedoutcome', 'grades', $csv_data[$imported_headers['outcome_shortname']]), 'info', false); continue; } // new outcome will be added, search for compatible existing scale... $params = array($csv_data[$imported_headers['scale_name']], $csv_data[$imported_headers['scale_items']], $courseid); $wheresql = 'name = ? AND scale = ? AND (courseid = ? OR courseid = 0)'; $scale = $DB->get_records_select('scale', $wheresql, $params); if ($scale) { // already exists in the right scope: use it. $scale_id = key($scale); } else { if (!has_capability('moodle/course:managescales', $context)) { echo $OUTPUT->notification(get_string('importskippedoutcome', 'grades', $csv_data[$imported_headers['outcome_shortname']]), 'warning', false); continue; } else { // scale doesn't exists : create it. $scale_data = array('name' => $csv_data[$imported_headers['scale_name']], 'scale' => $csv_data[$imported_headers['scale_items']], 'description' => $csv_data[$imported_headers['scale_description']], 'userid' => $USER->id); if ($local_scope) { $scale_data['courseid'] = $courseid; } else { $scale_data['courseid'] = 0; // 'global' : scale use '0', outcomes use null } $scale = new grade_scale($scale_data); $scale_id = $scale->insert(); } } // add outcome $outcome_data = array('shortname' => $csv_data[$imported_headers['outcome_shortname']], 'fullname' => $csv_data[$imported_headers['outcome_name']], 'scaleid' => $scale_id, 'description' => $csv_data[$imported_headers['outcome_description']], 'usermodified' => $USER->id); if ($local_scope) { $outcome_data['courseid'] = $courseid; } else { $outcome_data['courseid'] = null; // 'global' : scale use '0', outcomes use null } $outcome = new grade_outcome($outcome_data); $outcome_id = $outcome->insert(); $outcome_success_strings = new StdClass(); $outcome_success_strings->name = $outcome_data['fullname']; $outcome_success_strings->id = $outcome_id; echo $OUTPUT->notification(get_string('importoutcomesuccess', 'grades', $outcome_success_strings), 'success', false); } if ($fatal_error) { echo $OUTPUT->notification($errormessage, 'error', false); echo $OUTPUT->single_button(new moodle_url('/grade/edit/outcome/import.php', ['courseid' => $courseid]), get_string('back'), 'get'); } else { echo $OUTPUT->single_button(new moodle_url('/grade/edit/outcome/index.php', ['id' => $courseid]), get_string('continue'), 'get'); } } else { echo $OUTPUT->box(get_string('importoutcomenofile', 'grades', 0)); } // finish fclose($handle); // delete temp file unlink($imported_file); echo $OUTPUT->footer(); outcome/index.php 0000644 00000022723 15151222054 0010042 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/>. /** * Listing page for grade outcomes. * * @package core_grades * @copyright 2008 Nicolas Connault * @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'); require_once($CFG->libdir.'/gradelib.php'); $courseid = optional_param('id', 0, PARAM_INT); $action = optional_param('action', '', PARAM_ALPHA); $url = new moodle_url('/grade/edit/outcome/index.php', ['id' => $courseid]); $PAGE->set_url($url); $PAGE->set_pagelayout('admin'); /// Make sure they can even access this course if ($courseid) { $course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST); require_login($course); $context = context_course::instance($course->id); require_capability('moodle/grade:manageoutcomes', $context); if (empty($CFG->enableoutcomes)) { redirect('../../index.php?id='.$courseid); } // This page doesn't exist on the navigation so map it to another navigation_node::override_active_url(new moodle_url('/grade/edit/outcome/course.php', array('id'=>$courseid))); $PAGE->navbar->add(get_string('manageoutcomes', 'grades'), $url); } else { if (empty($CFG->enableoutcomes)) { redirect('../../../'); } require_once $CFG->libdir.'/adminlib.php'; admin_externalpage_setup('outcomes'); $context = context_system::instance(); $PAGE->set_primary_active_tab('siteadminnode'); } /// return tracking object $gpr = new grade_plugin_return(array('type'=>'edit', 'plugin'=>'outcome', 'courseid'=>$courseid)); $strshortname = get_string('outcomeshortname', 'grades'); $strfullname = get_string('outcomefullname', 'grades'); $strscale = get_string('scale'); $strstandardoutcome = get_string('outcomesstandard', 'grades'); $strcustomoutcomes = get_string('outcomescustom', 'grades'); $strcreatenewoutcome = get_string('outcomecreate', 'grades'); $stritems = get_string('items', 'grades'); $strcourses = get_string('courses'); $stredit = get_string('edit'); switch ($action) { case 'delete': if (!confirm_sesskey()) { break; } $outcomeid = required_param('outcomeid', PARAM_INT); if (!$outcome = grade_outcome::fetch(array('id'=>$outcomeid))) { break; } if (empty($outcome->courseid)) { require_capability('moodle/grade:manage', context_system::instance()); } else if ($outcome->courseid != $courseid) { throw new \moodle_exception('invalidcourseid'); } if (!$outcome->can_delete()) { break; } $deleteconfirmed = optional_param('deleteconfirmed', 0, PARAM_BOOL); if(!$deleteconfirmed){ $PAGE->set_title(get_string('outcomedelete', 'grades')); $PAGE->navbar->add(get_string('outcomedelete', 'grades')); echo $OUTPUT->header(); $confirmurl = new moodle_url('index.php', array( 'id' => $courseid, 'outcomeid' => $outcome->id, 'action'=> 'delete', 'sesskey' => sesskey(), 'deleteconfirmed'=> 1)); echo $OUTPUT->confirm(get_string('outcomeconfirmdelete', 'grades', $outcome->fullname), $confirmurl, "index.php?id={$courseid}"); echo $OUTPUT->footer(); die; }else{ $outcome->delete(); } break; } $systemcontext = context_system::instance(); $caneditsystemscales = has_capability('moodle/course:managescales', $systemcontext); if ($courseid) { $caneditcoursescales = has_capability('moodle/course:managescales', $context); } else { $caneditcoursescales = $caneditsystemscales; } $outcomes_tables = array(); $heading = get_string('outcomes', 'grades'); if ($courseid and $outcomes = grade_outcome::fetch_all_local($courseid)) { $return = $OUTPUT->heading($strcustomoutcomes, 3, 'main mt-3'); $data = array(); foreach($outcomes as $outcome) { $line = array(); $line[] = $outcome->get_name(); $line[] = $outcome->get_shortname(); $scale = $outcome->load_scale(); if (empty($scale->id)) { // hopefully never happens $line[] = $scale->get_name(); debugging("Found a scale with no ID ({$scale->get_name()}) while outputting course outcomes", DEBUG_DEVELOPER); } else { if (empty($scale->courseid)) { $caneditthisscale = $caneditsystemscales; } else if ($scale->courseid == $courseid) { $caneditthisscale = $caneditcoursescales; } else { $context = context_course::instance($scale->courseid); $caneditthisscale = has_capability('moodle/course:managescales', $context); } if ($caneditthisscale) { $line[] = grade_print_scale_link($courseid, $scale, $gpr); } else { $line[] = $scale->get_name(); } } $line[] = $outcome->get_item_uses_count(); $buttons = grade_button('edit', $courseid, $outcome); if ($outcome->can_delete()) { $buttons .= grade_button('delete', $courseid, $outcome); } $line[] = $buttons; $data[] = $line; } $table = new html_table(); $table->head = array($strfullname, $strshortname, $strscale, $stritems, $stredit); $table->size = array('30%', '20%', '20%', '20%', '10%' ); $table->align = array('left', 'left', 'left', 'center', 'center'); $table->width = '90%'; $table->data = $data; $return .= html_writer::table($table); $outcomes_tables[] = $return; } if ($outcomes = grade_outcome::fetch_all_global()) { $return = $OUTPUT->heading($strstandardoutcome, 3, 'main mt-3'); $data = array(); foreach($outcomes as $outcome) { $line = array(); $line[] = $outcome->get_name(); $line[] = $outcome->get_shortname(); $scale = $outcome->load_scale(); if (empty($scale->id)) { // hopefully never happens $line[] = $scale->get_name(); debugging("Found a scale with no ID ({$scale->get_name()}) while outputting global outcomes", DEBUG_DEVELOPER); } else { if (empty($scale->courseid)) { $caneditthisscale = $caneditsystemscales; } else if ($scale->courseid == $courseid) { $caneditthisscale = $caneditcoursescales; } else { $context = context_course::instance($scale->courseid); $caneditthisscale = has_capability('moodle/course:managescales', $context); } if ($caneditthisscale) { $line[] = grade_print_scale_link($courseid, $scale, $gpr); } else { $line[] = $scale->get_name(); } } $line[] = $outcome->get_course_uses_count(); $line[] = $outcome->get_item_uses_count(); $buttons = ""; if (has_capability('moodle/grade:manage', context_system::instance())) { $buttons .= grade_button('edit', $courseid, $outcome); } if (has_capability('moodle/grade:manage', context_system::instance()) and $outcome->can_delete()) { $buttons .= grade_button('delete', $courseid, $outcome); } $line[] = $buttons; $data[] = $line; } $table = new html_table(); $table->head = array($strfullname, $strshortname, $strscale, $strcourses, $stritems, $stredit); $table->size = array('30%', '20%', '20%', '10%', '10%', '10%'); $table->align = array('left', 'left', 'left', 'center', 'center', 'center'); $table->width = '90%'; $table->data = $data; $return .= html_writer::table($table); $outcomes_tables[] = $return; } $actionbar = new \core_grades\output\manage_outcomes_action_bar($context, !empty($outcomes_tables)); print_grade_page_head($courseid ?: SITEID, 'outcome', 'edit', $heading, false, false, true, null, null, null, $actionbar); // If there are existing outcomes, output the outcome tables. if (!empty($outcomes_tables)) { foreach ($outcomes_tables as $table) { echo $table; } } else { echo $OUTPUT->notification(get_string('noexistingoutcomes', 'grades'), 'info', false); } echo $OUTPUT->footer(); /** * Local shortcut function for creating a link to a scale. * @param int $courseid The Course ID * @param grade_scale $scale The Scale to link to * @param grade_plugin_return $gpr An object used to identify the page we just came from * @return string html */ function grade_print_scale_link($courseid, $scale, $gpr) { global $CFG, $OUTPUT; $url = new moodle_url('/grade/edit/scale/edit.php', array('courseid' => $courseid, 'id' => $scale->id)); $url = $gpr->add_url_params($url); return html_writer::link($url, $scale->get_name()); } settings/form.php 0000644 00000016114 15151222054 0010060 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 form for editing course grade settings * * @package core_grades * @copyright 2007 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->libdir.'/formslib.php'); /** * First implementation of the preferences in the form of a moodleform. * TODO add "reset to site defaults" button */ class course_settings_form extends moodleform { function definition() { global $USER, $CFG; $mform =& $this->_form; $systemcontext = context_system::instance(); $can_view_admin_links = false; if (has_capability('moodle/grade:manage', $systemcontext)) { $can_view_admin_links = true; } // General settings $strchangedefaults = get_string('changedefaults', 'grades'); $mform->addElement('header', 'general', get_string('generalsettings', 'grades')); if ($can_view_admin_links) { $link = '<a href="' . $CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=gradessettings">' . $strchangedefaults . '</a>'; $mform->addElement('static', 'generalsettingslink', null, $link); } $options = array(-1 => get_string('default', 'grades'), GRADE_REPORT_AGGREGATION_POSITION_FIRST => get_string('positionfirst', 'grades'), GRADE_REPORT_AGGREGATION_POSITION_LAST => get_string('positionlast', 'grades')); $default_gradedisplaytype = $CFG->grade_aggregationposition; foreach ($options as $key=>$option) { if ($key == $default_gradedisplaytype) { $options[-1] = get_string('defaultprev', 'grades', $option); break; } } $mform->addElement('select', 'aggregationposition', get_string('aggregationposition', 'grades'), $options); $mform->addHelpButton('aggregationposition', 'aggregationposition', 'grades'); if ($CFG->grade_minmaxtouse == GRADE_MIN_MAX_FROM_GRADE_ITEM) { $default = get_string('gradeitemminmax', 'grades'); } else if ($CFG->grade_minmaxtouse == GRADE_MIN_MAX_FROM_GRADE_GRADE) { $default = get_string('gradegrademinmax', 'grades'); } else { throw new coding_exception('Invalid $CFG->grade_minmaxtouse value.'); } $options = array( -1 => get_string('defaultprev', 'grades', $default), GRADE_MIN_MAX_FROM_GRADE_ITEM => get_string('gradeitemminmax', 'grades'), GRADE_MIN_MAX_FROM_GRADE_GRADE => get_string('gradegrademinmax', 'grades') ); $mform->addElement('select', 'minmaxtouse', get_string('minmaxtouse', 'grades'), $options); $mform->addHelpButton('minmaxtouse', 'minmaxtouse', 'grades'); // Grade item settings $mform->addElement('header', 'grade_item_settings', get_string('gradeitemsettings', 'grades')); $mform->setExpanded('grade_item_settings'); if ($can_view_admin_links) { $link = '<a href="' . $CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=gradeitemsettings">' . $strchangedefaults . '</a>'; $mform->addElement('static', 'gradeitemsettingslink', null, $link); } $options = array(-1 => get_string('default', 'grades'), GRADE_DISPLAY_TYPE_REAL => get_string('real', 'grades'), GRADE_DISPLAY_TYPE_REAL_PERCENTAGE => get_string('realpercentage', 'grades'), GRADE_DISPLAY_TYPE_REAL_LETTER => get_string('realletter', 'grades'), GRADE_DISPLAY_TYPE_PERCENTAGE => get_string('percentage', 'grades'), GRADE_DISPLAY_TYPE_PERCENTAGE_REAL => get_string('percentagereal', 'grades'), GRADE_DISPLAY_TYPE_PERCENTAGE_LETTER => get_string('percentageletter', 'grades'), GRADE_DISPLAY_TYPE_LETTER => get_string('letter', 'grades'), GRADE_DISPLAY_TYPE_LETTER_REAL => get_string('letterreal', 'grades'), GRADE_DISPLAY_TYPE_LETTER_PERCENTAGE => get_string('letterpercentage', 'grades')); $default_gradedisplaytype = $CFG->grade_displaytype; foreach ($options as $key=>$option) { if ($key == $default_gradedisplaytype) { $options[-1] = get_string('defaultprev', 'grades', $option); break; } } $mform->addElement('select', 'displaytype', get_string('gradedisplaytype', 'grades'), $options); $mform->addHelpButton('displaytype', 'gradedisplaytype', 'grades'); $mform->setDefault('displaytype', -1); $options = array(-1=> get_string('defaultprev', 'grades', $CFG->grade_decimalpoints), 0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5); $mform->addElement('select', 'decimalpoints', get_string('decimalpoints', 'grades'), $options); $mform->addHelpButton('decimalpoints', 'decimalpoints', 'grades'); // add setting options for plugins $types = array('report', 'export', 'import'); foreach($types as $type) { foreach (core_component::get_plugin_list('grade'.$type) as $plugin => $plugindir) { // Include all the settings commands for this plugin if there are any if (file_exists($plugindir.'/lib.php')) { require_once($plugindir.'/lib.php'); $functionname = 'grade_'.$type.'_'.$plugin.'_settings_definition'; if (function_exists($functionname)) { $mform->addElement('header', 'grade_'.$type.$plugin, get_string('pluginname', 'grade'.$type.'_'.$plugin, NULL)); $mform->setExpanded('grade_'.$type.$plugin); if ($can_view_admin_links) { $link = '<a href="' . $CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=gradereport' . $plugin . '">' . $strchangedefaults . '</a>'; $mform->addElement('static', 'gradeitemsettingslink', null, $link); } $functionname($mform); } } } } $mform->addElement('hidden', 'id'); $mform->setType('id', PARAM_INT); $this->add_action_buttons(false); } } settings/index.php 0000644 00000006025 15151222054 0010224 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 page for editing course grade settings * * @package core_grades * @copyright 2007 Petr Skoda * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once '../../../config.php'; require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->libdir.'/gradelib.php'; require_once 'form.php'; $courseid = optional_param('id', SITEID, PARAM_INT); $PAGE->set_url('/grade/edit/settings/index.php', array('id'=>$courseid)); $PAGE->set_pagelayout('admin'); if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($course->id); require_capability('moodle/grade:manage', $context); $gpr = new grade_plugin_return(array('type'=>'edit', 'plugin'=>'settings', 'courseid'=>$courseid)); $strgrades = get_string('grades'); $pagename = get_string('coursesettings', 'grades'); $mform = new course_settings_form(); $settings = grade_get_settings($course->id); $mform->set_data($settings); if ($data = $mform->get_data()) { $data = (array)$data; $general = array('displaytype', 'decimalpoints', 'aggregationposition', 'minmaxtouse'); foreach ($data as $key=>$value) { if (!in_array($key, $general) and strpos($key, 'report_') !== 0 and strpos($key, 'import_') !== 0 and strpos($key, 'export_') !== 0) { continue; } if ($value == -1) { $value = null; } grade_set_setting($course->id, $key, $value); $previousvalue = isset($settings->{$key}) ? $settings->{$key} : null; if ($key == 'minmaxtouse' && $previousvalue != $value) { // The min max has changed, we need to regrade the grades. grade_force_full_regrading($courseid); } } } print_grade_page_head($courseid, 'settings', 'coursesettings', get_string('coursegradesettings', 'grades')); // The settings could have been changed due to a notice shown in print_grade_page_head, we need to refresh them. $settings = grade_get_settings($course->id); $mform->set_data($settings); echo $OUTPUT->box_start('generalbox boxaligncenter boxwidthnormal centerpara'); echo get_string('coursesettingsexplanation', 'grades'); echo $OUTPUT->box_end(); $mform->display(); echo $OUTPUT->footer(); tree/grade.php 0000644 00000024262 15151222054 0007301 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/>. /** * Edit a user's grade for a particular activity * * @package core_grades * @copyright 2007 Petr Skoda * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once '../../../config.php'; require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->dirroot.'/grade/report/lib.php'; require_once 'grade_form.php'; $courseid = required_param('courseid', PARAM_INT); $id = optional_param('id', 0, PARAM_INT); $itemid = optional_param('itemid', 0, PARAM_INT); $userid = optional_param('userid', 0, PARAM_INT); $url = new moodle_url('/grade/edit/tree/grade.php', array('courseid'=>$courseid)); if ($id !== 0) { $url->param('id', $id); } if ($itemid !== 0) { $url->param('itemid', $itemid); } if ($userid !== 0) { $url->param('userid', $userid); } $PAGE->set_url($url); if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } $PAGE->set_pagelayout('incourse'); require_login($course); $context = context_course::instance($course->id); if (!has_capability('moodle/grade:manage', $context)) { require_capability('moodle/grade:edit', $context); } // default return url $gpr = new grade_plugin_return(); $returnurl = $gpr->get_return_url($CFG->wwwroot.'/grade/report/index.php?id='.$course->id); // security checks! if (!empty($id)) { if (!$grade = $DB->get_record('grade_grades', array('id' => $id))) { throw new \moodle_exception('invalidgroupid'); } if (!empty($itemid) and $itemid != $grade->itemid) { throw new \moodle_exception('invaliditemid'); } $itemid = $grade->itemid; if (!empty($userid) and $userid != $grade->userid) { throw new \moodle_exception('invaliduser'); } $userid = $grade->userid; unset($grade); } else if (empty($userid) or empty($itemid)) { throw new \moodle_exception('missinguseranditemid'); } if (!$grade_item = grade_item::fetch(array('id'=>$itemid, 'courseid'=>$courseid))) { throw new \moodle_exception('cannotfindgradeitem'); } // now verify grading user has access to all groups or is member of the same group when separate groups used in course if (groups_get_course_groupmode($COURSE) == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context)) { if ($groups = groups_get_all_groups($COURSE->id, $userid)) { $ok = false; foreach ($groups as $group) { if (groups_is_member($group->id, $USER->id)) { $ok = true; } } if (!$ok) { throw new \moodle_exception('cannotgradeuser'); } } else { throw new \moodle_exception('cannotgradeuser'); } } $mform = new edit_grade_form(null, array('grade_item'=>$grade_item, 'gpr'=>$gpr)); if ($grade = $DB->get_record('grade_grades', array('itemid' => $grade_item->id, 'userid' => $userid))) { // always clean existing feedback - grading should not have XSS risk if (empty($grade->feedback)) { $grade->feedback = ''; } else { $options = new stdClass(); $options->smiley = false; $options->filter = false; $options->noclean = false; $options->para = false; $grade->feedback = format_text($grade->feedback, $grade->feedbackformat, $options); } $grade->feedbackformat = FORMAT_HTML; $grade->locked = $grade->locked > 0 ? 1:0; $grade->overridden = $grade->overridden > 0 ? 1:0; $grade->excluded = $grade->excluded > 0 ? 1:0; if ($grade->hidden > 1) { $grade->hiddenuntil = $grade->hidden; $grade->hidden = 1; } else { $grade->hiddenuntil = 0; } if ($grade_item->is_hidden()) { $grade->hidden = 1; } if ($grade_item->is_locked()) { $grade->locked = 1; } // normalize the final grade value if ($grade_item->gradetype == GRADE_TYPE_SCALE) { if (empty($grade->finalgrade)) { $grade->finalgrade = -1; } else { $grade->finalgrade = (int)$grade->finalgrade; } } else if ($grade_item->gradetype == GRADE_TYPE_VALUE) { $grade->finalgrade = format_float($grade->finalgrade, $grade_item->get_decimals()); } $grade->oldgrade = $grade->finalgrade; $grade->oldfeedback = $grade->feedback; $grade->feedback = array('text'=>$grade->feedback, 'format'=>$grade->feedbackformat); $mform->set_data($grade); } else { $grade = new stdClass(); $grade->feedback = array('text'=>'', 'format'=>FORMAT_HTML); $mform->set_data(array('itemid'=>$itemid, 'userid'=>$userid, 'locked'=>$grade_item->locked, 'locktime'=>$grade_item->locktime)); } if ($mform->is_cancelled()) { redirect($returnurl); // form processing } else if ($data = $mform->get_data(false)) { if (isset($data->feedback) && is_array($data->feedback)) { $data->feedbackformat = $data->feedback['format']; $data->feedback = $data->feedback['text']; } $old_grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true); //might not exist yet // fix no grade for scales if (!isset($data->finalgrade) or $data->finalgrade == $data->oldgrade) { $data->finalgrade = $old_grade_grade->finalgrade; } else if ($grade_item->gradetype == GRADE_TYPE_SCALE) { if ($data->finalgrade < 1) { $data->finalgrade = NULL; } } else if ($grade_item->gradetype == GRADE_TYPE_VALUE) { $data->finalgrade = unformat_float($data->finalgrade); } else { //this should not happen $data->finalgrade = $old_grade_grade->finalgrade; } // the overriding of feedback is tricky - we have to care about external items only if (!property_exists($data, 'feedback') or $data->feedback == $data->oldfeedback) { $data->feedback = $old_grade_grade->feedback; $data->feedbackformat = $old_grade_grade->feedbackformat; } // update final grade or feedback // when we set override grade the first time, it happens here $grade_item->update_final_grade($data->userid, $data->finalgrade, 'editgrade', $data->feedback, $data->feedbackformat); $grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true); $grade_grade->grade_item =& $grade_item; // no db fetching if (has_capability('moodle/grade:manage', $context) or has_capability('moodle/grade:edit', $context)) { // change overridden flag if (!isset($data->overridden)) { $data->overridden = 0; // checkbox unticked } $grade_grade->set_overridden($data->overridden); } if (has_capability('moodle/grade:manage', $context) or has_capability('moodle/grade:hide', $context)) { $hidden = empty($data->hidden) ? 0: $data->hidden; $hiddenuntil = empty($data->hiddenuntil) ? 0: $data->hiddenuntil; if ($grade_item->is_hidden()) { if ($old_grade_grade->hidden == 1 and $hiddenuntil == 0) { //nothing to do - grade was originally hidden, we want to keep it that way } else { $grade_grade->set_hidden($hiddenuntil); } } else { if ($hiddenuntil) { $grade_grade->set_hidden($hiddenuntil); } else { $grade_grade->set_hidden($hidden); // checkbox data might be undefined } } } if (isset($data->locked) and !$grade_item->is_locked()) { if (($old_grade_grade->locked or $old_grade_grade->locktime) and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context))) { //ignore data } else if ((!$old_grade_grade->locked and !$old_grade_grade->locktime) and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context))) { //ignore data } else { $grade_grade->set_locktime($data->locktime); //set_lock may reset locktime $grade_grade->set_locked($data->locked, false, true); // reload grade in case it was regraded from activity $grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true); $grade_grade->grade_item =& $grade_item; // no db fetching } } if (isset($data->excluded) and has_capability('moodle/grade:manage', $context)) { $grade_grade->set_excluded($data->excluded); } // detect cases when we need to do full regrading if ($old_grade_grade->excluded != $grade_grade->excluded) { $parent = $grade_item->get_parent_category(); $parent->force_regrading(); } else if ($old_grade_grade->overridden != $grade_grade->overridden and empty($grade_grade->overridden)) { // only when unoverridding $grade_item->force_regrading(); } else if ($old_grade_grade->locktime != $grade_grade->locktime) { $grade_item->force_regrading(); } redirect($returnurl); } $strgrades = get_string('grades'); $strgraderreport = get_string('graderreport', 'grades'); $strgradeedit = get_string('editgrade', 'grades'); $struser = get_string('user'); grade_build_nav(__FILE__, $strgradeedit, array('courseid' => $courseid)); /*********** BEGIN OUTPUT *************/ $PAGE->set_title($strgrades . ': ' . $strgraderreport . ': ' . $strgradeedit); $PAGE->set_heading($course->fullname); echo $OUTPUT->header(); echo $OUTPUT->heading($strgradeedit); echo $OUTPUT->box_start(); // Form if in edit or add modes $mform->display(); echo $OUTPUT->box_end(); echo $OUTPUT->footer(); die; tree/outcomeitem.php 0000644 00000021325 15151222054 0010546 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 page to create or edit outcome grade items * * @package core_grades * @copyright 2007 Petr Skoda * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once '../../../config.php'; require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->dirroot.'/grade/report/lib.php'; require_once 'outcomeitem_form.php'; $courseid = required_param('courseid', PARAM_INT); $id = optional_param('id', 0, PARAM_INT); $url = new moodle_url('/grade/edit/tree/outcomeitem.php', array('courseid'=>$courseid)); if ($id !== 0) { $url->param('id', $id); } $PAGE->set_url($url); $PAGE->set_pagelayout('admin'); navigation_node::override_active_url(new moodle_url('/grade/edit/tree/index.php', array('id'=>$courseid))); if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($course->id); require_capability('moodle/grade:manage', $context); // default return url $gpr = new grade_plugin_return(); $returnurl = $gpr->get_return_url('index.php?id='.$course->id); $mform = new edit_outcomeitem_form(null, array('gpr'=>$gpr)); if ($mform->is_cancelled() || empty($CFG->enableoutcomes)) { redirect($returnurl); } $heading = get_string('outcomeitemsedit', 'grades'); if ($grade_item = grade_item::fetch(array('id'=>$id, 'courseid'=>$courseid))) { // redirect if outcomeid present if (empty($grade_item->outcomeid)) { $url = new moodle_url('/grade/edit/tree/item.php', ['id' => $id, 'courseid' => $courseid]); redirect($gpr->add_url_params($url)); } $item = $grade_item->get_record_data(); $parent_category = $grade_item->get_parent_category(); $item->parentcategory = $parent_category->id; if ($item->itemtype == 'mod') { $cm = get_coursemodule_from_instance($item->itemmodule, $item->iteminstance, $item->courseid); $item->cmid = $cm->id; } else { $item->cmid = 0; } } else { $heading = get_string('newoutcomeitem', 'grades'); $grade_item = new grade_item(array('courseid'=>$courseid, 'itemtype'=>'manual'), false); $item = $grade_item->get_record_data(); $item->cmid = 0; $parent_category = grade_category::fetch_course_category($courseid); $item->parentcategory = $parent_category->id; } $decimalpoints = $grade_item->get_decimals(); if ($item->hidden > 1) { $item->hiddenuntil = $item->hidden; $item->hidden = 0; } else { $item->hiddenuntil = 0; } $item->locked = !empty($item->locked); $item->gradepass = format_float($item->gradepass, $decimalpoints); if (empty($parent_category)) { $item->aggregationcoef = 0; } else if ($parent_category->aggregation == GRADE_AGGREGATE_SUM) { $item->aggregationcoef = $item->aggregationcoef > 0 ? 1 : 0; $item->aggregationcoef2 = format_float($item->aggregationcoef2 * 100.0); } else { $item->aggregationcoef = format_float($item->aggregationcoef, 4); } $mform->set_data($item); if ($data = $mform->get_data()) { // This is a new item, and the category chosen is different than the default category. if (empty($grade_item->id) && isset($data->parentcategory) && $parent_category->id != $data->parentcategory) { $parent_category = grade_category::fetch(array('id' => $data->parentcategory)); } // If unset, give the aggregation values a default based on parent aggregation method. $defaults = grade_category::get_default_aggregation_coefficient_values($parent_category->aggregation); if (!isset($data->aggregationcoef) || $data->aggregationcoef == '') { $data->aggregationcoef = $defaults['aggregationcoef']; } if (!isset($data->weightoverride)) { $data->weightoverride = $defaults['weightoverride']; } if (property_exists($data, 'calculation')) { $data->calculation = grade_item::normalize_formula($data->calculation, $course->id); } $hidden = empty($data->hidden) ? 0: $data->hidden; $hiddenuntil = empty($data->hiddenuntil) ? 0: $data->hiddenuntil; unset($data->hidden); unset($data->hiddenuntil); $locked = empty($data->locked) ? 0: $data->locked; $locktime = empty($data->locktime) ? 0: $data->locktime; unset($data->locked); unset($data->locktime); $convert = array('gradepass', 'aggregationcoef', 'aggregationcoef2'); foreach ($convert as $param) { if (property_exists($data, $param)) { $data->$param = unformat_float($data->$param); } } if (isset($data->aggregationcoef2) && $parent_category->aggregation == GRADE_AGGREGATE_SUM) { $data->aggregationcoef2 = $data->aggregationcoef2 / 100.0; } else { $data->aggregationcoef2 = $defaults['aggregationcoef2']; } $grade_item = new grade_item(array('id'=>$id, 'courseid'=>$courseid)); grade_item::set_properties($grade_item, $data); // fix activity links if (empty($data->cmid)) { // manual item $grade_item->itemtype = 'manual'; $grade_item->itemmodule = null; $grade_item->iteminstance = null; $grade_item->itemnumber = 0; } else { $params = array($data->cmid); $module = $DB->get_record_sql("SELECT cm.*, m.name as modname FROM {modules} m, {course_modules} cm WHERE cm.id = ? AND cm.module = m.id ", $params); $grade_item->itemtype = 'mod'; $grade_item->itemmodule = $module->modname; $grade_item->iteminstance = $module->instance; if ($items = grade_item::fetch_all(array('itemtype'=>'mod', 'itemmodule'=>$grade_item->itemmodule, 'iteminstance'=>$grade_item->iteminstance, 'courseid'=>$COURSE->id))) { if (!empty($grade_item->id) and in_array($grade_item, $items)) { //no change needed } else { $max = 999; foreach($items as $item) { if (empty($item->outcomeid)) { continue; } if ($item->itemnumber > $max) { $max = $item->itemnumber; } } $grade_item->itemnumber = $max + 1; } } else { $grade_item->itemnumber = 1000; } } // fix scale used $outcome = grade_outcome::fetch(array('id'=>$data->outcomeid)); $grade_item->gradetype = GRADE_TYPE_SCALE; $grade_item->scaleid = $outcome->scaleid; //TODO: we might recalculate existing outcome grades when changing scale if (empty($grade_item->id)) { $grade_item->insert(); // move next to activity if adding linked outcome if ($grade_item->itemtype == 'mod') { if ($item = grade_item::fetch(array('itemtype'=>'mod', 'itemmodule'=>$grade_item->itemmodule, 'iteminstance'=>$grade_item->iteminstance, 'itemnumber'=>0, 'courseid'=>$COURSE->id))) { $grade_item->set_parent($item->categoryid); $grade_item->move_after_sortorder($item->sortorder); } } else { // set parent if needed if (isset($data->parentcategory)) { $grade_item->set_parent($data->parentcategory, false); } } } else { $grade_item->update(); } // update hiding flag if ($hiddenuntil) { $grade_item->set_hidden($hiddenuntil, false); } else { $grade_item->set_hidden($hidden, false); } $grade_item->set_locktime($locktime); // locktime first - it might be removed when unlocking $grade_item->set_locked($locked, false, true); redirect($returnurl); } $PAGE->navbar->add($heading); print_grade_page_head($courseid, 'settings', null, $heading, false, false, false); if (!grade_outcome::fetch_all_available($COURSE->id)) { echo $OUTPUT->confirm(get_string('nooutcomes', 'grades'), $CFG->wwwroot.'/grade/edit/outcome/course.php?id='.$courseid, $returnurl); echo $OUTPUT->footer(); die(); } $mform->display(); echo $OUTPUT->footer(); tree/calculation.php 0000644 00000020455 15151222054 0010515 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/>. /** * Edit a calculated grade item * * @package core_grades * @copyright 2007 Petr Skoda * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once '../../../config.php'; require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->libdir.'/mathslib.php'; require_once 'calculation_form.php'; $courseid = required_param('courseid', PARAM_INT); $id = required_param('id', PARAM_INT); $section = optional_param('section', 'calculation', PARAM_ALPHA); $idnumbers = optional_param_array('idnumbers', null, PARAM_RAW); $url = new moodle_url('/grade/edit/tree/calculation.php', array('id'=>$id, 'courseid'=>$courseid)); if ($section !== 'calculation') { $url->param('section', $section); } $PAGE->set_url($url); if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($course->id); require_capability('moodle/grade:manage', $context); $PAGE->set_pagelayout('admin'); navigation_node::override_active_url(new moodle_url('/grade/edit/tree/index.php', array('id'=>$course->id))); // default return url $gpr = new grade_plugin_return(); $returnurl = $gpr->get_return_url($CFG->wwwroot.'/grade/report/index.php?id='.$course->id); if (!$grade_item = grade_item::fetch(array('id'=>$id, 'courseid'=>$course->id))) { throw new \moodle_exception('invaliditemid'); } // activity items and items without grade can not have calculation if ($grade_item->is_external_item() or ($grade_item->gradetype != GRADE_TYPE_VALUE and $grade_item->gradetype != GRADE_TYPE_SCALE)) { redirect($returnurl, get_string('errornocalculationallowed', 'grades')); } $mform = new edit_calculation_form(null, array('gpr'=>$gpr, 'itemid' => $grade_item->id)); if ($mform->is_cancelled()) { redirect($returnurl); } $calculation = calc_formula::localize($grade_item->calculation); $calculation = grade_item::denormalize_formula($calculation, $grade_item->courseid); $mform->set_data(array('courseid'=>$grade_item->courseid, 'calculation'=>$calculation, 'id'=>$grade_item->id, 'itemname'=>$grade_item->itemname)); $errors = array(); if ($data = $mform->get_data()) { $calculation = calc_formula::unlocalize($data->calculation); $grade_item->set_calculation($calculation); redirect($returnurl); } elseif (!empty($section) AND $section='idnumbers' AND !empty($idnumbers)) { // Handle idnumbers separately (non-mform) //first validate and store the new idnumbers foreach ($idnumbers as $giid => $value) { if ($gi = grade_item::fetch(array('id' => $giid))) { if ($gi->itemtype == 'mod') { $cm = get_coursemodule_from_instance($gi->itemmodule, $gi->iteminstance, $gi->courseid); } else { $cm = null; } if (!grade_verify_idnumber($value, $COURSE->id, $gi, $cm)) { $errors[$giid] = get_string('idnumbertaken'); continue; } if (empty($gi->idnumber) and !$gi->add_idnumber($idnumbers[$gi->id])) { $errors[$giid] = get_string('error'); continue; } } else { $errors[$giid] = 'Could not fetch the grade_item with id=' . $giid; } } } $gtree = new grade_tree($course->id, false, false); $strgrades = get_string('grades'); $strgraderreport = get_string('graderreport', 'grades'); $strcalculationedit = get_string('editcalculation', 'grades'); $PAGE->navbar->add($strcalculationedit); print_grade_page_head($courseid, 'settings', null, $strcalculationedit, false, false, false); $mform->display(); // Now show the gradetree with the idnumbers add/edit form echo ' <form class="mform" id="mform2" method="post" action="' . $CFG->wwwroot . '/grade/edit/tree/calculation.php?courseid='.$courseid.'&id='.$id.'"> <div style="display: none;"> <input type="hidden" value="'.$id.'" name="id"/> <input type="hidden" value="'.$courseid.'" name="courseid"/> <input type="hidden" value="'.$gpr->type.'" name="gpr_type"/> <input type="hidden" value="'.$gpr->plugin.'" name="gpr_plugin"/> <input type="hidden" value="'.$gpr->courseid.'" name="gpr_courseid"/> <input type="hidden" value="'.sesskey().'" name="sesskey"/> <input type="hidden" value="idnumbers" name="section"/> </div> <fieldset id="idnumbers" class="clearfix"> <legend class="ftoggler">'.get_string('idnumbers', 'grades').'</legend> <div class="fcontainer clearfix"> <ul> ' . get_grade_tree($gtree, $gtree->top_element, $id, $errors) . ' </ul> </div> </fieldset> <div class="fitem" style="text-align: center;"> <input id="id_addidnumbers" type="submit" class="btn btn-secondary" value="' . get_string('addidnumbers', 'grades') . '" name="addidnumbers" /> </div> </form>'; echo $OUTPUT->footer(); die(); /** * Simplified version of the print_grade_tree() recursive function found in grade/edit/tree/index.php * Only prints a tree with a basic icon for each element, and an edit field for * items without an idnumber. * @param object $gtree * @param object $element * @param int $current_itemid The itemid of this page: should be excluded from the tree * @param array $errors An array of idnumbers => error * @return string */ function get_grade_tree(&$gtree, $element, $current_itemid=null, $errors=null) { global $CFG; $object = $element['object']; $eid = $element['eid']; $type = $element['type']; $grade_item = $object->get_grade_item(); $name = $object->get_name(); $return_string = ''; //TODO: improve outcome visualisation if ($type == 'item' and !empty($object->outcomeid)) { $name = $name.' ('.get_string('outcome', 'grades').')'; } $idnumber = $object->get_idnumber(); // Don't show idnumber or input field for current item if given to function. Highlight the item instead. if ($type != 'category') { if (is_null($current_itemid) OR $grade_item->id != $current_itemid) { if ($idnumber) { $name .= ": [[$idnumber]]"; } else { $closingdiv = ''; if (!empty($errors[$grade_item->id])) { $name .= '<div class="error"><span class="error">' . $errors[$grade_item->id].'</span><br />'."\n"; $closingdiv = "</div>\n"; } $name .= '<label class="accesshide" for="id_idnumber_' . $grade_item->id . '">' . get_string('gradeitems', 'grades') .'</label>'; $name .= '<input class="idnumber" id="id_idnumber_'.$grade_item->id.'" type="text" name="idnumbers['.$grade_item->id.']" />' . "\n"; $name .= $closingdiv; } } else { $name = "<strong>$name</strong>"; } } $icon = $gtree->get_element_icon($element, true); $last = ''; $catcourseitem = ($element['type'] == 'courseitem' or $element['type'] == 'categoryitem'); if ($type != 'category') { $return_string .= '<li class="'.$type.'">'.$icon.$name.'</li>' . "\n"; } else { $return_string .= '<li class="'.$type.'">'.$icon.$name . "\n"; $return_string .= '<ul class="catlevel'.$element['depth'].'">'."\n"; $last = null; foreach($element['children'] as $child_el) { $return_string .= get_grade_tree($gtree, $child_el, $current_itemid, $errors); } if ($last) { $return_string .= get_grade_tree($gtree, $last, $current_itemid, $errors); } $return_string .= '</ul></li>'."\n"; } return $return_string; } tree/grade_form.php 0000644 00000021075 15151222054 0010323 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 moodleform to allow the editing of a user's grade for a particular activity * * @package core_grades * @copyright 2007 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->libdir.'/formslib.php'; class edit_grade_form extends moodleform { function definition() { global $CFG, $COURSE, $DB; $mform =& $this->_form; $grade_item = $this->_customdata['grade_item']; $gpr = $this->_customdata['gpr']; if ($grade_item->is_course_item()) { $grade_category = null; } else if ($grade_item->is_category_item()) { $grade_category = $grade_item->get_item_category(); $grade_category = $grade_category->get_parent_category(); } else { $grade_category = $grade_item->get_parent_category(); } /// information fields $mform->addElement('static', 'user', get_string('user')); $mform->addElement('static', 'itemname', get_string('itemname', 'grades')); $mform->addElement('checkbox', 'overridden', get_string('overridden', 'grades')); $mform->addHelpButton('overridden', 'overridden', 'grades'); /// actual grade - numeric or scale if ($grade_item->gradetype == GRADE_TYPE_VALUE) { // numeric grade $mform->addElement('text', 'finalgrade', get_string('finalgrade', 'grades')); $mform->setType('finalgrade', PARAM_RAW); $mform->addHelpButton('finalgrade', 'finalgrade', 'grades'); $mform->disabledIf('finalgrade', 'overridden', 'notchecked'); } else if ($grade_item->gradetype == GRADE_TYPE_SCALE) { // scale grade $scaleopt = array(); if (empty($grade_item->outcomeid)) { $scaleopt[-1] = get_string('nograde'); } else { $scaleopt[-1] = get_string('nooutcome', 'grades'); } $i = 1; if ($scale = $DB->get_record('scale', array('id' => $grade_item->scaleid))) { foreach (explode(",", $scale->scale) as $option) { $scaleopt[$i] = $option; $i++; } } $mform->addElement('select', 'finalgrade', get_string('finalgrade', 'grades'), $scaleopt); $mform->addHelpButton('finalgrade', 'finalgrade', 'grades'); $mform->disabledIf('finalgrade', 'overridden', 'notchecked'); } $mform->addElement('advcheckbox', 'excluded', get_string('excluded', 'grades')); $mform->addHelpButton('excluded', 'excluded', 'grades'); /// hiding /// advcheckbox is not compatible with disabledIf !! $mform->addElement('checkbox', 'hidden', get_string('hidden', 'grades')); $mform->addHelpButton('hidden', 'hidden', 'grades'); $mform->addElement('date_time_selector', 'hiddenuntil', get_string('hiddenuntil', 'grades'), array('optional'=>true)); $mform->disabledIf('hidden', 'hiddenuntil[enabled]', 'checked'); /// locking $mform->addElement('advcheckbox', 'locked', get_string('locked', 'grades')); $mform->addHelpButton('locked', 'locked', 'grades'); $mform->addElement('date_time_selector', 'locktime', get_string('locktime', 'grades'), array('optional'=>true)); $mform->disabledIf('locktime', 'gradetype', 'eq', GRADE_TYPE_NONE); // Feedback format is automatically converted to html if user has enabled editor $feedbackoptions = array('maxfiles'=>0, 'maxbytes'=>0); //TODO: no files here for now, if ever gets implemented use component 'grade' and filearea 'feedback' $mform->addElement('editor', 'feedback', get_string('feedback', 'grades'), null, $feedbackoptions); $mform->addHelpButton('feedback', 'feedback', 'grades'); $mform->setType('text', PARAM_RAW); // to be cleaned before display, no XSS risk // hidden params $mform->addElement('hidden', 'oldgrade'); $mform->setType('oldgrade', PARAM_RAW); $mform->addElement('hidden', 'oldfeedback'); $mform->setType('oldfeedback', PARAM_RAW); $mform->addElement('hidden', 'id', 0); $mform->setType('id', PARAM_INT); $mform->addElement('hidden', 'itemid', 0); $mform->setType('itemid', PARAM_INT); $mform->addElement('hidden', 'userid', 0); $mform->setType('userid', PARAM_INT); $mform->addElement('hidden', 'courseid', $COURSE->id); $mform->setType('courseid', PARAM_INT); /// add return tracking info $gpr->add_mform_elements($mform); //------------------------------------------------------------------------------- // buttons $this->add_action_buttons(); } function definition_after_data() { global $CFG, $COURSE, $DB; $context = context_course::instance($COURSE->id); $mform =& $this->_form; $grade_item = $this->_customdata['grade_item']; // fill in user name if user still exists $userid = $mform->getElementValue('userid'); if ($user = $DB->get_record('user', array('id' => $userid))) { $username = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$userid.'">'.fullname($user).'</a>'; $user_el =& $mform->getElement('user'); $user_el->setValue($username); } // add activity name + link if ($grade_item->itemtype == 'mod') { $cm = get_coursemodule_from_instance($grade_item->itemmodule, $grade_item->iteminstance, $grade_item->courseid); $itemname = '<a href="'.$CFG->wwwroot.'/mod/'.$grade_item->itemmodule.'/view.php?id='.$cm->id.'">'.$grade_item->get_name().'</a>'; } else { $itemname = $grade_item->get_name(); } $itemname_el =& $mform->getElement('itemname'); $itemname_el->setValue($itemname); // access control - disable not allowed elements if (!has_capability('moodle/grade:manage', $context)) { $mform->hardFreeze('excluded'); } if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:hide', $context)) { $mform->hardFreeze('hidden'); $mform->hardFreeze('hiddenuntil'); } $old_grade_grade = new grade_grade(array('itemid'=>$grade_item->id, 'userid'=>$userid)); $gradeitemoverridable = $grade_item->is_overridable_item(); if (!$gradeitemoverridable) { $mform->removeElement('overridden'); } if ($grade_item->is_hidden()) { $mform->hardFreeze('hidden'); } if ($old_grade_grade->is_locked()) { if ($grade_item->is_locked()) { $mform->hardFreeze('locked'); $mform->hardFreeze('locktime'); } if ($gradeitemoverridable) { $mform->hardFreeze('overridden'); } $mform->hardFreeze('finalgrade'); $mform->hardFreeze('feedback'); } else { if (empty($old_grade_grade->id)) { $old_grade_grade->locked = $grade_item->locked; $old_grade_grade->locktime = $grade_item->locktime; } if (($old_grade_grade->locked or $old_grade_grade->locktime) and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context))) { $mform->hardFreeze('locked'); $mform->hardFreeze('locktime'); } else if ((!$old_grade_grade->locked and !$old_grade_grade->locktime) and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context))) { $mform->hardFreeze('locked'); $mform->hardFreeze('locktime'); } } } } tree/outcomeitem_form.php 0000644 00000027141 15151222054 0011573 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 moodleform to allow the creation and editing of outcome grade items * * @package core_grades * @copyright 2007 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->libdir.'/formslib.php'; class edit_outcomeitem_form extends moodleform { function definition() { global $COURSE, $CFG; $mform =& $this->_form; /// visible elements $mform->addElement('header', 'general', get_string('gradeoutcomeitem', 'grades')); $mform->addElement('text', 'itemname', get_string('itemname', 'grades')); $mform->addRule('itemname', get_string('required'), 'required', null, 'client'); $mform->setType('itemname', PARAM_TEXT); $mform->addElement('text', 'iteminfo', get_string('iteminfo', 'grades')); $mform->addHelpButton('iteminfo', 'iteminfo', 'grades'); $mform->setType('iteminfo', PARAM_TEXT); $mform->addElement('text', 'idnumber', get_string('idnumbermod')); $mform->addHelpButton('idnumber', 'idnumbermod'); $mform->setType('idnumber', PARAM_RAW); // allow setting of outcomes on module items too $options = array(); if ($outcomes = grade_outcome::fetch_all_available($COURSE->id)) { foreach ($outcomes as $outcome) { $options[$outcome->id] = $outcome->get_name(); } } $mform->addElement('selectwithlink', 'outcomeid', get_string('outcome', 'grades'), $options, null, array('link' => $CFG->wwwroot.'/grade/edit/outcome/course.php?id='.$COURSE->id, 'label' => get_string('outcomeassigntocourse', 'grades'))); $mform->addHelpButton('outcomeid', 'outcome', 'grades'); $mform->addRule('outcomeid', get_string('required'), 'required'); $options = array(0=>get_string('none')); if ($coursemods = get_course_mods($COURSE->id)) { foreach ($coursemods as $coursemod) { if ($mod = get_coursemodule_from_id($coursemod->modname, $coursemod->id)) { $options[$coursemod->id] = format_string($mod->name); } } } $mform->addElement('select', 'cmid', get_string('linkedactivity', 'grades'), $options); $mform->addHelpButton('cmid', 'linkedactivity', 'grades'); $mform->setDefault('cmid', 0); /// hiding /// advcheckbox is not compatible with disabledIf !! $mform->addElement('checkbox', 'hidden', get_string('hidden', 'grades')); $mform->addHelpButton('hidden', 'hidden', 'grades'); $mform->addElement('date_time_selector', 'hiddenuntil', get_string('hiddenuntil', 'grades'), array('optional'=>true)); $mform->disabledIf('hidden', 'hiddenuntil[enabled]', 'checked'); //locking $mform->addElement('advcheckbox', 'locked', get_string('locked', 'grades')); $mform->addHelpButton('locked', 'locked', 'grades'); $mform->addElement('date_time_selector', 'locktime', get_string('locktime', 'grades'), array('optional'=>true)); /// parent category related settings $mform->addElement('header', 'headerparent', get_string('parentcategory', 'grades')); $mform->addElement('advcheckbox', 'weightoverride', get_string('adjustedweight', 'grades')); $mform->addHelpButton('weightoverride', 'weightoverride', 'grades'); $mform->addElement('text', 'aggregationcoef2', get_string('weight', 'grades')); $mform->addHelpButton('aggregationcoef2', 'weight', 'grades'); $mform->setType('aggregationcoef2', PARAM_RAW); $mform->disabledIf('aggregationcoef2', 'weightoverride'); $options = array(); $default = ''; $coefstring = ''; $categories = grade_category::fetch_all(array('courseid'=>$COURSE->id)); foreach ($categories as $cat) { $cat->apply_forced_settings(); $options[$cat->id] = $cat->get_name(); if ($cat->is_course_category()) { $default = $cat->id; } if ($cat->is_aggregationcoef_used()) { if ($cat->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) { $coefstring = ($coefstring=='' or $coefstring=='aggregationcoefweight') ? 'aggregationcoefweight' : 'aggregationcoef'; } else if ($cat->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN2) { $coefstring = ($coefstring=='' or $coefstring=='aggregationcoefextrasum') ? 'aggregationcoefextrasum' : 'aggregationcoef'; } else if ($cat->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN) { $coefstring = ($coefstring=='' or $coefstring=='aggregationcoefextraweight') ? 'aggregationcoefextraweight' : 'aggregationcoef'; } else if ($cat->aggregation == GRADE_AGGREGATE_SUM) { $coefstring = ($coefstring=='' or $coefstring=='aggregationcoefextrasum') ? 'aggregationcoefextrasum' : 'aggregationcoef'; } else { $coefstring = 'aggregationcoef'; } } else { $mform->disabledIf('aggregationcoef', 'parentcategory', 'eq', $cat->id); } } if (count($categories) > 1) { $mform->addElement('select', 'parentcategory', get_string('gradecategory', 'grades'), $options); $mform->disabledIf('parentcategory', 'cmid', 'noteq', 0); } if ($coefstring !== '') { if ($coefstring == 'aggregationcoefextrasum' || $coefstring == 'aggregationcoefextraweightsum') { // advcheckbox is not compatible with disabledIf! $coefstring = 'aggregationcoefextrasum'; $mform->addElement('checkbox', 'aggregationcoef', get_string($coefstring, 'grades')); } else { $mform->addElement('text', 'aggregationcoef', get_string($coefstring, 'grades')); } $mform->addHelpButton('aggregationcoef', $coefstring, 'grades'); } /// hidden params $mform->addElement('hidden', 'id', 0); $mform->setType('id', PARAM_INT); $mform->addElement('hidden', 'courseid', $COURSE->id); $mform->setType('courseid', PARAM_INT); /// add return tracking info $gpr = $this->_customdata['gpr']; $gpr->add_mform_elements($mform); /// mark advanced according to site settings if (isset($CFG->grade_item_advanced)) { $advanced = explode(',', $CFG->grade_item_advanced); foreach ($advanced as $el) { if ($mform->elementExists($el)) { $mform->setAdvanced($el); } } } //------------------------------------------------------------------------------- // buttons $this->add_action_buttons(); } /// tweak the form - depending on existing data function definition_after_data() { global $CFG, $COURSE; $mform =& $this->_form; if ($id = $mform->getElementValue('id')) { $grade_item = grade_item::fetch(array('id'=>$id)); //remove the aggregation coef element if not needed if ($grade_item->is_course_item()) { if ($mform->elementExists('parentcategory')) { $mform->removeElement('parentcategory'); } if ($mform->elementExists('aggregationcoef')) { $mform->removeElement('aggregationcoef'); } } else { // if we wanted to change parent of existing item - we would have to verify there are no circular references in parents!!! if ($mform->elementExists('parentcategory')) { $mform->hardFreeze('parentcategory'); } if ($grade_item->is_category_item()) { $category = $grade_item->get_item_category(); $parent_category = $category->get_parent_category(); } else { $parent_category = $grade_item->get_parent_category(); } $parent_category->apply_forced_settings(); if (!$parent_category->is_aggregationcoef_used() || !$parent_category->aggregateoutcomes) { if ($mform->elementExists('aggregationcoef')) { $mform->removeElement('aggregationcoef'); } } else { //fix label if needed $agg_el =& $mform->getElement('aggregationcoef'); $aggcoef = ''; if ($parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) { $aggcoef = 'aggregationcoefweight'; } else if ($parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN2) { $aggcoef = 'aggregationcoefextrasum'; } else if ($parent_category->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN) { $aggcoef = 'aggregationcoefextraweight'; } else if ($parent_category->aggregation == GRADE_AGGREGATE_SUM) { $aggcoef = 'aggregationcoefextrasum'; } if ($aggcoef !== '') { $agg_el->setLabel(get_string($aggcoef, 'grades')); $mform->addHelpButton('aggregationcoef', $aggcoef, 'grades'); } } // Remove the natural weighting fields for other aggregations, // or when the category does not aggregate outcomes. if ($parent_category->aggregation != GRADE_AGGREGATE_SUM || !$parent_category->aggregateoutcomes) { if ($mform->elementExists('weightoverride')) { $mform->removeElement('weightoverride'); } if ($mform->elementExists('aggregationcoef2')) { $mform->removeElement('aggregationcoef2'); } } } } // no parent header for course category if (!$mform->elementExists('aggregationcoef') and !$mform->elementExists('parentcategory')) { $mform->removeElement('headerparent'); } } /// perform extra validation before submission function validation($data, $files) { global $COURSE; $errors = parent::validation($data, $files); if (array_key_exists('idnumber', $data)) { if ($data['id']) { $grade_item = new grade_item(array('id'=>$data['id'], 'courseid'=>$data['courseid'])); } else { $grade_item = null; } if (!grade_verify_idnumber($data['idnumber'], $COURSE->id, $grade_item, null)) { $errors['idnumber'] = get_string('idnumbertaken'); } } return $errors; } } tree/category.php 0000644 00000014021 15151222054 0010024 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/>. /** * Edit the grade options for an individual grade category * * @package core_grades * @copyright 2007 Petr Skoda * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once('../../../config.php'); require_once($CFG->dirroot.'/grade/lib.php'); require_once($CFG->dirroot.'/grade/edit/tree/lib.php'); require_once($CFG->dirroot.'/grade/report/lib.php'); require_once('category_form.php'); $courseid = required_param('courseid', PARAM_INT); $id = optional_param('id', 0, PARAM_INT); // grade_category->id $url = new moodle_url('/grade/edit/tree/category.php', array('courseid'=>$courseid)); if ($id !== 0) { $url->param('id', $id); } $PAGE->set_url($url); $PAGE->set_pagelayout('admin'); navigation_node::override_active_url(new moodle_url('/grade/edit/tree/index.php', array('id'=>$courseid))); if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($course->id); require_capability('moodle/grade:manage', $context); // default return url $gpr = new grade_plugin_return(); $returnurl = $gpr->get_return_url('index.php?id='.$course->id); $heading = get_string('categoryedit', 'grades'); if ($id) { if (!$grade_category = grade_category::fetch(array('id'=>$id, 'courseid'=>$course->id))) { throw new \moodle_exception('invalidcategory'); } $grade_category->apply_forced_settings(); $category = $grade_category->get_record_data(); // set parent $category->parentcategory = $grade_category->parent; $grade_item = $grade_category->load_grade_item(); // nomalize coef values if needed $parent_category = $grade_category->get_parent_category(); foreach ($grade_item->get_record_data() as $key => $value) { $category->{"grade_item_$key"} = $value; } $decimalpoints = $grade_item->get_decimals(); $category->grade_item_grademax = format_float($category->grade_item_grademax, $decimalpoints); $category->grade_item_grademin = format_float($category->grade_item_grademin, $decimalpoints); $category->grade_item_gradepass = format_float($category->grade_item_gradepass, $decimalpoints); $category->grade_item_multfactor = format_float($category->grade_item_multfactor, 4); $category->grade_item_plusfactor = format_float($category->grade_item_plusfactor, 4); $category->grade_item_aggregationcoef2 = format_float($category->grade_item_aggregationcoef2 * 100.0, 4); if (!$parent_category) { // keep as is } else if ($parent_category->aggregation == GRADE_AGGREGATE_SUM or $parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN2) { $category->grade_item_aggregationcoef = $category->grade_item_aggregationcoef == 0 ? 0 : 1; } else { $category->grade_item_aggregationcoef = format_float($category->grade_item_aggregationcoef, 4); } // Check to see if the gradebook is frozen. This allows grades to not be altered at all until a user verifies that they // wish to update the grades. $gradebookcalculationsfreeze = get_config('core', 'gradebook_calculations_freeze_' . $courseid); // Stick with the original code if the grade book is frozen. if ($gradebookcalculationsfreeze && (int)$gradebookcalculationsfreeze <= 20150627) { if ($category->aggregation == GRADE_AGGREGATE_SUM) { // Input fields for grademin and grademax are disabled for the "Natural" category, // this means they will be ignored if user does not change aggregation method. // But if user does change aggregation method the default values should be used. $category->grademax = 100; $category->grade_item_grademax = 100; $category->grademin = 0; $category->grade_item_grademin = 0; } } else { if ($category->aggregation == GRADE_AGGREGATE_SUM && !$grade_item->is_calculated()) { // Input fields for grademin and grademax are disabled for the "Natural" category, // this means they will be ignored if user does not change aggregation method. // But if user does change aggregation method the default values should be used. // This does not apply to calculated category totals. $category->grademax = 100; $category->grade_item_grademax = 100; $category->grademin = 0; $category->grade_item_grademin = 0; } } } else { $heading = get_string('newcategory', 'grades'); $grade_category = new grade_category(array('courseid'=>$courseid), false); $grade_category->apply_default_settings(); $grade_category->apply_forced_settings(); $category = $grade_category->get_record_data(); $grade_item = new grade_item(array('courseid'=>$courseid, 'itemtype'=>'manual'), false); foreach ($grade_item->get_record_data() as $key => $value) { $category->{"grade_item_$key"} = $value; } } $mform = new edit_category_form(null, array('current'=>$category, 'gpr'=>$gpr)); if ($mform->is_cancelled()) { redirect($returnurl); } else if ($data = $mform->get_data()) { grade_edit_tree::update_gradecategory($grade_category, $data); redirect($returnurl); } $PAGE->navbar->add($heading); print_grade_page_head($courseid, 'settings', null, $heading, false, false, false); $mform->display(); echo $OUTPUT->footer(); die; tree/category_form.php 0000644 00000070464 15151222054 0011064 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 moodleform to edit the grade options for an individual grade category * * @package core_grades * @copyright 2007 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->libdir.'/formslib.php'; class edit_category_form extends moodleform { private $aggregation_options = array(); function definition() { global $CFG, $COURSE, $DB, $OUTPUT; $mform =& $this->_form; $category = $this->_customdata['current']; $this->aggregation_options = grade_helper::get_aggregation_strings(); // visible elements $mform->addElement('header', 'headercategory', get_string('gradecategory', 'grades')); $mform->addElement('text', 'fullname', get_string('categoryname', 'grades')); $mform->setType('fullname', PARAM_TEXT); $mform->addRule('fullname', null, 'required', null, 'client'); $mform->addElement('select', 'aggregation', get_string('aggregation', 'grades'), $this->aggregation_options); $mform->addHelpButton('aggregation', 'aggregation', 'grades'); if ((int)$CFG->grade_aggregation_flag & 2) { $mform->setAdvanced('aggregation'); } $mform->addElement('checkbox', 'aggregateonlygraded', get_string('aggregateonlygraded', 'grades')); $mform->addHelpButton('aggregateonlygraded', 'aggregateonlygraded', 'grades'); if ((int)$CFG->grade_aggregateonlygraded_flag & 2) { $mform->setAdvanced('aggregateonlygraded'); } if (empty($CFG->enableoutcomes)) { $mform->addElement('hidden', 'aggregateoutcomes'); $mform->setType('aggregateoutcomes', PARAM_INT); } else { $mform->addElement('checkbox', 'aggregateoutcomes', get_string('aggregateoutcomes', 'grades')); $mform->addHelpButton('aggregateoutcomes', 'aggregateoutcomes', 'grades'); if ((int)$CFG->grade_aggregateoutcomes_flag & 2) { $mform->setAdvanced('aggregateoutcomes'); } } $mform->addElement('text', 'keephigh', get_string('keephigh', 'grades'), 'size="3"'); $mform->setType('keephigh', PARAM_INT); $mform->addHelpButton('keephigh', 'keephigh', 'grades'); if ((int)$CFG->grade_keephigh_flag & 2) { $mform->setAdvanced('keephigh'); } $mform->addElement('text', 'droplow', get_string('droplow', 'grades'), 'size="3"'); $mform->setType('droplow', PARAM_INT); $mform->addHelpButton('droplow', 'droplow', 'grades'); $mform->disabledIf('droplow', 'keephigh', 'noteq', 0); if ((int)$CFG->grade_droplow_flag & 2) { $mform->setAdvanced('droplow'); } $mform->disabledIf('keephigh', 'droplow', 'noteq', 0); $mform->disabledIf('droplow', 'keephigh', 'noteq', 0); // Grade item settings // Displayed as Category total to avoid confusion between grade items requiring marking and category totals $mform->addElement('header', 'general', get_string('categorytotal', 'grades')); $mform->addElement('text', 'grade_item_itemname', get_string('categorytotalname', 'grades')); $mform->setType('grade_item_itemname', PARAM_TEXT); $mform->setAdvanced('grade_item_itemname'); $mform->addElement('text', 'grade_item_iteminfo', get_string('iteminfo', 'grades')); $mform->addHelpButton('grade_item_iteminfo', 'iteminfo', 'grades'); $mform->setType('grade_item_iteminfo', PARAM_TEXT); $mform->addElement('text', 'grade_item_idnumber', get_string('idnumbermod')); $mform->addHelpButton('grade_item_idnumber', 'idnumbermod'); $mform->setType('grade_item_idnumber', PARAM_RAW); if (!empty($category->id)) { $gradecategory = grade_category::fetch(array('id' => $category->id)); $gradeitem = $gradecategory->load_grade_item(); // If grades exist set a message so the user knows why they can not alter the grade type or scale. // We could never change the grade type for external items, so only need to show this for manual grade items. if ($gradeitem->has_overridden_grades()) { // Set a message so the user knows why the can not alter the grade type or scale. if ($gradeitem->gradetype == GRADE_TYPE_SCALE) { $gradesexistmsg = get_string('modgradecategorycantchangegradetyporscalemsg', 'grades'); } else { $gradesexistmsg = get_string('modgradecategorycantchangegradetypemsg', 'grades'); } $notification = new \core\output\notification($gradesexistmsg, \core\output\notification::NOTIFY_INFO); $notification->set_show_closebutton(false); $mform->addElement('static', 'gradesexistmsg', '', $OUTPUT->render($notification)); } } $options = array(GRADE_TYPE_NONE=>get_string('typenone', 'grades'), GRADE_TYPE_VALUE=>get_string('typevalue', 'grades'), GRADE_TYPE_SCALE=>get_string('typescale', 'grades'), GRADE_TYPE_TEXT=>get_string('typetext', 'grades')); $mform->addElement('select', 'grade_item_gradetype', get_string('gradetype', 'grades'), $options); $mform->addHelpButton('grade_item_gradetype', 'gradetype', 'grades'); $mform->setDefault('grade_item_gradetype', GRADE_TYPE_VALUE); $mform->disabledIf('grade_item_gradetype', 'aggregation', 'eq', GRADE_AGGREGATE_SUM); //$mform->addElement('text', 'calculation', get_string('calculation', 'grades')); //$mform->disabledIf('calculation', 'gradetype', 'eq', GRADE_TYPE_TEXT); //$mform->disabledIf('calculation', 'gradetype', 'eq', GRADE_TYPE_NONE); $options = array(0=>get_string('usenoscale', 'grades')); if ($scales = grade_scale::fetch_all_local($COURSE->id)) { foreach ($scales as $scale) { $options[$scale->id] = $scale->get_name(); } } if ($scales = grade_scale::fetch_all_global()) { foreach ($scales as $scale) { $options[$scale->id] = $scale->get_name(); } } // ugly BC hack - it was possible to use custom scale from other courses :-( if (!empty($category->grade_item_scaleid) and !isset($options[$category->grade_item_scaleid])) { if ($scale = grade_scale::fetch(array('id'=>$category->grade_item_scaleid))) { $options[$scale->id] = $scale->get_name().' '.get_string('incorrectcustomscale', 'grades'); } } $mform->addElement('select', 'grade_item_scaleid', get_string('scale'), $options); $mform->addHelpButton('grade_item_scaleid', 'typescale', 'grades'); $mform->disabledIf('grade_item_scaleid', 'grade_item_gradetype', 'noteq', GRADE_TYPE_SCALE); $mform->disabledIf('grade_item_scaleid', 'aggregation', 'eq', GRADE_AGGREGATE_SUM); $choices = array(); $choices[''] = get_string('choose'); $choices['no'] = get_string('no'); $choices['yes'] = get_string('yes'); $mform->addElement('select', 'grade_item_rescalegrades', get_string('modgradecategoryrescalegrades', 'grades'), $choices); $mform->addHelpButton('grade_item_rescalegrades', 'modgradecategoryrescalegrades', 'grades'); $mform->disabledIf('grade_item_rescalegrades', 'grade_item_gradetype', 'noteq', GRADE_TYPE_VALUE); $mform->addElement('float', 'grade_item_grademax', get_string('grademax', 'grades')); $mform->addHelpButton('grade_item_grademax', 'grademax', 'grades'); $mform->disabledIf('grade_item_grademax', 'grade_item_gradetype', 'noteq', GRADE_TYPE_VALUE); $mform->disabledIf('grade_item_grademax', 'aggregation', 'eq', GRADE_AGGREGATE_SUM); if ((bool) get_config('moodle', 'grade_report_showmin')) { $mform->addElement('float', 'grade_item_grademin', get_string('grademin', 'grades')); $mform->addHelpButton('grade_item_grademin', 'grademin', 'grades'); $mform->disabledIf('grade_item_grademin', 'grade_item_gradetype', 'noteq', GRADE_TYPE_VALUE); $mform->disabledIf('grade_item_grademin', 'aggregation', 'eq', GRADE_AGGREGATE_SUM); } $mform->addElement('float', 'grade_item_gradepass', get_string('gradepass', 'grades')); $mform->addHelpButton('grade_item_gradepass', 'gradepass', 'grades'); $mform->disabledIf('grade_item_gradepass', 'grade_item_gradetype', 'eq', GRADE_TYPE_NONE); $mform->disabledIf('grade_item_gradepass', 'grade_item_gradetype', 'eq', GRADE_TYPE_TEXT); /// grade display prefs $default_gradedisplaytype = grade_get_setting($COURSE->id, 'displaytype', $CFG->grade_displaytype); $options = array(GRADE_DISPLAY_TYPE_DEFAULT => get_string('default', 'grades'), GRADE_DISPLAY_TYPE_REAL => get_string('real', 'grades'), GRADE_DISPLAY_TYPE_PERCENTAGE => get_string('percentage', 'grades'), GRADE_DISPLAY_TYPE_LETTER => get_string('letter', 'grades'), GRADE_DISPLAY_TYPE_REAL_PERCENTAGE => get_string('realpercentage', 'grades'), GRADE_DISPLAY_TYPE_REAL_LETTER => get_string('realletter', 'grades'), GRADE_DISPLAY_TYPE_LETTER_REAL => get_string('letterreal', 'grades'), GRADE_DISPLAY_TYPE_LETTER_PERCENTAGE => get_string('letterpercentage', 'grades'), GRADE_DISPLAY_TYPE_PERCENTAGE_LETTER => get_string('percentageletter', 'grades'), GRADE_DISPLAY_TYPE_PERCENTAGE_REAL => get_string('percentagereal', 'grades') ); asort($options); foreach ($options as $key=>$option) { if ($key == $default_gradedisplaytype) { $options[GRADE_DISPLAY_TYPE_DEFAULT] = get_string('defaultprev', 'grades', $option); break; } } $mform->addElement('select', 'grade_item_display', get_string('gradedisplaytype', 'grades'), $options); $mform->addHelpButton('grade_item_display', 'gradedisplaytype', 'grades'); $mform->disabledIf('grade_item_display', 'grade_item_gradetype', 'in', array(GRADE_TYPE_TEXT, GRADE_TYPE_NONE)); $default_gradedecimals = grade_get_setting($COURSE->id, 'decimalpoints', $CFG->grade_decimalpoints); $options = array(-1=>get_string('defaultprev', 'grades', $default_gradedecimals), 0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5); $mform->addElement('select', 'grade_item_decimals', get_string('decimalpoints', 'grades'), $options); $mform->addHelpButton('grade_item_decimals', 'decimalpoints', 'grades'); $mform->setDefault('grade_item_decimals', -1); $mform->disabledIf('grade_item_decimals', 'grade_item_display', 'eq', GRADE_DISPLAY_TYPE_LETTER); $mform->disabledIf('grade_item_decimals', 'grade_item_gradetype', 'in', array(GRADE_TYPE_TEXT, GRADE_TYPE_NONE)); if ($default_gradedisplaytype == GRADE_DISPLAY_TYPE_LETTER) { $mform->disabledIf('grade_item_decimals', 'grade_item_display', "eq", GRADE_DISPLAY_TYPE_DEFAULT); } /// hiding // advcheckbox is not compatible with disabledIf! $mform->addElement('checkbox', 'grade_item_hidden', get_string('hidden', 'grades')); $mform->addHelpButton('grade_item_hidden', 'hidden', 'grades'); $mform->addElement('date_time_selector', 'grade_item_hiddenuntil', get_string('hiddenuntil', 'grades'), array('optional'=>true)); $mform->disabledIf('grade_item_hidden', 'grade_item_hiddenuntil[enabled]', 'checked'); /// locking $mform->addElement('checkbox', 'grade_item_locked', get_string('locked', 'grades')); $mform->addHelpButton('grade_item_locked', 'locked', 'grades'); $mform->addElement('date_time_selector', 'grade_item_locktime', get_string('locktime', 'grades'), array('optional'=>true)); $mform->disabledIf('grade_item_locktime', 'grade_item_gradetype', 'eq', GRADE_TYPE_NONE); /// parent category related settings $mform->addElement('header', 'headerparent', get_string('parentcategory', 'grades')); $mform->addElement('advcheckbox', 'grade_item_weightoverride', get_string('adjustedweight', 'grades')); $mform->addHelpButton('grade_item_weightoverride', 'weightoverride', 'grades'); $mform->addElement('float', 'grade_item_aggregationcoef2', get_string('weight', 'grades')); $mform->addHelpButton('grade_item_aggregationcoef2', 'weight', 'grades'); $mform->disabledIf('grade_item_aggregationcoef2', 'grade_item_weightoverride'); $options = array(); $default = -1; $categories = grade_category::fetch_all(array('courseid'=>$COURSE->id)); foreach ($categories as $cat) { $cat->apply_forced_settings(); $options[$cat->id] = $cat->get_name(); if ($cat->is_course_category()) { $default = $cat->id; } } if (count($categories) > 1) { $mform->addElement('select', 'parentcategory', get_string('parentcategory', 'grades'), $options); $mform->setDefault('parentcategory', $default); $mform->addElement('static', 'currentparentaggregation', get_string('currentparentaggregation', 'grades')); } // hidden params $mform->addElement('hidden', 'id', 0); $mform->setType('id', PARAM_INT); $mform->addElement('hidden', 'courseid', 0); $mform->setType('courseid', PARAM_INT); /// add return tracking info $gpr = $this->_customdata['gpr']; $gpr->add_mform_elements($mform); /// mark advanced according to site settings if (isset($CFG->grade_item_advanced)) { $advanced = explode(',', $CFG->grade_item_advanced); foreach ($advanced as $el) { $el = 'grade_item_'.$el; if ($mform->elementExists($el)) { $mform->setAdvanced($el); } } } //------------------------------------------------------------------------------- // buttons $this->add_action_buttons(); //------------------------------------------------------------------------------- $this->set_data($category); } /// tweak the form - depending on existing data function definition_after_data() { global $CFG, $COURSE; $mform =& $this->_form; $somecat = new grade_category(); foreach ($somecat->forceable as $property) { if ((int)$CFG->{"grade_{$property}_flag"} & 1) { if ($mform->elementExists($property)) { if (empty($CFG->grade_hideforcedsettings)) { $mform->hardFreeze($property); } else { if ($mform->elementExists($property)) { $mform->removeElement($property); } } } } } if ($CFG->grade_droplow > 0) { if ($mform->elementExists('keephigh')) { $mform->removeElement('keephigh'); } } else if ($CFG->grade_keephigh > 0) { if ($mform->elementExists('droplow')) { $mform->removeElement('droplow'); } } if ($id = $mform->getElementValue('id')) { $grade_category = grade_category::fetch(array('id'=>$id)); $grade_item = $grade_category->load_grade_item(); // remove agg coef if not used if ($grade_category->is_course_category()) { if ($mform->elementExists('parentcategory')) { $mform->removeElement('parentcategory'); } if ($mform->elementExists('currentparentaggregation')) { $mform->removeElement('currentparentaggregation'); } } else { // if we wanted to change parent of existing category - we would have to verify there are no circular references in parents!!! if ($mform->elementExists('parentcategory')) { $mform->hardFreeze('parentcategory'); } $parent_cat = $grade_category->get_parent_category(); $mform->setDefault('currentparentaggregation', $this->aggregation_options[$parent_cat->aggregation]); } // Prevent the user from using drop lowest/keep highest when the aggregation method cannot handle it. if (!$grade_category->can_apply_limit_rules()) { if ($mform->elementExists('keephigh')) { $mform->setConstant('keephigh', 0); $mform->hardFreeze('keephigh'); } if ($mform->elementExists('droplow')) { $mform->setConstant('droplow', 0); $mform->hardFreeze('droplow'); } } if ($grade_item->is_calculated()) { // following elements are ignored when calculation formula used if ($mform->elementExists('aggregation')) { $mform->removeElement('aggregation'); } if ($mform->elementExists('keephigh')) { $mform->removeElement('keephigh'); } if ($mform->elementExists('droplow')) { $mform->removeElement('droplow'); } if ($mform->elementExists('aggregateonlygraded')) { $mform->removeElement('aggregateonlygraded'); } if ($mform->elementExists('aggregateoutcomes')) { $mform->removeElement('aggregateoutcomes'); } } // If it is a course category, remove the "required" rule from the "fullname" element if ($grade_category->is_course_category()) { unset($mform->_rules['fullname']); $key = array_search('fullname', $mform->_required); unset($mform->_required[$key]); } // If it is a course category and its fullname is ?, show an empty field if ($grade_category->is_course_category() && $mform->getElementValue('fullname') == '?') { $mform->setDefault('fullname', ''); } // remove unwanted aggregation options if ($mform->elementExists('aggregation')) { $allaggoptions = array_keys($this->aggregation_options); $agg_el =& $mform->getElement('aggregation'); $visible = explode(',', $CFG->grade_aggregations_visible); if (!is_null($grade_category->aggregation)) { // current type is always visible $visible[] = $grade_category->aggregation; } foreach ($allaggoptions as $type) { if (!in_array($type, $visible)) { $agg_el->removeOption($type); } } } } else { // adding new category if ($mform->elementExists('currentparentaggregation')) { $mform->removeElement('currentparentaggregation'); } // remove unwanted aggregation options if ($mform->elementExists('aggregation')) { $allaggoptions = array_keys($this->aggregation_options); $agg_el =& $mform->getElement('aggregation'); $visible = explode(',', $CFG->grade_aggregations_visible); foreach ($allaggoptions as $type) { if (!in_array($type, $visible)) { $agg_el->removeOption($type); } } } $mform->removeElement('grade_item_rescalegrades'); } // no parent header for course category if (!$mform->elementExists('parentcategory')) { $mform->removeElement('headerparent'); } /// GRADE ITEM if ($id = $mform->getElementValue('id')) { $grade_category = grade_category::fetch(array('id'=>$id)); $grade_item = $grade_category->load_grade_item(); // Load appropriate "hidden"/"hidden until" defaults. if ($grade_item->is_hiddenuntil()) { $mform->setDefault('grade_item_hiddenuntil', $grade_item->get_hidden()); } else { $mform->setDefault('grade_item_hidden', $grade_item->get_hidden()); } if ($grade_item->is_outcome_item()) { // we have to prevent incompatible modifications of outcomes if outcomes disabled $mform->removeElement('grade_item_grademax'); if ($mform->elementExists('grade_item_grademin')) { $mform->removeElement('grade_item_grademin'); } $mform->removeElement('grade_item_gradetype'); $mform->removeElement('grade_item_display'); $mform->removeElement('grade_item_decimals'); $mform->hardFreeze('grade_item_scaleid'); // Only show the option to rescale grades on a category if its corresponding grade_item has overridden grade_grades. } else if ($grade_item->has_overridden_grades()) { // Can't change the grade type or the scale if there are grades. $mform->hardFreeze('grade_item_gradetype, grade_item_scaleid'); // If we are using scles then remove the unnecessary rescale and grade fields. if ($grade_item->gradetype == GRADE_TYPE_SCALE) { $mform->removeElement('grade_item_rescalegrades'); $mform->removeElement('grade_item_grademax'); if ($mform->elementExists('grade_item_grademin')) { $mform->removeElement('grade_item_grademin'); } } else { // Not using scale, so remove it. $mform->removeElement('grade_item_scaleid'); $mform->disabledIf('grade_item_grademax', 'grade_item_rescalegrades', 'eq', ''); $mform->disabledIf('grade_item_grademin', 'grade_item_rescalegrades', 'eq', ''); } } else { // Remove the rescale element if there are no grades. $mform->removeElement('grade_item_rescalegrades'); } //remove the aggregation coef element if not needed if ($grade_item->is_course_item()) { if ($mform->elementExists('grade_item_aggregationcoef')) { $mform->removeElement('grade_item_aggregationcoef'); } if ($mform->elementExists('grade_item_weightoverride')) { $mform->removeElement('grade_item_weightoverride'); } if ($mform->elementExists('grade_item_aggregationcoef2')) { $mform->removeElement('grade_item_aggregationcoef2'); } } else { if ($grade_item->is_category_item()) { $category = $grade_item->get_item_category(); $parent_category = $category->get_parent_category(); } else { $parent_category = $grade_item->get_parent_category(); } $parent_category->apply_forced_settings(); if (!$parent_category->is_aggregationcoef_used()) { if ($mform->elementExists('grade_item_aggregationcoef')) { $mform->removeElement('grade_item_aggregationcoef'); } } else { $coefstring = $grade_item->get_coefstring(); if ($coefstring == 'aggregationcoefextrasum' || $coefstring == 'aggregationcoefextraweightsum') { // advcheckbox is not compatible with disabledIf! $coefstring = 'aggregationcoefextrasum'; $element =& $mform->createElement('checkbox', 'grade_item_aggregationcoef', get_string($coefstring, 'grades')); } else { $element =& $mform->createElement('text', 'grade_item_aggregationcoef', get_string($coefstring, 'grades')); } $mform->insertElementBefore($element, 'parentcategory'); $mform->addHelpButton('grade_item_aggregationcoef', $coefstring, 'grades'); } // Remove fields used by natural weighting if the parent category is not using natural weighting. // Or if the item is a scale and scales are not used in aggregation. if ($parent_category->aggregation != GRADE_AGGREGATE_SUM || (empty($CFG->grade_includescalesinaggregation) && $grade_item->gradetype == GRADE_TYPE_SCALE)) { if ($mform->elementExists('grade_item_weightoverride')) { $mform->removeElement('grade_item_weightoverride'); } if ($mform->elementExists('grade_item_aggregationcoef2')) { $mform->removeElement('grade_item_aggregationcoef2'); } } } } } /// perform extra validation before submission function validation($data, $files) { global $COURSE; $gradeitem = false; if ($data['id']) { $gradecategory = grade_category::fetch(array('id' => $data['id'])); $gradeitem = $gradecategory->load_grade_item(); } $errors = parent::validation($data, $files); if (array_key_exists('grade_item_gradetype', $data) and $data['grade_item_gradetype'] == GRADE_TYPE_SCALE) { if (empty($data['grade_item_scaleid'])) { $errors['grade_item_scaleid'] = get_string('missingscale', 'grades'); } } // We need to make all the validations related with grademax and grademin // with them being correct floats, keeping the originals unmodified for // later validations / showing the form back... // TODO: Note that once MDL-73994 is fixed we'll have to re-visit this and // adapt the code below to the new values arriving here, without forgetting // the special case of empties and nulls. $grademax = isset($data['grade_item_grademax']) ? unformat_float($data['grade_item_grademax']) : null; $grademin = isset($data['grade_item_grademin']) ? unformat_float($data['grade_item_grademin']) : null; if (!is_null($grademin) and !is_null($grademax)) { if (($grademax != 0 OR $grademin != 0) AND ($grademax == $grademin OR $grademax < $grademin)) { $errors['grade_item_grademin'] = get_string('incorrectminmax', 'grades'); $errors['grade_item_grademax'] = get_string('incorrectminmax', 'grades'); } } if ($data['id'] && $gradeitem->has_overridden_grades()) { if ($gradeitem->gradetype == GRADE_TYPE_VALUE) { if (grade_floats_different($grademin, $gradeitem->grademin) || grade_floats_different($grademax, $gradeitem->grademax)) { if (empty($data['grade_item_rescalegrades'])) { $errors['grade_item_rescalegrades'] = get_string('mustchooserescaleyesorno', 'grades'); } } } } return $errors; } } tree/item_form.php 0000644 00000056164 15151222054 0010206 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 moodleform allowing the editing of the grade options for an individual grade item * * @package core_grades * @copyright 2007 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->libdir.'/formslib.php'; class edit_item_form extends moodleform { private $displayoptions; function definition() { global $COURSE, $CFG, $DB; $mform =& $this->_form; $item = $this->_customdata['current']; /// visible elements $mform->addElement('header', 'general', get_string('gradeitem', 'grades')); $mform->addElement('text', 'itemname', get_string('itemname', 'grades')); $mform->setType('itemname', PARAM_TEXT); $mform->addElement('text', 'iteminfo', get_string('iteminfo', 'grades')); $mform->addHelpButton('iteminfo', 'iteminfo', 'grades'); $mform->setType('iteminfo', PARAM_TEXT); $mform->addElement('text', 'idnumber', get_string('idnumbermod')); $mform->addHelpButton('idnumber', 'idnumbermod'); $mform->setType('idnumber', PARAM_RAW); if (!empty($item->id)) { $gradeitem = new grade_item(array('id' => $item->id, 'courseid' => $item->courseid)); // If grades exist set a message so the user knows why they can not alter the grade type or scale. // We could never change the grade type for external items, so only need to show this for manual grade items. if ($gradeitem->has_grades() && !$gradeitem->is_external_item()) { // Set a message so the user knows why they can not alter the grade type or scale. if ($gradeitem->gradetype == GRADE_TYPE_SCALE) { $gradesexistmsg = get_string('modgradecantchangegradetyporscalemsg', 'grades'); } else { $gradesexistmsg = get_string('modgradecantchangegradetypemsg', 'grades'); } $gradesexisthtml = '<div class=\'alert\'>' . $gradesexistmsg . '</div>'; $mform->addElement('static', 'gradesexistmsg', '', $gradesexisthtml); } } // Manual grade items cannot have grade type GRADE_TYPE_NONE. $options = array(GRADE_TYPE_VALUE => get_string('typevalue', 'grades'), GRADE_TYPE_SCALE => get_string('typescale', 'grades'), GRADE_TYPE_TEXT => get_string('typetext', 'grades')); $mform->addElement('select', 'gradetype', get_string('gradetype', 'grades'), $options); $mform->addHelpButton('gradetype', 'gradetype', 'grades'); $mform->setDefault('gradetype', GRADE_TYPE_VALUE); //$mform->addElement('text', 'calculation', get_string('calculation', 'grades')); //$mform->disabledIf('calculation', 'gradetype', 'eq', GRADE_TYPE_TEXT); //$mform->disabledIf('calculation', 'gradetype', 'eq', GRADE_TYPE_NONE); $options = array(0=>get_string('usenoscale', 'grades')); if ($scales = grade_scale::fetch_all_local($COURSE->id)) { foreach ($scales as $scale) { $options[$scale->id] = $scale->get_name(); } } if ($scales = grade_scale::fetch_all_global()) { foreach ($scales as $scale) { $options[$scale->id] = $scale->get_name(); } } // ugly BC hack - it was possible to use custom scale from other courses :-( if (!empty($item->scaleid) and !isset($options[$item->scaleid])) { if ($scale = grade_scale::fetch(array('id'=>$item->scaleid))) { $options[$scale->id] = $scale->get_name().get_string('incorrectcustomscale', 'grades'); } } $mform->addElement('select', 'scaleid', get_string('scale'), $options); $mform->addHelpButton('scaleid', 'typescale', 'grades'); $mform->disabledIf('scaleid', 'gradetype', 'noteq', GRADE_TYPE_SCALE); $choices = array(); $choices[''] = get_string('choose'); $choices['no'] = get_string('no'); $choices['yes'] = get_string('yes'); $mform->addElement('select', 'rescalegrades', get_string('modgraderescalegrades', 'grades'), $choices); $mform->addHelpButton('rescalegrades', 'modgraderescalegrades', 'grades'); $mform->disabledIf('rescalegrades', 'gradetype', 'noteq', GRADE_TYPE_VALUE); $mform->addElement('float', 'grademax', get_string('grademax', 'grades')); $mform->addHelpButton('grademax', 'grademax', 'grades'); $mform->disabledIf('grademax', 'gradetype', 'noteq', GRADE_TYPE_VALUE); if ((bool) get_config('moodle', 'grade_report_showmin')) { $mform->addElement('float', 'grademin', get_string('grademin', 'grades')); $mform->addHelpButton('grademin', 'grademin', 'grades'); $mform->disabledIf('grademin', 'gradetype', 'noteq', GRADE_TYPE_VALUE); } $mform->addElement('float', 'gradepass', get_string('gradepass', 'grades')); $mform->addHelpButton('gradepass', 'gradepass', 'grades'); $mform->disabledIf('gradepass', 'gradetype', 'eq', GRADE_TYPE_NONE); $mform->disabledIf('gradepass', 'gradetype', 'eq', GRADE_TYPE_TEXT); $mform->addElement('float', 'multfactor', get_string('multfactor', 'grades')); $mform->addHelpButton('multfactor', 'multfactor', 'grades'); $mform->setAdvanced('multfactor'); $mform->disabledIf('multfactor', 'gradetype', 'eq', GRADE_TYPE_NONE); $mform->disabledIf('multfactor', 'gradetype', 'eq', GRADE_TYPE_TEXT); $mform->addElement('float', 'plusfactor', get_string('plusfactor', 'grades')); $mform->addHelpButton('plusfactor', 'plusfactor', 'grades'); $mform->setAdvanced('plusfactor'); $mform->disabledIf('plusfactor', 'gradetype', 'eq', GRADE_TYPE_NONE); $mform->disabledIf('plusfactor', 'gradetype', 'eq', GRADE_TYPE_TEXT); /// grade display prefs $default_gradedisplaytype = grade_get_setting($COURSE->id, 'displaytype', $CFG->grade_displaytype); $options = array(GRADE_DISPLAY_TYPE_DEFAULT => get_string('default', 'grades'), GRADE_DISPLAY_TYPE_REAL => get_string('real', 'grades'), GRADE_DISPLAY_TYPE_PERCENTAGE => get_string('percentage', 'grades'), GRADE_DISPLAY_TYPE_LETTER => get_string('letter', 'grades'), GRADE_DISPLAY_TYPE_REAL_PERCENTAGE => get_string('realpercentage', 'grades'), GRADE_DISPLAY_TYPE_REAL_LETTER => get_string('realletter', 'grades'), GRADE_DISPLAY_TYPE_LETTER_REAL => get_string('letterreal', 'grades'), GRADE_DISPLAY_TYPE_LETTER_PERCENTAGE => get_string('letterpercentage', 'grades'), GRADE_DISPLAY_TYPE_PERCENTAGE_LETTER => get_string('percentageletter', 'grades'), GRADE_DISPLAY_TYPE_PERCENTAGE_REAL => get_string('percentagereal', 'grades') ); asort($options); foreach ($options as $key=>$option) { if ($key == $default_gradedisplaytype) { $options[GRADE_DISPLAY_TYPE_DEFAULT] = get_string('defaultprev', 'grades', $option); break; } } $mform->addElement('select', 'display', get_string('gradedisplaytype', 'grades'), $options); $mform->addHelpButton('display', 'gradedisplaytype', 'grades'); $mform->disabledIf('display', 'gradetype', 'eq', GRADE_TYPE_TEXT); $default_gradedecimals = grade_get_setting($COURSE->id, 'decimalpoints', $CFG->grade_decimalpoints); $options = array(-1=>get_string('defaultprev', 'grades', $default_gradedecimals), 0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5); $mform->addElement('select', 'decimals', get_string('decimalpoints', 'grades'), $options); $mform->addHelpButton('decimals', 'decimalpoints', 'grades'); $mform->setDefault('decimals', -1); $mform->disabledIf('decimals', 'display', 'eq', GRADE_DISPLAY_TYPE_LETTER); if ($default_gradedisplaytype == GRADE_DISPLAY_TYPE_LETTER) { $mform->disabledIf('decimals', 'display', "eq", GRADE_DISPLAY_TYPE_DEFAULT); } $mform->disabledIf('decimals', 'gradetype', 'eq', GRADE_TYPE_TEXT); /// hiding if ($item->cancontrolvisibility) { $mform->addElement('advcheckbox', 'hidden', get_string('hidden', 'grades'), '', [], [0, 1]); $mform->addElement('date_time_selector', 'hiddenuntil', get_string('hiddenuntil', 'grades'), array('optional'=>true)); $mform->disabledIf('hidden', 'hiddenuntil[enabled]', 'checked'); } else { $mform->addElement('static', 'hidden', get_string('hidden', 'grades'), get_string('componentcontrolsvisibility', 'grades')); // Unset hidden to avoid data override. unset($item->hidden); } $mform->addHelpButton('hidden', 'hidden', 'grades'); /// locking $mform->addElement('advcheckbox', 'locked', get_string('locked', 'grades')); $mform->addHelpButton('locked', 'locked', 'grades'); $mform->addElement('date_time_selector', 'locktime', get_string('locktime', 'grades'), array('optional'=>true)); $mform->disabledIf('locktime', 'gradetype', 'eq', GRADE_TYPE_NONE); /// parent category related settings $mform->addElement('header', 'headerparent', get_string('parentcategory', 'grades')); $mform->addElement('advcheckbox', 'weightoverride', get_string('adjustedweight', 'grades')); $mform->addHelpButton('weightoverride', 'weightoverride', 'grades'); $mform->disabledIf('weightoverride', 'gradetype', 'eq', GRADE_TYPE_NONE); $mform->disabledIf('weightoverride', 'gradetype', 'eq', GRADE_TYPE_TEXT); $mform->addElement('float', 'aggregationcoef2', get_string('weight', 'grades')); $mform->addHelpButton('aggregationcoef2', 'weight', 'grades'); $mform->disabledIf('aggregationcoef2', 'weightoverride'); $mform->disabledIf('aggregationcoef2', 'gradetype', 'eq', GRADE_TYPE_NONE); $mform->disabledIf('aggregationcoef2', 'gradetype', 'eq', GRADE_TYPE_TEXT); $options = array(); $coefstring = ''; $categories = grade_category::fetch_all(array('courseid'=>$COURSE->id)); foreach ($categories as $cat) { $cat->apply_forced_settings(); $options[$cat->id] = $cat->get_name(); } if (count($categories) > 1) { $mform->addElement('select', 'parentcategory', get_string('gradecategory', 'grades'), $options); } /// hidden params $mform->addElement('hidden', 'id', 0); $mform->setType('id', PARAM_INT); $mform->addElement('hidden', 'courseid', $COURSE->id); $mform->setType('courseid', PARAM_INT); $mform->addElement('hidden', 'itemtype', 'manual'); // all new items are manual only $mform->setType('itemtype', PARAM_ALPHA); /// add return tracking info $gpr = $this->_customdata['gpr']; $gpr->add_mform_elements($mform); /// mark advanced according to site settings if (isset($CFG->grade_item_advanced)) { $advanced = explode(',', $CFG->grade_item_advanced); foreach ($advanced as $el) { if ($mform->elementExists($el)) { $mform->setAdvanced($el); } } } //------------------------------------------------------------------------------- // buttons $this->add_action_buttons(); //------------------------------------------------------------------------------- $this->set_data($item); } /// tweak the form - depending on existing data function definition_after_data() { global $CFG, $COURSE; $mform =& $this->_form; if ($id = $mform->getElementValue('id')) { $gradeitem = grade_item::fetch(array('id' => $id)); $parentcategory = $gradeitem->get_parent_category(); } else { // If we do not have an id, we are creating a new grade item. $gradeitem = new grade_item(array('courseid' => $COURSE->id, 'itemtype' => 'manual'), false); // Assign the course category to this grade item. $parentcategory = grade_category::fetch_course_category($COURSE->id); $gradeitem->parent_category = $parentcategory; } if (!$gradeitem->is_raw_used()) { $mform->removeElement('plusfactor'); $mform->removeElement('multfactor'); } if ($gradeitem->is_outcome_item()) { // We have to prevent incompatible modifications of outcomes if outcomes disabled. $mform->removeElement('grademax'); if ($mform->elementExists('grademin')) { $mform->removeElement('grademin'); } $mform->removeElement('gradetype'); $mform->removeElement('display'); $mform->removeElement('decimals'); $mform->hardFreeze('scaleid'); } else { if ($gradeitem->is_external_item()) { // Following items are set up from modules and should not be overrided by user. if ($mform->elementExists('grademin')) { // The site setting grade_report_showmin may have prevented grademin being added to the form. $mform->hardFreeze('grademin'); } $mform->hardFreeze('itemname,gradetype,grademax,scaleid'); if ($gradeitem->itemnumber == 0) { // The idnumber of grade itemnumber 0 is synced with course_modules. $mform->hardFreeze('idnumber'); } // For external items we can not change the grade type, even if no grades exist, so if it is set to // scale, then remove the grademax and grademin fields from the form - no point displaying them. if ($gradeitem->gradetype == GRADE_TYPE_SCALE) { $mform->removeElement('grademax'); if ($mform->elementExists('grademin')) { $mform->removeElement('grademin'); } } else { // Not using scale, so remove it. $mform->removeElement('scaleid'); } // Always remove the rescale grades element if it's an external item. $mform->removeElement('rescalegrades'); } else if ($gradeitem->has_grades()) { // Can't change the grade type or the scale if there are grades. $mform->hardFreeze('gradetype, scaleid'); // If we are using scales then remove the unnecessary rescale and grade fields. if ($gradeitem->gradetype == GRADE_TYPE_SCALE) { $mform->removeElement('rescalegrades'); $mform->removeElement('grademax'); if ($mform->elementExists('grademin')) { $mform->removeElement('grademin'); } } else { // Remove the scale field. $mform->removeElement('scaleid'); // Set the maximum grade to disabled unless a grade is chosen. $mform->disabledIf('grademax', 'rescalegrades', 'eq', ''); } } else { // Remove the rescale element if there are no grades. $mform->removeElement('rescalegrades'); } } // If we wanted to change parent of existing item - we would have to verify there are no circular references in parents!!! if ($id && $mform->elementExists('parentcategory')) { $mform->hardFreeze('parentcategory'); } $parentcategory->apply_forced_settings(); if (!$parentcategory->is_aggregationcoef_used()) { if ($mform->elementExists('aggregationcoef')) { $mform->removeElement('aggregationcoef'); } } else { $coefstring = $gradeitem->get_coefstring(); if ($coefstring !== '') { if ($coefstring == 'aggregationcoefextrasum' || $coefstring == 'aggregationcoefextraweightsum') { // The advcheckbox is not compatible with disabledIf! $coefstring = 'aggregationcoefextrasum'; $element =& $mform->createElement('checkbox', 'aggregationcoef', get_string($coefstring, 'grades')); } else { $element =& $mform->createElement('text', 'aggregationcoef', get_string($coefstring, 'grades')); } if ($mform->elementExists('parentcategory')) { $mform->insertElementBefore($element, 'parentcategory'); } else { $mform->insertElementBefore($element, 'id'); } $mform->addHelpButton('aggregationcoef', $coefstring, 'grades'); } $mform->disabledIf('aggregationcoef', 'gradetype', 'eq', GRADE_TYPE_NONE); $mform->disabledIf('aggregationcoef', 'gradetype', 'eq', GRADE_TYPE_TEXT); $mform->disabledIf('aggregationcoef', 'parentcategory', 'eq', $parentcategory->id); } // Remove fields used by natural weighting if the parent category is not using natural weighting. // Or if the item is a scale and scales are not used in aggregation. if ($parentcategory->aggregation != GRADE_AGGREGATE_SUM || (empty($CFG->grade_includescalesinaggregation) && $gradeitem->gradetype == GRADE_TYPE_SCALE)) { if ($mform->elementExists('weightoverride')) { $mform->removeElement('weightoverride'); } if ($mform->elementExists('aggregationcoef2')) { $mform->removeElement('aggregationcoef2'); } } if ($category = $gradeitem->get_item_category()) { if ($category->aggregation == GRADE_AGGREGATE_SUM) { if ($mform->elementExists('gradetype')) { $mform->hardFreeze('gradetype'); } if ($mform->elementExists('grademin')) { $mform->hardFreeze('grademin'); } if ($mform->elementExists('grademax')) { $mform->hardFreeze('grademax'); } if ($mform->elementExists('scaleid')) { $mform->removeElement('scaleid'); } } } // no parent header for course category if (!$mform->elementExists('aggregationcoef') and !$mform->elementExists('parentcategory')) { $mform->removeElement('headerparent'); } } /// perform extra validation before submission function validation($data, $files) { global $COURSE; $grade_item = false; if ($data['id']) { $grade_item = new grade_item(array('id' => $data['id'], 'courseid' => $data['courseid'])); } $errors = parent::validation($data, $files); if (array_key_exists('idnumber', $data)) { if ($grade_item) { if ($grade_item->itemtype == 'mod') { $cm = get_coursemodule_from_instance($grade_item->itemmodule, $grade_item->iteminstance, $grade_item->courseid); } else { $cm = null; } } else { $grade_item = null; $cm = null; } if (!grade_verify_idnumber($data['idnumber'], $COURSE->id, $grade_item, $cm)) { $errors['idnumber'] = get_string('idnumbertaken'); } } if (array_key_exists('gradetype', $data) and $data['gradetype'] == GRADE_TYPE_SCALE) { if (empty($data['scaleid'])) { $errors['scaleid'] = get_string('missingscale', 'grades'); } } // We need to make all the validations related with grademax and grademin // with them being correct floats, keeping the originals unmodified for // later validations / showing the form back... // TODO: Note that once MDL-73994 is fixed we'll have to re-visit this and // adapt the code below to the new values arriving here, without forgetting // the special case of empties and nulls. $grademax = isset($data['grademax']) ? unformat_float($data['grademax']) : null; $grademin = isset($data['grademin']) ? unformat_float($data['grademin']) : null; if (!is_null($grademin) and !is_null($grademax)) { if ($grademax == $grademin or $grademax < $grademin) { $errors['grademin'] = get_string('incorrectminmax', 'grades'); $errors['grademax'] = get_string('incorrectminmax', 'grades'); } } // We do not want the user to be able to change the grade type or scale for this item if grades exist. if ($grade_item && $grade_item->has_grades()) { // Check that grade type is set - should never not be set unless form has been modified. if (!isset($data['gradetype'])) { $errors['gradetype'] = get_string('modgradecantchangegradetype', 'grades'); } else if ($data['gradetype'] !== $grade_item->gradetype) { // Check if we are changing the grade type. $errors['gradetype'] = get_string('modgradecantchangegradetype', 'grades'); } else if ($data['gradetype'] == GRADE_TYPE_SCALE) { // Check if we are changing the scale - can't do this when grades exist. if (isset($data['scaleid']) && ($data['scaleid'] !== $grade_item->scaleid)) { $errors['scaleid'] = get_string('modgradecantchangescale', 'grades'); } } } if ($grade_item) { if ($grade_item->gradetype == GRADE_TYPE_VALUE) { if ((((bool) get_config('moodle', 'grade_report_showmin')) && grade_floats_different($grademin, $grade_item->grademin)) || grade_floats_different($grademax, $grade_item->grademax)) { if ($grade_item->has_grades() && empty($data['rescalegrades'])) { $errors['rescalegrades'] = get_string('mustchooserescaleyesorno', 'grades'); } } } } return $errors; } } tree/action.php 0000644 00000012334 15151222054 0007471 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/>. /** * Performs actions on grade items and categories like hiding and locking * * @package core_grades * @copyright 2007 Petr Skoda * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once '../../../config.php'; require_once $CFG->dirroot.'/grade/lib.php'; $courseid = required_param('id', PARAM_INT); $action = required_param('action', PARAM_ALPHA); $eid = required_param('eid', PARAM_ALPHANUM); $PAGE->set_url('/grade/edit/tree/action.php', array('id'=>$courseid, 'action'=>$action, 'eid'=>$eid)); /// Make sure they can even access this course if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($course->id); // default return url $gpr = new grade_plugin_return(); $returnurl = $gpr->get_return_url($CFG->wwwroot.'/grade/edit/tree/index.php?id='.$course->id); // get the grading tree object $gtree = new grade_tree($courseid, false, false); // what are we working with? if (!$element = $gtree->locate_element($eid)) { throw new \moodle_exception('invalidelementid', '', $returnurl); } $object = $element['object']; $type = $element['type']; switch ($action) { case 'hide': if ($eid and confirm_sesskey()) { if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:hide', $context)) { throw new \moodle_exception('nopermissiontohide', '', $returnurl); } if ($type == 'grade' and empty($object->id)) { $object->insert(); } if (!$object->can_control_visibility()) { throw new \moodle_exception('componentcontrolsvisibility', 'grades', $returnurl); } $object->set_hidden(1, true); } break; case 'show': if ($eid and confirm_sesskey()) { if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:hide', $context)) { throw new \moodle_exception('nopermissiontoshow', '', $returnurl); } if ($type == 'grade' and empty($object->id)) { $object->insert(); } if (!$object->can_control_visibility()) { throw new \moodle_exception('componentcontrolsvisibility', 'grades', $returnurl); } $object->set_hidden(0, true); } break; case 'lock': if ($eid and confirm_sesskey()) { if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context)) { throw new \moodle_exception('nopermissiontolock', '', $returnurl); } if ($type == 'grade' and empty($object->id)) { $object->insert(); } $object->set_locked(1, true, true); } break; case 'unlock': if ($eid and confirm_sesskey()) { if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context)) { throw new \moodle_exception('nopermissiontounlock', '', $returnurl); } if ($type == 'grade' and empty($object->id)) { $object->insert(); } $object->set_locked(0, true, true); } break; case 'resetweights': if ($eid && confirm_sesskey()) { // This is specific to category items with natural weight as an aggregation method, and can // only be done by someone who can manage the grades. if ($type != 'category' || $object->aggregation != GRADE_AGGREGATE_SUM || !has_capability('moodle/grade:manage', $context)) { throw new \moodle_exception('nopermissiontoresetweights', 'grades', $returnurl); } // Remove the weightoverride flag from the children. $children = $object->get_children(); foreach ($children as $item) { if ($item['type'] == 'category') { $gradeitem = $item['object']->load_grade_item(); } else { $gradeitem = $item['object']; } if ($gradeitem->weightoverride == false) { continue; } $gradeitem->weightoverride = false; $gradeitem->update(); } // Force regrading. $object->force_regrading(); } } redirect($returnurl); //redirect($returnurl, 'debug delay', 5); tree/item.php 0000644 00000016553 15151222054 0007161 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/>. /** * Edit the grade options for an individual grade item * * @package core_grades * @copyright 2007 Petr Skoda * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once '../../../config.php'; require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->dirroot.'/grade/report/lib.php'; require_once 'item_form.php'; $courseid = required_param('courseid', PARAM_INT); $id = optional_param('id', 0, PARAM_INT); $url = new moodle_url('/grade/edit/tree/item.php', array('courseid'=>$courseid)); if ($id !== 0) { $url->param('id', $id); } $PAGE->set_url($url); $PAGE->set_pagelayout('admin'); navigation_node::override_active_url(new moodle_url('/grade/edit/tree/index.php', array('id'=>$courseid))); if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($course->id); require_capability('moodle/grade:manage', $context); // default return url $gpr = new grade_plugin_return(); $returnurl = $gpr->get_return_url('index.php?id='.$course->id); $heading = get_string('itemsedit', 'grades'); if ($grade_item = grade_item::fetch(array('id'=>$id, 'courseid'=>$courseid))) { // redirect if outcomeid present if (!empty($grade_item->outcomeid) && !empty($CFG->enableoutcomes)) { $url = new moodle_url('/grade/edit/tree/outcomeitem.php', ['id' => $id, 'courseid' => $courseid]); redirect($gpr->add_url_params($url)); } if ($grade_item->is_course_item() or $grade_item->is_category_item()) { $grade_category = $grade_item->get_item_category(); $url = new moodle_url('/grade/edit/tree/category.php', ['id' => $grade_category->id, 'courseid' => $courseid]); redirect($gpr->add_url_params($url)); } $item = $grade_item->get_record_data(); $parent_category = $grade_item->get_parent_category(); $item->parentcategory = $parent_category->id; } else { $heading = get_string('newitem', 'grades'); $grade_item = new grade_item(array('courseid'=>$courseid, 'itemtype'=>'manual'), false); $item = $grade_item->get_record_data(); $parent_category = grade_category::fetch_course_category($courseid); $item->parentcategory = $parent_category->id; } $decimalpoints = $grade_item->get_decimals(); if ($item->hidden > 1) { $item->hiddenuntil = $item->hidden; $item->hidden = 0; } else { $item->hiddenuntil = 0; } $item->locked = !empty($item->locked); $item->grademax = format_float($item->grademax, $decimalpoints); $item->grademin = format_float($item->grademin, $decimalpoints); $item->gradepass = format_float($item->gradepass, $decimalpoints); $item->multfactor = format_float($item->multfactor, 4); $item->plusfactor = format_float($item->plusfactor, 4); if ($parent_category->aggregation == GRADE_AGGREGATE_SUM or $parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN2) { $item->aggregationcoef = $item->aggregationcoef == 0 ? 0 : 1; } else { $item->aggregationcoef = format_float($item->aggregationcoef, 4); } if ($parent_category->aggregation == GRADE_AGGREGATE_SUM) { $item->aggregationcoef2 = format_float($item->aggregationcoef2 * 100.0); } $item->cancontrolvisibility = $grade_item->can_control_visibility(); $mform = new edit_item_form(null, array('current'=>$item, 'gpr'=>$gpr)); if ($mform->is_cancelled()) { redirect($returnurl); } else if ($data = $mform->get_data()) { // This is a new item, and the category chosen is different than the default category. if (empty($grade_item->id) && isset($data->parentcategory) && $parent_category->id != $data->parentcategory) { $parent_category = grade_category::fetch(array('id' => $data->parentcategory)); } // If unset, give the aggregation values a default based on parent aggregation method. $defaults = grade_category::get_default_aggregation_coefficient_values($parent_category->aggregation); if (!isset($data->aggregationcoef) || $data->aggregationcoef == '') { $data->aggregationcoef = $defaults['aggregationcoef']; } if (!isset($data->weightoverride)) { $data->weightoverride = $defaults['weightoverride']; } if (!isset($data->gradepass) || $data->gradepass == '') { $data->gradepass = 0; } if (!isset($data->grademin) || $data->grademin == '') { $data->grademin = 0; } $hide = empty($data->hiddenuntil) ? 0 : $data->hiddenuntil; if (!$hide) { $hide = empty($data->hidden) ? 0 : $data->hidden; } unset($data->hidden); unset($data->hiddenuntil); $locked = empty($data->locked) ? 0: $data->locked; $locktime = empty($data->locktime) ? 0: $data->locktime; unset($data->locked); unset($data->locktime); $convert = array('grademax', 'grademin', 'gradepass', 'multfactor', 'plusfactor', 'aggregationcoef', 'aggregationcoef2'); foreach ($convert as $param) { if (property_exists($data, $param)) { $data->$param = unformat_float($data->$param); } } if (isset($data->aggregationcoef2) && $parent_category->aggregation == GRADE_AGGREGATE_SUM) { $data->aggregationcoef2 = $data->aggregationcoef2 / 100.0; } else { $data->aggregationcoef2 = $defaults['aggregationcoef2']; } $gradeitem = new grade_item(array('id' => $id, 'courseid' => $courseid)); $oldmin = $gradeitem->grademin; $oldmax = $gradeitem->grademax; grade_item::set_properties($gradeitem, $data); $gradeitem->outcomeid = null; // Handle null decimals value if (!property_exists($data, 'decimals') or $data->decimals < 0) { $gradeitem->decimals = null; } if (empty($gradeitem->id)) { $gradeitem->itemtype = 'manual'; // All new items to be manual only. $gradeitem->insert(); // set parent if needed if (isset($data->parentcategory)) { $gradeitem->set_parent($data->parentcategory, false); } } else { $gradeitem->update(); if (!empty($data->rescalegrades) && $data->rescalegrades == 'yes') { $newmin = $gradeitem->grademin; $newmax = $gradeitem->grademax; $gradeitem->rescale_grades_keep_percentage($oldmin, $oldmax, $newmin, $newmax, 'gradebook'); } } if ($item->cancontrolvisibility) { // Update hiding flag. $gradeitem->set_hidden($hide, true); } $gradeitem->set_locktime($locktime); // Locktime first - it might be removed when unlocking. $gradeitem->set_locked($locked, false, true); redirect($returnurl); } $PAGE->navbar->add($heading); print_grade_page_head($courseid, 'settings', null, $heading, false, false, false); $mform->display(); echo $OUTPUT->footer(); tree/index.php 0000644 00000024742 15151222054 0007331 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/>. /** * The Gradebook setup page. * * @package core_grades * @copyright 2008 Nicolas Connault * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ define('NO_OUTPUT_BUFFERING', true); // The progress bar may be used here. require_once '../../../config.php'; require_once $CFG->dirroot.'/grade/lib.php'; require_once $CFG->dirroot.'/grade/report/lib.php'; // for preferences require_once $CFG->dirroot.'/grade/edit/tree/lib.php'; $courseid = required_param('id', PARAM_INT); $action = optional_param('action', 0, PARAM_ALPHA); $eid = optional_param('eid', 0, PARAM_ALPHANUM); $weightsadjusted = optional_param('weightsadjusted', 0, PARAM_INT); $url = new moodle_url('/grade/edit/tree/index.php', array('id' => $courseid)); $PAGE->set_url($url); $PAGE->set_pagelayout('admin'); /// Make sure they can even access this course if (!$course = $DB->get_record('course', array('id' => $courseid))) { throw new \moodle_exception('invalidcourseid'); } require_login($course); $context = context_course::instance($course->id); require_capability('moodle/grade:manage', $context); $PAGE->requires->js_call_amd('core_grades/edittree_index', 'enhance'); /// return tracking object $gpr = new grade_plugin_return(array('type'=>'edit', 'plugin'=>'tree', 'courseid'=>$courseid)); $returnurl = $gpr->get_return_url(null); // get the grading tree object // note: total must be first for moving to work correctly, if you want it last moving code must be rewritten! $gtree = new grade_tree($courseid, false, false); if (empty($eid)) { $element = null; $object = null; } else { if (!$element = $gtree->locate_element($eid)) { throw new \moodle_exception('invalidelementid', '', $returnurl); } $object = $element['object']; } $switch = grade_get_setting($course->id, 'aggregationposition', $CFG->grade_aggregationposition); $strgrades = get_string('grades'); $strgraderreport = get_string('graderreport', 'grades'); $moving = false; $movingeid = false; if ($action == 'moveselect') { if ($eid and confirm_sesskey()) { $movingeid = $eid; $moving=true; } } $grade_edit_tree = new grade_edit_tree($gtree, $movingeid, $gpr); switch ($action) { case 'duplicate': if ($eid and confirm_sesskey()) { if (!$el = $gtree->locate_element($eid)) { throw new \moodle_exception('invalidelementid', '', $returnurl); } $object->duplicate(); redirect($returnurl); } break; case 'delete': if ($eid && confirm_sesskey()) { if (!$grade_edit_tree->element_deletable($element)) { // no deleting of external activities - they would be recreated anyway! // exception is activity without grading or misconfigured activities break; } $confirm = optional_param('confirm', 0, PARAM_BOOL); if ($confirm) { $object->delete('grade/report/grader/category'); redirect($returnurl); } else { $PAGE->set_title($strgrades . ': ' . $strgraderreport); $PAGE->set_heading($course->fullname); echo $OUTPUT->header(); $strdeletecheckfull = get_string('deletecheck', '', $object->get_name()); $optionsyes = array('eid'=>$eid, 'confirm'=>1, 'sesskey'=>sesskey(), 'id'=>$course->id, 'action'=>'delete'); $optionsno = array('id'=>$course->id); $formcontinue = new single_button(new moodle_url('index.php', $optionsyes), get_string('yes')); $formcancel = new single_button(new moodle_url('index.php', $optionsno), get_string('no'), 'get'); echo $OUTPUT->confirm($strdeletecheckfull, $formcontinue, $formcancel); echo $OUTPUT->footer(); die; } } break; case 'autosort': //TODO: implement autosorting based on order of mods on course page, categories first, manual items last break; case 'move': if ($eid and confirm_sesskey()) { $moveafter = required_param('moveafter', PARAM_ALPHANUM); $first = optional_param('first', false, PARAM_BOOL); // If First is set to 1, it means the target is the first child of the category $moveafter if(!$after_el = $gtree->locate_element($moveafter)) { throw new \moodle_exception('invalidelementid', '', $returnurl); } $after = $after_el['object']; $sortorder = $after->get_sortorder(); if (!$first) { $parent = $after->get_parent_category(); $object->set_parent($parent->id); } else { $object->set_parent($after->id); } $object->move_after_sortorder($sortorder); redirect($returnurl); } break; default: break; } //if we go straight to the db to update an element we need to recreate the tree as // $grade_edit_tree has already been constructed. //Ideally we could do the updates through $grade_edit_tree to avoid recreating it $recreatetree = false; if ($data = data_submitted() and confirm_sesskey()) { // Perform bulk actions first if (!empty($data->bulkmove)) { $elements = array(); foreach ($data as $key => $value) { if (preg_match('/select_(ig[0-9]*)/', $key, $matches)) { $elements[] = $matches[1]; } } $grade_edit_tree->move_elements($elements, $returnurl); } // Update weights (extra credits) on categories and items. foreach ($data as $key => $value) { if (preg_match('/^weight_([0-9]+)$/', $key, $matches)) { $aid = $matches[1]; $value = unformat_float($value); $value = clean_param($value, PARAM_FLOAT); $grade_item = grade_item::fetch(array('id' => $aid, 'courseid' => $courseid)); // Convert weight to aggregation coef2. $aggcoef = $grade_item->get_coefstring(); if ($aggcoef == 'aggregationcoefextraweightsum') { // The field 'weight' should only be sent when the checkbox 'weighoverride' is checked, // so there is not need to set weightoverride here, it is done below. $value = $value / 100.0; $grade_item->aggregationcoef2 = $value; } else if ($aggcoef == 'aggregationcoefweight' || $aggcoef == 'aggregationcoefextraweight') { $grade_item->aggregationcoef = $value; } $grade_item->update(); $recreatetree = true; // Grade item checkbox inputs. } elseif (preg_match('/^(weightoverride)_([0-9]+)$/', $key, $matches)) { $param = $matches[1]; $aid = $matches[2]; $value = clean_param($value, PARAM_BOOL); $grade_item = grade_item::fetch(array('id' => $aid, 'courseid' => $courseid)); $grade_item->$param = $value; $grade_item->update(); $recreatetree = true; } } } $originalweights = grade_helper::fetch_all_natural_weights_for_course($courseid); /** * Callback function to adjust the URL if weights changed after the * regrade. * * @param int $courseid The course ID * @param array $originalweights The weights before the regrade * @param int $weightsadjusted Whether weights have been adjusted * @return moodle_url A URL to redirect to after regrading when a progress bar is displayed. */ $grade_edit_tree_index_checkweights = function() use ($courseid, $originalweights, &$weightsadjusted) { global $PAGE; $alteredweights = grade_helper::fetch_all_natural_weights_for_course($courseid); if (array_diff($originalweights, $alteredweights)) { $weightsadjusted = 1; return new moodle_url($PAGE->url, array('weightsadjusted' => $weightsadjusted)); } return $PAGE->url; }; if (grade_regrade_final_grades_if_required($course, $grade_edit_tree_index_checkweights)) { $recreatetree = true; } $actionbar = new \core_grades\output\gradebook_setup_action_bar($context); print_grade_page_head($courseid, 'settings', 'setup', get_string('gradebooksetup', 'grades'), false, false, true, null, null, null, $actionbar); // Print Table of categories and items echo $OUTPUT->box_start('gradetreebox generalbox'); //did we update something in the db and thus invalidate $grade_edit_tree? if ($recreatetree) { $grade_edit_tree = new grade_edit_tree($gtree, $movingeid, $gpr); } $bulkmoveoptions = ['' => get_string('choosedots')] + $grade_edit_tree->categories; $tpldata = (object) [ 'actionurl' => $returnurl, 'sesskey' => sesskey(), 'showsave' => !$moving, 'showbulkmove' => !$moving && count($grade_edit_tree->categories) > 1, 'bulkmoveoptions' => array_map(function($option) use ($bulkmoveoptions) { return [ 'name' => $bulkmoveoptions[$option], 'value' => $option ]; }, array_keys($bulkmoveoptions)) ]; // Check to see if we have a normalisation message to send. if ($weightsadjusted) { $notification = new \core\output\notification(get_string('weightsadjusted', 'grades'), \core\output\notification::NOTIFY_INFO); $tpldata->notification = $notification->export_for_template($OUTPUT); } $tpldata->table = html_writer::table($grade_edit_tree->table); echo $OUTPUT->render_from_template('core_grades/edit_tree', $tpldata); echo $OUTPUT->box_end(); // Print action buttons echo $OUTPUT->container_start('buttons mdl-align'); if ($moving) { echo $OUTPUT->single_button(new moodle_url('index.php', array('id'=>$course->id)), get_string('cancel'), 'get'); } echo $OUTPUT->container_end(); $PAGE->requires->js_call_amd('core_form/changechecker', 'watchFormById', ['gradetreeform']); echo $OUTPUT->footer(); die; tree/lib.php 0000644 00000124173 15151222054 0006767 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 library of classes used by the grade edit pages * * @package core_grades * @copyright 2009 Nicolas Connault * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class grade_edit_tree { public $columns = array(); /** * @var grade_tree $gtree @see grade/lib.php */ public $gtree; /** * @var grade_plugin_return @see grade/lib.php */ public $gpr; /** * @var string $moving The eid of the category or item being moved */ public $moving; public $deepest_level; public $uses_weight = false; public $table; public $categories = array(); /** * Show calculator icons next to manual grade items * @var bool $show_calculations */ private $show_calculations; /** * Constructor */ public function __construct($gtree, $moving, $gpr) { global $USER, $OUTPUT, $COURSE; $systemdefault = get_config('moodle', 'grade_report_showcalculations'); $this->show_calculations = get_user_preferences('grade_report_showcalculations', $systemdefault); $this->gtree = $gtree; $this->moving = $moving; $this->gpr = $gpr; $this->deepest_level = $this->get_deepest_level($this->gtree->top_element); $this->columns = array(grade_edit_tree_column::factory('name', array('deepest_level' => $this->deepest_level))); if ($this->uses_weight) { $this->columns[] = grade_edit_tree_column::factory('weight', array('adv' => 'weight')); } $this->columns[] = grade_edit_tree_column::factory('range'); // This is not a setting... How do we deal with it? $this->columns[] = grade_edit_tree_column::factory('actions'); if ($this->deepest_level > 1) { $this->columns[] = grade_edit_tree_column::factory('select'); } $this->table = new html_table(); $this->table->id = "grade_edit_tree_table"; $this->table->attributes['class'] = 'generaltable simple setup-grades'; if ($this->moving) { $this->table->attributes['class'] .= ' moving'; } foreach ($this->columns as $column) { if (!($this->moving && $column->hide_when_moving)) { $this->table->head[] = $column->get_header_cell(); } } $rowcount = 0; $this->table->data = $this->build_html_tree($this->gtree->top_element, true, array(), 0, $rowcount); } /** * Recursive function for building the table holding the grade categories and items, * with CSS indentation and styles. * * @param array $element The current tree element being rendered * @param boolean $totals Whether or not to print category grade items (category totals) * @param array $parents An array of parent categories for the current element (used for indentation and row classes) * * @return string HTML */ public function build_html_tree($element, $totals, $parents, $level, &$row_count) { global $CFG, $COURSE, $PAGE, $OUTPUT; $object = $element['object']; $eid = $element['eid']; $object->name = $this->gtree->get_element_header($element, true, true, true, true, true); $object->stripped_name = $this->gtree->get_element_header($element, false, false, false); $is_category_item = false; if ($element['type'] == 'categoryitem' || $element['type'] == 'courseitem') { $is_category_item = true; } $rowclasses = array(); foreach ($parents as $parent_eid) { $rowclasses[] = $parent_eid; } $moveaction = ''; $actionsmenu = new action_menu(); $actionsmenu->set_menu_trigger(get_string('edit')); $actionsmenu->set_owner_selector('grade-item-' . $eid); if (!$is_category_item && ($icon = $this->gtree->get_edit_icon($element, $this->gpr, true))) { $actionsmenu->add($icon); } // MDL-49281 if grade_item already has calculation, it should be editable even if global setting is off. $type = $element['type']; $iscalculated = ($type == 'item' or $type == 'courseitem' or $type == 'categoryitem') && $object->is_calculated(); $icon = $this->gtree->get_calculation_icon($element, $this->gpr, true); if ($iscalculated || ($this->show_calculations && $icon)) { $actionsmenu->add($icon); } if ($element['type'] == 'item' or ($element['type'] == 'category' and $element['depth'] > 1)) { if ($this->element_deletable($element)) { $aurl = new moodle_url('index.php', array('id' => $COURSE->id, 'action' => 'delete', 'eid' => $eid, 'sesskey' => sesskey())); $icon = new action_menu_link_secondary($aurl, new pix_icon('t/delete', get_string('delete')), get_string('delete')); $actionsmenu->add($icon); } if ($this->element_duplicatable($element)) { $duplicateparams = array(); $duplicateparams['id'] = $COURSE->id; $duplicateparams['action'] = 'duplicate'; $duplicateparams['eid'] = $eid; $duplicateparams['sesskey'] = sesskey(); $aurl = new moodle_url('index.php', $duplicateparams); $duplicateicon = new pix_icon('t/copy', get_string('duplicate')); $icon = new action_menu_link_secondary($aurl, $duplicateicon, get_string('duplicate')); $actionsmenu->add($icon); } $aurl = new moodle_url('index.php', array('id' => $COURSE->id, 'action' => 'moveselect', 'eid' => $eid, 'sesskey' => sesskey())); $moveaction .= $OUTPUT->action_icon($aurl, new pix_icon('t/move', get_string('move'))); } if ($icon = $this->gtree->get_hiding_icon($element, $this->gpr, true)) { $actionsmenu->add($icon); } if ($icon = $this->gtree->get_reset_icon($element, $this->gpr, true)) { $actionsmenu->add($icon); } $actions = $OUTPUT->render($actionsmenu); $returnrows = array(); $root = false; $id = required_param('id', PARAM_INT); /// prepare move target if needed $last = ''; /// print the list items now if ($this->moving == $eid) { // do not diplay children $cell = new html_table_cell(); $cell->colspan = 12; $cell->attributes['class'] = $element['type'] . ' moving column-name level' . ($level + 1) . ' level' . ($level % 2 ? 'even' : 'odd'); $cell->text = $object->name.' ('.get_string('move').')'; return array(new html_table_row(array($cell))); } if ($element['type'] == 'category') { $level++; $this->categories[$object->id] = $object->stripped_name; $category = grade_category::fetch(array('id' => $object->id)); $item = $category->get_grade_item(); // Add aggregation coef input if not a course item and if parent category has correct aggregation type $dimmed = ($item->is_hidden()) ? 'dimmed_text' : ''; // Before we print the category's row, we must find out how many rows will appear below it (for the filler cell's rowspan) $aggregation_position = grade_get_setting($COURSE->id, 'aggregationposition', $CFG->grade_aggregationposition); $category_total_data = null; // Used if aggregationposition is set to "last", so we can print it last $html_children = array(); $row_count = 0; foreach($element['children'] as $child_el) { $moveto = null; if (empty($child_el['object']->itemtype)) { $child_el['object']->itemtype = false; } if (($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') && !$totals) { continue; } $child_eid = $child_el['eid']; $first = ''; if ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') { $first = array('first' => 1); $child_eid = $eid; } if ($this->moving && $this->moving != $child_eid) { $strmove = get_string('move'); $actions = $moveaction = ''; // no action icons when moving $aurl = new moodle_url('index.php', array('id' => $COURSE->id, 'action' => 'move', 'eid' => $this->moving, 'moveafter' => $child_eid, 'sesskey' => sesskey())); if ($first) { $aurl->params($first); } $cell = new html_table_cell(); $cell->colspan = 12; $cell->attributes['class'] = 'movehere level' . ($level + 1) . ' level' . ($level % 2 ? 'even' : 'odd'); $cell->text = html_writer::link($aurl, '', array('title' => get_string('movehere'), 'class' => 'movehere')); $moveto = new html_table_row(array($cell)); } $newparents = $parents; $newparents[] = $eid; $row_count++; $child_row_count = 0; // If moving, do not print course and category totals, but still print the moveto target box if ($this->moving && ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category')) { $html_children[] = $moveto; } elseif ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') { // We don't build the item yet because we first need to know the deepest level of categories (for category/name colspans) $category_total_item = $this->build_html_tree($child_el, $totals, $newparents, $level, $child_row_count); if (!$aggregation_position) { $html_children = array_merge($html_children, $category_total_item); } } else { $html_children = array_merge($html_children, $this->build_html_tree($child_el, $totals, $newparents, $level, $child_row_count)); if (!empty($moveto)) { $html_children[] = $moveto; } if ($this->moving) { $row_count++; } } $row_count += $child_row_count; // If the child is a category, increment row_count by one more (for the extra coloured row) if ($child_el['type'] == 'category') { $row_count++; } } // Print category total at the end if aggregation position is "last" (1) if (!empty($category_total_item) && $aggregation_position) { $html_children = array_merge($html_children, $category_total_item); } // Determine if we are at the root if (isset($element['object']->grade_item) && $element['object']->grade_item->is_course_item()) { $root = true; } $levelclass = "level$level level" . ($level % 2 ? 'odd' : 'even'); $courseclass = ''; if ($level == 1) { $courseclass = 'coursecategory'; } $row = new html_table_row(); $row->id = 'grade-item-' . $eid; $row->attributes['class'] = $courseclass . ' category ' . $dimmed; $row->attributes['data-category'] = $eid; $row->attributes['data-itemid'] = $category->get_grade_item()->id; foreach ($rowclasses as $class) { $row->attributes['class'] .= ' ' . $class; } $headercell = new html_table_cell(); $headercell->header = true; $headercell->scope = 'row'; $headercell->attributes['title'] = $object->stripped_name; $headercell->attributes['class'] = 'cell column-rowspan rowspan ' . $levelclass; $headercell->rowspan = $row_count + 1; $row->cells[] = $headercell; foreach ($this->columns as $column) { if (!($this->moving && $column->hide_when_moving)) { $row->cells[] = $column->get_category_cell($category, $levelclass, [ 'id' => $id, 'name' => $object->name, 'level' => $level, 'actions' => $actions, 'moveaction' => $moveaction, 'eid' => $eid, ]); } } $returnrows[] = $row; $returnrows = array_merge($returnrows, $html_children); // Print a coloured row to show the end of the category across the table $endcell = new html_table_cell(); $endcell->colspan = (19 - $level); $endcell->attributes['class'] = 'emptyrow colspan ' . $levelclass; $returnrows[] = new html_table_row(array($endcell)); } else { // Dealing with a grade item $item = grade_item::fetch(array('id' => $object->id)); $element['type'] = 'item'; $element['object'] = $item; $categoryitemclass = ''; if ($item->itemtype == 'category') { $categoryitemclass = 'categoryitem'; } if ($item->itemtype == 'course') { $categoryitemclass = 'courseitem'; } $dimmed = ($item->is_hidden()) ? "dimmed_text" : ""; $gradeitemrow = new html_table_row(); $gradeitemrow->id = 'grade-item-' . $eid; $gradeitemrow->attributes['class'] = $categoryitemclass . ' item ' . $dimmed; $gradeitemrow->attributes['data-itemid'] = $object->id; foreach ($rowclasses as $class) { $gradeitemrow->attributes['class'] .= ' ' . $class; } foreach ($this->columns as $column) { if (!($this->moving && $column->hide_when_moving)) { $gradeitemrow->cells[] = $column->get_item_cell($item, array('id' => $id, 'name' => $object->name, 'level' => $level, 'actions' => $actions, 'element' => $element, 'eid' => $eid, 'moveaction' => $moveaction, 'itemtype' => $object->itemtype)); } } $returnrows[] = $gradeitemrow; } return $returnrows; } /** * Given a grade_item object, returns a labelled input if an aggregation coefficient (weight or extra credit) applies to it. * @param grade_item $item * @return string HTML */ static function get_weight_input($item) { global $OUTPUT; if (!is_object($item) || get_class($item) !== 'grade_item') { throw new Exception('grade_edit_tree::get_weight_input($item) was given a variable that is not of the required type (grade_item object)'); return false; } if ($item->is_course_item()) { return ''; } $parent_category = $item->get_parent_category(); $parent_category->apply_forced_settings(); $aggcoef = $item->get_coefstring(); $itemname = $item->itemname; if ($item->is_category_item()) { // Remember, the parent category of a category item is the category itself. $itemname = $parent_category->get_name(); } $str = ''; if ($aggcoef == 'aggregationcoefweight' || $aggcoef == 'aggregationcoef' || $aggcoef == 'aggregationcoefextraweight') { return $OUTPUT->render_from_template('core_grades/weight_field', [ 'id' => $item->id, 'itemname' => $itemname, 'value' => self::format_number($item->aggregationcoef) ]); } else if ($aggcoef == 'aggregationcoefextraweightsum') { $tpldata = [ 'id' => $item->id, 'itemname' => $itemname, 'value' => self::format_number($item->aggregationcoef2 * 100.0), 'checked' => $item->weightoverride, 'disabled' => !$item->weightoverride ]; $str .= $OUTPUT->render_from_template('core_grades/weight_override_field', $tpldata); } return $str; } // Trims trailing zeros. // Used on the 'Gradebook setup' page for grade items settings like aggregation co-efficient. // Grader report has its own decimal place settings so they are handled elsewhere. static function format_number($number) { $formatted = rtrim(format_float($number, 4),'0'); if (substr($formatted, -1)==get_string('decsep', 'langconfig')) { //if last char is the decimal point $formatted .= '0'; } return $formatted; } /** * Given an element of the grade tree, returns whether it is deletable or not (only manual grade items are deletable) * * @param array $element * @return bool */ function element_deletable($element) { global $COURSE; if ($element['type'] != 'item') { return true; } $grade_item = $element['object']; if ($grade_item->itemtype != 'mod' or $grade_item->is_outcome_item() or $grade_item->gradetype == GRADE_TYPE_NONE) { return true; } $modinfo = get_fast_modinfo($COURSE); if (!isset($modinfo->instances[$grade_item->itemmodule][$grade_item->iteminstance])) { // module does not exist return true; } return false; } /** * Given an element of the grade tree, returns whether it is duplicatable or not (only manual grade items are duplicatable) * * @param array $element * @return bool */ public function element_duplicatable($element) { if ($element['type'] != 'item') { return false; } $gradeitem = $element['object']; if ($gradeitem->itemtype != 'mod') { return true; } return false; } /** * Given the grade tree and an array of element ids (e.g. c15, i42), and expecting the 'moveafter' URL param, * moves the selected items to the requested location. Then redirects the user to the given $returnurl * * @param object $gtree The grade tree (a recursive representation of the grade categories and grade items) * @param array $eids * @param string $returnurl */ function move_elements($eids, $returnurl) { $moveafter = required_param('moveafter', PARAM_INT); if (!is_array($eids)) { $eids = array($eids); } if(!$after_el = $this->gtree->locate_element("cg$moveafter")) { throw new \moodle_exception('invalidelementid', '', $returnurl); } $after = $after_el['object']; $parent = $after; $sortorder = $after->get_sortorder(); foreach ($eids as $eid) { if (!$element = $this->gtree->locate_element($eid)) { throw new \moodle_exception('invalidelementid', '', $returnurl); } $object = $element['object']; $object->set_parent($parent->id); $object->move_after_sortorder($sortorder); $sortorder++; } redirect($returnurl, '', 0); } /** * Recurses through the entire grade tree to find and return the maximum depth of the tree. * This should be run only once from the root element (course category), and is used for the * indentation of the Name column's cells (colspan) * * @param array $element An array of values representing a grade tree's element (all grade items in this case) * @param int $level The level of the current recursion * @param int $deepest_level A value passed to each subsequent level of recursion and incremented if $level > $deepest_level * @return int Deepest level */ function get_deepest_level($element, $level=0, $deepest_level=1) { $object = $element['object']; $level++; $coefstring = $element['object']->get_coefstring(); if ($element['type'] == 'category') { if ($coefstring == 'aggregationcoefweight' || $coefstring == 'aggregationcoefextraweightsum' || $coefstring == 'aggregationcoefextraweight') { $this->uses_weight = true; } foreach($element['children'] as $child_el) { if ($level > $deepest_level) { $deepest_level = $level; } $deepest_level = $this->get_deepest_level($child_el, $level, $deepest_level); } $category = grade_category::fetch(array('id' => $object->id)); $item = $category->get_grade_item(); if ($item->gradetype == GRADE_TYPE_NONE) { // Add 1 more level for grade category that has no total. $deepest_level++; } } return $deepest_level; } /** * Updates the provided gradecategory item with the provided data. * * @param grade_category $gradecategory The category to update. * @param stdClass $data the data to update the category with. * @return void */ public static function update_gradecategory(grade_category $gradecategory, stdClass $data) { // If no fullname is entered for a course category, put ? in the DB. if (!isset($data->fullname) || $data->fullname == '') { $data->fullname = '?'; } if (!isset($data->aggregateonlygraded)) { $data->aggregateonlygraded = 0; } if (!isset($data->aggregateoutcomes)) { $data->aggregateoutcomes = 0; } grade_category::set_properties($gradecategory, $data); // CATEGORY. if (empty($gradecategory->id)) { $gradecategory->insert(); } else { $gradecategory->update(); } // GRADE ITEM. // Grade item data saved with prefix "grade_item_". $itemdata = new stdClass(); foreach ($data as $k => $v) { if (preg_match('/grade_item_(.*)/', $k, $matches)) { $itemdata->{$matches[1]} = $v; } } if (!isset($itemdata->aggregationcoef)) { $itemdata->aggregationcoef = 0; } if (!isset($itemdata->gradepass) || $itemdata->gradepass == '') { $itemdata->gradepass = 0; } if (!isset($itemdata->grademax) || $itemdata->grademax == '') { $itemdata->grademax = 0; } if (!isset($itemdata->grademin) || $itemdata->grademin == '') { $itemdata->grademin = 0; } $hidden = empty($itemdata->hidden) ? 0 : $itemdata->hidden; $hiddenuntil = empty($itemdata->hiddenuntil) ? 0 : $itemdata->hiddenuntil; unset($itemdata->hidden); unset($itemdata->hiddenuntil); $locked = empty($itemdata->locked) ? 0 : $itemdata->locked; $locktime = empty($itemdata->locktime) ? 0 : $itemdata->locktime; unset($itemdata->locked); unset($itemdata->locktime); $convert = array('grademax', 'grademin', 'gradepass', 'multfactor', 'plusfactor', 'aggregationcoef', 'aggregationcoef2'); foreach ($convert as $param) { if (property_exists($itemdata, $param)) { $itemdata->$param = unformat_float($itemdata->$param); } } if (isset($itemdata->aggregationcoef2)) { $itemdata->aggregationcoef2 = $itemdata->aggregationcoef2 / 100.0; } // When creating a new category, a number of grade item fields are filled out automatically, and are required. // If the user leaves these fields empty during creation of a category, we let the default values take effect. // Otherwise, we let the user-entered grade item values take effect. $gradeitem = $gradecategory->load_grade_item(); $gradeitemcopy = fullclone($gradeitem); grade_item::set_properties($gradeitem, $itemdata); if (empty($gradeitem->id)) { $gradeitem->id = $gradeitemcopy->id; } if (empty($gradeitem->grademax) && $gradeitem->grademax != '0') { $gradeitem->grademax = $gradeitemcopy->grademax; } if (empty($gradeitem->grademin) && $gradeitem->grademin != '0') { $gradeitem->grademin = $gradeitemcopy->grademin; } if (empty($gradeitem->gradepass) && $gradeitem->gradepass != '0') { $gradeitem->gradepass = $gradeitemcopy->gradepass; } if (empty($gradeitem->aggregationcoef) && $gradeitem->aggregationcoef != '0') { $gradeitem->aggregationcoef = $gradeitemcopy->aggregationcoef; } // Handle null decimals value - must be done before update! if (!property_exists($itemdata, 'decimals') or $itemdata->decimals < 0) { $gradeitem->decimals = null; } // Change weightoverride flag. Check if the value is set, because it is not when the checkbox is not ticked. $itemdata->weightoverride = isset($itemdata->weightoverride) ? $itemdata->weightoverride : 0; if ($gradeitem->weightoverride != $itemdata->weightoverride && $gradecategory->aggregation == GRADE_AGGREGATE_SUM) { // If we are using natural weight and the weight has been un-overriden, force parent category to recalculate weights. $gradecategory->force_regrading(); } $gradeitem->weightoverride = $itemdata->weightoverride; $gradeitem->outcomeid = null; // This means we want to rescale overridden grades as well. if (!empty($data->grade_item_rescalegrades) && $data->grade_item_rescalegrades == 'yes') { $gradeitem->markasoverriddenwhengraded = false; $gradeitem->rescale_grades_keep_percentage($gradeitemcopy->grademin, $gradeitemcopy->grademax, $gradeitem->grademin, $gradeitem->grademax, 'gradebook'); } // Only update the category's 'hidden' status if it has changed. Leaving a category as 'unhidden' (checkbox left // unmarked) and submitting the form without this conditional check will result in displaying any grade items that // are in the category, including those that were previously 'hidden'. if (($gradecategory->get_hidden() != $hiddenuntil) || ($gradecategory->get_hidden() != $hidden)) { if ($hiddenuntil) { $gradecategory->set_hidden($hiddenuntil, true); } else { $gradecategory->set_hidden($hidden, true); } } $gradeitem->set_locktime($locktime); // Locktime first - it might be removed when unlocking. $gradeitem->set_locked($locked, false, true); $gradeitem->update(); // We don't need to insert it, it's already created when the category is created. // Set parent if needed. if (isset($data->parentcategory)) { $gradecategory->set_parent($data->parentcategory, 'gradebook'); } } } /** * Class grade_edit_tree_column * * @package core_grades * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ abstract class grade_edit_tree_column { public $forced; public $hidden; public $forced_hidden; public $advanced_hidden; public $hide_when_moving = true; /** * html_table_cell object used as a template for header cells in all categories. * It must be cloned before being used. * @var html_table_cell $headercell */ public $headercell; /** * html_table_cell object used as a template for category cells in all categories. * It must be cloned before being used. * @var html_table_cell $categorycell */ public $categorycell; /** * html_table_cell object used as a template for item cells in all categories. * It must be cloned before being used. * @var html_table_cell $itemcell */ public $itemcell; public static function factory($name, $params=array()) { $class_name = "grade_edit_tree_column_$name"; if (class_exists($class_name)) { return new $class_name($params); } } public abstract function get_header_cell(); public function get_category_cell($category, $levelclass, $params) { $cell = clone($this->categorycell); $cell->attributes['class'] .= ' ' . $levelclass; $cell->attributes['text'] = ''; return $cell; } public function get_item_cell($item, $params) { $cell = clone($this->itemcell); $cell->attributes['text'] = ''; if (isset($params['level'])) { $level = $params['level'] + (($item->itemtype == 'category' || $item->itemtype == 'course') ? 0 : 1); $cell->attributes['class'] .= ' level' . $level; $cell->attributes['class'] .= ' level' . ($level % 2 ? 'odd' : 'even'); } return $cell; } public function __construct() { $this->headercell = new html_table_cell(); $this->headercell->header = true; $this->headercell->attributes['class'] = 'header'; $this->categorycell = new html_table_cell(); $this->categorycell->attributes['class'] = 'cell'; $this->itemcell = new html_table_cell(); $this->itemcell->attributes['class'] = 'cell'; if (preg_match('/^grade_edit_tree_column_(\w*)$/', get_class($this), $matches)) { $this->headercell->attributes['class'] .= ' column-' . $matches[1]; $this->categorycell->attributes['class'] .= ' column-' . $matches[1]; $this->itemcell->attributes['class'] .= ' column-' . $matches[1]; } } } /** * Class grade_edit_tree_column_name * * @package core_grades * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class grade_edit_tree_column_name extends grade_edit_tree_column { public $forced = false; public $hidden = false; public $forced_hidden = false; public $advanced_hidden = false; public $deepest_level = 1; public $hide_when_moving = false; public function __construct($params) { if (empty($params['deepest_level'])) { throw new Exception('Tried to instantiate a grade_edit_tree_column_name object without the "deepest_level" param!'); } $this->deepest_level = $params['deepest_level']; parent::__construct(); } public function get_header_cell() { $headercell = clone($this->headercell); $headercell->colspan = $this->deepest_level + 1; $headercell->text = get_string('name'); return $headercell; } public function get_category_cell($category, $levelclass, $params) { global $OUTPUT; if (empty($params['name']) || empty($params['level'])) { throw new Exception('Array key (name or level) missing from 3rd param of grade_edit_tree_column_name::get_category_cell($category, $levelclass, $params)'); } $moveaction = isset($params['moveaction']) ? $params['moveaction'] : ''; $categorycell = parent::get_category_cell($category, $levelclass, $params); $categorycell->colspan = ($this->deepest_level +1) - $params['level']; $categorycell->text = $OUTPUT->heading($moveaction . $params['name'], 4); return $categorycell; } public function get_item_cell($item, $params) { global $CFG; if (empty($params['element']) || empty($params['name']) || empty($params['level'])) { throw new Exception('Array key (name, level or element) missing from 2nd param of grade_edit_tree_column_name::get_item_cell($item, $params)'); } $name = $params['name']; $moveaction = isset($params['moveaction']) ? $params['moveaction'] : ''; $itemcell = parent::get_item_cell($item, $params); $itemcell->colspan = ($this->deepest_level + 1) - $params['level']; $itemcell->text = $moveaction . $name; return $itemcell; } } /** * Class grade_edit_tree_column_weight * * @package core_grades * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class grade_edit_tree_column_weight extends grade_edit_tree_column { public function get_header_cell() { global $OUTPUT; $headercell = clone($this->headercell); $headercell->text = get_string('weights', 'grades').$OUTPUT->help_icon('aggregationcoefweight', 'grades'); return $headercell; } public function get_category_cell($category, $levelclass, $params) { $item = $category->get_grade_item(); $categorycell = parent::get_category_cell($category, $levelclass, $params); $categorycell->text = grade_edit_tree::get_weight_input($item); return $categorycell; } public function get_item_cell($item, $params) { global $CFG; if (empty($params['element'])) { throw new Exception('Array key (element) missing from 2nd param of grade_edit_tree_column_weightorextracredit::get_item_cell($item, $params)'); } $itemcell = parent::get_item_cell($item, $params); $itemcell->text = ' '; $object = $params['element']['object']; if (!in_array($object->itemtype, array('courseitem', 'categoryitem', 'category')) && !in_array($object->gradetype, array(GRADE_TYPE_NONE, GRADE_TYPE_TEXT)) && (!$object->is_outcome_item() || $object->load_parent_category()->aggregateoutcomes) && ($object->gradetype != GRADE_TYPE_SCALE || !empty($CFG->grade_includescalesinaggregation))) { $itemcell->text = grade_edit_tree::get_weight_input($item); } return $itemcell; } } /** * Class grade_edit_tree_column_range * * @package core_grades * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class grade_edit_tree_column_range extends grade_edit_tree_column { public function get_header_cell() { $headercell = clone($this->headercell); $headercell->text = get_string('maxgrade', 'grades'); return $headercell; } public function get_category_cell($category, $levelclass, $params) { $categorycell = parent::get_category_cell($category, $levelclass, $params); $categorycell->text = ' - '; return $categorycell; } public function get_item_cell($item, $params) { global $DB, $OUTPUT; // If the parent aggregation is Natural, we should show the number, even for scales, as that value is used... // ...in the computation. For text grades, the grademax is not used, so we can still show the no value string. $parentcat = $item->get_parent_category(); if ($item->gradetype == GRADE_TYPE_TEXT) { $grademax = ' - '; } else if ($item->gradetype == GRADE_TYPE_SCALE) { $scale = $DB->get_record('scale', array('id' => $item->scaleid)); $scale_items = null; if (empty($scale)) { //if the item is using a scale that's been removed $scale_items = array(); } else { $scale_items = explode(',', $scale->scale); } if ($parentcat->aggregation == GRADE_AGGREGATE_SUM) { $grademax = end($scale_items) . ' (' . format_float($item->grademax, $item->get_decimals()) . ')'; } else { $grademax = end($scale_items) . ' (' . count($scale_items) . ')'; } } else { $grademax = format_float($item->grademax, $item->get_decimals()); } $isextracredit = false; if ($item->aggregationcoef > 0) { // For category grade items, we need the grandparent category. // The parent is just category the grade item represents. if ($item->is_category_item()) { $grandparentcat = $parentcat->get_parent_category(); if ($grandparentcat->is_extracredit_used()) { $isextracredit = true; } } else if ($parentcat->is_extracredit_used()) { $isextracredit = true; } } if ($isextracredit) { $grademax .= ' ' . html_writer::tag('abbr', get_string('aggregationcoefextrasumabbr', 'grades'), array('title' => get_string('aggregationcoefextrasum', 'grades'))); } $itemcell = parent::get_item_cell($item, $params); $itemcell->text = $grademax; return $itemcell; } } /** * Class grade_edit_tree_column_actions * * @package core_grades * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class grade_edit_tree_column_actions extends grade_edit_tree_column { public function __construct($params) { parent::__construct(); } public function get_header_cell() { $headercell = clone($this->headercell); $headercell->text = get_string('actions'); return $headercell; } public function get_category_cell($category, $levelclass, $params) { if (empty($params['actions'])) { throw new Exception('Array key (actions) missing from 3rd param of grade_edit_tree_column_actions::get_category_actions($category, $levelclass, $params)'); } $categorycell = parent::get_category_cell($category, $levelclass, $params); $categorycell->text = $params['actions']; return $categorycell; } public function get_item_cell($item, $params) { if (empty($params['actions'])) { throw new Exception('Array key (actions) missing from 2nd param of grade_edit_tree_column_actions::get_item_cell($item, $params)'); } $itemcell = parent::get_item_cell($item, $params); $itemcell->text = $params['actions']; return $itemcell; } } /** * Class grade_edit_tree_column_select * * @package core_grades * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class grade_edit_tree_column_select extends grade_edit_tree_column { public function get_header_cell() { $headercell = clone($this->headercell); $headercell->text = get_string('select'); return $headercell; } public function get_category_cell($category, $levelclass, $params) { global $OUTPUT; if (empty($params['eid'])) { throw new Exception('Array key (eid) missing from 3rd param of grade_edit_tree_column_select::get_category_cell($category, $levelclass, $params)'); } // Get toggle group for this master checkbox. $togglegroup = $this->get_checkbox_togglegroup($category); // Set label for this master checkbox. $masterlabel = get_string('all'); // Use category name if available. if ($category->fullname !== '?') { $masterlabel = format_string($category->fullname, true, ['escape' => false]); // Limit the displayed category name to prevent the Select column from getting too wide. if (core_text::strlen($masterlabel) > 20) { $masterlabel = get_string('textellipsis', 'core', core_text::substr($masterlabel, 0, 12)); } } // Build the master checkbox. $mastercheckbox = new \core\output\checkbox_toggleall($togglegroup, true, [ 'id' => $togglegroup, 'name' => $togglegroup, 'value' => 1, 'classes' => 'itemselect ignoredirty', 'label' => $masterlabel, // Consistent label to prevent the select column from resizing. 'selectall' => $masterlabel, 'deselectall' => $masterlabel, 'labelclasses' => 'm-0', ]); $categorycell = parent::get_category_cell($category, $levelclass, $params); $categorycell->text = $OUTPUT->render($mastercheckbox); return $categorycell; } public function get_item_cell($item, $params) { if (empty($params['itemtype']) || empty($params['eid'])) { throw new \moodle_exception('missingitemtypeoreid', 'core_grades'); } $itemcell = parent::get_item_cell($item, $params); if ($params['itemtype'] != 'course' && $params['itemtype'] != 'category') { global $OUTPUT; // Fetch the grade item's category. $category = grade_category::fetch(['id' => $item->categoryid]); $togglegroup = $this->get_checkbox_togglegroup($category); $checkboxid = 'select_' . $params['eid']; $checkbox = new \core\output\checkbox_toggleall($togglegroup, false, [ 'id' => $checkboxid, 'name' => $checkboxid, 'label' => get_string('select', 'grades', $item->itemname), 'labelclasses' => 'accesshide', 'classes' => 'itemselect ignoredirty', ]); $itemcell->text = $OUTPUT->render($checkbox); } return $itemcell; } /** * Generates a toggle group name for a bulk-action checkbox based on the given grade category. * * @param grade_category $category The grade category. * @return string */ protected function get_checkbox_togglegroup(grade_category $category): string { $levels = []; $categories = explode('/', $category->path); foreach ($categories as $categoryid) { $level = 'category' . $categoryid; if (!in_array($level, $levels)) { $levels[] = 'category' . $categoryid; } } $togglegroup = implode(' ', $levels); return $togglegroup; } } tree/calculation_form.php 0000644 00000007204 15151222054 0011535 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 moodleform to allow the editing of a calculated grade item * * @package core_grades * @copyright 2007 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->libdir.'/formslib.php'; class edit_calculation_form extends moodleform { public $available; public $noidnumbers; function definition() { global $COURSE; $mform =& $this->_form; $itemid = $this->_customdata['itemid']; $this->available = grade_item::fetch_all(array('courseid'=>$COURSE->id)); $this->noidnumbers = array(); // All items that have no idnumbers are added to a separate section of the form (hidden by default), // enabling the user to assign idnumbers to these grade_items. foreach ($this->available as $item) { if (empty($item->idnumber)) { $this->noidnumbers[$item->id] = $item; unset($this->available[$item->id]); } if ($item->id == $itemid) { // Do not include the current grade_item in the available section unset($this->available[$item->id]); } } /// visible elements $mform->addElement('header', 'general', get_string('gradeitem', 'grades')); $mform->addElement('static', 'itemname', get_string('itemname', 'grades')); $mform->addElement('textarea', 'calculation', get_string('calculation', 'grades'), 'cols="60" rows="5"'); $mform->addHelpButton('calculation', 'calculation', 'grades'); $mform->setForceLtr('calculation'); /// hidden params $mform->addElement('hidden', 'id', 0); $mform->setType('id', PARAM_INT); $mform->addElement('hidden', 'courseid', 0); $mform->setType('courseid', PARAM_INT); $mform->addElement('hidden', 'section', 0); $mform->setType('section', PARAM_ALPHA); $mform->setDefault('section', 'calculation'); /// add return tracking info $gpr = $this->_customdata['gpr']; $gpr->add_mform_elements($mform); $this->add_action_buttons(); } function definition_after_data() { global $CFG, $COURSE; $mform =& $this->_form; } /// perform extra validation before submission function validation($data, $files) { $errors = parent::validation($data, $files); $mform =& $this->_form; // check the calculation formula if ($data['calculation'] != '') { $grade_item = grade_item::fetch(array('id'=>$data['id'], 'courseid'=>$data['courseid'])); $calculation = calc_formula::unlocalize(stripslashes($data['calculation'])); $result = $grade_item->validate_formula($calculation); if ($result !== true) { $errors['calculation'] = $result; } } return $errors; } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | ���֧ߧ֧�ѧ�ڧ� ����ѧߧڧ��: 0 |
proxy
|
phpinfo
|
���ѧ����ۧܧ�