]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-19932 First drafts of Rubric strategy
authorDavid Mudrak <david.mudrak@gmail.com>
Mon, 4 Jan 2010 18:15:38 +0000 (18:15 +0000)
committerDavid Mudrak <david.mudrak@gmail.com>
Mon, 4 Jan 2010 18:15:38 +0000 (18:15 +0000)
Assessment form editing should work

mod/workshop/form/lib.php
mod/workshop/form/rubric/edit_form.php
mod/workshop/form/rubric/lang/en_utf8/workshopform_rubric.php
mod/workshop/form/rubric/lib.php
mod/workshop/styles.php

index d482978b37e9957f0405cc0deed36376385f520d..97609477136ed492f94ff8da557ced8a4e3e3a7b 100644 (file)
@@ -25,9 +25,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-define('WORKSHOPFORM_MINDIMS', 3);    // default number of dimensions to show
-define('WORKSHOP_STRATEGY_ADDDIMS', 2);    // number of dimensions to add
-
 /**
  * Strategy interface defines all methods that strategy subplugins has to implement
  */
index 7aad1922dfe9b66243c44e466cd76eb4a2df540c..f4532240035bee0c68b4f41ff33eeefe5423a370 100644 (file)
@@ -25,7 +25,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-require_once(dirname(dirname(dirname(__FILE__))).'/lib.php');   // module library
 require_once(dirname(dirname(__FILE__)).'/edit_form.php');    // parent class definition
 
 /**
@@ -35,6 +34,9 @@ require_once(dirname(dirname(__FILE__)).'/edit_form.php');    // parent class de
  */
 class workshop_edit_rubric_strategy_form extends workshop_edit_strategy_form {
 
+    const MINLEVELS = 4;
+    const ADDLEVELS = 2;
+
     /**
      * Define the elements to be displayed at the form
      *
@@ -45,6 +47,7 @@ class workshop_edit_rubric_strategy_form extends workshop_edit_strategy_form {
     protected function definition_inner(&$mform) {
 
         $norepeats          = $this->_customdata['norepeats'];          // number of dimensions to display
+        $addlevels          = $this->_customdata['addlevels'];          // additional levels required
         $descriptionopts    = $this->_customdata['descriptionopts'];    // wysiwyg fields options
         $current            = $this->_customdata['current'];            // current data to be set
 
@@ -52,26 +55,50 @@ class workshop_edit_rubric_strategy_form extends workshop_edit_strategy_form {
         // value not to be overridden by submitted value
         $mform->setConstants(array('norepeats' => $norepeats));
 
-        $weights = workshop_get_dimension_weights();
+        $levelgrades = array();
+        for ($i = 100; $i >= 0; $i--) {
+            $levelgrades[$i] = $i;
+        }
 
         for ($i = 0; $i < $norepeats; $i++) {
             $mform->addElement('header', 'dimension'.$i, get_string('dimensionnumber', 'workshopform_rubric', $i+1));
             $mform->addElement('hidden', 'dimensionid__idx_'.$i);
             $mform->addElement('editor', 'description__idx_'.$i.'_editor',
                                 get_string('dimensiondescription', 'workshopform_rubric'), '', $descriptionopts);
-            // todo replace modgrade with an advanced element (usability issue discussed with Olli)
-            $mform->addElement('modgrade', 'grade__idx_'.$i,
-                                get_string('dimensionmaxgrade','workshopform_rubric'), null, true);
-            $mform->setDefault('grade__idx_'.$i, 10);
-            $mform->addElement('select', 'weight__idx_'.$i,
-                                get_string('dimensionweight', 'workshopform_rubric'), $weights);
-            $mform->setDefault('weight__idx_'.$i, 1);
+            if (isset($current->{'numoflevels__idx_' . $i})) {
+                $numoflevels = max($current->{'numoflevels__idx_' . $i} + self::ADDLEVELS, self::MINLEVELS);
+            } else {
+                $numoflevels = self::MINLEVELS;
+            }
+            $prevlevel = 0;
+            for ($j = 0; $j < $numoflevels; $j++) {
+                $mform->addElement('hidden', 'levelid__idx_' . $i . '__idy_' . $j);
+                $levelgrp = array();
+                $levelgrp[] = $mform->createElement('select', 'grade__idx_'.$i.'__idy_'.$j,'', $levelgrades);
+                $levelgrp[] = $mform->createElement('textarea', 'definition__idx_'.$i.'__idy_'.$j, '',  array('cols' => 60, 'rows' => 3));
+                $mform->addGroup($levelgrp, 'level__idx_'.$i.'__idy_'.$j, get_string('levelgroup', 'workshopform_rubric'), array(' '), false);
+                $mform->setDefault('grade__idx_'.$i.'__idy_'.$j, $prevlevel + 1);
+                if (isset($current->{'grade__idx_'.$i.'__idy_'.$j})) {
+                    $prevlevel = $current->{'grade__idx_'.$i.'__idy_'.$j};
+                } else {
+                    $prevlevel++;
+                }
+            }
         }
 
-        $mform->registerNoSubmitButton('noadddims');
-        $mform->addElement('submit', 'noadddims', get_string('addmoredimensions', 'workshopform_rubric',
-                                                                    WORKSHOP_STRATEGY_ADDDIMS));
-        $mform->closeHeaderBefore('noadddims');
+        $mform->registerNoSubmitButton('adddims');
+        $mform->addElement('submit', 'adddims', get_string('addmoredimensions', 'workshopform_rubric',
+                workshop_rubric_strategy::ADDDIMS));
+        $mform->closeHeaderBefore('adddims');
+
+        $mform->addElement('header', 'configheader', get_string('configuration', 'workshopform_rubric'));
+        $layoutgrp = array();
+        $layoutgrp[] = $mform->createElement('radio', 'config_layout', '',
+                get_string('layoutlist', 'workshopform_rubric'), 'list');
+        $layoutgrp[] = $mform->createElement('radio', 'config_layout', '',
+                get_string('layoutgrid', 'workshopform_rubric'), 'grid');
+        $mform->addGroup($layoutgrp, 'layoutgrp', get_string('layout', 'workshopform_rubric'), array('<br />'), false);
+        $mform->setDefault('config_layout', 'list');
         $this->set_data($current);
     }
 }
index 26753748b65811a67e7eb6c78fdb7cd976da52e6..ae64b218e3315238dac003bc5568aa791ed6f675 100644 (file)
 
 defined('MOODLE_INTERNAL') || die();
 
+$string['addmoredimensions'] = 'Blanks for $a more criteria';
+$string['configuration'] = 'Rubric configuration';
+$string['dimensiondescription'] = 'Description';
+$string['dimensionnumber'] = 'Criterion $a';
+$string['layoutgrid'] = 'Grid';
+$string['layoutlist'] = 'List';
+$string['layout'] = 'Rubric layout';
+$string['levelgroup'] = 'Level grade and definition';
 $string['pluginname'] = 'Rubric';
index 2932cd63123757aa78dad894d2f119a26a365033..760c831a1080590e447e10f697271272fe66d36b 100644 (file)
@@ -66,348 +66,390 @@ class workshop_rubric_strategy implements workshop_strategy {
         $this->config           = $this->load_config();
         $this->descriptionopts  = array('trusttext' => true, 'subdirs' => false, 'maxfiles' => -1);
         $this->definitionopts   = array('trusttext' => true, 'subdirs' => false, 'maxfiles' => -1);
-        print_object($this->config); die(); // DONOTCOMMIT
     }
 
-    /**
-     * Factory method returning an instance of an assessment form editor class
-     *
-     * @param $actionurl URL of form handler, defaults to auto detect the current url
-     */
-    public function get_edit_strategy_form($actionurl=null) {
-        global $CFG;    // needed because the included files use it
-        global $PAGE;
-
-        require_once(dirname(__FILE__) . '/edit_form.php');
-
-        $fields             = $this->prepare_form_fields($this->dimensions);
-        $nodimensions       = count($this->dimensions);
-        $norepeatsdefault   = max($nodimensions + self::ADDDIMS, self::MINDIMS);
-        $norepeats          = optional_param('norepeats', $norepeatsdefault, PARAM_INT);    // number of dimensions
-        $noadddims          = optional_param('noadddims', '', PARAM_ALPHA);                 // shall we add more?
-        if ($noadddims) {
-            $norepeats += self::ADDDIMS;
-        }
+/**
+ * Factory method returning an instance of an assessment form editor class
+ *
+ * @param $actionurl URL of form handler, defaults to auto detect the current url
+ */
+public function get_edit_strategy_form($actionurl=null) {
+    global $CFG;    // needed because the included files use it
+    global $DB;
+
+    require_once(dirname(__FILE__) . '/edit_form.php');
+
+    $fields             = $this->prepare_form_fields($this->dimensions);
+    $fields->config_layout = $DB->get_field('workshopform_rubric_config', 'layout', array('workshopid' => $this->workshop->id));
+
+    $nodimensions       = count($this->dimensions);
+    $norepeatsdefault   = max($nodimensions + self::ADDDIMS, self::MINDIMS);
+    $norepeats          = optional_param('norepeats', $norepeatsdefault, PARAM_INT);    // number of dimensions
+    $adddims            = optional_param('adddims', '', PARAM_ALPHA);                   // shall we add more dimensions?
+    $addlevels          = optional_param('addlevels', '', PARAM_ALPHA);                 // shall we add more dimensions?
+    if ($adddims) {
+        $norepeats += self::ADDDIMS;
+    }
+    $addlevels = (bool)$addlevels;  // string to boolean
 
-        // prepare the embeded files
-        for ($i = 0; $i < $nodimensions; $i++) {
-            // prepare all editor elements
-            $fields = file_prepare_standard_editor($fields, 'description__idx_'.$i, $this->descriptionopts,
-                $PAGE->context, 'workshop_dimension_description', $fields->{'dimensionid__idx_'.$i});
-        }
+    // prepare the embeded files
+    for ($i = 0; $i < $nodimensions; $i++) {
+        // prepare all editor elements
+        $fields = file_prepare_standard_editor($fields, 'description__idx_'.$i, $this->descriptionopts,
+            $this->workshop->context, 'workshopform_rubric_description', $fields->{'dimensionid__idx_'.$i});
+    }
 
-        $customdata = array();
-        $customdata['workshop'] = $this->workshop;
-        $customdata['strategy'] = $this;
-        $customdata['norepeats'] = $norepeats;
-        $customdata['descriptionopts'] = $this->descriptionopts;
-        $customdata['current']  = $fields;
-        $attributes = array('class' => 'editstrategyform');
+    $customdata = array();
+    $customdata['workshop'] = $this->workshop;
+    $customdata['strategy'] = $this;
+    $customdata['norepeats'] = $norepeats;
+    $customdata['addlevels'] = $addlevels;
+    $customdata['descriptionopts'] = $this->descriptionopts;
+    $customdata['current']  = $fields;
+    $attributes = array('class' => 'editstrategyform');
+
+    return new workshop_edit_rubric_strategy_form($actionurl, $customdata, 'post', '', $attributes);
+}
 
-        return new workshop_edit_rubric_strategy_form($actionurl, $customdata, 'post', '', $attributes);
+/**
+ * Save the assessment dimensions into database
+ *
+ * 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 removed from database.
+ * The passed data object are the raw data returned by the get_data().
+ *
+ * @uses $DB
+ * @param stdClass $data Raw data returned by the dimension editor form
+ * @return void
+ */
+public function save_edit_strategy_form(stdClass $data) {
+    global $DB;
+
+    $norepeats  = $data->norepeats;
+    $layout     = $data->config_layout;
+    $data       = $this->prepare_database_fields($data);
+    $deletedims = array();  // dimension ids to be deleted
+    $deletelevs = array();  // level ids to be deleted
+
+    if ($DB->record_exists('workshopform_rubric_config', array('workshopid' => $this->workshop->id))) {
+        $DB->set_field('workshopform_rubric_config', 'layout', $layout, array('workshopid' => $this->workshop->id));
+    } else {
+        $record = new stdClass();
+        $record->workshopid = $this->workshop->id;
+        $record->layout     = $layout;
+        $DB->insert_record('workshopform_rubric_config', $record, false);
     }
 
-    /**
-     * Save the assessment dimensions into database
-     *
-     * 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 removed from database.
-     * The passed data object are the raw data returned by the get_data().
-     *
-     * @uses $DB
-     * @param stdClass $data Raw data returned by the dimension editor form
-     * @return void
-     */
-    public function save_edit_strategy_form(stdClass $data) {
-        global $DB, $PAGE;
-
-        $workshopid = $data->workshopid;
-        $norepeats  = $data->norepeats;
-
-        $data       = $this->prepare_database_fields($data);
-        $records    = $data->rubric;  // records to be saved into {workshopform_rubric}
-        $todelete   = array();              // dimension ids to be deleted
-
-        for ($i=0; $i < $norepeats; $i++) {
-            $record = $records[$i];
-            if (empty($record->description_editor['text'])) {
-                if (!empty($record->id)) {
-                    // existing record with empty description - to be deleted
-                    $todelete[] = $record->id;
+    foreach ($data as $record) {
+        if (0 == strlen(trim($record->description_editor['text']))) {
+            if (!empty($record->id)) {
+                // existing record with empty description - to be deleted
+                $deletedims[] = $record->id;
+                foreach ($record->levels as $level) {
+                    if (!empty($level->id)) {
+                        $deletelevs[] = $level->id;
+                    }
+                }
+            }
+            continue;
+        }
+        if (empty($record->id)) {
+            // new field
+            $record->id = $DB->insert_record('workshopform_rubric', $record);
+        } else {
+            // exiting field
+            $DB->update_record('workshopform_rubric', $record);
+        }
+        // re-save with correct path to embeded media files
+        $record = file_postupdate_standard_editor($record, 'description', $this->descriptionopts,
+                                                  $this->workshop->context, 'workshopform_rubric_description', $record->id);
+        $DB->update_record('workshopform_rubric', $record);
+
+        // create/update the criterion levels
+        foreach ($record->levels as $level) {
+            $level->dimensionid = $record->id;
+            if (0 == strlen(trim($level->definition))) {
+                if (!empty($level->id)) {
+                    $deletelevs[] = $level->id;
                 }
                 continue;
             }
-            if (empty($record->id)) {
+            if (empty($level->id)) {
                 // new field
-                $record->id         = $DB->insert_record('workshopform_rubric', $record);
+                $level->id = $DB->insert_record('workshopform_rubric_levels', $level);
             } else {
                 // exiting field
-                $DB->update_record('workshopform_rubric', $record);
+                $DB->update_record('workshopform_rubric_levels', $level);
             }
-            // re-save with correct path to embeded media files
-            $record = file_postupdate_standard_editor($record, 'description', $this->descriptionopts,
-                                                      $PAGE->context, 'workshopform_rubric_description', $record->id);
-            $DB->update_record('workshopform_rubric', $record);
         }
-        $this->delete_dimensions($todelete);
     }
+    $DB->delete_records_list('workshopform_rubric_levels', 'id', $deletelevs);
+    $this->delete_dimensions($deletedims);
+}
 
-    /**
-     * Factory method returning an instance of an assessment form
-     *
-     * @param moodle_url $actionurl URL of form handler, defaults to auto detect the current url
-     * @param string $mode          Mode to open the form in: preview/assessment
-     */
-    public function get_assessment_form(moodle_url $actionurl=null, $mode='preview', stdClass $assessment=null) {
-        global $CFG;    // needed because the included files use it
-        global $PAGE;
-        global $DB;
-        require_once(dirname(__FILE__) . '/assessment_form.php');
-
-        $fields         = $this->prepare_form_fields($this->dimensions);
-        $nodimensions   = count($this->dimensions);
-
-        // rewrite URLs to the embeded files
-        for ($i = 0; $i < $nodimensions; $i++) {
-            $fields->{'description__idx_'.$i} = file_rewrite_pluginfile_urls($fields->{'description__idx_'.$i},
-                'pluginfile.php', $PAGE->context->id, 'workshopform_rubric_description', $fields->{'dimensionid__idx_'.$i});
-        }
-
-        if ('assessment' === $mode and !empty($assessment)) {
-            // load the previously saved assessment data
-            $grades = $this->get_current_assessment_data($assessment);
-            $current = new stdClass();
-            for ($i = 0; $i < $nodimensions; $i++) {
-                $dimid = $fields->{'dimensionid__idx_'.$i};
-                if (isset($grades[$dimid])) {
-                    $current->{'gradeid__idx_'.$i}      = $grades[$dimid]->id;
-                    $current->{'grade__idx_'.$i}        = $grades[$dimid]->grade;
-                    $current->{'peercomment__idx_'.$i}  = $grades[$dimid]->peercomment;
-                }
-            }
-        }
+/**
+ * Factory method returning an instance of an assessment form
+ *
+ * @param moodle_url $actionurl URL of form handler, defaults to auto detect the current url
+ * @param string $mode          Mode to open the form in: preview/assessment
+ */
+public function get_assessment_form(moodle_url $actionurl=null, $mode='preview', stdClass $assessment=null) {
+    global $CFG;    // needed because the included files use it
+    global $DB;
+    require_once(dirname(__FILE__) . '/assessment_form.php');
 
-        // set up the required custom data common for all strategies
-        $customdata['strategy'] = $this;
-        $customdata['workshop'] = $this->workshop;
-        $customdata['mode']     = $mode;
+    $fields         = $this->prepare_form_fields($this->dimensions);
+    $nodimensions   = count($this->dimensions);
 
-        // set up strategy-specific custom data
-        $customdata['nodims']   = $nodimensions;
-        $customdata['fields']   = $fields;
-        $customdata['current']  = isset($current) ? $current : null;
-        $attributes = array('class' => 'assessmentform rubric');
+    // rewrite URLs to the embeded files
+    for ($i = 0; $i < $nodimensions; $i++) {
+        $fields->{'description__idx_'.$i} = file_rewrite_pluginfile_urls($fields->{'description__idx_'.$i},
+            'pluginfile.php', $this->workshop->context->id, 'workshopform_rubric_description', $fields->{'dimensionid__idx_'.$i});
 
-        return new workshop_rubric_assessment_form($actionurl, $customdata, 'post', '', $attributes);
     }
 
-    /**
-     * Saves the filled assessment
-     *
-     * This method processes data submitted using the form returned by {@link get_assessment_form()}
-     *
-     * @param stdClass $assessment Assessment being filled
-     * @param stdClass $data       Raw data as returned by the assessment form
-     * @return float|null          Raw grade (0.00000 to 100.00000) for submission as suggested by the peer
-     */
-    public function save_assessment(stdClass $assessment, stdClass $data) {
-        global $DB;
-
-        if (!isset($data->nodims)) {
-            throw coding_expection('You did not send me the number of assessment dimensions to process');
-        }
-        for ($i = 0; $i < $data->nodims; $i++) {
-            $grade = new stdClass();
-            $grade->id = $data->{'gradeid__idx_' . $i};
-            $grade->assessmentid = $assessment->id;
-            $grade->strategy = 'rubric';
-            $grade->dimensionid = $data->{'dimensionid__idx_' . $i};
-            $grade->grade = $data->{'grade__idx_' . $i};
-            $grade->peercomment = $data->{'peercomment__idx_' . $i};
-            $grade->peercommentformat = FORMAT_MOODLE;
-            if (empty($grade->id)) {
-                // new grade
-                $grade->id = $DB->insert_record('workshop_grades', $grade);
-            } else {
-                // updated grade
-                $DB->update_record('workshop_grades', $grade);
+    if ('assessment' === $mode and !empty($assessment)) {
+        // load the previously saved assessment data
+        $grades = $this->get_current_assessment_data($assessment);
+        $current = new stdClass();
+        for ($i = 0; $i < $nodimensions; $i++) {
+            $dimid = $fields->{'dimensionid__idx_'.$i};
+            if (isset($grades[$dimid])) {
+                $current->{'gradeid__idx_'.$i}      = $grades[$dimid]->id;
+                $current->{'grade__idx_'.$i}        = $grades[$dimid]->grade;
+                $current->{'peercomment__idx_'.$i}  = $grades[$dimid]->peercomment;
             }
         }
-        return $this->update_peer_grade($assessment);
     }
 
-    /**
-     * Has the assessment form been defined and is ready to be used by the reviewers?
-     *
-     * @return boolean
-     */
-    public function form_ready() {
-        if (count($this->dimensions) > 0) {
-            return true;
-        }
-        return false;
-    }
+    // set up the required custom data common for all strategies
+    $customdata['strategy'] = $this;
+    $customdata['workshop'] = $this->workshop;
+    $customdata['mode']     = $mode;
 
-    /**
-     * Returns true if the given evaluation method is supported by this strategy
-     *
-     * To support an evaluation method, the strategy subplugin must usually implement some
-     * required public methods. In theory, this is what interfaces should be used for.
-     * Unfortunatelly, we can't extend "implements" declaration as the interface must
-     * be known to the PHP interpret. So we can't declare implementation of a non-installed
-     * evaluation subplugin.
-     *
-     * @param workshop_evaluation $evaluation the instance of grading evaluation class
-     * @return bool true if the evaluation method is supported, false otherwise
-     */
-    public function supports_evaluation(workshop_evaluation $evaluation) {
-        if (is_a($evaluation, 'workshop_best_evaluation')) {
-            return true;
-        }
-        // all other evaluation methods are not supported yet
-        return false;
-    }
+    // set up strategy-specific custom data
+    $customdata['nodims']   = $nodimensions;
+    $customdata['fields']   = $fields;
+    $customdata['current']  = isset($current) ? $current : null;
+    $attributes = array('class' => 'assessmentform rubric');
 
-    ////////////////////////////////////////////////////////////////////////////////
-    // Methods required by the 'best' evaluation plugin                           //
-    ////////////////////////////////////////////////////////////////////////////////
+    return new workshop_rubric_assessment_form($actionurl, $customdata, 'post', '', $attributes);
+}
 
-    /**
-     * TODO
-     *
-     * @param resource $restrict 
-     * @return TODO
-     */
-    public function eval_best_get_assessments_recordset($restrict) {
-        global $DB;
+/**
+ * Saves the filled assessment
+ *
+ * This method processes data submitted using the form returned by {@link get_assessment_form()}
+ *
+ * @param stdClass $assessment Assessment being filled
+ * @param stdClass $data       Raw data as returned by the assessment form
+ * @return float|null          Raw grade (0.00000 to 100.00000) for submission as suggested by the peer
+ */
+public function save_assessment(stdClass $assessment, stdClass $data) {
+    global $DB;
 
-        $sql = 'SELECT s.id AS submissionid,
-                       a.id AS assessmentid, a.weight AS assessmentweight, a.reviewerid, a.gradinggrade,
-                       g.dimensionid, g.grade
-                  FROM {workshop_submissions} s
-                  JOIN {workshop_assessments} a ON (a.submissionid = s.id)
-                  JOIN {workshop_grades} g ON (g.assessmentid = a.id AND g.strategy = :strategy)
-                 WHERE s.example=0 AND s.workshopid=:workshopid'; // to be cont.
-        $params = array('workshopid' => $this->workshop->id, 'strategy' => $this->workshop->strategy);
-
-        if (is_null($restrict)) {
-            // update all users - no more conditions
-        } elseif (!empty($restrict)) {
-            list($usql, $uparams) = $DB->get_in_or_equal($restrict, SQL_PARAMS_NAMED);
-            $sql .= " AND a.reviewerid $usql";
-            $params = array_merge($params, $uparams);
+    if (!isset($data->nodims)) {
+        throw coding_expection('You did not send me the number of assessment dimensions to process');
+    }
+    for ($i = 0; $i < $data->nodims; $i++) {
+        $grade = new stdClass();
+        $grade->id = $data->{'gradeid__idx_' . $i};
+        $grade->assessmentid = $assessment->id;
+        $grade->strategy = 'rubric';
+        $grade->dimensionid = $data->{'dimensionid__idx_' . $i};
+        $grade->grade = $data->{'grade__idx_' . $i};
+        $grade->peercomment = $data->{'peercomment__idx_' . $i};
+        $grade->peercommentformat = FORMAT_MOODLE;
+        if (empty($grade->id)) {
+            // new grade
+            $grade->id = $DB->insert_record('workshop_grades', $grade);
         } else {
-            throw new coding_exception('Empty value is not a valid parameter here');
+            // updated grade
+            $DB->update_record('workshop_grades', $grade);
         }
+    }
+    return $this->update_peer_grade($assessment);
+}
 
-        $sql .= ' ORDER BY s.id'; // this is important for bulk processing
+/**
+ * Has the assessment form been defined and is ready to be used by the reviewers?
+ *
+ * @return boolean
+ */
+public function form_ready() {
+    if (count($this->dimensions) > 0) {
+        return true;
+    }
+    return false;
+}
 
-        return $DB->get_recordset_sql($sql, $params);
+/**
+ * Returns true if the given evaluation method is supported by this strategy
+ *
+ * To support an evaluation method, the strategy subplugin must usually implement some
+ * required public methods. In theory, this is what interfaces should be used for.
+ * Unfortunatelly, we can't extend "implements" declaration as the interface must
+ * be known to the PHP interpret. So we can't declare implementation of a non-installed
+ * evaluation subplugin.
+ *
+ * @param workshop_evaluation $evaluation the instance of grading evaluation class
+ * @return bool true if the evaluation method is supported, false otherwise
+ */
+public function supports_evaluation(workshop_evaluation $evaluation) {
+    if (is_a($evaluation, 'workshop_best_evaluation')) {
+        return true;
     }
+    // all other evaluation methods are not supported yet
+    return false;
+}
 
-    /**
-     * TODO: short description.
-     *
-     * @return array [dimid] => stdClass (->id ->max ->min ->weight)
-     */
-    public function eval_best_dimensions_info() {
-        global $DB;
+////////////////////////////////////////////////////////////////////////////////
+// Methods required by the 'best' evaluation plugin                           //
+////////////////////////////////////////////////////////////////////////////////
 
-        $sql = 'SELECT d.id, d.grade, d.weight, s.scale
-                  FROM {workshopform_rubric} d
-             LEFT JOIN {scale} s ON (d.grade < 0 AND -d.grade = s.id)
-                 WHERE d.workshopid = :workshopid';
-        $params = array('workshopid' => $this->workshop->id);
-        $dimrecords = $DB->get_records_sql($sql, $params);
-        $diminfo = array();
-        foreach ($dimrecords as $dimid => $dimrecord) {
-            $diminfo[$dimid] = new stdClass();
-            $diminfo[$dimid]->id = $dimid;
-            $diminfo[$dimid]->weight = $dimrecord->weight;
-            if ($dimrecord->grade < 0) {
-                // the dimension uses a scale
-                $diminfo[$dimid]->min = 1;
-                $diminfo[$dimid]->max = count(explode(',', $dimrecord->scale));
-            } else {
-                // the dimension uses points
-                $diminfo[$dimid]->min = 0;
-                $diminfo[$dimid]->max = grade_floatval($dimrecord->grade);
-            }
-        }
-        return $diminfo;
+/**
+ * TODO
+ *
+ * @param resource $restrict 
+ * @return TODO
+ */
+public function eval_best_get_assessments_recordset($restrict) {
+    global $DB;
+
+    $sql = 'SELECT s.id AS submissionid,
+                   a.id AS assessmentid, a.weight AS assessmentweight, a.reviewerid, a.gradinggrade,
+                   g.dimensionid, g.grade
+              FROM {workshop_submissions} s
+              JOIN {workshop_assessments} a ON (a.submissionid = s.id)
+              JOIN {workshop_grades} g ON (g.assessmentid = a.id AND g.strategy = :strategy)
+             WHERE s.example=0 AND s.workshopid=:workshopid'; // to be cont.
+    $params = array('workshopid' => $this->workshop->id, 'strategy' => $this->workshop->strategy);
+
+    if (is_null($restrict)) {
+        // update all users - no more conditions
+    } elseif (!empty($restrict)) {
+        list($usql, $uparams) = $DB->get_in_or_equal($restrict, SQL_PARAMS_NAMED);
+        $sql .= " AND a.reviewerid $usql";
+        $params = array_merge($params, $uparams);
+    } else {
+        throw new coding_exception('Empty value is not a valid parameter here');
     }
 
-    ////////////////////////////////////////////////////////////////////////////////
-    // Internal methods                                                           //
-    ////////////////////////////////////////////////////////////////////////////////
+    $sql .= ' ORDER BY s.id'; // this is important for bulk processing
 
-    /**
-     * Loads the fields of the assessment form currently used in this workshop
-     *
-     * @return array definition of assessment dimensions
-     */
-    protected function load_fields() {
-        global $DB;
+    return $DB->get_recordset_sql($sql, $params);
+}
 
-        $sql = 'SELECT r.id AS rid, l.id AS lid, *
-                  FROM {workshopform_rubric} r
-             LEFT JOIN {workshopform_rubric_levels} l ON (l.dimensionid = r.id)
-                 WHERE r.workshopid = :workshopid
-                 ORDER BY r.sort, l.grade';
-        $params = array('workshopid' => $this->workshop->id);
-
-        $rs = $DB->get_recordset_sql($sql, $params);
-        $fields = array();
-        foreach ($rs as $record) {
-            if (!isset($fields[$record->rid])) {
-                $fields[$record->rid] = new stdClass();
-                $fields[$record->rid]->id = $record->rid;
-                $fields[$record->rid]->sort = $record->sort;
-                $fields[$record->rid]->description = $record->description;
-                $fields[$record->rid]->descriptionformat = $record->descriptionformat;
-                $fields[$record->rid]->levels = array();
-            }
-            $fields[$record->rid]->levels[$record->lid] = new stdClass();
-            $fields[$record->rid]->levels[$record->lid]->id = $record->lid;
-            $fields[$record->rid]->levels[$record->lid]->grade = $record->grade;
-            $fields[$record->rid]->levels[$record->lid]->definition = $record->definition;
-            $fields[$record->rid]->levels[$record->lid]->definitionformat = $record->definitionformat;
+/**
+ * TODO: short description.
+ *
+ * @return array [dimid] => stdClass (->id ->max ->min ->weight)
+ */
+public function eval_best_dimensions_info() {
+    global $DB;
+
+    $sql = 'SELECT d.id, d.grade, d.weight, s.scale
+              FROM {workshopform_rubric} d
+         LEFT JOIN {scale} s ON (d.grade < 0 AND -d.grade = s.id)
+             WHERE d.workshopid = :workshopid';
+    $params = array('workshopid' => $this->workshop->id);
+    $dimrecords = $DB->get_records_sql($sql, $params);
+    $diminfo = array();
+    foreach ($dimrecords as $dimid => $dimrecord) {
+        $diminfo[$dimid] = new stdClass();
+        $diminfo[$dimid]->id = $dimid;
+        $diminfo[$dimid]->weight = $dimrecord->weight;
+        if ($dimrecord->grade < 0) {
+            // the dimension uses a scale
+            $diminfo[$dimid]->min = 1;
+            $diminfo[$dimid]->max = count(explode(',', $dimrecord->scale));
+        } else {
+            // the dimension uses points
+            $diminfo[$dimid]->min = 0;
+            $diminfo[$dimid]->max = grade_floatval($dimrecord->grade);
         }
-        $rs->close();
-        return $fields;
     }
+    return $diminfo;
+}
 
-    /**
-     * Get the configuration for the current rubric strategy
-     *
-     * @return object
-     */
-    protected function load_config() {
-        global $DB;
+////////////////////////////////////////////////////////////////////////////////
+// Internal methods                                                           //
+////////////////////////////////////////////////////////////////////////////////
 
-        if (!$config = $DB->get_record('workshopform_rubric_config', array('workshopid' => $this->workshop->id), 'layout')) {
-            $config = (object)array('layout' => 'list');
+/**
+ * Loads the fields of the assessment form currently used in this workshop
+ *
+ * @return array definition of assessment dimensions
+ */
+protected function load_fields() {
+    global $DB;
+
+    $sql = 'SELECT r.id AS rid, l.id AS lid, *
+              FROM {workshopform_rubric} r
+         LEFT JOIN {workshopform_rubric_levels} l ON (l.dimensionid = r.id)
+             WHERE r.workshopid = :workshopid
+             ORDER BY r.sort, l.grade';
+    $params = array('workshopid' => $this->workshop->id);
+
+    $rs = $DB->get_recordset_sql($sql, $params);
+    $fields = array();
+    foreach ($rs as $record) {
+        if (!isset($fields[$record->rid])) {
+            $fields[$record->rid] = new stdClass();
+            $fields[$record->rid]->id = $record->rid;
+            $fields[$record->rid]->sort = $record->sort;
+            $fields[$record->rid]->description = $record->description;
+            $fields[$record->rid]->descriptionformat = $record->descriptionformat;
+            $fields[$record->rid]->levels = array();
         }
-        return $config;
+        $fields[$record->rid]->levels[$record->lid] = new stdClass();
+        $fields[$record->rid]->levels[$record->lid]->id = $record->lid;
+        $fields[$record->rid]->levels[$record->lid]->grade = $record->grade;
+        $fields[$record->rid]->levels[$record->lid]->definition = $record->definition;
+        $fields[$record->rid]->levels[$record->lid]->definitionformat = $record->definitionformat;
     }
+    $rs->close();
+    return $fields;
+}
 
-    /**
-     * Maps the dimension data from DB to the form fields
-     *
-     * @param array $raw Array of raw dimension records as returned by {@link load_fields()}
-     * @return array Array of fields data to be used by the mform set_data
-     */
-    protected function prepare_form_fields(array $raw) {
-
-        $formdata = new stdClass();
-        $key = 0;
-        foreach ($raw as $dimension) {
-            $formdata->{'dimensionid__idx_' . $key}             = $dimension->id;
-            $formdata->{'description__idx_' . $key}             = $dimension->description;
-            $formdata->{'description__idx_' . $key.'format'}    = $dimension->descriptionformat;
-            $formdata->{'grade__idx_' . $key}                   = $dimension->grade;
-            $formdata->{'weight__idx_' . $key}                  = $dimension->weight;
+/**
+ * Get the configuration for the current rubric strategy
+ *
+ * @return object
+ */
+protected function load_config() {
+    global $DB;
+
+    if (!$config = $DB->get_record('workshopform_rubric_config', array('workshopid' => $this->workshop->id), 'layout')) {
+        $config = (object)array('layout' => 'list');
+    }
+    return $config;
+}
+
+/**
+ * Maps the dimension data from DB to the form fields
+ *
+ * @param array $fields Array of dimensions definition as returned by {@link load_fields()}
+ * @return stdClass of fields data to be used by the mform set_data
+ */
+protected function prepare_form_fields(array $fields) {
+
+    $formdata = new stdClass();
+    $key = 0;
+    foreach ($fields as $field) {
+        $formdata->{'dimensionid__idx_' . $key}             = $field->id;
+        $formdata->{'description__idx_' . $key}             = $field->description;
+        $formdata->{'description__idx_' . $key.'format'}    = $field->descriptionformat;
+        $formdata->{'numoflevels__idx_' . $key}             = count($field->levels);
+        $lev = 0;
+        foreach ($field->levels as $level) {
+            $formdata->{'levelid__idx_' . $key . '__idy_' . $lev} = $level->id;
+            $formdata->{'grade__idx_' . $key . '__idy_' . $lev} = $level->grade;
+            $formdata->{'definition__idx_' . $key . '__idy_' . $lev} = $level->definition;
+            $formdata->{'definition__idx_' . $key . '__idy_' . $lev . 'format'} = $level->definitionformat;
+                $lev++;
+            }
             $key++;
         }
         return $formdata;
@@ -422,12 +464,12 @@ class workshop_rubric_strategy implements workshop_strategy {
      * @return void
      */
     protected function delete_dimensions(array $ids) {
-        global $DB, $PAGE;
+        global $DB;
 
         $fs = get_file_storage();
         foreach ($ids as $id) {
             if (!empty($id)) {   // to prevent accidental removal of all files in the area
-                $fs->delete_area_files($PAGE->context->id, 'workshopform_rubric_description', $id);
+                $fs->delete_area_files($this->workshop->context->id, 'workshopform_rubric_description', $id);
             }
         }
         $DB->delete_records_list('workshopform_rubric', 'id', $ids);
@@ -445,20 +487,29 @@ class workshop_rubric_strategy implements workshop_strategy {
      * @return array Array of objects to be inserted/updated in DB
      */
     protected function prepare_database_fields(stdClass $raw) {
-        global $PAGE;
 
-        $cook               = new stdClass(); // to be returned
-        $cook->rubric = array();        // records to be stored in {workshopform_rubric}
+        $cook = array();
 
         for ($i = 0; $i < $raw->norepeats; $i++) {
-            $cook->rubric[$i]                     = new stdClass();
-            $cook->rubric[$i]->id                 = $raw->{'dimensionid__idx_'.$i};
-            $cook->rubric[$i]->workshopid         = $this->workshop->id;
-            $cook->rubric[$i]->sort               = $i + 1;
-            $cook->rubric[$i]->description_editor = $raw->{'description__idx_'.$i.'_editor'};
-            $cook->rubric[$i]->grade              = $raw->{'grade__idx_'.$i};
-            $cook->rubric[$i]->weight             = $raw->{'weight__idx_'.$i};
+            $cook[$i]                       = new stdClass();
+            $cook[$i]->id                   = $raw->{'dimensionid__idx_'.$i};
+            $cook[$i]->workshopid           = $this->workshop->id;
+            $cook[$i]->sort                 = $i + 1;
+            $cook[$i]->description_editor   = $raw->{'description__idx_'.$i.'_editor'};
+            $cook[$i]->levels               = array();
+
+            $j = 0;
+            while (isset($raw->{'levelid__idx_' . $i . '__idy_' . $j})) {
+                $level                      = new stdClass();
+                $level->id                  = $raw->{'levelid__idx_' . $i . '__idy_' . $j};
+                $level->grade               = $raw->{'grade__idx_'.$i.'__idy_'.$j};
+                $level->definition          = $raw->{'definition__idx_'.$i.'__idy_'.$j};
+                $level->definitionformat    = FORMAT_HTML;
+                $cook[$i]->levels[]         = $level;
+                $j++;
+            }
         }
+
         return $cook;
     }
 
index 51dc407feb7e981239d0d804b61ee395a09e4760..7c7d04d92348a984844b7c79354506f296aa5cd5 100644 (file)
     border: 1px solid #ddd;
 }
 
+/**
+ * Edit assessment form
+ */
+#mod-workshop-editform fieldset.fgroup * {
+    vertical-align: top;
+}
+
 /**
  * Misc
  */