MDL-48273 singleview: add load_user method and other group validations
[moodle.git] / grade / report / singleview / classes / local / screen / screen.php
CommitLineData
57fac09a
DW
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 * Abstract class used as a base for the 3 screens.
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
25namespace gradereport_singleview\local\screen;
26
27use context_course;
28use moodle_url;
29use html_writer;
30use grade_structure;
31use grade_grade;
32use grade_item;
33use stdClass;
34
35defined('MOODLE_INTERNAL') || die;
36
37/**
38 * Abstract class used as a base for the 3 screens.
39 *
40 * @package gradereport_singleview
41 * @copyright 2014 Moodle Pty Ltd (http://moodle.com)
42 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
43 */
44abstract class screen {
45
46 /** @var int $courseid The id of the course */
47 protected $courseid;
48
49 /** @var int $itemid Either a user id or a grade_item id */
50 protected $itemid;
51
52 /** @var int $groupid The currently set groupid (if set) */
53 protected $groupid;
54
55 /** @var course_context $context The course context */
56 protected $context;
57
58 /** @var int $page The page number */
59 protected $page;
60
61 /** @var int $perpage Results per page */
62 protected $perpage;
63
64 /** @var array $items List of items on the page, they could be users or grade_items */
65 protected $items;
66
67 /**
68 * Constructor
69 *
70 * @param int $courseid The course id
71 * @param int $itemid The item id
72 * @param int $groupid The group id
73 */
74 public function __construct($courseid, $itemid, $groupid = null) {
75 global $DB;
76
77 $this->courseid = $courseid;
78 $this->itemid = $itemid;
79 $this->groupid = $groupid;
80
81 $this->context = context_course::instance($this->courseid);
82 $this->course = $DB->get_record('course', array('id' => $courseid));
83
84 $this->page = optional_param('page', 0, PARAM_INT);
85 $this->perpage = optional_param('perpage', 100, PARAM_INT);
86 if ($this->perpage > 100) {
87 $this->perpage = 100;
88 }
89
90 $this->init(empty($itemid));
91 }
92
93 /**
94 * Cache the grade_structure class
95 */
96 public function setup_structure() {
97 $this->structure = new grade_structure();
98 $this->structure->modinfo = get_fast_modinfo($this->course);
99 }
100
101 /**
102 * Create a nice link from a thing (user or grade_item).
103 *
104 * @param string $screen
105 * @param int $itemid
106 * @param bool $display Should we wrap this in an anchor ?
107 * @return string The link
108 */
109 public function format_link($screen, $itemid, $display = null) {
110 $url = new moodle_url('/grade/report/singleview/index.php', array(
111 'id' => $this->courseid,
112 'item' => $screen,
113 'itemid' => $itemid,
114 'group' => $this->groupid,
115 ));
116
117 if ($display) {
118 return html_writer::link($url, $display);
119 } else {
120 return $url;
121 }
122 }
123
124 /**
125 * Get the grade_grade
126 *
127 * @param grade_item $item The grade_item
128 * @param int $userid The user id
129 * @return grade_grade
130 */
131 public function fetch_grade_or_default($item, $userid) {
132 $grade = grade_grade::fetch(array(
133 'itemid' => $item->id, 'userid' => $userid
134 ));
135
136 if (!$grade) {
137 $default = new stdClass;
138
139 $default->userid = $userid;
140 $default->itemid = $item->id;
141 $default->feedback = '';
142
143 $grade = new grade_grade($default, false);
144 }
145
146 $grade->grade_item = $item;
147
148 return $grade;
149 }
150
151 /**
152 * Make the HTML element that toggles all the checkboxes on or off.
153 *
154 * @param string $key A unique key for this control - inserted in the classes.
155 * @return string
156 */
157 public function make_toggle($key) {
158 $attrs = array('href' => '#');
159
dd01789b
JC
160 // Do proper lang strings for title attributes exist for the given key?
161 $strmanager = \get_string_manager();
162 $titleall = get_string('all');
163 $titlenone = get_string('none');
164 if ($strmanager->string_exists(strtolower($key) . 'all', 'gradereport_singleview')) {
165 $titleall = get_string(strtolower($key) . 'all', 'gradereport_singleview');
166 }
167 if ($strmanager->string_exists(strtolower($key) . 'none', 'gradereport_singleview')) {
168 $titlenone = get_string(strtolower($key) . 'none', 'gradereport_singleview');
169 }
170
57fac09a 171 $all = html_writer::tag('a', get_string('all'), $attrs + array(
dd01789b
JC
172 'class' => 'include all ' . $key,
173 'title' => $titleall
57fac09a
DW
174 ));
175
176 $none = html_writer::tag('a', get_string('none'), $attrs + array(
dd01789b
JC
177 'class' => 'include none ' . $key,
178 'title' => $titlenone
57fac09a
DW
179 ));
180
181 return html_writer::tag('span', "$all / $none", array(
182 'class' => 'inclusion_links'
183 ));
184 }
185
186 /**
187 * Make a toggle link with some text before it.
188 *
189 * @param string $key A unique key for this control - inserted in the classes.
190 * @return string
191 */
192 public function make_toggle_links($key) {
193 return get_string($key, 'gradereport_singleview') . ' ' .
194 $this->make_toggle($key);
195 }
196
197 /**
198 * Get the default heading for the screen.
199 *
200 * @return string
201 */
202 public function heading() {
203 return get_string('pluginname', 'gradereport_singleview');
204 }
205
206 /**
207 * Override this to init the screen.
208 *
209 * @param boolean $selfitemisempty True if no item has been selected yet.
210 */
211 public abstract function init($selfitemisempty = false);
212
213 /**
214 * Get the type of items in the list.
215 *
216 * @return string
217 */
218 public abstract function item_type();
219
220 /**
221 * Get the entire screen as a string.
222 *
223 * @return string
224 */
225 public abstract function html();
226
227 /**
228 * Does this screen support paging?
229 *
230 * @return bool
231 */
232 public function supports_paging() {
233 return true;
234 }
235
236 /**
237 * Default pager
238 *
239 * @return string
240 */
241 public function pager() {
242 return '';
243 }
244
245 /**
246 * Initialise the js for this screen.
247 */
248 public function js() {
249 global $PAGE;
250
251 $module = array(
252 'name' => 'gradereport_singleview',
253 'fullpath' => '/grade/report/singleview/js/singleview.js',
254 'requires' => array('base', 'dom', 'event', 'event-simulate', 'io-base')
255 );
256
257 $PAGE->requires->js_init_call('M.gradereport_singleview.init', array(), false, $module);
258 }
259
260 /**
261 * Process the data from a form submission.
262 *
263 * @param array $data
264 * @return array of warnings
265 */
266 public function process($data) {
267 $warnings = array();
268
269 $fields = $this->definition();
270
50e30bd4
ZD
271 // Avoiding execution timeouts when updating
272 // a large amount of grades.
273 $progress = 0;
274 $progressbar = new \core\progress\display_if_slow();
275 $progressbar->start_html();
276 $progressbar->start_progress(get_string('savegrades', 'gradereport_singleview'), count((array) $data) - 1);
277 $changecount = array();
278
57fac09a 279 foreach ($data as $varname => $throw) {
50e30bd4
ZD
280 $progressbar->progress($progress);
281 $progress++;
57fac09a
DW
282 if (preg_match("/(\w+)_(\d+)_(\d+)/", $varname, $matches)) {
283 $itemid = $matches[2];
284 $userid = $matches[3];
285 } else {
286 continue;
287 }
288
57fac09a
DW
289 $gradeitem = grade_item::fetch(array(
290 'id' => $itemid, 'courseid' => $this->courseid
291 ));
292
1b2c1ccb
ZD
293 if (preg_match('/^old[oe]{1}/', $varname)) {
294 $elementname = preg_replace('/^old/', '', $varname);
295 if (!isset($data->$elementname)) {
50e30bd4
ZD
296 // Decrease the progress because we've increased the
297 // size of the array we are iterating through.
298 $progress--;
1b2c1ccb
ZD
299 $data->$elementname = false;
300 }
301 }
302
303 if (!in_array($matches[1], $fields)) {
304 continue;
305 }
306
57fac09a
DW
307 if (!$gradeitem) {
308 continue;
309 }
310
311 $grade = $this->fetch_grade_or_default($gradeitem, $userid);
312
313 $classname = '\\gradereport_singleview\\local\\ui\\' . $matches[1];
314 $element = new $classname($grade);
315
316 $name = $element->get_name();
317 $oldname = "old$name";
318
319 $posted = $data->$name;
320
321 $format = $element->determine_format();
322
323 if ($format->is_textbox() and trim($data->$name) === '') {
324 $data->$name = null;
325 }
326
327 // Same value; skip.
328 if (isset($data->$oldname) && $data->$oldname == $posted) {
329 continue;
330 }
331
332 $msg = $element->set($posted);
333
334 // Optional type.
335 if (!empty($msg)) {
336 $warnings[] = $msg;
337 }
50e30bd4
ZD
338 if (preg_match('/_(\d+)_(\d+)/', $varname, $matchelement)) {
339 $changecount[$matchelement[0]] = 1;
340 }
57fac09a
DW
341 }
342
343 // Some post-processing.
344 $eventdata = new stdClass;
345 $eventdata->warnings = $warnings;
346 $eventdata->post_data = $data;
347 $eventdata->instance = $this;
50e30bd4
ZD
348 $eventdata->changecount = $changecount;
349
350 $progressbar->end_html();
57fac09a 351
50e30bd4 352 return $eventdata;
57fac09a
DW
353 }
354
355 /**
356 * By default there are no options.
357 * @return array
358 */
359 public function options() {
360 return array();
361 }
362
363 /**
364 * Should we show the group selector?
365 * @return bool
366 */
367 public function display_group_selector() {
368 return true;
369 }
370
371 /**
372 * Should we show the next prev selector?
373 * @return bool
374 */
375 public function supports_next_prev() {
376 return true;
377 }
aac66bef
SL
378
379 /**
380 * Load a valid list of users for this gradebook as the screen "items".
381 * @return array $users A list of enroled users.
382 */
383 protected function load_users() {
384 global $CFG;
385
386 // Create a graded_users_iterator because it will properly check the groups etc.
387 $defaultgradeshowactiveenrol = !empty($CFG->grade_report_showonlyactiveenrol);
388 $showonlyactiveenrol = get_user_preferences('grade_report_showonlyactiveenrol', $defaultgradeshowactiveenrol);
389 $showonlyactiveenrol = $showonlyactiveenrol || !has_capability('moodle/course:viewsuspendedusers', $this->context);
390
391 require_once($CFG->dirroot.'/grade/lib.php');
392 $gui = new \graded_users_iterator($this->course, null, $this->groupid);
393 $gui->require_active_enrolment($showonlyactiveenrol);
394 $gui->init();
395
396 // Flatten the users.
397 $users = array();
398 while ($user = $gui->next_user()) {
399 $users[$user->user->id] = $user->user;
400 }
401 return $users;
402 }
57fac09a 403}