Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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 user screen.
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_seq;
28
use gradereport_singleview;
29
use moodle_url;
30
use pix_icon;
31
use html_writer;
32
use gradereport_singleview\local\ui\range;
33
use gradereport_singleview\local\ui\bulk_insert;
34
use grade_item;
35
use grade_grade;
36
use stdClass;
37
 
38
defined('MOODLE_INTERNAL') || die;
39
 
40
/**
41
 * The user screen.
42
 *
43
 * @package   gradereport_singleview
44
 * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
45
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
46
 */
47
class user extends tablelike implements selectable_items {
48
 
49
    /** @var array $categories A cache for grade_item categories */
50
    private $categories = [];
51
 
52
    /** @var int $requirespaging Do we have more items than the paging limit? */
53
    private $requirespaging = true;
54
 
55
    /** @var array get a valid user.  */
56
    public $item = [];
57
 
58
    /**
59
     * Get the label for the select box that chooses items for this page.
60
     * @return string
61
     */
62
    public function select_label(): string {
63
        return get_string('selectgrade', 'gradereport_singleview');
64
    }
65
 
66
    /**
67
     * Get the description for the screen.
68
     *
69
     * @return string
70
     */
71
    public function description(): string {
72
        return get_string('gradeitems', 'grades');
73
    }
74
 
75
    /**
76
     * Convert the list of items to a list of options.
77
     *
78
     * @return array
79
     */
80
    public function options(): array {
81
        $result = [];
82
        foreach ($this->items as $itemid => $item) {
83
            $result[$itemid] = $item->get_name();
84
        }
85
        return $result;
86
    }
87
 
88
    /**
89
     * Get the type of items on this screen.
90
     *
91
     * @return string
92
     */
93
    public function item_type(): string {
94
        return 'grade';
95
    }
96
 
97
    /**
98
     * Init the screen
99
     *
100
     * @param bool $selfitemisempty Have we selected an item yet?
101
     */
102
    public function init($selfitemisempty = false) {
103
 
104
        if (!$selfitemisempty) {
105
            $validusers = \grade_report::get_gradable_users($this->courseid, $this->groupid);
106
            if (!isset($validusers[$this->itemid])) {
107
                // If the passed user id is not valid, show the first user from the list instead.
108
                $this->item = reset($validusers);
109
                $this->itemid = $this->item->id;
110
            } else {
111
                $this->item = $validusers[$this->itemid];
112
            }
113
        }
114
 
115
        $seq = new grade_seq($this->courseid, true);
116
 
117
        $this->items = [];
118
        foreach ($seq->items as $itemid => $item) {
119
            if (grade::filter($item)) {
120
                $this->items[$itemid] = $item;
121
            }
122
        }
123
 
124
        // If we change perpage on pagination we might end up with a page that doesn't exist.
125
        if ($this->perpage) {
126
            $numpages = intval(count($this->items) / $this->perpage) + 1;
127
            if ($numpages <= $this->page) {
128
                $this->page = 0;
129
            }
130
        } else {
131
            $this->page = 0;
132
        }
133
 
134
        $this->requirespaging = count($this->items) > $this->perpage;
135
 
136
        $this->setup_structure();
137
 
138
        $this->definition = [
139
            'finalgrade', 'feedback', 'override', 'exclude'
140
        ];
141
        $this->set_headers($this->original_headers());
142
    }
143
 
144
    /**
145
     * Get the list of headers for the table.
146
     *
147
     * @return array List of headers
148
     */
149
    public function original_headers(): array {
150
        return [
151
            get_string('assessmentname', 'gradereport_singleview'),
152
            '', // For filter icon.
153
            get_string('gradecategory', 'grades'),
154
            get_string('gradenoun'),
155
            get_string('range', 'grades'),
156
            get_string('feedback', 'grades'),
157
            get_string('override', 'gradereport_singleview'),
158
            get_string('exclude', 'gradereport_singleview'),
159
        ];
160
    }
161
 
162
    /**
163
     * Format each row of the table.
164
     *
165
     * @param grade_item $item
166
     * @return array
167
     */
168
    public function format_line($item): array {
169
        global $OUTPUT;
170
 
171
        $grade = $this->fetch_grade_or_default($item, $this->item->id);
172
        $gradestatus = '';
173
 
174
        $context = [
175
            'hidden' => $grade->is_hidden(),
176
            'locked' => $grade->is_locked(),
177
        ];
178
 
179
        if (in_array(true, $context)) {
180
            $context['classes'] = 'gradestatus';
181
            $gradestatus = $OUTPUT->render_from_template('core_grades/status_icons', $context);
182
        }
183
 
184
        // Create a fake gradetreeitem so we can call get_element_header().
185
        // The type logic below is from grade_category->_get_children_recursion().
186
        $gradetreeitem = [];
187
 
188
        $type = in_array($item->itemtype, ['course', 'category']) ? "{$item->itemtype}item" : 'item';
189
        $gradetreeitem['type'] = $type;
190
        $gradetreeitem['object'] = $item;
191
        $gradetreeitem['userid'] = $this->item->id;
192
 
193
        $itemname = \grade_helper::get_element_header($gradetreeitem, true, false, false, false, true);
194
        $grade->label = $item->get_name();
195
 
196
        $formatteddefinition = $this->format_definition($grade);
197
 
198
        $itemicon = html_writer::div($this->format_icon($item), 'mr-1');
199
        $itemtype = \html_writer::span(\grade_helper::get_element_type_string($gradetreeitem),
200
            'd-block text-uppercase small dimmed_text');
201
 
202
        $itemtitle = html_writer::div($itemname, 'rowtitle');
203
        $itemcontent = html_writer::div($itemtype . $itemtitle);
204
 
205
        $line = [
206
            html_writer::div($itemicon . $itemcontent, "{$type} d-flex align-items-center"),
207
            $this->get_item_action_menu($item),
208
            $this->category($item),
209
            $formatteddefinition['finalgrade'] . $gradestatus,
210
            new range($item),
211
            $formatteddefinition['feedback'],
212
            $formatteddefinition['override'],
213
            $formatteddefinition['exclude'],
214
        ];
215
        $lineclasses = [
216
            'gradeitem',
217
            'action',
218
            'category',
219
            'grade',
220
            'range',
221
        ];
222
 
223
        $outputline = [];
224
        $i = 0;
225
        foreach ($line as $key => $value) {
226
            $cell = new \html_table_cell($value);
227
            if ($isheader = $i == 0) {
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
        }
237
 
238
        return $outputline;
239
    }
240
 
241
    /**
242
     * Helper to get the icon for an item.
243
     *
244
     * @param grade_item $item
245
     * @return string
246
     */
247
    private function format_icon($item): string {
248
        $element = ['type' => 'item', 'object' => $item];
249
        return \grade_helper::get_element_icon($element);
250
    }
251
 
252
    /**
253
     * Return the action menu HTML for the grade item.
254
     *
255
     * @param grade_item $item
256
     * @return mixed
257
     */
258
    private function get_item_action_menu(grade_item $item) {
259
        global $OUTPUT;
260
 
261
        $menuitems = [];
262
        $url = new moodle_url($this->format_link('grade', $item->id));
263
        $title = get_string('showallgrades', 'core_grades');
264
        $menuitems[] = new \action_menu_link_secondary($url, null, $title);
265
        $menu = new \action_menu($menuitems);
266
        $icon = $OUTPUT->pix_icon('i/moremenu', get_string('actions'));
267
        $extraclasses = 'btn btn-link btn-icon icon-size-3 d-flex align-items-center justify-content-center';
268
        $menu->set_menu_trigger($icon, $extraclasses);
269
        $menu->set_menu_left();
270
        $menu->set_boundary('window');
271
 
272
        return $OUTPUT->render($menu);
273
    }
274
 
275
    /**
276
     * Helper to get the category for an item.
277
     *
278
     * @param grade_item $item
279
     * @return string
280
     */
281
    private function category(grade_item $item): string {
282
        global $DB;
283
 
284
        if (empty($item->categoryid)) {
285
 
286
            if ($item->itemtype == 'course') {
287
                return $this->course->fullname;
288
            }
289
 
290
            $params = ['id' => $item->iteminstance];
291
            $elem = $DB->get_record('grade_categories', $params);
292
 
293
            return $elem->fullname;
294
        }
295
 
296
        if (!isset($this->categories[$item->categoryid])) {
297
            $category = $item->get_parent_category();
298
 
299
            $this->categories[$category->id] = $category;
300
        }
301
 
302
        return $this->categories[$item->categoryid]->get_name();
303
    }
304
 
305
    /**
306
     * Get the heading for the page.
307
     *
308
     * @return string
309
     */
310
    public function heading(): string {
311
        global $PAGE;
312
        $headinglangstring = $PAGE->user_is_editing() ? 'gradeuseredit' : 'gradeuser';
313
        return get_string($headinglangstring, 'gradereport_singleview', fullname($this->item));
314
    }
315
 
316
    /**
317
     * Get the summary for this table.
318
     *
319
     * @return string
320
     */
321
    public function summary(): string {
322
        return get_string('summaryuser', 'gradereport_singleview');
323
    }
324
 
325
    /**
326
     * Default pager
327
     *
328
     * @return string
329
     */
330
    public function pager(): string {
331
        global $OUTPUT;
332
 
333
        if (!$this->supports_paging()) {
334
            return '';
335
        }
336
 
337
        return $OUTPUT->paging_bar(
338
            count($this->items), $this->page, $this->perpage,
339
            new moodle_url('/grade/report/singleview/index.php', [
340
                'perpage' => $this->perpage,
341
                'id' => $this->courseid,
342
                'group' => $this->groupid,
343
                'itemid' => $this->itemid,
344
                'item' => 'user'
345
            ])
346
        );
347
    }
348
 
349
    /**
350
     * Does this page require paging?
351
     *
352
     * @return bool
353
     */
354
    public function supports_paging(): bool {
355
        return $this->requirespaging;
356
    }
357
 
358
 
359
    /**
360
     * Process the data from the form.
361
     *
362
     * @param array $data
363
     * @return stdClass of warnings
364
     */
365
    public function process($data): stdClass {
366
        $bulk = new bulk_insert($this->item);
367
        // Bulk insert messages the data to be passed in
368
        // ie: for all grades of empty grades apply the specified value.
369
        if ($bulk->is_applied($data)) {
370
            $filter = $bulk->get_type($data);
371
            $insertvalue = $bulk->get_insert_value($data);
372
 
373
            $userid = $this->item->id;
374
            foreach ($this->items as $gradeitemid => $gradeitem) {
375
                $null = $gradeitem->gradetype == GRADE_TYPE_SCALE ? -1 : '';
376
                $field = "finalgrade_{$gradeitem->id}_{$this->itemid}";
377
                if (isset($data->$field)) {
378
                    continue;
379
                }
380
 
381
                $oldfinalgradefield = "oldfinalgrade_{$gradeitem->id}_{$this->itemid}";
382
                // Bulk grade changes for all grades need to be processed and shouldn't be skipped if they had a previous grade.
383
                if ($gradeitem->is_course_item() || ($filter != 'all' && !empty($data->$oldfinalgradefield))) {
384
                    if ($gradeitem->is_course_item()) {
385
                        // The course total should not be overridden.
386
                        unset($data->$field);
387
                        unset($data->oldfinalgradefield);
388
                        $oldoverride = "oldoverride_{$gradeitem->id}_{$this->itemid}";
389
                        unset($data->$oldoverride);
390
                        $oldfeedback = "oldfeedback_{$gradeitem->id}_{$this->itemid}";
391
                        unset($data->$oldfeedback);
392
                    }
393
                    continue;
394
                }
395
                $grade = grade_grade::fetch([
396
                    'itemid' => $gradeitemid,
397
                    'userid' => $userid
398
                ]);
399
 
400
                $data->$field = empty($grade) ? $null : $grade->finalgrade;
401
                $data->{"old$field"} = $data->$field;
402
            }
403
 
404
            foreach ($data as $varname => $value) {
405
                if (preg_match('/^oldoverride_(\d+)_(\d+)/', $varname, $matches)) {
406
                    // If we've selected overriding all grades.
407
                    if ($filter == 'all') {
408
                        $override = "override_{$matches[1]}_{$matches[2]}";
409
                        $data->$override = '1';
410
                    }
411
                }
412
                if (!preg_match('/^finalgrade_(\d+)_(\d+)/', $varname, $matches)) {
413
                    continue;
414
                }
415
 
416
                $gradeitem = grade_item::fetch([
417
                    'courseid' => $this->courseid,
418
                    'id' => $matches[1],
419
                ]);
420
 
421
                $isscale = ($gradeitem->gradetype == GRADE_TYPE_SCALE);
422
 
423
                $empties = (trim($value ?? '') === '' || ($isscale && $value == -1));
424
 
425
                if ($filter == 'all' || $empties) {
426
                    $data->$varname = ($isscale && empty($insertvalue)) ? -1 : $insertvalue;
427
                }
428
            }
429
        }
430
        return parent::process($data);
431
    }
432
}