Differences Between: [Versions 400 and 403] [Versions 401 and 403] [Versions 402 and 403]
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 namespace qbank_columnsortorder; 18 19 defined('MOODLE_INTERNAL') || die(); 20 21 use advanced_testcase; 22 use context_course; 23 use core_question\local\bank\column_base; 24 use core_question\local\bank\question_edit_contexts; 25 use core_question\local\bank\view; 26 use moodle_url; 27 28 global $CFG; 29 require_once($CFG->dirroot . '/question/tests/fixtures/testable_core_question_column.php'); 30 require_once($CFG->dirroot . '/question/classes/external.php'); 31 32 /** 33 * Test class for columnsortorder feature. 34 * 35 * @package qbank_columnsortorder 36 * @copyright 2021 Catalyst IT Australia Pty Ltd 37 * @author Ghaly Marc-Alexandre <marc-alexandreghaly@catalyst-ca.net> 38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 39 * @covers \qbank_columnsortorder\column_manager 40 */ 41 class column_manager_test extends advanced_testcase { 42 43 /** 44 * Generate a course and return a question bank view for the course context. 45 * 46 * @return view 47 */ 48 protected static function get_question_bank(): view { 49 $course = self::getDataGenerator()->create_course(); 50 $questionbank = new view( 51 new question_edit_contexts(context_course::instance($course->id)), 52 new moodle_url('/'), 53 $course 54 ); 55 return $questionbank; 56 } 57 58 /** 59 * Return an array of visible columns for the question bank. 60 * 61 * @return array 62 */ 63 protected static function get_columns(): array { 64 $questionbank = self::get_question_bank(); 65 $columns = []; 66 foreach ($questionbank->get_visiblecolumns() as $column) { 67 $columns[] = $column->get_column_id(); 68 } 69 return $columns; 70 } 71 72 /** 73 * Provide examples for testing each column setting function, with test data and data format. 74 * 75 * @return array[] 76 */ 77 public static function settings_provider(): array { 78 return [ 79 'Test set_column_order' => [ 80 'setting' => 'enabledcol', 81 'function' => 'set_column_order', 82 'datamethod' => [__CLASS__, 'get_columns'], 83 'csv' => true, 84 ], 85 'Test set_hidden_columns' => [ 86 'setting' => 'hiddencols', 87 'function' => 'set_hidden_columns', 88 'datamethod' => [__CLASS__, 'get_columns'], 89 'csv' => true, 90 ], 91 'Test set_column_size' => [ 92 'setting' => 'colsize', 93 'function' => 'set_column_size', 94 'datamethod' => 'random_string', 95 'csv' => false, 96 ], 97 ]; 98 } 99 100 /** 101 * Retrieve data using the specified method. 102 * This function is used to retrieve data from various data methods defined within this class. 103 * 104 * @param array|string $datamethod This can be either a function name or an array containing the class and method name. 105 * @return array|string The retrieved data as an array or string, depending on the data method used. 106 */ 107 protected function get_data_from_datamethod(array|string $datamethod): array|string { 108 return call_user_func($datamethod); 109 } 110 111 112 /** 113 * Test setting config settings 114 * 115 * @dataProvider settings_provider 116 * @param string $setting The name of the setting being saved 117 * @param string $function The name of the function being called 118 * @param array|string $datamethod The property of the test class to pass to the function. 119 * @param bool $csv True of the data is stored as a comma-separated list. 120 * @return void 121 */ 122 public function test_settings( 123 string $setting, 124 string $function, 125 array|string $datamethod, 126 bool $csv, 127 ): void { 128 $data = $this->get_data_from_datamethod($datamethod); 129 $this->setAdminUser(); 130 $this->resetAfterTest(true); 131 $this->assertFalse(get_config('qbank_columnsortorder', $setting)); 132 $this->assertEmpty(get_user_preferences('qbank_columnsortorder_' . $setting)); 133 column_manager::{$function}($data, true); 134 $expected = $csv ? implode(',', $data) : $data; 135 $this->assertEquals($expected, get_config('qbank_columnsortorder', $setting)); 136 $this->assertEmpty(get_user_preferences('qbank_columnsortorder_' . $setting)); 137 } 138 139 /** 140 * Test passing null clears the corresponding config setting. 141 * 142 * @dataProvider settings_provider 143 * @param string $setting The name of the setting being saved 144 * @param string $function The name of the function being called 145 * @param array|string $datamethod The property of the test class to pass to the function. 146 * @param bool $csv True of the data is stored as a comma-separated list. 147 * @return void 148 */ 149 public function test_reset_settings( 150 string $setting, 151 string $function, 152 array|string $datamethod, 153 bool $csv, 154 ): void { 155 $data = $this->get_data_from_datamethod($datamethod); 156 $this->setAdminUser(); 157 $this->resetAfterTest(true); 158 $initial = $csv ? implode(',', $data) : $data; 159 set_config($setting, $initial, 'qbank_columnsortorder'); 160 $this->assertEquals($initial, get_config('qbank_columnsortorder', $setting)); 161 column_manager::{$function}(null, true); 162 $this->assertFalse(get_config('qbank_columnsortorder', $setting)); 163 } 164 165 /** 166 * Test setting user preferences 167 * 168 * @dataProvider settings_provider 169 * @param string $setting The name of the setting being saved 170 * @param string $function The name of the function being called 171 * @param array|string $datamethod The property of the test class to pass to the function. 172 * @param bool $csv True of the data is stored as a comma-separated list. 173 * @return void 174 */ 175 public function test_settings_user( 176 string $setting, 177 string $function, 178 array|string $datamethod, 179 bool $csv, 180 ): void { 181 $this->resetAfterTest(true); 182 $data = $this->get_data_from_datamethod($datamethod); 183 $this->assertFalse(get_config('qbank_columnsortorder', $setting)); 184 $this->assertEmpty(get_user_preferences('qbank_columnsortorder_' . $setting)); 185 column_manager::{$function}($data); 186 $expected = $csv ? implode(',', $data) : $data; 187 $this->assertFalse(get_config('qbank_columnsortorder', $setting)); 188 $this->assertEquals($expected, get_user_preferences('qbank_columnsortorder_' . $setting)); 189 } 190 191 /** 192 * Test passing null clears the corresponding user preference. 193 * 194 * @dataProvider settings_provider 195 * @param string $setting The name of the setting being saved 196 * @param string $function The name of the function being called 197 * @param array|string $datamethod The property of the test class to pass to the function. 198 * @param bool $csv True of the data is stored as a comma-separated list. 199 * @return void 200 */ 201 public function test_reset_user_settings( 202 string $setting, 203 string $function, 204 array|string $datamethod, 205 bool $csv, 206 ): void { 207 $data = $this->get_data_from_datamethod($datamethod); 208 $this->setAdminUser(); 209 $this->resetAfterTest(true); 210 $initial = $csv ? implode(',', $data) : $data; 211 set_user_preference('qbank_columnsortorder_' . $setting, $initial); 212 $this->assertEquals($initial, get_user_preferences('qbank_columnsortorder_' . $setting)); 213 column_manager::{$function}(null); 214 $this->assertEmpty(get_user_preferences('qbank_columnsortorder_' . $setting)); 215 } 216 217 /** 218 * Test function get_columns in helper class, that proper data is returned. 219 * 220 * @covers ::get_columns 221 */ 222 public function test_getcolumns_function(): void { 223 $this->resetAfterTest(true); 224 $this->setAdminUser(); 225 $columnmanager = new column_manager(true); 226 $questionlistcolumns = $columnmanager->get_columns(); 227 $this->assertIsArray($questionlistcolumns); 228 foreach ($questionlistcolumns as $columnnobject) { 229 $this->assertObjectHasAttribute('class', $columnnobject); 230 $this->assertObjectHasAttribute('name', $columnnobject); 231 $this->assertObjectHasAttribute('colname', $columnnobject); 232 } 233 } 234 235 /** 236 * The get_sorted_columns method should return the provided columns sorted according to enabledcol setting. 237 * 238 * @return void 239 */ 240 public function test_get_sorted_columns(): void { 241 $this->resetAfterTest(true); 242 $this->setAdminUser(); 243 $questionbank = $this->get_question_bank(); 244 $columns = $this->get_columns($questionbank); 245 $neworder = $columns; 246 shuffle($neworder); 247 set_config('enabledcol', implode(',', $neworder), 'qbank_columnsortorder'); 248 249 $columnmanager = new column_manager(true); 250 $columnstosort = []; 251 foreach ($columns as $column) { 252 $columnstosort[$column] = $column; 253 } 254 255 $sortedcolumns = $columnmanager->get_sorted_columns($columnstosort); 256 257 $expectedorder = ['core_question\local\bank\checkbox_column' . column_base::ID_SEPARATOR . 'checkbox_column' => 0]; 258 foreach ($neworder as $columnid) { 259 $expectedorder[$columnid] = $columnid; 260 } 261 $this->assertSame($expectedorder, $sortedcolumns); 262 } 263 264 /** 265 * Test disabled columns are removed from enabledcol setting and added to disabledcol setting. 266 * 267 * @return void 268 */ 269 public function test_disable_columns(): void { 270 $this->resetAfterTest(true); 271 $this->setAdminUser(); 272 $questionbank = $this->get_question_bank(); 273 $columns = $this->get_columns($questionbank); 274 // Set up enabledcol with all plugins. 275 set_config('enabledcol', implode(',', $columns), 'qbank_columnsortorder'); 276 $questionbank = $this->get_question_bank(); 277 $columns = $this->get_columns($questionbank); 278 $columnmanager = new column_manager(true); 279 $this->assertFalse(get_config('qbank_columnsortorder', 'disabledcol')); 280 281 // Disable a random plugin. 282 $plugincolumns = array_filter($columns, fn($column) => str_starts_with($column, 'qbank_')); 283 $randomcolumn = $plugincolumns[array_rand($plugincolumns, 1)]; 284 $randomplugin = explode('\\', $randomcolumn)[0]; 285 $columnmanager->disable_columns($randomplugin); 286 287 // The enabledcol setting should now contain all columns except the disabled plugin. 288 $expectedconfig = array_filter($columns, fn($column) => !str_starts_with($column, $randomplugin)); 289 sort($expectedconfig); 290 $newconfig = explode(',', get_config('qbank_columnsortorder', 'enabledcol')); 291 sort($newconfig); 292 $this->assertEquals($expectedconfig, $newconfig); 293 $this->assertNotContains($randomcolumn, $newconfig); 294 // The disabledcol setting should only contain columns from the disabled plugin. 295 $disabledconfig = explode(',', get_config('qbank_columnsortorder', 'disabledcol')); 296 array_walk($disabledconfig, fn($column) => $this->assertStringStartsWith($randomplugin, $column)); 297 } 298 299 /** 300 * Test enabling and disabling columns through event observers 301 * 302 * @covers \qbank_columnsortorder\event\plugin_observer 303 */ 304 public function test_plugin_enabled_disabled_observers(): void { 305 $this->resetAfterTest(true); 306 $this->setAdminUser(); 307 $questionbank = $this->get_question_bank(); 308 $columns = $this->get_columns($questionbank); 309 $columnmanager = new column_manager(true); 310 $neworder = $columnmanager->get_sorted_columns($columns); 311 shuffle($neworder); 312 $columnmanager::set_column_order($neworder, true); 313 // Get the list of enabled columns, excluding core columns (we can't disable those). 314 $currentconfig = get_config('qbank_columnsortorder', 'enabledcol'); 315 $currentconfig = array_filter(explode(',', $currentconfig), fn($class) => !str_starts_with($class, 'core')); 316 // Pick a column at random and get its plugin name. 317 $randomcolumnid = $currentconfig[array_rand($currentconfig, 1)]; 318 [$randomcolumnclass] = explode(column_base::ID_SEPARATOR, $randomcolumnid, 2); 319 [$randomplugintodisable] = explode('\\', $randomcolumnclass); 320 $olddisabledconfig = get_config('qbank_columnsortorder', 'disabledcol'); 321 \core\event\qbank_plugin_disabled::create_for_plugin($randomplugintodisable)->trigger(); 322 $newdisabledconfig = get_config('qbank_columnsortorder', 'disabledcol'); 323 $this->assertNotEquals($olddisabledconfig, $newdisabledconfig); 324 \core\event\qbank_plugin_enabled::create_for_plugin($randomplugintodisable)->trigger(); 325 $newdisabledconfig = get_config('qbank_columnsortorder', 'disabledcol'); 326 $this->assertEmpty($newdisabledconfig); 327 $enabledconfig = get_config('qbank_columnsortorder', 'enabledcol'); 328 $contains = strpos($enabledconfig, $randomplugintodisable); 329 $this->assertNotFalse($contains); 330 $this->assertIsInt($contains); 331 } 332 333 /** 334 * Test enabled columns are removed from disabledcol setting and added to enabledcol setting. 335 * 336 * @return void 337 */ 338 public function test_enable_columns() { 339 $this->resetAfterTest(true); 340 $this->setAdminUser(); 341 $questionbank = $this->get_question_bank(); 342 $columns = $this->get_columns($questionbank); 343 // Set up disablecol with columns from 2 random plugins, and enabledcol with all other columns. 344 $plugincolumns = array_filter($columns, fn($column) => str_starts_with($column, 'qbank_')); 345 $plugins = array_unique(array_map(fn($column) => explode('\\', $column)[0], $plugincolumns)); 346 $randomplugins = array_rand($plugins, 2); 347 $randomplugin1 = $plugins[$randomplugins[0]]; 348 $randomplugin2 = $plugins[$randomplugins[1]]; 349 350 $disabledcols = array_filter( 351 $columns, 352 fn($column) => str_starts_with($column, $randomplugin1) || str_starts_with($column, $randomplugin2) 353 ); 354 $enabledcols = array_diff($columns, $disabledcols); 355 356 set_config('enabledcol', implode(',', $enabledcols), 'qbank_columnsortorder'); 357 set_config('disabledcol', implode(',', $disabledcols), 'qbank_columnsortorder'); 358 359 // Enable one of the disabled plugins. 360 $columnmanager = new column_manager(true); 361 $columnmanager->enable_columns($randomplugin1); 362 // The enabledcol setting should now contain all columns except the remaining disabled plugin. 363 $expectedenabled = array_filter($columns, fn($column) => !str_starts_with($column, $randomplugin2)); 364 $expecteddisabled = array_filter($disabledcols, fn($column) => str_starts_with($column, $randomplugin2)); 365 sort($expectedenabled); 366 sort($expecteddisabled); 367 $newenabled = explode(',', get_config('qbank_columnsortorder', 'enabledcol')); 368 sort($newenabled); 369 $this->assertEquals($expectedenabled, $newenabled); 370 $this->assertNotContains(reset($expecteddisabled), $newenabled); 371 // The disabledcol setting should only contain columns from the remaining disabled plugin. 372 $newdisabled = explode(',', get_config('qbank_columnsortorder', 'disabledcol')); 373 array_walk($newdisabled, fn($column) => $this->assertStringStartsWith($randomplugin2, $column)); 374 } 375 376 /** 377 * Test that get_disabled_columns returns names of all the columns in the disabledcol setting 378 * 379 * @return void 380 */ 381 public function test_get_disabled_columns(): void { 382 $this->resetAfterTest(true); 383 $this->setAdminUser(); 384 $questionbank = $this->get_question_bank(); 385 $columns = $this->get_columns($questionbank); 386 // Set up disablecol with columns from 2 random plugins, and enabledcol with all other columns. 387 $plugincolumns = array_filter($columns, fn($column) => str_starts_with($column, 'qbank_')); 388 $randomcolumn = $plugincolumns[array_rand($plugincolumns, 1)]; 389 $randomplugin = explode('\\', $randomcolumn)[0]; 390 391 $disabledcols = array_filter($columns, fn($column) => str_starts_with($column, $randomplugin)); 392 393 set_config('disabledcol', implode(',', $disabledcols), 'qbank_columnsortorder'); 394 395 $columnmanager = new column_manager(true); 396 $expecteddisablednames = []; 397 foreach ($disabledcols as $disabledcolid) { 398 [$columnclass, $columnname] = explode(column_base::ID_SEPARATOR, $disabledcolid, 2); 399 $columnobject = $columnclass::from_column_name($questionbank, $columnname); 400 $expecteddisablednames[$disabledcolid] = (object) [ 401 'disabledname' => $columnobject->get_title(), 402 ]; 403 } 404 $disablednames = $columnmanager->get_disabled_columns(); 405 $this->assertEquals($expecteddisablednames, $disablednames); 406 } 407 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body