Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [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 /** 18 * The screen with a list of users. 19 * 20 * @package gradereport_singleview 21 * @copyright 2014 Moodle Pty Ltd (http://moodle.com) 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace gradereport_singleview\local\screen; 26 27 use grade_report; 28 use gradereport_singleview\local\ui\range; 29 use gradereport_singleview\local\ui\bulk_insert; 30 use grade_grade; 31 use grade_item; 32 use moodle_url; 33 use pix_icon; 34 use html_writer; 35 use gradereport_singleview; 36 37 defined('MOODLE_INTERNAL') || die; 38 39 /** 40 * The screen with a list of users. 41 * 42 * @package gradereport_singleview 43 * @copyright 2014 Moodle Pty Ltd (http://moodle.com) 44 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 45 */ 46 class grade extends tablelike implements selectable_items, filterable_items { 47 48 /** 49 * Used for paging 50 * @var int $totalitemcount 51 */ 52 private $totalitemcount = 0; 53 54 /** 55 * True if this is a manual grade item 56 * @var bool $requiresextra 57 */ 58 private $requiresextra = false; 59 60 /** 61 * True if there are more users than our limit. 62 * @var bool $requirepaging 63 */ 64 private $requirespaging = true; 65 66 /** 67 * To store UI element that generates a grade_item min/max range. 68 * @var range; 69 */ 70 protected $range; 71 72 /** 73 * Returns a grade_item instance or false if none found. 74 * @var grade_item|bool 75 */ 76 public $item; 77 78 /** 79 * True if $CFG->grade_overridecat is true 80 * 81 * @return bool 82 */ 83 public static function allowcategories(): bool { 84 return get_config('moodle', 'grade_overridecat'); 85 } 86 87 /** 88 * Filter the list excluding category items (if required)? 89 * @param grade_item $item The grade item. 90 * @return bool 91 */ 92 public static function filter($item): bool { 93 return get_config('moodle', 'grade_overridecat') || 94 !($item->is_course_item() || $item->is_category_item()); 95 } 96 97 /** 98 * Get the label for the select box that chooses items for this page. 99 * @return string 100 */ 101 public function select_label(): string { 102 return get_string('selectuser', 'gradereport_singleview'); 103 } 104 105 /** 106 * Get the description of this page 107 * @return string 108 */ 109 public function description(): string { 110 return get_string('users'); 111 } 112 113 /** 114 * Convert this list of items into an options list 115 * 116 * @return array 117 */ 118 public function options(): array { 119 $options = []; 120 foreach ($this->items as $userid => $user) { 121 $options[$userid] = fullname($user); 122 } 123 124 return $options; 125 } 126 127 /** 128 * Return the type of the things in this list. 129 * @return string 130 */ 131 public function item_type(): string { 132 return 'user'; 133 } 134 135 /** 136 * Get the original settings for this item 137 * @return array 138 */ 139 public function original_definition(): array { 140 return [ 141 'finalgrade', 142 'feedback', 143 'override', 144 'exclude' 145 ]; 146 } 147 148 /** 149 * Init this page 150 * 151 * @param bool $selfitemisempty True if we have not selected a user. 152 */ 153 public function init($selfitemisempty = false) { 154 155 $this->items = grade_report::get_gradable_users($this->courseid, $this->groupid); 156 $this->totalitemcount = count($this->items); 157 158 if ($selfitemisempty) { 159 return; 160 } 161 162 // If we change perpage on pagination we might end up with a page that doesn't exist. 163 if ($this->perpage) { 164 $numpages = intval($this->totalitemcount / $this->perpage) + 1; 165 if ($numpages <= $this->page) { 166 $this->page = 0; 167 } 168 } else { 169 $this->page = 0; 170 } 171 172 $params = [ 173 'id' => $this->itemid, 174 'courseid' => $this->courseid 175 ]; 176 177 $this->item = grade_item::fetch($params); 178 if (!self::filter($this->item)) { 179 $this->items = []; 180 $this->set_init_error(get_string('gradeitemcannotbeoverridden', 'gradereport_singleview')); 181 } 182 183 $this->requiresextra = !$this->item->is_manual_item(); 184 185 $this->setup_structure(); 186 187 $this->set_definition($this->original_definition()); 188 $this->set_headers($this->original_headers()); 189 } 190 191 /** 192 * Get the table headers 193 * 194 * @return array 195 */ 196 public function original_headers() { 197 return [ 198 get_string('fullnameuser', 'core'), 199 '', // For filter icon. 200 get_string('grade', 'grades'), 201 get_string('range', 'grades'), 202 get_string('feedback', 'grades'), 203 get_string('override', 'gradereport_singleview'), 204 get_string('exclude', 'gradereport_singleview'), 205 ]; 206 } 207 208 /** 209 * Format a row in the table 210 * 211 * @param stdClass $item 212 * @return array 213 */ 214 public function format_line($item): array { 215 global $OUTPUT; 216 217 $grade = $this->fetch_grade_or_default($this->item, $item->id); 218 219 $gradestatus = ''; 220 $context = [ 221 'hidden' => $grade->is_hidden(), 222 'locked' => $grade->is_locked(), 223 ]; 224 225 if (in_array(true, $context)) { 226 $context['classes'] = 'gradestatus'; 227 $gradestatus = $OUTPUT->render_from_template('core_grades/status_icons', $context); 228 } 229 230 if (has_capability('moodle/site:viewfullnames', \context_course::instance($this->courseid))) { 231 $fullname = fullname($item, true); 232 } else { 233 $fullname = fullname($item); 234 } 235 236 $item->imagealt = $fullname; 237 $url = new moodle_url("/user/view.php", ['id' => $item->id, 'course' => $this->courseid]); 238 $grade->label = $fullname; 239 $userpic = $OUTPUT->user_picture($item, ['link' => false, 'visibletoscreenreaders' => false]); 240 241 $formatteddefinition = $this->format_definition($grade); 242 243 $line = [ 244 html_writer::link($url, $userpic . $fullname), 245 $this->get_user_action_menu($item), 246 $formatteddefinition['finalgrade'] . $gradestatus, 247 $this->item_range(), 248 $formatteddefinition['feedback'], 249 $formatteddefinition['override'], 250 $formatteddefinition['exclude'], 251 ]; 252 $lineclasses = [ 253 'user', 254 'action', 255 'grade', 256 'range', 257 ]; 258 $outputline = []; 259 $i = 0; 260 foreach ($line as $key => $value) { 261 $cell = new \html_table_cell($value); 262 if ($isheader = $i == 0) { 263 $cell->header = $isheader; 264 $cell->scope = "row"; 265 } 266 if (array_key_exists($key, $lineclasses)) { 267 $cell->attributes['class'] = $lineclasses[$key]; 268 } 269 $outputline[] = $cell; 270 $i++; 271 } 272 273 return $outputline; 274 } 275 276 /** 277 * Get the range ui element for this grade_item 278 * 279 * @return element; 280 */ 281 public function item_range() { 282 if (empty($this->range)) { 283 $this->range = new range($this->item); 284 } 285 286 return $this->range; 287 } 288 289 /** 290 * Does this page require paging? 291 * 292 * @return bool 293 */ 294 public function supports_paging(): bool { 295 return $this->requirespaging; 296 } 297 298 /** 299 * Get the pager for this page. 300 * 301 * @return string 302 */ 303 public function pager(): string { 304 global $OUTPUT; 305 306 return $OUTPUT->paging_bar( 307 $this->totalitemcount, $this->page, $this->perpage, 308 new moodle_url('/grade/report/singleview/index.php', [ 309 'perpage' => $this->perpage, 310 'id' => $this->courseid, 311 'group' => $this->groupid, 312 'itemid' => $this->itemid, 313 'item' => 'grade' 314 ]) 315 ); 316 } 317 318 /** 319 * Get the heading for this page. 320 * 321 * @return string 322 */ 323 public function heading(): string { 324 global $PAGE; 325 $headinglangstring = $PAGE->user_is_editing() ? 'gradeitemedit' : 'gradeitem'; 326 return get_string($headinglangstring, 'gradereport_singleview', $this->item->get_name()); 327 } 328 329 /** 330 * Get the summary for this table. 331 * 332 * @return string 333 */ 334 public function summary(): string { 335 return get_string('summarygrade', 'gradereport_singleview'); 336 } 337 338 /** 339 * Process the data from the form. 340 * 341 * @param array $data 342 * @return \stdClass of warnings 343 */ 344 public function process($data): \stdClass { 345 $bulk = new bulk_insert($this->item); 346 // Bulk insert messages the data to be passed in 347 // ie: for all grades of empty grades apply the specified value. 348 if ($bulk->is_applied($data)) { 349 $filter = $bulk->get_type($data); 350 $insertvalue = $bulk->get_insert_value($data); 351 // Appropriately massage data that may not exist. 352 if ($this->supports_paging()) { 353 $gradeitem = grade_item::fetch([ 354 'courseid' => $this->courseid, 355 'id' => $this->item->id 356 ]); 357 358 $null = $gradeitem->gradetype == GRADE_TYPE_SCALE ? -1 : ''; 359 360 foreach ($this->items as $itemid => $item) { 361 $field = "finalgrade_{$gradeitem->id}_{$itemid}"; 362 if (isset($data->$field)) { 363 continue; 364 } 365 366 $grade = grade_grade::fetch([ 367 'itemid' => $gradeitem->id, 368 'userid' => $itemid 369 ]); 370 371 $data->$field = empty($grade) ? $null : $grade->finalgrade; 372 $data->{"old$field"} = $data->$field; 373 } 374 } 375 376 foreach ($data as $varname => $value) { 377 if (preg_match('/^oldoverride_(\d+)_(\d+)/', $varname, $matches)) { 378 // If we've selected overriding all grades. 379 if ($filter == 'all') { 380 $override = "override_{$matches[1]}_{$matches[2]}"; 381 $data->$override = '1'; 382 } 383 } 384 if (!preg_match('/^finalgrade_(\d+)_/', $varname, $matches)) { 385 continue; 386 } 387 388 $gradeitem = grade_item::fetch([ 389 'courseid' => $this->courseid, 390 'id' => $matches[1] 391 ]); 392 393 $isscale = ($gradeitem->gradetype == GRADE_TYPE_SCALE); 394 395 $empties = (trim($value) === '' || ($isscale && $value == -1)); 396 397 if ($filter == 'all' || $empties) { 398 $data->$varname = ($isscale && empty($insertvalue)) ? 399 -1 : $insertvalue; 400 } 401 } 402 } 403 return parent::process($data); 404 } 405 406 /** 407 * Return the action menu HTML for the user item. 408 * 409 * @param \stdClass $user 410 * @return mixed 411 */ 412 private function get_user_action_menu(\stdClass $user) { 413 global $OUTPUT; 414 415 $menuitems = []; 416 $url = new moodle_url($this->format_link('user', $user->id)); 417 $title = get_string('showallgrades', 'core_grades'); 418 $menuitems[] = new \action_menu_link_secondary($url, null, $title); 419 $menu = new \action_menu($menuitems); 420 $icon = $OUTPUT->pix_icon('i/moremenu', get_string('actions')); 421 $extraclasses = 'btn btn-link btn-icon icon-size-3 d-flex align-items-center justify-content-center'; 422 $menu->set_menu_trigger($icon, $extraclasses); 423 $menu->set_menu_left(); 424 $menu->set_boundary('window'); 425 426 return $OUTPUT->render($menu); 427 } 428 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body