0550af3f275550987cea1f135213fd130480246d
[moodle.git] / grade / report / singleview / classes / local / screen / screen.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  * 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  */
25 namespace gradereport_singleview\local\screen;
27 use context_course;
28 use moodle_url;
29 use html_writer;
30 use grade_structure;
31 use grade_grade;
32 use grade_item;
33 use stdClass;
35 defined('MOODLE_INTERNAL') || die;
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  */
44 abstract class screen {
46     /** @var int $courseid The id of the course */
47     protected $courseid;
49     /** @var int $itemid Either a user id or a grade_item id */
50     protected $itemid;
52     /** @var int $groupid The currently set groupid (if set) */
53     protected $groupid;
55     /** @var course_context $context The course context */
56     protected $context;
58     /** @var int $page The page number */
59     protected $page;
61     /** @var int $perpage Results per page */
62     protected $perpage;
64     /** @var array $items List of items on the page, they could be users or grade_items */
65     protected $items;
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;
77         $this->courseid = $courseid;
78         $this->itemid = $itemid;
79         $this->groupid = $groupid;
81         $this->context = context_course::instance($this->courseid);
82         $this->course = $DB->get_record('course', array('id' => $courseid));
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         }
90         $this->init(empty($itemid));
91     }
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     }
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         ));
117         if ($display) {
118             return html_writer::link($url, $display);
119         } else {
120             return $url;
121         }
122     }
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         ));
136         if (!$grade) {
137             $default = new stdClass;
139             $default->userid = $userid;
140             $default->itemid = $item->id;
141             $default->feedback = '';
143             $grade = new grade_grade($default, false);
144         }
146         $grade->grade_item = $item;
148         return $grade;
149     }
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' => '#');
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         }
171         $all = html_writer::tag('a', get_string('all'), $attrs + array(
172             'class' => 'include all ' . $key,
173             'title' => $titleall
174         ));
176         $none = html_writer::tag('a', get_string('none'), $attrs + array(
177             'class' => 'include none ' . $key,
178             'title' => $titlenone
179         ));
181         return html_writer::tag('span', "$all / $none", array(
182             'class' => 'inclusion_links'
183         ));
184     }
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     }
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     }
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);
213     /**
214      * Get the type of items in the list.
215      *
216      * @return string
217      */
218     public abstract function item_type();
220     /**
221      * Get the entire screen as a string.
222      *
223      * @return string
224      */
225     public abstract function html();
227     /**
228      * Does this screen support paging?
229      *
230      * @return bool
231      */
232     public function supports_paging() {
233         return true;
234     }
236     /**
237      * Default pager
238      *
239      * @return string
240      */
241     public function pager() {
242         return '';
243     }
245     /**
246      * Initialise the js for this screen.
247      */
248     public function js() {
249         global $PAGE;
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         );
257         $PAGE->requires->js_init_call('M.gradereport_singleview.init', array(), false, $module);
258     }
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();
269         $fields = $this->definition();
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();
279         foreach ($data as $varname => $throw) {
280             $progressbar->progress($progress);
281             $progress++;
282             if (preg_match("/(\w+)_(\d+)_(\d+)/", $varname, $matches)) {
283                 $itemid = $matches[2];
284                 $userid = $matches[3];
285             } else {
286                 continue;
287             }
289             $gradeitem = grade_item::fetch(array(
290                 'id' => $itemid, 'courseid' => $this->courseid
291             ));
293             if (preg_match('/^old[oe]{1}/', $varname)) {
294                 $elementname = preg_replace('/^old/', '', $varname);
295                 if (!isset($data->$elementname)) {
296                     // Decrease the progress because we've increased the
297                     // size of the array we are iterating through.
298                     $progress--;
299                     $data->$elementname = false;
300                 }
301             }
303             if (!in_array($matches[1], $fields)) {
304                 continue;
305             }
307             if (!$gradeitem) {
308                 continue;
309             }
311             $grade = $this->fetch_grade_or_default($gradeitem, $userid);
313             $classname = '\\gradereport_singleview\\local\\ui\\' . $matches[1];
314             $element = new $classname($grade);
316             $name = $element->get_name();
317             $oldname = "old$name";
319             $posted = $data->$name;
321             $format = $element->determine_format();
323             if ($format->is_textbox() and trim($data->$name) === '') {
324                 $data->$name = null;
325             }
327             // Same value; skip.
328             if (isset($data->$oldname) && $data->$oldname == $posted) {
329                 continue;
330             }
332             $msg = $element->set($posted);
334             // Optional type.
335             if (!empty($msg)) {
336                 $warnings[] = $msg;
337             }
338             if (preg_match('/_(\d+)_(\d+)/', $varname, $matchelement)) {
339                 $changecount[$matchelement[0]] = 1;
340             }
341         }
343         // Some post-processing.
344         $eventdata = new stdClass;
345         $eventdata->warnings = $warnings;
346         $eventdata->post_data = $data;
347         $eventdata->instance = $this;
348         $eventdata->changecount = $changecount;
350         $progressbar->end_html();
352         return $eventdata;
353     }
355     /**
356      * By default there are no options.
357      * @return array
358      */
359     public function options() {
360         return array();
361     }
363     /**
364      * Should we show the group selector?
365      * @return bool
366      */
367     public function display_group_selector() {
368         return true;
369     }
371     /**
372      * Should we show the next prev selector?
373      * @return bool
374      */
375     public function supports_next_prev() {
376         return true;
377     }