MDL-29479 The draft of embedding the UI widgets into the page

The patch makes more sense when reviewed together with the parallel work
on gradingform_random (see MDL-29631) where the developed API is
actually tested.
This commit is contained in:
David Mudrak 2011-10-08 00:59:01 +02:00
parent b7a6bb9ba8
commit 21d37aa623
4 changed files with 214 additions and 14 deletions

View File

@ -16,6 +16,8 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Common classes used by gradingform plugintypes are defined here
*
* @package core
* @subpackage grading
* @copyright 2011 David Mudrak <david@moodle.com>
@ -25,13 +27,14 @@
defined('MOODLE_INTERNAL') || die();
/**
* Grading method controller encapsulates the logic of the plugin
*
* @copyright 2011 David Mudrak <david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* Grading method controller represents a plugin used in a particular area
*/
abstract class gradingform_controller {
const DEFINITION_STATUS_WORKINPROGRESS = 0;
const DEFINITION_STATUS_PRIVATE = 1;
const DEFINITION_STATUS_PUBLIC = 2;
/** @var stdClass the context */
protected $context;
@ -53,6 +56,9 @@ abstract class gradingform_controller {
/** @var bool is the target grading page finalized for sending output to the browser */
protected $pagefinalized = false;
/** @var array list of widgets made by this controller for $this->page */
protected $widgets = array();
/**
* Do not instantinate this directly, use {@link grading_manager::get_controller()}
*
@ -70,26 +76,52 @@ abstract class gradingform_controller {
}
/**
* Is the grading form defined and released for usage?
* Is the grading form defined and released for usage by the given user?
*
* @param int $foruserid the id of the user who attempts to work with the form
* @return boolean
*/
public function is_form_available() {
return true; // todo make this dependent on grading_definitions existence and its status
public function is_form_available($foruserid = null) {
global $USER;
if (is_null($foruserid)) {
$foruserid = $USER->id;
}
if (empty($this->definition)) {
return false;
}
if ($this->definition->status == self::DEFINITION_STATUS_PUBLIC) {
return true;
}
if ($this->definition->status == self::DEFINITION_STATUS_PRIVATE) {
if ($this->definition->usercreated == $foruserid) {
return true;
}
}
return false;
}
/**
* Prepare a grading widget for the given rater and item
*
* If you make multiple widgets, pass bulk = true. Note that then it is
* the caller's responsibility to call {@link finalize_page()} method explicitly.
* The options array MUST contain (string)displayas set to either 'scale' or 'grade'.
* If scale is used, the (int)scaleid must be provided. If grade is used, (int)maxgrade
* must be provided and (int)decimals can be provided (defaults to 0).
* The options array CAN contain (bool)bulk to signalize whether there are more widgets to be
* made by this controller instance or whether this is the last one.
* If you make multiple widgets, pass bulk option se to true. Note that then it is
* the caller's responsibility to call {@link finalize_page()} method explicitly then.
*
* @param int $raterid the user who will use the widget for grading
* @param int $itemid the graded item
* @param bool $bulk are more widgets to be made by this instance or is this the last one?
* @param array $options the widget options
* @return gradingform_widget renderable widget to insert into the page
*/
abstract public function make_grading_widget($raterid, $itemid, $bulk = false);
abstract public function make_grading_widget($raterid, $itemid, array $options);
/**
* Does everything needed before the page is sent to the browser
@ -132,9 +164,95 @@ abstract class gradingform_controller {
}
/**
* Loads the form definition is it exists
* Saves the defintion data into database
*
* The default implementation tries to load just the record ftom the {grading_definitions}
* The default implementation stored the record into the {grading_definition} table. The
* plugins are likely to extend this and save their data into own tables, too.
*
* @param stdClass $definition
*/
public function update_definition(stdClass $definition, $usermodified = null) {
global $DB, $USER;
if (is_null($usermodified)) {
$usermodified = $USER->id;
}
if ($this->definition) {
// the following fields can't be altered by the caller
$definition->id = $this->definition->id;
$definition->timemodified = time();
$definition->usermodified = $usermodified;
unset($definition->areaid);
unset($definition->method);
unset($definition->timecreated);
$DB->update_record('grading_definitions', $definition);
} else if ($this->definition === false) {
// the record did not existed when the controller was instantinated
// let us assume it still does not exist (this may throw exception
// in case of two users working on the same form definition at the same time)
unset($definition->id);
$definition->areaid = $this->areaid;
$definition->method = $this->get_method_name();
$definition->timecreated = time();
$definition->usercreated = $usermodified;
$definition->timemodified = $definition->timecreated;
$definition->usermodified = $definition->usercreated;
$definition->status = self::DEFINITION_STATUS_WORKINPROGRESS;
$DB->insert_record('grading_definitions', $definition);
} else {
// this should not happen - the record cache status is unknown, let us
// reload it and start again
$this->load_definition();
$this->update_definition($definition, $usermodified);
}
}
/**
* Makes sure there is a form instance for the given rater grading the given item
*
* Plugins will probably override/extend this and load additional data of how their
* forms are filled in one complex query.
*
* @todo this might actually become abstract method
* @param int $raterid
* @param int $itemid
* @return stdClass newly created or existing record from {grading_instances}
*/
public function prepare_instance($raterid, $itemid) {
global $DB;
if (empty($this->definition)) {
throw new coding_exception('Attempting to prepare an instance of non-existing grading form');
}
$current = $DB->get_record('grading_instances', array(
'formid' => $this->definition->id,
'raterid' => $raterid,
'itemid' => $itemid), '*', IGNORE_MISSING);
if (empty($current)) {
$instance = new stdClass();
$instance->formid = $this->definition->id;
$instance->raterid = $raterid;
$instance->itemid = $itemid;
$instance->timemodified = time();
$instance->id = $DB->insert_record('grading_instances', $instance);
return $instance;
} else {
return $current;
}
}
/**
* Loads the form definition if it exists
*
* The default implementation just tries to load the record from the {grading_definitions}
* table. The plugins are likely to override this with a more complex query that loads
* all required data at once.
*/
@ -159,4 +277,47 @@ abstract class gradingform_renderer extends plugin_renderer_base {
* Base class for all gradingform renderable widgets
*/
abstract class gradingform_widget implements renderable {
/** @var string unique identifier that can be used as the element id during the rendering, for example */
public $id;
/** @var gradingform_controller instance of the controller that created this widget */
public $controller;
/** @var array the widget options */
public $options;
/** @var stdClass the current instance data */
public $instance;
/**
* @param gradingform_controller the method controller that created this widget
*/
public function __construct(gradingform_controller $controller, array $options, stdClass $instance) {
$this->id = uniqid(get_class($this));
$this->controller = $controller;
$this->options = $options;
$this->instance = $instance;
}
}
/**
* Base class for all gradingform renderable grading widgets
*
* Grading widget is the UI element that raters use when they interact with
* the grading form.
*/
abstract class gradingform_grading_widget extends gradingform_widget {
}
/**
* Base class for all gradingform renderable editor widgets
*
* Plugins that implement editor UI via its own renderable widgets should
* probably extend this. Editor widget is the UI element that course designers
* use when they design (define) the grading form.
*/
abstract class gradingform_editor_widget implements renderable {
}

View File

@ -31,7 +31,16 @@ require_once($CFG->dirroot.'/grade/grading/form/lib.php'); // parent class
/**
* This controller encapsulates the rubric grading logic
*/
class rubric_grading_controller extends grading_controller {
class gradingform_rubric_controller extends gradingform_controller {
/**
* @see parent::make_grading_widget()
* @return gradingform_rubric_grading_widget
*/
public function make_grading_widget($raterid, $itemid, array $options) {
// todo
}
/**
* Extends the module settings navigation with the rubric grading settings
@ -48,4 +57,11 @@ class rubric_grading_controller extends grading_controller {
new moodle_url('/grade/grading/form/rubric/edit.php', array('area' => $this->areaid)), settings_navigation::TYPE_CUSTOM,
null, null, new pix_icon('icon', '', 'gradingform_rubric'));
}
/**
* @see parent::get_method_name()
*/
protected function get_method_name() {
return 'rubric';
}
}

View File

@ -91,6 +91,13 @@ class grading_manager {
/** @var stdClass|false|null the raw record from {grading_areas}, false if does not exist, null if invalidated cache */
private $areacache = null;
/**
* @return stdClass grading manager context
*/
public function get_context() {
return $this->context;
}
/**
* Sets the context the manager operates on
*
@ -101,6 +108,13 @@ class grading_manager {
$this->context = $context;
}
/**
* @return string grading manager component
*/
public function get_component() {
return $this->component;
}
/**
* Sets the component the manager operates on
*
@ -112,6 +126,13 @@ class grading_manager {
$this->component = $type.'_'.$name;
}
/**
* @return string grading manager area name
*/
public function get_area() {
return $this->area;
}
/**
* Sets the area the manager operates on
*

View File

@ -26,7 +26,9 @@
defined('MOODLE_INTERNAL') || die();
$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['gradinginarea'] = 'Grading ({$a})';
$string['gradingmethod'] = 'Grading method';
$string['gradingmethods'] = 'Grading methods';
$string['gradingmethodnone'] = 'Simple direct grading';
$string['noitemid'] = 'Grading not possible. The graded item does not exist.';