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 require_once($CFG->libdir . '/questionlib.php'); 22 23 use context_system; 24 use core_question\local\bank\column_base; 25 use core_question\local\bank\column_manager_base; 26 use core_question\local\bank\question_edit_contexts; 27 use core_question\local\bank\view; 28 use qbank_columnsortorder\local\bank\column_action_move; 29 use qbank_columnsortorder\local\bank\column_action_remove; 30 use qbank_columnsortorder\local\bank\column_action_resize; 31 use qbank_columnsortorder\local\bank\preview_view; 32 use moodle_url; 33 34 /** 35 * Class column_manager responsible for loading and saving order to the config setting. 36 * 37 * @package qbank_columnsortorder 38 * @copyright 2021 Catalyst IT Australia Pty Ltd 39 * @author Ghaly Marc-Alexandre <marc-alexandreghaly@catalyst-ca.net> 40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 41 */ 42 class column_manager extends column_manager_base { 43 /** 44 * @var array Column order as set in config_plugins 'class' => 'position', ie: question_type_column => 3. 45 */ 46 public $columnorder; 47 48 /** 49 * @var array hidden columns. 50 */ 51 public $hiddencolumns; 52 53 /** 54 * @var array columns with size. 55 */ 56 public $colsize; 57 58 /** 59 * @var array Disabled columns in config_plugins table. 60 */ 61 public $disabledcolumns; 62 63 /** 64 * Constructor for column_manager class. 65 * 66 * @param bool $globalsettings Only use the global default settings, ignoring user preferences? 67 */ 68 public function __construct(bool $globalsettings = false) { 69 $this->columnorder = $this->setup_property('enabledcol', $globalsettings); 70 if (empty($this->columnorder)) { 71 $this->columnorder = [ 72 'core_question\local\bank\checkbox_column' . column_base::ID_SEPARATOR . 'checkbox_column', 73 'qbank_viewquestiontype\question_type_column' . column_base::ID_SEPARATOR . 'question_type_column', 74 'qbank_viewquestionname\question_name_idnumber_tags_column' . column_base::ID_SEPARATOR . 75 'question_name_idnumber_tags_column', 76 'core_question\local\bank\edit_menu_column' . column_base::ID_SEPARATOR . 'edit_menu_column', 77 'qbank_editquestion\question_status_column' . column_base::ID_SEPARATOR . 'question_status_column', 78 'qbank_history\version_number_column' . column_base::ID_SEPARATOR . 'version_number_column', 79 'qbank_viewcreator\creator_name_column' . column_base::ID_SEPARATOR . 'creator_name_column', 80 'qbank_comment\comment_count_column' . column_base::ID_SEPARATOR . 'comment_count_column', 81 ]; 82 } 83 $this->hiddencolumns = $this->setup_property('hiddencols', $globalsettings); 84 $this->colsize = $this->setup_property('colsize', $globalsettings, 'json'); 85 $this->disabledcolumns = $this->setup_property('disabledcol', true); // No user preference for disabledcol. 86 87 if ($this->columnorder) { 88 $this->columnorder = array_flip($this->columnorder); 89 } 90 if ($this->disabledcolumns) { 91 $this->disabledcolumns = array_flip($this->disabledcolumns); 92 } 93 } 94 95 /** 96 * Return the value for the given property, based the saved user preference or config setting. 97 * 98 * If no value is currently stored, returns an empty array. 99 * 100 * @param string $setting The identifier used for the saved config and user preference settings. 101 * @param bool $global Only get the global default, ignoring the user preference? 102 * @param string $encoding The encoding used to store the property - csv or json 103 * @return array 104 */ 105 private function setup_property(string $setting, bool $global = false, $encoding = 'csv'): array { 106 $value = get_config('qbank_columnsortorder', $setting); 107 if (!$global) { 108 $value = get_user_preferences("qbank_columnsortorder_{$setting}", $value); 109 } 110 if (empty($value)) { 111 return []; 112 } 113 return $encoding == 'csv' ? explode(',', $value) : json_decode($value); 114 } 115 116 /** 117 * Sets column order in the qbank_columnsortorder plugin config. 118 * 119 * @param ?array $columns Column order to set. Null value clears the setting. 120 * @param bool $global save this as a global default, rather than a user preference? 121 */ 122 public static function set_column_order(?array $columns, bool $global = false) : void { 123 if (!is_null($columns)) { 124 $columns = implode(',', $columns); 125 } 126 self::save_preference('enabledcol', $columns, $global); 127 } 128 129 /** 130 * Hidden Columns. 131 * 132 * @param ?array $columns List of hidden columns. Null value clears the setting. 133 * @param bool $global save this as a global default, rather than a user preference? 134 */ 135 public static function set_hidden_columns(?array $columns, bool $global = false) : void { 136 if (!is_null($columns)) { 137 $columns = implode(',', $columns); 138 } 139 self::save_preference('hiddencols', $columns, $global); 140 } 141 142 /** 143 * Column size. 144 * 145 * @param ?string $sizes columns with width. Null value clears the setting. 146 * @param bool $global save this as a global default, rather than a user preference? 147 */ 148 public static function set_column_size(?string $sizes, bool $global = false) : void { 149 self::save_preference('colsize', $sizes, $global); 150 } 151 152 /** 153 * Save Preferences. 154 * 155 * @param string $name name of a configuration 156 * @param ?string $value value of a configuration. Null value clears the setting. 157 * @param bool $global save this as a global default, rather than a user preference? 158 */ 159 private static function save_preference(string $name, ?string $value, bool $global = false): void { 160 if ($global) { 161 require_capability('moodle/site:config', context_system::instance()); 162 set_config($name, $value, 'qbank_columnsortorder'); 163 } else { 164 set_user_preference("qbank_columnsortorder_{$name}", $value); 165 } 166 } 167 168 /** 169 * Get qbank. 170 * 171 * @return view 172 */ 173 public function get_questionbank(): view { 174 $course = (object) ['id' => 0]; 175 $context = context_system::instance(); 176 $contexts = new question_edit_contexts($context); 177 $category = question_make_default_categories($contexts->all()); 178 $params = ['cat' => $category->id . ',' . $context->id]; 179 // Dummy call to get the objects without error. 180 $questionbank = new preview_view( 181 $contexts, 182 new moodle_url('/question/bank/columnsortorder/sortcolumns.php'), 183 $course, 184 null, 185 $params 186 ); 187 return $questionbank; 188 } 189 190 /** 191 * Get enabled columns. 192 * 193 * @return array 194 */ 195 public function get_columns(): array { 196 $columns = []; 197 foreach ($this->get_questionbank()->get_visiblecolumns() as $key => $column) { 198 if ($column->get_name() === 'checkbox') { 199 continue; 200 } 201 $columns[] = (object) [ 202 'class' => get_class($column), 203 'name' => $column->get_title(), 204 'colname' => $column->get_column_name(), 205 'id' => $column->get_column_id(), 206 ]; 207 } 208 return $columns; 209 } 210 211 /** 212 * Get disabled columns. 213 * 214 * @return array 215 */ 216 public function get_disabled_columns(): array { 217 $disabled = []; 218 if ($this->disabledcolumns) { 219 foreach (array_keys($this->disabledcolumns) as $column) { 220 [$classname, $columnname] = explode(column_base::ID_SEPARATOR, $column, 2); 221 $columnobject = $classname::from_column_name($this->get_questionbank(), $columnname); 222 $disabled[$column] = (object) [ 223 'disabledname' => $columnobject->get_title(), 224 ]; 225 } 226 } 227 return $disabled; 228 } 229 230 /** 231 * Updates enabled and disabled config for 'qbank_columnsortorder' plugin. 232 * 233 * @param array $enabledcolumns Enabled columns to set. 234 * @param array $disabledcolumns Disabled columns to set. 235 */ 236 protected function update_config($enabledcolumns, $disabledcolumns): void { 237 if (!empty($enabledcolumns)) { 238 $configenabled = implode(',', array_flip($enabledcolumns)); 239 set_config('enabledcol', $configenabled, 'qbank_columnsortorder'); 240 } 241 if (!empty($disabledcolumns)) { 242 $configdisabled = implode(',', array_flip($disabledcolumns)); 243 set_config('disabledcol', $configdisabled, 'qbank_columnsortorder'); 244 } else { 245 set_config('disabledcol', null, 'qbank_columnsortorder'); 246 } 247 } 248 249 /** 250 * Enables columns. 251 * 252 * @param string $plugin Plugin type and name ie: qbank_viewcreator. 253 */ 254 public function enable_columns(string $plugin): void { 255 $enabledcolumns = []; 256 $disabledcolumns = []; 257 if ($this->columnorder) { 258 $enabledcolumns = $this->columnorder; 259 } 260 if ($this->disabledcolumns) { 261 $disabledcolumns = $this->disabledcolumns; 262 foreach ($disabledcolumns as $class => $column) { 263 if (strpos($class, $plugin) !== false) { 264 $enabledcolumns[$class] = $class; 265 if (isset($disabledcolumns[$class])) { 266 unset($disabledcolumns[$class]); 267 } 268 } 269 } 270 } 271 $this->update_config($enabledcolumns, $disabledcolumns); 272 } 273 274 /** 275 * Disables columns. 276 * 277 * @param string $plugin Plugin type and name ie: qbank_viewcreator. 278 */ 279 public function disable_columns(string $plugin): void { 280 $disabledcolumns = []; 281 $enabledcolumns = []; 282 $allcolumns = $this->get_columns(); 283 if ($this->disabledcolumns) { 284 $disabledcolumns = $this->disabledcolumns; 285 } 286 if ($this->columnorder) { 287 $enabledcolumns = $this->columnorder; 288 } 289 290 foreach ($allcolumns as $column) { 291 if (str_contains($column->class, $plugin)) { 292 $disabledcolumns[$column->id] = $column->id; 293 if (isset($enabledcolumns[$column->id])) { 294 unset($enabledcolumns[$column->id]); 295 } 296 } 297 } 298 $this->update_config($enabledcolumns, $disabledcolumns); 299 } 300 301 /** 302 * Orders columns in the question bank view according to config_plugins table 'qbank_columnsortorder' config. 303 * 304 * @param array $ordertosort Unordered array of columns, [columnname => class] 305 * @return array $properorder|$ordertosort Returns array ordered if 'qbank_columnsortorder' config exists. 306 */ 307 public function get_sorted_columns($ordertosort): array { 308 // Check if db has order set. 309 if (!empty($this->columnorder)) { 310 // Merge new order with old one. 311 $columnsortorder = $this->columnorder; 312 asort($columnsortorder); 313 $columnorder = []; 314 foreach ($columnsortorder as $columnid => $colposition) { 315 if (array_key_exists($columnid, $ordertosort)) { 316 $columnorder[$columnid] = $colposition; 317 } 318 } 319 $properorder = array_merge($columnorder, $ordertosort); 320 // Always have the checkbox at first column position. 321 $checkboxid = 'core_question\local\bank\checkbox_column' . column_base::ID_SEPARATOR . 'checkbox_column'; 322 if (isset($properorder[$checkboxid])) { 323 $checkboxfirstelement = $properorder[$checkboxid]; 324 unset($properorder[$checkboxid]); 325 $properorder = array_merge([ 326 $checkboxid => $checkboxfirstelement 327 ], $properorder); 328 } 329 return $properorder; 330 } 331 return $ordertosort; 332 } 333 334 /** 335 * Given an array of columns, set the isvisible attribute according to $this->hiddencolumns and $this->disabledcolumns. 336 * 337 * @param column_base[] $columns 338 * @return array 339 */ 340 public function set_columns_visibility(array $columns): array { 341 foreach ($columns as $column) { 342 if (!is_object($column)) { 343 continue; 344 } 345 $columnid = $column->get_column_id(); 346 347 $column->isvisible = !in_array($columnid, $this->hiddencolumns) && !array_key_exists($columnid, $this->disabledcolumns); 348 } 349 return $columns; 350 } 351 352 /** 353 * Return $this->colsize mapped as an array of column name => width, excluding empty sizes. 354 * 355 * @return array 356 */ 357 public function get_colsize_map(): array { 358 $sizes = array_reduce($this->colsize, function($result, $colsize) { 359 $result[$colsize->column] = $colsize->width; 360 return $result; 361 }, []); 362 return array_filter($sizes); 363 } 364 365 /** 366 * Return an array of hidden columns as an array of class => column name 367 * 368 * @return array 369 */ 370 public function get_hidden_columns(): array { 371 return array_reduce($this->hiddencolumns, function($result, $hiddencolumn) { 372 [$columnclass, $columnname] = explode(column_base::ID_SEPARATOR, $hiddencolumn, 2); 373 $result[$hiddencolumn] = $columnclass::from_column_name($this->get_questionbank(), $columnname)->get_title(); 374 return $result; 375 }, []); 376 } 377 378 public function get_column_width(column_base $column): string { 379 $colsizemap = $this->get_colsize_map(); 380 $columnid = $column->get_column_id(); 381 if (array_key_exists($columnid, $colsizemap)) { 382 return $colsizemap[$columnid] . 'px'; 383 } 384 return parent::get_column_width($column); 385 } 386 387 public function get_column_actions(view $qbank): array { 388 return [ 389 new column_action_move($qbank), 390 new column_action_remove($qbank), 391 new column_action_resize($qbank), 392 ]; 393 } 394 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body