Merge branch 'wip-MDL-47174-master' of git://github.com/marinaglancy/moodle
[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
160 $all = html_writer::tag('a', get_string('all'), $attrs + array(
161 'class' => 'include all ' . $key
162 ));
163
164 $none = html_writer::tag('a', get_string('none'), $attrs + array(
165 'class' => 'include none ' . $key
166 ));
167
168 return html_writer::tag('span', "$all / $none", array(
169 'class' => 'inclusion_links'
170 ));
171 }
172
173 /**
174 * Make a toggle link with some text before it.
175 *
176 * @param string $key A unique key for this control - inserted in the classes.
177 * @return string
178 */
179 public function make_toggle_links($key) {
180 return get_string($key, 'gradereport_singleview') . ' ' .
181 $this->make_toggle($key);
182 }
183
184 /**
185 * Get the default heading for the screen.
186 *
187 * @return string
188 */
189 public function heading() {
190 return get_string('pluginname', 'gradereport_singleview');
191 }
192
193 /**
194 * Override this to init the screen.
195 *
196 * @param boolean $selfitemisempty True if no item has been selected yet.
197 */
198 public abstract function init($selfitemisempty = false);
199
200 /**
201 * Get the type of items in the list.
202 *
203 * @return string
204 */
205 public abstract function item_type();
206
207 /**
208 * Get the entire screen as a string.
209 *
210 * @return string
211 */
212 public abstract function html();
213
214 /**
215 * Does this screen support paging?
216 *
217 * @return bool
218 */
219 public function supports_paging() {
220 return true;
221 }
222
223 /**
224 * Default pager
225 *
226 * @return string
227 */
228 public function pager() {
229 return '';
230 }
231
232 /**
233 * Initialise the js for this screen.
234 */
235 public function js() {
236 global $PAGE;
237
238 $module = array(
239 'name' => 'gradereport_singleview',
240 'fullpath' => '/grade/report/singleview/js/singleview.js',
241 'requires' => array('base', 'dom', 'event', 'event-simulate', 'io-base')
242 );
243
244 $PAGE->requires->js_init_call('M.gradereport_singleview.init', array(), false, $module);
245 }
246
247 /**
248 * Process the data from a form submission.
249 *
250 * @param array $data
251 * @return array of warnings
252 */
253 public function process($data) {
254 $warnings = array();
255
256 $fields = $this->definition();
257
50e30bd4
ZD
258 // Avoiding execution timeouts when updating
259 // a large amount of grades.
260 $progress = 0;
261 $progressbar = new \core\progress\display_if_slow();
262 $progressbar->start_html();
263 $progressbar->start_progress(get_string('savegrades', 'gradereport_singleview'), count((array) $data) - 1);
264 $changecount = array();
265
57fac09a 266 foreach ($data as $varname => $throw) {
50e30bd4
ZD
267 $progressbar->progress($progress);
268 $progress++;
57fac09a
DW
269 if (preg_match("/(\w+)_(\d+)_(\d+)/", $varname, $matches)) {
270 $itemid = $matches[2];
271 $userid = $matches[3];
272 } else {
273 continue;
274 }
275
57fac09a
DW
276 $gradeitem = grade_item::fetch(array(
277 'id' => $itemid, 'courseid' => $this->courseid
278 ));
279
1b2c1ccb
ZD
280 if (preg_match('/^old[oe]{1}/', $varname)) {
281 $elementname = preg_replace('/^old/', '', $varname);
282 if (!isset($data->$elementname)) {
50e30bd4
ZD
283 // Decrease the progress because we've increased the
284 // size of the array we are iterating through.
285 $progress--;
1b2c1ccb
ZD
286 $data->$elementname = false;
287 }
288 }
289
290 if (!in_array($matches[1], $fields)) {
291 continue;
292 }
293
57fac09a
DW
294 if (!$gradeitem) {
295 continue;
296 }
297
298 $grade = $this->fetch_grade_or_default($gradeitem, $userid);
299
300 $classname = '\\gradereport_singleview\\local\\ui\\' . $matches[1];
301 $element = new $classname($grade);
302
303 $name = $element->get_name();
304 $oldname = "old$name";
305
306 $posted = $data->$name;
307
308 $format = $element->determine_format();
309
310 if ($format->is_textbox() and trim($data->$name) === '') {
311 $data->$name = null;
312 }
313
314 // Same value; skip.
315 if (isset($data->$oldname) && $data->$oldname == $posted) {
316 continue;
317 }
318
319 $msg = $element->set($posted);
320
321 // Optional type.
322 if (!empty($msg)) {
323 $warnings[] = $msg;
324 }
50e30bd4
ZD
325 if (preg_match('/_(\d+)_(\d+)/', $varname, $matchelement)) {
326 $changecount[$matchelement[0]] = 1;
327 }
57fac09a
DW
328 }
329
330 // Some post-processing.
331 $eventdata = new stdClass;
332 $eventdata->warnings = $warnings;
333 $eventdata->post_data = $data;
334 $eventdata->instance = $this;
50e30bd4
ZD
335 $eventdata->changecount = $changecount;
336
337 $progressbar->end_html();
57fac09a 338
50e30bd4 339 return $eventdata;
57fac09a
DW
340 }
341
342 /**
343 * By default there are no options.
344 * @return array
345 */
346 public function options() {
347 return array();
348 }
349
350 /**
351 * Should we show the group selector?
352 * @return bool
353 */
354 public function display_group_selector() {
355 return true;
356 }
357
358 /**
359 * Should we show the next prev selector?
360 * @return bool
361 */
362 public function supports_next_prev() {
363 return true;
364 }
365}