2965451c0860fbd8747643a8e499d40a7d0003d5
[moodle.git] / calendar / classes / external / day_exporter.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  * Contains event class for displaying the day view.
19  *
20  * @package   core_calendar
21  * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>
22  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 namespace core_calendar\external;
27 defined('MOODLE_INTERNAL') || die();
29 require_once($CFG->dirroot . '/calendar/lib.php');
31 use core\external\exporter;
32 use renderer_base;
33 use moodle_url;
35 /**
36  * Class for displaying the day view.
37  *
38  * @package   core_calendar
39  * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>
40  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41  */
42 class day_exporter extends exporter {
44     /**
45      * @var \calendar_information $calendar The calendar being displayed.
46      */
47     protected $calendar;
49     /**
50      * @var moodle_url
51      */
52     protected $url;
53     /**
54      * Constructor.
55      *
56      * @param \calendar_information $calendar The calendar information for the period being displayed
57      * @param mixed $data Either an stdClass or an array of values.
58      * @param array $related Related objects.
59      */
60     public function __construct(\calendar_information $calendar, $data, $related) {
61         $this->calendar = $calendar;
62         $this->url = new moodle_url('/calendar/view.php', [
63             'view' => 'day',
64             'time' => $calendar->time,
65             'course' => $this->calendar->course->id,
66         ]);
67         parent::__construct($data, $related);
68     }
70     /**
71      * Return the list of properties.
72      *
73      * @return array
74      */
75     protected static function define_properties() {
76         // These are the default properties as returned by getuserdate()
77         // but without the formatted month and week names.
78         return [
79             'seconds' => [
80                 'type' => PARAM_INT,
81             ],
82             'minutes' => [
83                 'type' => PARAM_INT,
84             ],
85             'hours' => [
86                 'type' => PARAM_INT,
87             ],
88             'mday' => [
89                 'type' => PARAM_INT,
90             ],
91             'wday' => [
92                 'type' => PARAM_INT,
93             ],
94             'year' => [
95                 'type' => PARAM_INT,
96             ],
97             'yday' => [
98                 'type' => PARAM_INT,
99             ],
100         ];
101     }
103     /**
104      * Return the list of additional properties.
105      *
106      * @return array
107      */
108     protected static function define_other_properties() {
109         return [
110             'timestamp' => [
111                 'type' => PARAM_INT,
112             ],
113             'neweventtimestamp' => [
114                 'type' => PARAM_INT,
115             ],
116             'viewdaylink' => [
117                 'type' => PARAM_URL,
118                 'optional' => true,
119             ],
120             'events' => [
121                 'type' => calendar_event_exporter::read_properties_definition(),
122                 'multiple' => true,
123             ],
124             'calendareventtypes' => [
125                 'type' => PARAM_RAW,
126                 'multiple' => true,
127             ],
128             'previousperiod' => [
129                 'type' => PARAM_INT,
130             ],
131             'nextperiod' => [
132                 'type' => PARAM_INT,
133             ],
134             'navigation' => [
135                 'type' => PARAM_RAW,
136             ],
137             'popovertitle' => [
138                 'type' => PARAM_RAW,
139                 'default' => '',
140             ],
141             'haslastdayofevent' => [
142                 'type' => PARAM_BOOL,
143                 'default' => false,
144             ],
145             'filter_selector' => [
146                 'type' => PARAM_RAW,
147             ],
148             'new_event_button' => [
149                 'type' => PARAM_RAW,
150             ],
151         ];
152     }
154     /**
155      * Get the additional values to inject while exporting.
156      *
157      * @param renderer_base $output The renderer.
158      * @return array Keys are the property names, values are their values.
159      */
160     protected function get_other_values(renderer_base $output) {
161         $daytimestamp = $this->calendar->time;
162         $timestamp = $this->data[0];
163         // Need to account for user's timezone.
164         $usernow = usergetdate(time());
165         $today = new \DateTimeImmutable();
166         // The start time should use the day's date but the current
167         // time of the day (adjusted for user's timezone).
168         $neweventstarttime = $today->setTimestamp($timestamp)->setTime(
169             $usernow['hours'],
170             $usernow['minutes'],
171             $usernow['seconds']
172         );
174         $return = [
175             'timestamp' => $timestamp,
176             'neweventtimestamp' => $neweventstarttime->getTimestamp(),
177             'previousperiod' => $this->get_previous_day_timestamp($daytimestamp),
178             'nextperiod' => $this->get_next_day_timestamp($daytimestamp),
179             'navigation' => $this->get_navigation(),
180             'filter_selector' => $this->get_course_filter_selector($output),
181             'new_event_button' => $this->get_new_event_button(),
182         ];
184         $return['viewdaylink'] = $this->url->out(false);
186         $cache = $this->related['cache'];
187         $eventexporters = array_map(function($event) use ($cache, $output) {
188             $context = $cache->get_context($event);
189             $course = $cache->get_course($event);
190             $exporter = new calendar_event_exporter($event, [
191                 'context' => $context,
192                 'course' => $course,
193                 'daylink' => $this->url,
194                 'type' => $this->related['type'],
195                 'today' => $this->data[0],
196             ]);
198             return $exporter;
199         }, $this->related['events']);
201         $return['events'] = array_map(function($exporter) use ($output) {
202             return $exporter->export($output);
203         }, $eventexporters);
205         $return['calendareventtypes'] = array_map(function($exporter) {
206             return $exporter->get_calendar_event_type();
207         }, $eventexporters);
208         $return['calendareventtypes'] = array_values(array_unique($return['calendareventtypes']));
210         $return['haslastdayofevent'] = false;
211         foreach ($return['events'] as $event) {
212             if ($event->islastday) {
213                 $return['haslastdayofevent'] = true;
214                 break;
215             }
216         }
218         return $return;
219     }
221     /**
222      * Returns a list of objects that are related.
223      *
224      * @return array
225      */
226     protected static function define_related() {
227         return [
228             'events' => '\core_calendar\local\event\entities\event_interface[]',
229             'cache' => '\core_calendar\external\events_related_objects_cache',
230             'type' => '\core_calendar\type_base',
231         ];
232     }
234     /**
235      * Get the previous day timestamp.
236      *
237      * @param int $daytimestamp The current day timestamp.
238      * @return int The previous day timestamp.
239      */
240     protected function get_previous_day_timestamp($daytimestamp) {
241         return $this->related['type']->get_prev_day($daytimestamp);
242     }
244     /**
245      * Get the next day timestamp.
246      *
247      * @param int $daytimestamp The current day timestamp.
248      * @return int The next day timestamp.
249      */
250     protected function get_next_day_timestamp($daytimestamp) {
251         return $this->related['type']->get_next_day($daytimestamp);
252     }
254     /**
255      * Get the calendar navigation controls.
256      *
257      * @return string The html code to the calendar top navigation.
258      */
259     protected function get_navigation() {
260         return calendar_top_controls('day', [
261             'id' => $this->calendar->courseid,
262             'time' => $this->calendar->time,
263         ]);
264     }
266     /**
267      * Get the course filter selector.
268      *
269      * This is a temporary solution, this code will be removed by MDL-60096.
270      *
271      * @param renderer_base $output
272      * @return string The html code for the course filter selector.
273      */
274     protected function get_course_filter_selector(renderer_base $output) {
275         global $CFG;
276         // TODO remove this code on MDL-60096.
277         if (!isloggedin() or isguestuser()) {
278             return '';
279         }
281         if (has_capability('moodle/calendar:manageentries', \context_system::instance()) && !empty($CFG->calendar_adminseesall)) {
282             $courses = get_courses('all', 'c.shortname', 'c.id, c.shortname');
283         } else {
284             $courses = enrol_get_my_courses();
285         }
287         unset($courses[SITEID]);
289         $courseoptions = array();
290         $courseoptions[SITEID] = get_string('fulllistofcourses');
291         foreach ($courses as $course) {
292             $coursecontext = \context_course::instance($course->id);
293             $courseoptions[$course->id] = format_string($course->shortname, true, array('context' => $coursecontext));
294         }
296         if ($this->calendar->courseid !== SITEID) {
297             $selected = $this->calendar->courseid;
298         } else {
299             $selected = '';
300         }
302         $courseurl = new moodle_url($this->url);
303         $courseurl->remove_params('course');
304         $select = new \single_select($courseurl, 'courseselect', $courseoptions, $selected, null);
305         $select->class = 'm-r-1';
306         $label = get_string('dayviewfor', 'calendar');
307         if ($label !== null) {
308             $select->set_label($label);
309         } else {
310             $select->set_label(get_string('listofcourses'), array('class' => 'accesshide'));
311         }
313         return $output->render($select);
314     }
316     /**
317      * Get the course filter selector.
318      *
319      * This is a temporary solution, this code will be removed by MDL-60096.
320      *
321      * @return string The html code for the course filter selector.
322      */
323     protected function get_new_event_button() {
324         // TODO remove this code on MDL-60096.
325         $output = \html_writer::start_tag('div', array('class' => 'buttons'));
326         $output .= \html_writer::start_tag('form',
327                 array('action' => CALENDAR_URL . 'event.php', 'method' => 'get'));
328         $output .= \html_writer::start_tag('div');
329         $output .= \html_writer::empty_tag('input',
330                 array('type' => 'hidden', 'name' => 'action', 'value' => 'new'));
331         $output .= \html_writer::empty_tag('input',
332                 array('type' => 'hidden', 'name' => 'course', 'value' => $this->calendar->courseid));
333         $output .= \html_writer::empty_tag('input',
334                 array('type' => 'hidden', 'name' => 'time', 'value' => $this->calendar->time));
335         $attributes = array('type' => 'submit', 'value' => get_string('newevent', 'calendar'),
336             'class' => 'btn btn-secondary');
337         $output .= \html_writer::empty_tag('input', $attributes);
338         $output .= \html_writer::end_tag('div');
339         $output .= \html_writer::end_tag('form');
340         $output .= \html_writer::end_tag('div');
341         return $output;
342     }