MDL-51709 gradebook: Name display in single view.
[moodle.git] / grade / report / singleview / classes / local / screen / grade.php
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/>.
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  */
25 namespace gradereport_singleview\local\screen;
27 use gradereport_singleview\local\ui\range;
28 use gradereport_singleview\local\ui\bulk_insert;
29 use grade_grade;
30 use grade_item;
31 use moodle_url;
32 use pix_icon;
33 use html_writer;
34 use gradereport_singleview;
36 defined('MOODLE_INTERNAL') || die;
38 /**
39  * The screen with a list of users.
40  *
41  * @package   gradereport_singleview
42  * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
43  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
44  */
45 class grade extends tablelike implements selectable_items, filterable_items {
47     /** @var int $totalitemcount Used for paging */
48     private $totalitemcount = 0;
50     /** @var bool $requiresextra True if this is a manual grade item */
51     private $requiresextra = false;
53     /** @var bool $requirepaging True if there are more users than our limit. */
54     private $requirespaging = true;
56     /**
57      * True if $CFG->grade_overridecat is true
58      *
59      * @return bool
60      */
61     public static function allowcategories() {
62         return get_config('moodle', 'grade_overridecat');
63     }
65     /**
66      * Filter the list excluding category items (if required)?
67      * @param grade_item $item The grade item.
68      */
69     public static function filter($item) {
70         return get_config('moodle', 'grade_overridecat') ||
71                 !($item->is_course_item() || $item->is_category_item());
72     }
74     /**
75      * Get the label for the select box that chooses items for this page.
76      * @return string
77      */
78     public function select_label() {
79         return get_string('selectuser', 'gradereport_singleview');
80     }
82     /**
83      * Get the description of this page
84      * @return string
85      */
86     public function description() {
87         return get_string('users');
88     }
90     /**
91      * Convert this list of items into an options list
92      *
93      * @return array
94      */
95     public function options() {
96         $options = array();
97         foreach ($this->items as $userid => $user) {
98             $options[$userid] = fullname($user);
99         }
101         return $options;
102     }
104     /**
105      * Return the type of the things in this list.
106      * @return string
107      */
108     public function item_type() {
109         return 'user';
110     }
112     /**
113      * Get the original settings for this item
114      * @return array
115      */
116     public function original_definition() {
117         $def = array('finalgrade', 'feedback');
119         $def[] = 'override';
121         $def[] = 'exclude';
123         return $def;
124     }
126     /**
127      * Init this page
128      *
129      * @param bool $selfitemisempty True if we have not selected a user.
130      */
131     public function init($selfitemisempty = false) {
133         $this->items = $this->load_users();
134         $this->totalitemcount = count($this->items);
136         if ($selfitemisempty) {
137             return;
138         }
140         $params = array(
141             'id' => $this->itemid,
142             'courseid' => $this->courseid
143         );
145         $this->item = grade_item::fetch($params);
146         if (!self::filter($this->item)) {
147             $this->items = array();
148             $this->set_init_error(get_string('gradeitemcannotbeoverridden', 'gradereport_singleview'));
149         }
151         $this->requiresextra = !$this->item->is_manual_item();
153         $this->setup_structure();
155         $this->set_definition($this->original_definition());
156         $this->set_headers($this->original_headers());
157     }
159     /**
160      * Get the table headers
161      *
162      * @return array
163      */
164     public function original_headers() {
165         return array(
166             '', // For filter icon.
167             get_string('fullnameuser', 'core'),
168             get_string('range', 'grades'),
169             get_string('grade', 'grades'),
170             get_string('feedback', 'grades'),
171             $this->make_toggle_links('override'),
172             $this->make_toggle_links('exclude')
173         );
174     }
176     /**
177      * Format a row in the table
178      *
179      * @param user $item
180      * @return string
181      */
182     public function format_line($item) {
183         global $OUTPUT;
185         $grade = $this->fetch_grade_or_default($this->item, $item->id);
187         $lockicon = '';
189         $lockedgrade = $lockedgradeitem = 0;
190         if (!empty($grade->locked)) {
191             $lockedgrade = 1;
192         }
193         if (!empty($grade->grade_item->locked)) {
194             $lockedgradeitem = 1;
195         }
196         // Check both grade and grade item.
197         if ( $lockedgrade || $lockedgradeitem ) {
198             $lockicon = $OUTPUT->pix_icon('t/locked', 'grade is locked') . ' ';
199         }
201         if (has_capability('moodle/site:viewfullnames', \context_course::instance($this->courseid))) {
202             $fullname = $lockicon . fullname($item, true);
203         } else {
204             $fullname = $lockicon . fullname($item);
205         }
207         $item->imagealt = $fullname;
208         $url = new moodle_url("/user/view.php", array('id' => $item->id, 'course' => $this->courseid));
209         $iconstring = get_string('filtergrades', 'gradereport_singleview', $fullname);
210         $grade->label = $fullname;
211         $userpic = $OUTPUT->user_picture($item, ['link' => false, 'visibletoscreenreaders' => false]);
213         $line = array(
214             $OUTPUT->action_icon($this->format_link('user', $item->id), new pix_icon('t/editstring', ''), null,
215                     ['title' => $iconstring, 'aria-label' => $iconstring]),
216             html_writer::link($url, $userpic . $fullname),
217             $this->item_range()
218         );
219         $lineclasses = array(
220             "action",
221             "user",
222             "range"
223         );
224         $outputline = array();
225         $i = 0;
226         foreach ($line as $key => $value) {
227             $cell = new \html_table_cell($value);
228             if ($isheader = $i == 1) {
229                 $cell->header = $isheader;
230                 $cell->scope = "row";
231             }
232             if (array_key_exists($key, $lineclasses)) {
233                 $cell->attributes['class'] = $lineclasses[$key];
234             }
235             $outputline[] = $cell;
236             $i++;
237         }
239         return $this->format_definition($outputline, $grade);
240     }
242     /**
243      * Get the range ui element for this grade_item
244      *
245      * @return element;
246      */
247     public function item_range() {
248         if (empty($this->range)) {
249             $this->range = new range($this->item);
250         }
252         return $this->range;
253     }
255     /**
256      * Does this page require paging?
257      *
258      * @return bool
259      */
260     public function supports_paging() {
261         return $this->requirespaging;
262     }
264     /**
265      * Get the pager for this page.
266      *
267      * @return string
268      */
269     public function pager() {
270         global $OUTPUT;
272         return $OUTPUT->paging_bar(
273             $this->totalitemcount, $this->page, $this->perpage,
274             new moodle_url('/grade/report/singleview/index.php', array(
275                 'perpage' => $this->perpage,
276                 'id' => $this->courseid,
277                 'group' => $this->groupid,
278                 'itemid' => $this->itemid,
279                 'item' => 'grade'
280             ))
281         );
282     }
284     /**
285      * Get the heading for this page.
286      *
287      * @return string
288      */
289     public function heading() {
290         return get_string('gradeitem', 'gradereport_singleview', $this->item->get_name());
291     }
293     /**
294      * Get the summary for this table.
295      *
296      * @return string
297      */
298     public function summary() {
299         return get_string('summarygrade', 'gradereport_singleview');
300     }
302     /**
303      * Process the data from the form.
304      *
305      * @param array $data
306      * @return array of warnings
307      */
308     public function process($data) {
309         $bulk = new bulk_insert($this->item);
310         // Bulk insert messages the data to be passed in
311         // ie: for all grades of empty grades apply the specified value.
312         if ($bulk->is_applied($data)) {
313             $filter = $bulk->get_type($data);
314             $insertvalue = $bulk->get_insert_value($data);
315             // Appropriately massage data that may not exist.
316             if ($this->supports_paging()) {
317                 $gradeitem = grade_item::fetch(array(
318                     'courseid' => $this->courseid,
319                     'id' => $this->item->id
320                 ));
322                 $null = $gradeitem->gradetype == GRADE_TYPE_SCALE ? -1 : '';
324                 foreach ($this->items as $itemid => $item) {
325                     $field = "finalgrade_{$gradeitem->id}_{$itemid}";
326                     if (isset($data->$field)) {
327                         continue;
328                     }
330                     $grade = grade_grade::fetch(array(
331                         'itemid' => $gradeitem->id,
332                         'userid' => $itemid
333                     ));
335                     $data->$field = empty($grade) ? $null : $grade->finalgrade;
336                     $data->{"old$field"} = $data->$field;
337                 }
338             }
340             foreach ($data as $varname => $value) {
341                 if (preg_match('/^oldoverride_(\d+)_(\d+)/', $varname, $matches)) {
342                     // If we've selected overriding all grades.
343                     if ($filter == 'all') {
344                         $override = "override_{$matches[1]}_{$matches[2]}";
345                         $data->$override = '1';
346                     }
347                 }
348                 if (!preg_match('/^finalgrade_(\d+)_/', $varname, $matches)) {
349                     continue;
350                 }
352                 $gradeitem = grade_item::fetch(array(
353                     'courseid' => $this->courseid,
354                     'id' => $matches[1]
355                 ));
357                 $isscale = ($gradeitem->gradetype == GRADE_TYPE_SCALE);
359                 $empties = (trim($value) === '' or ($isscale and $value == -1));
361                 if ($filter == 'all' or $empties) {
362                     $data->$varname = ($isscale and empty($insertvalue)) ?
363                         -1 : $insertvalue;
364                 }
365             }
366         }
368         return parent::process($data);
369     }