Cooking dimension editor's raw data is done by the strategy class.
add_to_log($course->id, "workshop", "editgradingform", "editgradingform.php?id=$cm->id", "$workshop->id");
-// where should the user be sent in case of error of canceling
+// where should the user be sent after closing the editing form
$returnurl = "{$CFG->wwwroot}/mod/workshop/view.php?id={$cm->id}";
+// the URL of this editing form
$selfurl = "{$CFG->wwwroot}/mod/workshop/editgradingform.php?id={$cm->id}";
// load the grading strategy logic
if ($mform->is_cancelled()) {
redirect($returnurl);
} elseif ($data = $mform->get_data()) {
- print_object($data); die();
+ $strategy->save_dimensions($data);
+ if (isset($data->saveandclose)) {
+ redirect($returnurl);
+ } else {
+ redirect($selfurl);
+ }
}
// build the navigation and the header
* @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
-}
+defined('MOODLE_INTERNAL') || die();
-require_once(dirname(dirname(__FILE__)).'/gradingform.php'); // parent class definition
+require_once(dirname(dirname(dirname(__FILE__))).'/lib.php'); // module library
+require_once(dirname(dirname(__FILE__)).'/gradingform.php'); // parent class definition
/**
$repeated = array();
$repeated[] =& $mform->createElement('hidden', 'dimensionid', 0);
- $repeated[] =& $mform->createElement('header', 'dimension', get_string('dimensionnumberaccumulative', 'workshop', '{no}'));
- $repeated[] =& $mform->createElement('textarea', 'description',
- get_string('dimensiondescription', 'workshop'), array('cols'=>60));
+ $repeated[] =& $mform->createElement('header', 'dimension',
+ get_string('dimensionnumberaccumulative', 'workshop', '{no}'));
+ $repeated[] =& $mform->createElement('htmleditor', 'description',
+ get_string('dimensiondescription', 'workshop'), array());
$repeated[] =& $mform->createElement('select', 'grade', get_string('grade'), $gradeoptions);
$repeated[] =& $mform->createElement('select', 'weight', get_string('dimensionweight', 'workshop'), $weights);
}
- /**
- * Return the mapping of the db fields to the form fields for every dimension of assessment
- *
- * @access protected
- * @return array Array ['field_db_name' => 'field_form_name']
- */
- protected function get_dimension_fieldnames() {
- return array(
- 'id' => 'dimensionid',
- 'description' => 'description',
- 'descriptionformat' => 'descriptionformat',
- 'grade' => 'grade',
- 'weight' => 'weight',
- );
- }
-
-
}
--- /dev/null
+<?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/>.
+
+
+/**
+ * Unit tests for (some of) mod/workshop/grading/accumulative/strategy.php
+ *
+ * @package mod-workshop
+ * @copyright 2009 David Mudrak <david.mudrak@gmail.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+// Include the code to test
+require_once($CFG->dirroot . '/mod/workshop/grading/accumulative/strategy.php');
+
+
+/**
+ * Test subclass that makes all the protected methods we want to test public
+ */
+class testable_workshop_accumulative_strategy extends workshop_accumulative_strategy {
+
+ public function cook_form_data($raw) {
+ return parent::cook_form_data($raw);
+ }
+}
+
+
+class workshop_accumulative_strategy_test extends UnitTestCase {
+
+ /** workshop instance emulation */
+ protected $workshop;
+
+ /** instance of the strategy logic class being tested */
+ protected $strategy;
+
+ /** this emulates data returned by get_data() of a submitted strategy edit form */
+ protected $rawdata;
+
+ /** setup testing environment */
+ public function setUp() {
+
+ $this->workshop = new stdClass;
+ $this->workshop->id = 42;
+ $this->workshop->strategy = 'accumulative';
+
+ $this->strategy = new testable_workshop_accumulative_strategy($this->workshop);
+
+ // emulate a form with 5 dimensions. The first three are already in DB, the forth is new and the
+ // fifth is left empty
+ $this->rawdata = new stdClass;
+ $this->rawdata->workshopid = 42;
+ $this->rawdata->strategy = 'accumulative';
+ $this->rawdata->numofdimensions = 5;
+ $this->rawdata->dimensionid = array(0 => 3, 1=> 2, 2 => 1, 3 => 0, 4 => 0);
+ $this->rawdata->description = array(0 => 'First', 1 => 'Second', 2 => 'Third', 3 => 'Forth', 4 => '');
+ $this->rawdata->descriptionformat = array(0 => 1, 1 => 1, 2 => 1, 3 => 1, 4 => 1);
+ $this->rawdata->grade = array(0 => 10, 1 => 5, 2 => 5, 3 => 2, 4 => 10);
+ $this->rawdata->weight = array(0 => 1, 1 => 1, 2 => 2, 3 => 2, 4 => 1);
+ }
+
+ public function tearDown() {
+ $this->strategy = null;
+ }
+
+ public function test_cook_form_data() {
+
+ $cooked = $this->strategy->cook_form_data($this->rawdata);
+ $this->assertIsA($cooked, 'Array');
+ $this->assertEqual($cooked[2], (object)array(
+ 'id' => 1,
+ 'workshopid' => 42,
+ 'sort' => 3,
+ 'description' => 'Third',
+ 'descriptionformat' => 1,
+ 'grade' => 5,
+ 'weight' => 2,
+ ));
+ $this->assertEqual($cooked[3], (object)array(
+ 'id' => 0,
+ 'workshopid' => 42,
+ 'sort' => 4,
+ 'description' => 'Forth',
+ 'descriptionformat' => 1,
+ 'grade' => 2,
+ 'weight' => 2,
+ ));
+ $this->assertEqual($cooked[4], (object)array(
+ 'id' => 0,
+ 'workshopid' => 42,
+ 'sort' => 5,
+ 'description' => '',
+ 'descriptionformat' => 1,
+ 'grade' => 10,
+ 'weight' => 1,
+ ));
+ }
+
+}
*/
class workshop_accumulative_strategy extends workshop_strategy {
+ /**
+ * Mapping of the db fields to the form fields for every dimension of assessment
+ *
+ * @return array Array ['field_db_name' => 'field_form_name']
+ */
+ public function map_dimension_fieldnames() {
+ return array(
+ 'id' => 'dimensionid',
+ 'description' => 'description',
+ 'descriptionformat' => 'descriptionformat',
+ 'grade' => 'grade',
+ 'weight' => 'weight',
+ );
+ }
+
+
}
* @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
-}
+defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/formslib.php'); // parent class definition
*/
class workshop_edit_strategy_form extends moodleform {
- /**
- * Number of dimensions that are populated from DB
- *
- * @var mixed
- * @access protected
- */
+ /** strategy logic instance that this class is editor of */
+ protected $strategy;
+
+ /** number of dimensions that are populated from DB */
protected $numofdimensions;
/**
* Constructor
*
+ * @param object $strategy The instance of the strategy logic
* @param str $actionurl URL to handle data
* @param bool $editable Should the form be editable?
* @param int $initialdimensions Number of assessment dimensions that are already filled
* @access public
* @return void
*/
- public function __construct($actionurl, $editable=true, $initialdimensions=0) {
+ public function __construct(workshop_strategy $strategy, $actionurl, $editable=true, $initialdimensions=0) {
- $this->numofdimensions = $initialdimensions;
+ $this->strategy = $strategy;
+ $this->numofdimensions = $initialdimensions;
parent::moodleform($actionurl, null, 'post', '', array('class' => 'editstrategyform'), $editable);
}
}
$buttonarray = array();
- $buttonarray[] = &$mform->createElement('submit', 'submitbutton', get_string('savechanges'));
+ $buttonarray[] = &$mform->createElement('submit', 'saveandclose', get_string('saveandclose', 'workshop'));
+ $buttonarray[] = &$mform->createElement('submit', 'saveandcontinue', get_string('saveandcontinue', 'workshop'));
$buttonarray[] = &$mform->createElement('cancel');
$mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
$mform->closeHeaderBefore('buttonar');
* Set the form data before it is displayed
*
* Strategy plugins should provide the list of fields to be mapped from
- * DB record to the form fields in their get_dimension_fieldnames() method
+ * DB record to the form fields in their map_dimension_fieldnames() method
*
* @param object $formdata Should contain the array $formdata->dimensions
* @access public
$key = 0;
$default_values = array();
foreach ($formdata->dimensions as $dimension) {
- foreach ($this->get_dimension_fieldnames() as $fielddbname => $fieldformname) {
+ foreach ($this->strategy->map_dimension_fieldnames() as $fielddbname => $fieldformname) {
$default_values[$fieldformname . '[' . $key . ']'] = $dimension->$fielddbname;
}
$key++;
}
- /**
- * Return the mapping of the db fields to the form fields for every assessment dimension
- *
- * @access protected
- * @return array Array ['field_db_name' => 'field_form_name']
- */
- protected function get_dimension_fieldnames() {
- return array();
- }
-
}
* @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
-}
-
+defined('MOODLE_INTERNAL') || die();
/**
* Strategy interface defines all methods that strategy subplugins has to implemens
*/
interface workshop_strategy_interface {
+ /**
+ * Factory method returning an instance of an assessment form editor class
+ *
+ * The returned class will probably expand the base workshop_edit_strategy_form
+ *
+ * @param string $actionurl URL of the action handler script
+ * @param boolean $edit Open the form in editing mode
+ * @param int $nodimensions Number of dimensions to be provided by set_data
+ * @access public
+ * @return object The instance of the assessment form editor class
+ */
+ public function get_edit_strategy_form($actionurl, $edit=true, $nodimensions=0);
+
+
/**
* Load the assessment dimensions from database
*
* to be evaluated. Each dimension consists of a set of form fields. Strategy-specific information
* are saved in workshop_forms_{strategyname} tables.
*
- * @uses $DB
* @access public
- * @return void
+ * @return array Array of database records
*/
public function load_dimensions();
+
+ /**
+ * Save the assessment dimensions into database
+ *
+ * Assessment dimension (also know as assessment element) represents one aspect or criterion
+ * to be evaluated. Each dimension consists of a set of form fields. Strategy-specific information
+ * are saved in workshop_forms_{strategyname} tables.
+ *
+ * @access public
+ * @return void
+ */
+ public function save_dimensions($data);
}
/**
- * Base class for grading strategy logic.
+ * Base class for grading strategy logic
+ *
+ * This base class implements the default behaviour that should be suitable for the most
+ * of simple grading strategies.
*/
class workshop_strategy implements workshop_strategy_interface {
}
+ /**
+ * Factory method returning an instance of an assessment form editor class
+ *
+ * By default, the class is defined in grading/{strategy}/gradingform.php and is named
+ * workshop_edit_{strategy}_strategy_form
+ */
public function get_edit_strategy_form($actionurl, $edit=true, $nodimensions=0) {
global $CFG; // needed because the included files use it
}
$classname = 'workshop_edit_' . $this->name . '_strategy_form';
- return new $classname($actionurl, $edit, $nodimensions);
+ return new $classname($this, $actionurl, $edit, $nodimensions);
}
+
/**
* Load the assessment dimensions from database
*
- * This base method just fetches all relevant records from the strategy form table.
+ * This base method just fetches all relevant records from the main strategy form table.
*
* @uses $DB
* @access public
return $DB->get_records('workshop_forms_' . $this->name, array('workshopid' => $this->_workshop->id), 'sort');
}
+
+ /**
+ * Save the assessment dimensions into database
+ *
+ * This base method saves data into the main strategy form table. If the record->id is null or zero,
+ * new record is created. If the record->id is not empty, the existing record is updated. Records with
+ * empty 'description' field are not saved.
+ * The passed data object are the raw data returned by the get_data(). They must be cooked here.
+ *
+ * @uses $DB
+ * @param object $data Raw data returned by the dimension editor form
+ * @access public
+ * @return void
+ */
+ public function save_dimensions($data) {
+ global $DB;
+
+ $data = $this->cook_form_data($data);
+
+ foreach ($data as $record) {
+ if (empty($record->description)) {
+ continue;
+ }
+ if (empty($record->id)) {
+ // new field
+ $record->id = $DB->insert_record('workshop_forms_' . $this->name, $record);
+ } else {
+ // exiting field
+ $DB->update_record('workshop_forms_' . $this->name, $record);
+ }
+ }
+ }
+
+
+ /**
+ * The default implementation transposes the returned structure
+ *
+ * It automatically adds 'sort' column and 'workshopid' column into every record.
+ * The sorting is done by the order of the returned array and starts with 1.
+ *
+ * @param object $raw
+ * @return void
+ */
+ protected function cook_form_data($raw) {
+
+ $cook = array();
+ foreach (array_flip($this->map_dimension_fieldnames()) as $formfield => $dbfield) {
+ for ($k = 0; $k < $raw->numofdimensions; $k++) {
+ $cook[$k]->{$dbfield} = isset($raw->{$formfield}[$k]) ? $raw->{$formfield}[$k] : null;
+ $cook[$k]->sort = $k + 1;
+ $cook[$k]->workshopid = $raw->workshopid;
+ }
+ }
+ return $cook;
+ }
+
+
+ /**
+ * Return the mapping of the db fields to the form fields for every assessment dimension
+ *
+ * This must be public because it is also used by the dimensions editor class.
+ *
+ * @return array Array ['field_db_name' => 'field_form_name']
+ */
+ public function map_dimension_fieldnames() {
+ return array();
+ }
+
+
+
}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+defined('MOODLE_INTERNAL') || die();
+
+$string[''] = '';
+$string[''] = '';
+$string[''] = '';
+$string[''] = '';
+$string[''] = '';
+$string[''] = '';
+$string[''] = '';
+$string[''] = '';
+$string[''] = '';
+$string[''] = '';
+$string[''] = '';
+$string[''] = '';
+$string[''] = '';
$string['accesscontrol'] = 'Access control';
$string['addmoredimensionsaccumulative'] = 'Blanks for $a more aspects';
$string['agreeassessments'] = 'Assessments must be agreed';
$string['confignexassessments'] = 'Default number of examples to be reviewed by a user in the example assessment phase';
$string['confignsassessments'] = 'Default number of allocated submissions to be reviewed by a user in the assessment phase';
$string['configstrategy'] = 'Default grading strategy for workshops';
-$string['editgradingform'] = 'Edit grading form';
-$string['editinggradingform'] = 'Editing grading form';
$string['dimensiondescription'] = 'Description';
-$string['dimensionweight'] = 'Weight';
$string['dimensionnumberaccumulative'] = 'Aspect $a';
+$string['dimensionweight'] = 'Weight';
+$string['editgradingform'] = 'Edit grading form';
+$string['editinggradingform'] = 'Editing grading form';
$string['examplesbeforeassessment'] = 'Examples are available after own submission and must be assessed before peer/self assessment phase';
$string['examplesbeforesubmission'] = 'Examples must be assessed before own submission';
$string['examplesmode'] = 'Mode of examples assessment';
$string['nsassessments'] = 'Number of required assessments of other users\' work';
$string['releasegrades'] = 'Push final grades into the gradebook';
$string['requirepassword'] = 'Require password';
+$string['saveandclose'] = 'Save and close';
+$string['saveandcontinue'] = 'Save and continue';
$string['strategyaccumulative'] = 'Accumulative grading';
$string['strategyerrorbanded'] = 'Error banded grading';
$string['strategy'] = 'Grading strategy';
$string['useselfassessment'] = 'Use self assessment';
$string['workshopfeatures'] = 'Workshop features';
$string['workshopname'] = 'Workshop name';
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';
-$string[''] = '';