See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402]
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 * Unit tests for importing csv files. 19 * 20 * @package mod_data 21 * @category test 22 * @copyright 2019 Tobias Reischmann 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 /** 29 * Unit tests for import.php. 30 * 31 * @package mod_data 32 * @copyright 2019 Tobias Reischmann 33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 */ 35 class mod_data_import_test extends advanced_testcase { 36 37 /** 38 * Set up function. 39 */ 40 protected function setUp() { 41 parent::setUp(); 42 43 global $CFG; 44 require_once($CFG->dirroot . '/mod/data/lib.php'); 45 require_once($CFG->dirroot . '/lib/datalib.php'); 46 require_once($CFG->dirroot . '/lib/csvlib.class.php'); 47 require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php'); 48 require_once($CFG->dirroot . '/mod/data/tests/generator/lib.php'); 49 } 50 51 /** 52 * Get the test data. 53 * In this instance we are setting up database records to be used in the unit tests. 54 * 55 * @return array 56 */ 57 protected function get_test_data(): array { 58 $this->resetAfterTest(true); 59 60 $generator = $this->getDataGenerator()->get_plugin_generator('mod_data'); 61 $course = $this->getDataGenerator()->create_course(); 62 $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher'); 63 $this->setUser($teacher); 64 $student = $this->getDataGenerator()->create_and_enrol($course, 'student', array('username' => 'student')); 65 66 $data = $generator->create_instance(array('course' => $course->id)); 67 $cm = get_coursemodule_from_instance('data', $data->id); 68 69 // Add fields. 70 $fieldrecord = new StdClass(); 71 $fieldrecord->name = 'ID'; // Identifier of the records for testing. 72 $fieldrecord->type = 'number'; 73 $generator->create_field($fieldrecord, $data); 74 75 $fieldrecord->name = 'Param2'; 76 $fieldrecord->type = 'text'; 77 $generator->create_field($fieldrecord, $data); 78 79 80 return [ 81 'teacher' => $teacher, 82 'student' => $student, 83 'data' => $data, 84 'cm' => $cm, 85 ]; 86 } 87 88 /** 89 * Test uploading entries for a data instance without userdata. 90 * @throws dml_exception 91 */ 92 public function test_import(): void { 93 [ 94 'data' => $data, 95 'cm' => $cm, 96 'teacher' => $teacher, 97 ] = $this->get_test_data(); 98 99 $filecontent = file_get_contents(__DIR__ . '/fixtures/test_data_import.csv'); 100 ob_start(); 101 data_import_csv($cm, $data, $filecontent, 'UTF-8', 'comma'); 102 ob_end_clean(); 103 104 // No userdata is present in the file: Fallback is to assign the uploading user as author. 105 $expecteduserids = array(); 106 $expecteduserids[1] = $teacher->id; 107 $expecteduserids[2] = $teacher->id; 108 109 $records = $this->get_data_records($data->id); 110 $this->assertCount(2, $records); 111 foreach ($records as $record) { 112 $identifier = $record->items['ID']->content; 113 $this->assertEquals($expecteduserids[$identifier], $record->userid); 114 } 115 } 116 117 /** 118 * Test uploading entries for a data instance with userdata. 119 * 120 * At least one entry has an identifiable user, which is assigned as author. 121 * @throws dml_exception 122 */ 123 public function test_import_with_userdata(): void { 124 [ 125 'data' => $data, 126 'cm' => $cm, 127 'teacher' => $teacher, 128 'student' => $student, 129 ] = $this->get_test_data(); 130 131 $filecontent = file_get_contents(__DIR__ . '/fixtures/test_data_import_with_userdata.csv'); 132 ob_start(); 133 data_import_csv($cm, $data, $filecontent, 'UTF-8', 'comma'); 134 ob_end_clean(); 135 136 $expecteduserids = array(); 137 $expecteduserids[1] = $student->id; // User student exists and is assigned as author. 138 $expecteduserids[2] = $teacher->id; // User student2 does not exist. Fallback is the uploading user. 139 140 $records = $this->get_data_records($data->id); 141 $this->assertCount(2, $records); 142 foreach ($records as $record) { 143 $identifier = $record->items['ID']->content; 144 $this->assertEquals($expecteduserids[$identifier], $record->userid); 145 } 146 } 147 148 /** 149 * Test uploading entries for a data instance with userdata and a defined field 'Username'. 150 * 151 * This should test the corner case, in which a user has defined a data fields, which has the same name 152 * as the current lang string for username. In that case, the first Username entry is used for the field. 153 * The second one is used to identify the author. 154 * @throws coding_exception 155 * @throws dml_exception 156 */ 157 public function test_import_with_field_username(): void { 158 [ 159 'data' => $data, 160 'cm' => $cm, 161 'teacher' => $teacher, 162 'student' => $student, 163 ] = $this->get_test_data(); 164 $generator = $this->getDataGenerator()->get_plugin_generator('mod_data'); 165 166 // Add username field. 167 $fieldrecord = new StdClass(); 168 $fieldrecord->name = 'Username'; 169 $fieldrecord->type = 'text'; 170 $generator->create_field($fieldrecord, $data); 171 172 $filecontent = file_get_contents(__DIR__ . '/fixtures/test_data_import_with_field_username.csv'); 173 ob_start(); 174 data_import_csv($cm, $data, $filecontent, 'UTF-8', 'comma'); 175 ob_end_clean(); 176 177 $expecteduserids = array(); 178 $expecteduserids[1] = $student->id; // User student exists and is assigned as author. 179 $expecteduserids[2] = $teacher->id; // User student2 does not exist. Fallback is the uploading user. 180 $expecteduserids[3] = $student->id; // User student exists and is assigned as author. 181 182 $expectedcontent = array(); 183 $expectedcontent[1] = array( 184 'Username' => 'otherusername1', 185 'Param2' => 'My first entry', 186 ); 187 $expectedcontent[2] = array( 188 'Username' => 'otherusername2', 189 'Param2' => 'My second entry', 190 ); 191 $expectedcontent[3] = array( 192 'Username' => 'otherusername3', 193 'Param2' => 'My third entry', 194 ); 195 196 $records = $this->get_data_records($data->id); 197 $this->assertCount(3, $records); 198 foreach ($records as $record) { 199 $identifier = $record->items['ID']->content; 200 $this->assertEquals($expecteduserids[$identifier], $record->userid); 201 202 foreach ($expectedcontent[$identifier] as $field => $value) { 203 $this->assertEquals($value, $record->items[$field]->content, 204 "The value of field \"$field\" for the record at position \"$identifier\" ". 205 "which is \"{$record->items[$field]->content}\" does not match the expected value \"$value\"."); 206 } 207 } 208 } 209 210 /** 211 * Test uploading entries for a data instance with a field 'Username' but only one occurrence in the csv file. 212 * 213 * This should test the corner case, in which a user has defined a data fields, which has the same name 214 * as the current lang string for username. In that case, the only Username entry is used for the field. 215 * The author should not be set. 216 * @throws coding_exception 217 * @throws dml_exception 218 */ 219 public function test_import_with_field_username_without_userdata(): void { 220 [ 221 'data' => $data, 222 'cm' => $cm, 223 'teacher' => $teacher, 224 'student' => $student, 225 ] = $this->get_test_data(); 226 $generator = $this->getDataGenerator()->get_plugin_generator('mod_data'); 227 228 // Add username field. 229 $fieldrecord = new StdClass(); 230 $fieldrecord->name = 'Username'; 231 $fieldrecord->type = 'text'; 232 $generator->create_field($fieldrecord, $data); 233 234 $filecontent = file_get_contents(__DIR__ . '/fixtures/test_data_import_with_userdata.csv'); 235 ob_start(); 236 data_import_csv($cm, $data, $filecontent, 'UTF-8', 'comma'); 237 ob_end_clean(); 238 239 // No userdata is present in the file: Fallback is to assign the uploading user as author. 240 $expecteduserids = array(); 241 $expecteduserids[1] = $teacher->id; 242 $expecteduserids[2] = $teacher->id; 243 244 $expectedcontent = array(); 245 $expectedcontent[1] = array( 246 'Username' => 'student', 247 'Param2' => 'My first entry', 248 ); 249 $expectedcontent[2] = array( 250 'Username' => 'student2', 251 'Param2' => 'My second entry', 252 ); 253 254 $records = $this->get_data_records($data->id); 255 $this->assertCount(2, $records); 256 foreach ($records as $record) { 257 $identifier = $record->items['ID']->content; 258 $this->assertEquals($expecteduserids[$identifier], $record->userid); 259 260 foreach ($expectedcontent[$identifier] as $field => $value) { 261 $this->assertEquals($value, $record->items[$field]->content, 262 "The value of field \"$field\" for the record at position \"$identifier\" ". 263 "which is \"{$record->items[$field]->content}\" does not match the expected value \"$value\"."); 264 } 265 } 266 } 267 268 /** 269 * Returns the records of the data instance. 270 * 271 * Each records has an item entry, which contains all fields associated with this item. 272 * Each fields has the parameters name, type and content. 273 * @param int $dataid Id of the data instance. 274 * @return array The records of the data instance. 275 * @throws dml_exception 276 */ 277 private function get_data_records(int $dataid): array { 278 global $DB; 279 280 $records = $DB->get_records('data_records', ['dataid' => $dataid]); 281 foreach ($records as $record) { 282 $sql = 'SELECT f.name, f.type, con.content FROM 283 {data_content} con JOIN {data_fields} f ON con.fieldid = f.id 284 WHERE con.recordid = :recordid'; 285 $items = $DB->get_records_sql($sql, array('recordid' => $record->id)); 286 $record->items = $items; 287 } 288 return $records; 289 } 290 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body