]> git.mjollnir.org Git - moodle.git/commitdiff
Yay! Saving dimensions works
authorDavid Mudrak <david.mudrak@gmail.com>
Mon, 4 Jan 2010 17:37:31 +0000 (17:37 +0000)
committerDavid Mudrak <david.mudrak@gmail.com>
Mon, 4 Jan 2010 17:37:31 +0000 (17:37 +0000)
Cooking dimension editor's raw data is done by the strategy class.

mod/workshop/editgradingform.php
mod/workshop/grading/accumulative/gradingform.php
mod/workshop/grading/accumulative/simpletest/teststrategy.php [new file with mode: 0644]
mod/workshop/grading/accumulative/strategy.php
mod/workshop/grading/gradingform.php
mod/workshop/grading/strategy.php
mod/workshop/lang/en_utf8/workshop.php

index 0a9660907dd2117639857608590eaba112cc4602..11fc39478f82279cb433d679a71e401b5125c323 100644 (file)
@@ -62,8 +62,9 @@ require_login($course, true, $cm);
 
 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
@@ -92,7 +93,12 @@ $mform->set_data($formdata);
 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
index 284241a211a9c19f7948620bfded44620edcade7..d467730632b91c2124edb6ed949ec5ac7e2c5929 100644 (file)
  * @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
 
 
 /**
@@ -53,9 +52,10 @@ class workshop_edit_accumulative_strategy_form extends workshop_edit_strategy_fo
 
         $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);
         
@@ -73,21 +73,4 @@ class workshop_edit_accumulative_strategy_form extends workshop_edit_strategy_fo
     }
 
 
-    /**
-     * 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',
-            );
-    }
-
-
 }
diff --git a/mod/workshop/grading/accumulative/simpletest/teststrategy.php b/mod/workshop/grading/accumulative/simpletest/teststrategy.php
new file mode 100644 (file)
index 0000000..0ffcf7f
--- /dev/null
@@ -0,0 +1,114 @@
+<?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,
+                            ));
+    }
+    
+}
index f9a63d3ada485f88ea3763c4b4201d962ce33af4..0ecfd81d0d69dd5e2f1a61ad67153329e25f97e2 100644 (file)
@@ -36,4 +36,20 @@ require_once(dirname(dirname(__FILE__)) . '/strategy.php'); // parent class
  */
 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',
+            );
+    }
+
+
 }
index 4aa732ddfc811274e8946f3e6bff85fe7319abc3..9553dafff92767d99186869a423dadeba1ced434 100644 (file)
@@ -24,9 +24,7 @@
  * @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
 
@@ -42,26 +40,26 @@ 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);
     }
 
@@ -96,7 +94,8 @@ class workshop_edit_strategy_form extends moodleform {
         }
 
         $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');
@@ -117,7 +116,7 @@ class workshop_edit_strategy_form extends moodleform {
      * 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
@@ -130,7 +129,7 @@ class workshop_edit_strategy_form extends moodleform {
             $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++;
@@ -141,14 +140,4 @@ class workshop_edit_strategy_form extends moodleform {
     }
 
 
-    /**
-     * 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();
-    }
-
 }
index e820445593cf319c3cda7680246446fef3cddc4b..da42ecee66126a8bb4365e7f758589346a1ca3e0 100644 (file)
  * @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
      * 
@@ -41,16 +52,30 @@ interface workshop_strategy_interface {
      * 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 {
 
@@ -74,6 +99,12 @@ 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
     
@@ -85,14 +116,15 @@ class workshop_strategy implements workshop_strategy_interface {
         }
         $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
@@ -104,4 +136,74 @@ class workshop_strategy implements workshop_strategy_interface {
         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();
+    }
+
+
+
 }
index 346acbc2ecce674835208c17e05cf7bb8f777858..ac22488f448aef3451fea7e0dc0918f05e9162e5 100644 (file)
  * @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';
@@ -54,11 +69,11 @@ $string['configmaxbytes'] = 'Default maximum submission file size for all worksh
 $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';
@@ -79,6 +94,8 @@ $string['nexassessments'] = 'Number of required assessments of examples';
 $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';
@@ -96,18 +113,3 @@ $string['useselfassessmentdesc'] = 'Users perform self assessment of their own w
 $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[''] = '';