Saving a form as a public template
There is a new API method get_definition_copy() that is expected to return the definition structure as if the form was written from scratch via the editor. Such a prepared structure is passed to a controller's update_definition() method in the new target area. The same mechanism will be used for copying definitions from a shared area to a normal gradable area.
This commit is contained in:
@@ -183,6 +183,36 @@ abstract class gradingform_controller {
|
||||
return $this->definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the form definition suitable for cloning into another area
|
||||
*
|
||||
* @param gradingform_controller $target the controller of the new copy
|
||||
* @return stdClass definition structure to pass to the target's {@link update_definition()}
|
||||
*/
|
||||
public function get_definition_copy(gradingform_controller $target) {
|
||||
|
||||
if (get_class($this) != get_class($target)) {
|
||||
throw new coding_exception('The source and copy controller mismatch');
|
||||
}
|
||||
|
||||
if ($target->is_form_defined()) {
|
||||
throw new coding_exception('The target controller already contains a form definition');
|
||||
}
|
||||
|
||||
$old = $this->get_definition();
|
||||
// keep our id
|
||||
$new = new stdClass();
|
||||
$new->copiedfromid = $old->id;
|
||||
$new->name = $old->name;
|
||||
// once we support files embedded into the description, we will want to
|
||||
// relink them into the new file area here (that is why we accept $target)
|
||||
$new->description = $old->description;
|
||||
$new->descriptionformat = $old->descriptionformat;
|
||||
$new->options = $old->options;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the defintion data into the database
|
||||
*
|
||||
|
||||
@@ -233,6 +233,39 @@ class gradingform_rubric_controller extends gradingform_controller {
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the form definition suitable for cloning into another area
|
||||
*
|
||||
* @see parent::get_definition_copy()
|
||||
* @param gradingform_controller $target the controller of the new copy
|
||||
* @return stdClass definition structure to pass to the target's {@link update_definition()}
|
||||
*/
|
||||
public function get_definition_copy(gradingform_controller $target) {
|
||||
|
||||
$new = parent::get_definition_copy($target);
|
||||
$old = $this->get_definition();
|
||||
$new->rubric_criteria = array();
|
||||
$newcritid = 1;
|
||||
$newlevid = 1;
|
||||
foreach ($old->rubric_criteria as $oldcritid => $oldcrit) {
|
||||
unset($oldcrit['id']);
|
||||
if (isset($oldcrit['levels'])) {
|
||||
foreach ($oldcrit['levels'] as $oldlevid => $oldlev) {
|
||||
unset($oldlev['id']);
|
||||
$oldcrit['levels']['NEWID'.$newlevid] = $oldlev;
|
||||
unset($oldcrit['levels'][$oldlevid]);
|
||||
$newlevid++;
|
||||
}
|
||||
} else {
|
||||
$oldcrit['levels'] = array();
|
||||
}
|
||||
$new->rubric_criteria['NEWID'.$newcritid] = $oldcrit;
|
||||
$newcritid++;
|
||||
}
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
public function get_grading($raterid, $itemid) {
|
||||
global $DB;
|
||||
$sql = "SELECT f.id, f.criterionid, f.levelid, f.remark, f.remarkformat
|
||||
@@ -250,6 +283,7 @@ class gradingform_rubric_controller extends gradingform_controller {
|
||||
}
|
||||
// TODO: remarks
|
||||
}
|
||||
$rs->close();
|
||||
return $grading;
|
||||
}
|
||||
|
||||
|
||||
+57
-8
@@ -155,13 +155,26 @@ class grading_manager {
|
||||
public function get_component_title() {
|
||||
|
||||
$this->ensure_isset(array('context', 'component'));
|
||||
list($context, $course, $cm) = get_context_info_array($this->get_context()->id);
|
||||
|
||||
if (!empty($cm->name)) {
|
||||
$title = $cm->name;
|
||||
if ($this->get_context()->contextlevel == CONTEXT_SYSTEM) {
|
||||
if ($this->get_component() == 'core_grading') {
|
||||
$title = ''; // we are in the bank UI
|
||||
} else {
|
||||
throw new coding_exception('Unsupported component at the system context');
|
||||
}
|
||||
|
||||
} else if ($this->get_context()->contextlevel >= CONTEXT_COURSE) {
|
||||
list($context, $course, $cm) = get_context_info_array($this->get_context()->id);
|
||||
|
||||
if (!empty($cm->name)) {
|
||||
$title = $cm->name;
|
||||
} else {
|
||||
debugging('Gradable areas are currently supported at the course module level only', DEBUG_DEVELOPER);
|
||||
$title = $this->get_component();
|
||||
}
|
||||
|
||||
} else {
|
||||
debugging('Gradable areas are currently supported at the course module level only', DEBUG_DEVELOPER);
|
||||
$title = $this->get_component();
|
||||
throw new coding_exception('Unsupported gradable area context level');
|
||||
}
|
||||
|
||||
return $title;
|
||||
@@ -174,10 +187,22 @@ class grading_manager {
|
||||
*/
|
||||
public function get_area_title() {
|
||||
|
||||
$this->ensure_isset(array('context', 'component', 'area'));
|
||||
$areas = $this->get_available_areas();
|
||||
if ($this->get_context()->contextlevel == CONTEXT_SYSTEM) {
|
||||
return '';
|
||||
|
||||
return $areas[$this->get_area()];
|
||||
} else if ($this->get_context()->contextlevel >= CONTEXT_COURSE) {
|
||||
$this->ensure_isset(array('context', 'component', 'area'));
|
||||
$areas = $this->get_available_areas();
|
||||
if (array_key_exists($this->get_area(), $areas)) {
|
||||
return $areas[$this->get_area()];
|
||||
} else {
|
||||
debugging('Unknown area!');
|
||||
return '???';
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new coding_exception('Unsupported context level');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,6 +265,7 @@ class grading_manager {
|
||||
// require_once($CFG->dirroot.'/mod/assignment/lib.php');
|
||||
// return assignment_gradable_area_list();
|
||||
|
||||
// todo - what to return for bank areas in the system context
|
||||
// todo - hardcoded list for now
|
||||
return array('submission' => 'Submissions');
|
||||
}
|
||||
@@ -465,6 +491,29 @@ class grading_manager {
|
||||
return new moodle_url('/grade/grading/manage.php', $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new shared area to hold a grading form template
|
||||
*
|
||||
* Shared area are implemented as virtual gradable areas at the system level context
|
||||
* with the component set to core_grading and unique random area name.
|
||||
*
|
||||
* @param string $method the name of the plugin we create the area for
|
||||
* @return int the new area id
|
||||
*/
|
||||
public function create_shared_area($method) {
|
||||
global $DB;
|
||||
|
||||
// generate some unique random name for the new area
|
||||
$name = $method . '_' . sha1(rand().uniqid($method, true));
|
||||
// create new area record
|
||||
$area = array(
|
||||
'contextid' => get_system_context()->id,
|
||||
'component' => 'core_grading',
|
||||
'areaname' => $name,
|
||||
'activemethod' => $method);
|
||||
return $DB->insert_record('grading_areas', $area);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,12 +25,22 @@
|
||||
require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
|
||||
require_once($CFG->dirroot.'/grade/grading/lib.php');
|
||||
|
||||
// identify gradable area by its id
|
||||
$areaid = optional_param('areaid', null, PARAM_INT);
|
||||
// alternatively the context, component and areaname must be provided
|
||||
$contextid = optional_param('contextid', null, PARAM_INT);
|
||||
$component = optional_param('component', null, PARAM_COMPONENT);
|
||||
$area = optional_param('area', null, PARAM_AREA);
|
||||
// keep the caller's URL so that we know where to send the user finally
|
||||
$returnurl = optional_param('returnurl', null, PARAM_LOCALURL);
|
||||
// active method selector
|
||||
$setmethod = optional_param('setmethod', null, PARAM_PLUGIN);
|
||||
// publish the given form definition as a new template in the forms bank
|
||||
$shareform = optional_param('shareform', null, PARAM_INT);
|
||||
// consider the required action as confirmed
|
||||
$confirmed = optional_param('confirmed', false, PARAM_BOOL);
|
||||
// a message to display, typically a previous action's result
|
||||
$message = optional_param('message', null, PARAM_NOTAGS);
|
||||
|
||||
if (!is_null($areaid)) {
|
||||
// get manager by id
|
||||
@@ -47,17 +57,30 @@ if (!is_null($areaid)) {
|
||||
// currently active method
|
||||
$method = $manager->get_active_method();
|
||||
|
||||
list($context, $course, $cm) = get_context_info_array($manager->get_context()->id);
|
||||
if ($manager->get_context()->contextlevel == CONTEXT_SYSTEM) {
|
||||
// this is a shared area in the forms bank, redirect the user
|
||||
$params = array('areaid' =>$areaid);
|
||||
if (!is_null($returnurl)) {
|
||||
$params['returnurl'] = $returnurl;
|
||||
}
|
||||
redirect(new moodle_url('/grade/grading/bank.php', $params));
|
||||
|
||||
} else if ($manager->get_context()->contextlevel >= CONTEXT_COURSE) {
|
||||
list($context, $course, $cm) = get_context_info_array($manager->get_context()->id);
|
||||
|
||||
if (is_null($returnurl)) {
|
||||
$returnurl = new moodle_url('/course/view.php', array('id' => $course->id));
|
||||
} else {
|
||||
$returnurl = new moodle_url($returnurl);
|
||||
}
|
||||
|
||||
require_login($course, true, $cm);
|
||||
require_capability('moodle/grade:managegradingforms', $context);
|
||||
|
||||
if (is_null($returnurl)) {
|
||||
$returnurl = new moodle_url('/course/view.php', array('id' => $course->id));
|
||||
} else {
|
||||
$returnurl = new moodle_url($returnurl);
|
||||
throw new coding_exception('Unsupported gradable area context level');
|
||||
}
|
||||
|
||||
require_login($course, true, $cm);
|
||||
require_capability('moodle/grade:managegradingforms', $context);
|
||||
|
||||
$PAGE->set_url($manager->get_management_url($returnurl));
|
||||
navigation_node::override_active_url($manager->get_management_url());
|
||||
$PAGE->set_title(get_string('gradingmanagement', 'core_grading'));
|
||||
@@ -75,7 +98,35 @@ if (!empty($setmethod)) {
|
||||
redirect($PAGE->url);
|
||||
}
|
||||
|
||||
// publish the form as a template
|
||||
if (!empty($shareform)) {
|
||||
require_capability('moodle/grade:sharegradingforms', get_system_context());
|
||||
$controller = $manager->get_controller($method);
|
||||
$definition = $controller->get_definition();
|
||||
if (!$confirmed) {
|
||||
// let the user confirm they understand what they are doing (haha ;-)
|
||||
echo $output->header();
|
||||
echo $output->confirm(get_string('manageactionshareconfirm', 'core_grading', s($definition->name)),
|
||||
new moodle_url($PAGE->url, array('shareform' => $shareform, 'confirmed' => 1)),
|
||||
$PAGE->url);
|
||||
echo $output->footer();
|
||||
die();
|
||||
} else {
|
||||
require_sesskey();
|
||||
$newareaid = $manager->create_shared_area($method);
|
||||
$targetarea = get_grading_manager($newareaid);
|
||||
$targetcontroller = $targetarea->get_controller($method);
|
||||
$targetcontroller->update_definition($controller->get_definition_copy($targetcontroller));
|
||||
redirect(new moodle_url($PAGE->url, array('message' => get_string('manageactionsharedone', 'core_grading'))));
|
||||
}
|
||||
}
|
||||
|
||||
echo $output->header();
|
||||
|
||||
if (!empty($message)) {
|
||||
echo $output->management_message($message);
|
||||
}
|
||||
|
||||
echo $output->heading(get_string('gradingmanagementtitle', 'core_grading', array(
|
||||
'component' => $manager->get_component_title(), 'area' => $manager->get_area_title())));
|
||||
|
||||
@@ -88,10 +139,15 @@ if (!empty($method)) {
|
||||
// display relevant actions
|
||||
echo $output->container_start('actions');
|
||||
if ($controller->is_form_defined()) {
|
||||
$definition = $controller->get_definition();
|
||||
echo $output->management_action_icon($controller->get_editor_url($returnurl),
|
||||
get_string('manageactionedit', 'core_grading'), 'b/document-properties');
|
||||
get_string('manageactionedit', 'core_grading'), 'b/document-edit');
|
||||
echo $output->management_action_icon($PAGE->url,
|
||||
get_string('manageactiondelete', 'core_grading'), 'b/edit-delete');
|
||||
if (has_capability('moodle/grade:sharegradingforms', get_system_context())) {
|
||||
echo $output->management_action_icon(new moodle_url($PAGE->url, array('shareform' => $definition->id)),
|
||||
get_string('manageactionshare', 'core_grading'), 'b/bookmark-new');
|
||||
}
|
||||
} else {
|
||||
echo $output->management_action_icon($controller->get_editor_url($returnurl),
|
||||
get_string('manageactionnew', 'core_grading'), 'b/document-new');
|
||||
|
||||
@@ -66,6 +66,18 @@ class core_grading_renderer extends plugin_renderer_base {
|
||||
return html_writer::link($url, $img . $txt, array('class' => 'action'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a message for the user, typically as an action result
|
||||
*
|
||||
* @param string $message
|
||||
* @return string
|
||||
*/
|
||||
public function management_message($message) {
|
||||
$this->page->requires->strings_for_js(array('clicktoclose'), 'core_grading');
|
||||
$this->page->requires->yui_module('moodle-core_grading-manage', 'M.core_grading.init_manage');
|
||||
return $this->output->box(format_string($message).html_writer::tag('span', ''), 'message', 'actionresultmessagebox');
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the common information about the form definition
|
||||
*
|
||||
|
||||
Vendored
+48
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* YUI module for advanced grading methods - the manage page
|
||||
*
|
||||
* @author David Mudrak <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
YUI.add('moodle-core_grading-manage', function(Y) {
|
||||
|
||||
var MANAGE = function() {
|
||||
MANAGE.superclass.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
Y.extend(MANAGE, Y.Base, {
|
||||
|
||||
initializer : function(config) {
|
||||
this.setup_messagebox();
|
||||
},
|
||||
|
||||
setup_messagebox : function() {
|
||||
Y.one('#actionresultmessagebox span').setContent(M.util.get_string('clicktoclose', 'core_grading'));
|
||||
Y.one('#actionresultmessagebox').on('click', function(e) {
|
||||
e.halt();
|
||||
var box = e.currentTarget;
|
||||
var anim = new Y.Anim({
|
||||
node: box,
|
||||
from: { opacity: 1 },
|
||||
to: { opacity: 0 },
|
||||
});
|
||||
anim.run();
|
||||
anim.on('end', function() {
|
||||
var box = this.get('node'); // this === anim
|
||||
box.remove(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}, {
|
||||
NAME : 'grading_manage_page',
|
||||
ATTRS : { }
|
||||
});
|
||||
|
||||
M.core_grading = M.core_grading || {};
|
||||
|
||||
M.core_grading.init_manage = function(config) {
|
||||
return new MANAGE(config);
|
||||
}
|
||||
|
||||
}, '@VERSION@', { requires:['base', 'anim'] });
|
||||
+6
-2
@@ -29,6 +29,7 @@ defined('MOODLE_INTERNAL') || die();
|
||||
$string['activemethodinfo'] = '\'{$a->method}\' is selected as the active grading method for the \'{$a->area}\' area';
|
||||
$string['activemethodinfonone'] = 'There is no advanced grading method selected for the \'{$a->area}\' area. Simple direct grading will be used.';
|
||||
$string['changeactivemethod'] = 'Change active grading method to';
|
||||
$string['clicktoclose'] = 'click to close';
|
||||
$string['exc_gradingformelement'] = 'Unable to instantiate grading form element';
|
||||
$string['formnotavailable'] = 'Advanced grading method was selected to use but the grading form is not available yet. You may need to define it first via a link in the Settings block.';
|
||||
$string['gradingmanagement'] = 'Advanced grading';
|
||||
@@ -37,10 +38,13 @@ $string['gradingmethod'] = 'Grading method';
|
||||
$string['gradingmethod_help'] = 'Choose the advanced grading method that should be used for calculating grades in the given context.
|
||||
|
||||
To disable advance grading and switch back to the default grading mechanism, choose \'Simple direct grading\'.';
|
||||
$string['gradingmethods'] = 'Grading methods';
|
||||
$string['gradingmethodnone'] = 'Simple direct grading';
|
||||
$string['manageactionclone'] = 'Create new grading form from template';
|
||||
$string['gradingmethods'] = 'Grading methods';
|
||||
$string['manageactionclone'] = 'Create new grading form from a template';
|
||||
$string['manageactiondelete'] = 'Remove the currently defined form';
|
||||
$string['manageactionedit'] = 'Edit the current form definition';
|
||||
$string['manageactionnew'] = 'Define new grading form from scratch';
|
||||
$string['manageactionshare'] = 'Publish the form as a new template';
|
||||
$string['manageactionshareconfirm'] = 'You are going to save a copy of the grading form \'{$a}\' as a new public template. Other users at your site will be able to create new grading forms in their activities from that template. Note that users are able to reuse their own grading forms in other activities even if the forms were not saved as template.';
|
||||
$string['manageactionsharedone'] = 'The form was successfully saved as a template';
|
||||
$string['noitemid'] = 'Grading not possible. The graded item does not exist.';
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
@@ -41,4 +41,7 @@ td.grade div.overridden {background-color: #DDDDDD;}
|
||||
#page-grade-grading-manage .actions {text-align:center;}
|
||||
#page-grade-grading-manage .action {display:inline-block;width: 150px;background-color:#EEE;border:2px solid #CCC;
|
||||
margin:0.5em;padding:0.5em;text-align:center;-moz-border-radius:5px}
|
||||
#page-grade-grading-manage .action:hover {text-decoration:none;background-color:#F6F6F6;
|
||||
#page-grade-grading-manage .action:hover {text-decoration:none;background-color:#F6F6F6;}
|
||||
#page-grade-grading-manage #actionresultmessagebox {background-color:#D2EBFF;width:60%;margin:1em auto 1em auto;text-align:center;
|
||||
padding:0.5em;border:2px solid #CCC;text-align:center;-moz-border-radius:5px;position:relative}
|
||||
#page-grade-grading-manage #actionresultmessagebox span {position:absolute;right:0px;top:-1.2em;color:#666;font-size:80%}
|
||||
|
||||
Reference in New Issue
Block a user