51346d1b99a78bd738c83d9609312b5371e7a066
[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 description of this page
76      * @return string
77      */
78     public function description() {
79         return get_string('users');
80     }
82     /**
83      * Convert this list of items into an options list
84      *
85      * @return array
86      */
87     public function options() {
88         $options = array();
89         foreach ($this->items as $userid => $user) {
90             $options[$userid] = fullname($user);
91         }
93         return $options;
94     }
96     /**
97      * Return the type of the things in this list.
98      * @return string
99      */
100     public function item_type() {
101         return 'user';
102     }
104     /**
105      * Get the original settings for this item
106      * @return array
107      */
108     public function original_definition() {
109         $def = array('finalgrade', 'feedback');
111         $def[] = 'override';
113         $def[] = 'exclude';
115         return $def;
116     }
118     /**
119      * Init this page
120      *
121      * @param bool $selfitemisempty True if we have not selected a user.
122      */
123     public function init($selfitemisempty = false) {
124         $roleids = explode(',', get_config('moodle', 'gradebookroles'));
126         $this->items = array();
127         foreach ($roleids as $roleid) {
128             // Keeping the first user appearance.
129             $this->items = $this->items + get_role_users(
130                 $roleid, $this->context, false, '',
131                 'u.lastname, u.firstname', null, $this->groupid);
132         }
134         $this->totalitemcount = count_role_users($roleids, $this->context);
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('firstname') . ' (' . get_string('alternatename') . ') ' . get_string('lastname'),
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 (!empty($item->alternatename)) {
202             $fullname = $lockicon . $item->alternatename . ' (' . $item->firstname . ') ' . $item->lastname;
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;
212         $line = array(
213             $OUTPUT->action_icon($this->format_link('user', $item->id), new pix_icon('t/editstring', $iconstring)),
214             $OUTPUT->user_picture($item, array('visibletoscreenreaders' => false)) .
215             html_writer::link($url, $fullname),
216             $this->item_range()
217         );
218         $lineclasses = array(
219             "action",
220             "user",
221             "range"
222         );
223         $outputline = array();
224         $i = 0;
225         foreach ($line as $key => $value) {
226             $cell = new \html_table_cell($value);
227             if ($isheader = $i == 1) {
228                 $cell->header = $isheader;
229                 $cell->scope = "row";
230             }
231             if (array_key_exists($key, $lineclasses)) {
232                 $cell->attributes['class'] = $lineclasses[$key];
233             }
234             $outputline[] = $cell;
235             $i++;
236         }
238         return $this->format_definition($outputline, $grade);
239     }
241     /**
242      * Get the range ui element for this grade_item
243      *
244      * @return element;
245      */
246     public function item_range() {
247         if (empty($this->range)) {
248             $this->range = new range($this->item);
249         }
251         return $this->range;
252     }
254     /**
255      * Does this page require paging?
256      *
257      * @return bool
258      */
259     public function supports_paging() {
260         return $this->requirespaging;
261     }
263     /**
264      * Get the pager for this page.
265      *
266      * @return string
267      */
268     public function pager() {
269         global $OUTPUT;
271         return $OUTPUT->paging_bar(
272             $this->totalitemcount, $this->page, $this->perpage,
273             new moodle_url('/grade/report/singleview/index.php', array(
274                 'perpage' => $this->perpage,
275                 'id' => $this->courseid,
276                 'groupid' => $this->groupid,
277                 'itemid' => $this->itemid,
278                 'item' => 'grade'
279             ))
280         );
281     }
283     /**
284      * Get the heading for this page.
285      *
286      * @return string
287      */
288     public function heading() {
289         return $this->item->get_name();
290     }
292     /**
293      * Get the summary for this table.
294      *
295      * @return string
296      */
297     public function summary() {
298         return get_string('summarygrade', 'gradereport_singleview');
299     }
301     /**
302      * Process the data from the form.
303      *
304      * @param array $data
305      * @return array of warnings
306      */
307     public function process($data) {
308         $bulk = new bulk_insert($this->item);
309         // Bulk insert messages the data to be passed in
310         // ie: for all grades of empty grades apply the specified value.
311         if ($bulk->is_applied($data)) {
312             $filter = $bulk->get_type($data);
313             $insertvalue = $bulk->get_insert_value($data);
314             // Appropriately massage data that may not exist.
315             if ($this->supports_paging()) {
316                 $gradeitem = grade_item::fetch(array(
317                     'courseid' => $this->courseid,
318                     'id' => $this->item->id
319                 ));
321                 $null = $gradeitem->gradetype == GRADE_TYPE_SCALE ? -1 : '';
323                 foreach ($this->items as $itemid => $item) {
324                     $field = "finalgrade_{$gradeitem->id}_{$itemid}";
325                     if (isset($data->$field)) {
326                         continue;
327                     }
329                     $grade = grade_grade::fetch(array(
330                         'itemid' => $gradeitem->id,
331                         'userid' => $itemid
332                     ));
334                     $data->$field = empty($grade) ? $null : $grade->finalgrade;
335                     $data->{"old$field"} = $data->$field;
337                     preg_match('/_(\d+)_(\d+)/', $field, $oldoverride);
338                     $oldoverride = 'oldoverride' . $oldoverride[0];
339                     if (empty($data->$oldoverride)) {
340                         $data->$field = (!isset($grade->rawgrade)) ? $null : $grade->rawgrade;
341                     }
342                 }
343             }
345             foreach ($data as $varname => $value) {
346                 if (preg_match('/override_(\d+)_(\d+)/', $varname, $matches)) {
347                     $data->$matches[0] = '1';
348                 }
349                 if (!preg_match('/^finalgrade_(\d+)_/', $varname, $matches)) {
350                     continue;
351                 }
353                 $gradeitem = grade_item::fetch(array(
354                     'courseid' => $this->courseid,
355                     'id' => $matches[1]
356                 ));
358                 $isscale = ($gradeitem->gradetype == GRADE_TYPE_SCALE);
360                 $empties = (trim($value) === '' or ($isscale and $value == -1));
362                 if ($filter == 'all' or $empties) {
363                     $data->$varname = ($isscale and empty($insertvalue)) ?
364                         -1 : $insertvalue;
365                 }
366             }
367         }
369         return parent::process($data);
370     }