1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Generator for the gradingforum_rubric plugin. 19 * 20 * @package gradingform_rubric 21 * @category test 22 * @copyright 2019 Andrew Nicols <andrew@nicols.co.uk> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 require_once (__DIR__ . '/rubric.php'); 29 require_once (__DIR__ . '/criterion.php'); 30 31 use tests\gradingform_rubric\generator\rubric; 32 use tests\gradingform_rubric\generator\criterion; 33 34 /** 35 * Generator for the gradingforum_rubric plugintype. 36 * 37 * @package gradingform_rubric 38 * @category test 39 * @copyright 2019 Andrew Nicols <andrew@nicols.co.uk> 40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 41 */ 42 class gradingform_rubric_generator extends component_generator_base { 43 44 /** 45 * Create an instance of a rubric. 46 * 47 * @param context $context 48 * @param string $component 49 * @param string $area 50 * @param string $name 51 * @param string $description 52 * @param array $criteria The list of criteria to add to the generated rubric 53 * @return gradingform_rubric_controller 54 */ 55 public function create_instance( 56 context $context, 57 string $component, 58 string $area, 59 string $name, 60 string $description, 61 array $criteria 62 ): gradingform_rubric_controller { 63 global $USER; 64 65 if ($USER->id === 0) { 66 throw new \coding_exception('Creation of a rubric must currently be run as a user.'); 67 } 68 69 // Fetch the controller for this context/component/area. 70 $generator = \testing_util::get_data_generator(); 71 $gradinggenerator = $generator->get_plugin_generator('core_grading'); 72 $controller = $gradinggenerator->create_instance($context, $component, $area, 'rubric'); 73 74 // Generate a definition for the supplied rubric. 75 $rubric = $this->get_rubric($name, $description); 76 foreach ($criteria as $name => $criterion) { 77 $rubric->add_criteria($this->get_criterion($name, $criterion)); 78 } 79 80 // Update the controller wih the rubric definition. 81 $controller->update_definition($rubric->get_definition()); 82 83 return $controller; 84 } 85 86 /** 87 * Get a new rubric for use with the rubric controller. 88 * 89 * Note: This is just a helper class used to build a new definition. It does not persist the data. 90 * 91 * @param string $name 92 * @param string $description 93 * @return rubric 94 */ 95 protected function get_rubric(string $name, string $description): rubric { 96 return new rubric($name, $description); 97 } 98 99 /** 100 * Get a new rubric for use with a gradingform_rubric_generator_rubric. 101 * 102 * Note: This is just a helper class used to build a new definition. It does not persist the data. 103 * 104 * @param string $description 105 * @param array $levels Set of levels in the form definition => score 106 * @return gradingform_rubric_generator_criterion 107 */ 108 protected function get_criterion(string $description, array $levels = []): criterion { 109 return new criterion($description, $levels); 110 } 111 112 /** 113 * Given a controller instance, fetch the level and criterion information for the specified values. 114 * 115 * @param gradingform_controller $controller 116 * @param string $description The description to match the criterion on 117 * @param float $score The value to match the level on 118 * @return array 119 */ 120 public function get_level_and_criterion_for_values( 121 gradingform_controller $controller, 122 string $description, 123 float $score 124 ): array { 125 $definition = $controller->get_definition(); 126 $criteria = $definition->rubric_criteria; 127 128 $criterion = $level = null; 129 130 $criterion = array_reduce($criteria, function($carry, $criterion) use ($description) { 131 if ($criterion['description'] === $description) { 132 $carry = $criterion; 133 } 134 135 return $carry; 136 }, null); 137 138 if ($criterion) { 139 $criterion = (object) $criterion; 140 $level = array_reduce($criterion->levels, function($carry, $level) use ($score) { 141 if ($level['score'] == $score) { 142 $carry = $level; 143 } 144 return $carry; 145 }); 146 $level = $level ? (object) $level : null; 147 } 148 149 return [ 150 'criterion' => $criterion, 151 'level' => $level, 152 ]; 153 } 154 155 /** 156 * Get submitted form data for the supplied controller, itemid, and values. 157 * The returned data is in the format used by rubric when handling form submission. 158 * 159 * @param gradingform_rubric_controller $controller 160 * @param int $itemid 161 * @param array $values A set of array values where the array key is the name of the criterion, and the value is an 162 * array with the desired score, and any remark. 163 */ 164 public function get_submitted_form_data(gradingform_rubric_controller $controller, int $itemid, array $values): array { 165 $result = [ 166 'itemid' => $itemid, 167 'criteria' => [], 168 ]; 169 foreach ($values as $criterionname => ['score' => $score, 'remark' => $remark]) { 170 [ 171 'criterion' => $criterion, 172 'level' => $level, 173 ] = $this->get_level_and_criterion_for_values($controller, $criterionname, $score); 174 $result['criteria'][$criterion->id] = [ 175 'levelid' => $level->id, 176 'remark' => $remark, 177 ]; 178 } 179 180 return $result; 181 } 182 183 /** 184 * Generate a rubric controller with sample data required for testing of this class. 185 * 186 * @param context $context 187 * @param string $component 188 * @param string $area 189 * @return gradingform_rubric_controller 190 */ 191 public function get_test_rubric(context $context, string $component, string $area): gradingform_rubric_controller { 192 $criteria = [ 193 'Spelling is important' => [ 194 'Nothing but mistakes' => 0, 195 'Several mistakes' => 1, 196 'No mistakes' => 2, 197 ], 198 'Pictures' => [ 199 'No pictures' => 0, 200 'One picture' => 1, 201 'More than one picture' => 2, 202 ], 203 ]; 204 205 return $this->create_instance($context, $component, $area, 'testrubric', 'Description text', $criteria); 206 } 207 208 /** 209 * Fetch a set of sample data. 210 * 211 * @param gradingform_rubric_controller $controller 212 * @param int $itemid 213 * @param float $spellingscore 214 * @param string $spellingremark 215 * @param float $picturescore 216 * @param string $pictureremark 217 * @return array 218 */ 219 public function get_test_form_data( 220 gradingform_rubric_controller $controller, 221 int $itemid, 222 float $spellingscore, 223 string $spellingremark, 224 float $picturescore, 225 string $pictureremark 226 ): array { 227 $generator = \testing_util::get_data_generator(); 228 $rubricgenerator = $generator->get_plugin_generator('gradingform_rubric'); 229 return $rubricgenerator->get_submitted_form_data($controller, $itemid, [ 230 'Spelling is important' => [ 231 'score' => $spellingscore, 232 'remark' => $spellingremark, 233 ], 234 'Pictures' => [ 235 'score' => $picturescore, 236 'remark' => $pictureremark, 237 ], 238 ]); 239 } 240 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body