MDL-37810 roles: added manager case to test_get_user_roles_in_course()
[moodle.git] / calendar / classes / external / month_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 month 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 use core\external\exporter;
30 use renderer_base;
31 use moodle_url;
33 /**
34  * Class for displaying the month view.
35  *
36  * @package   core_calendar
37  * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>
38  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39  */
40 class month_exporter extends exporter {
42     /**
43      * @var \calendar_information $calendar The calendar to be rendered.
44      */
45     protected $calendar;
47     /**
48      * @var int $firstdayofweek The first day of the week.
49      */
50     protected $firstdayofweek;
52     /**
53      * @var moodle_url $url The URL for the events page.
54      */
55     protected $url;
57     /**
58      * Constructor for month_exporter.
59      *
60      * @param \calendar_information $calendar The calendar being represented
61      * @param \core_calendar\type_base $type The calendar type (e.g. Gregorian)
62      * @param array $related The related information
63      */
64     public function __construct(\calendar_information $calendar, \core_calendar\type_base $type, $related) {
65         $this->calendar = $calendar;
66         $this->firstdayofweek = $type->get_starting_weekday();
68         $this->url = new moodle_url('/calendar/view.php', [
69                 'view' => 'month',
70                 'time' => $calendar->time,
71             ]);
73         if ($this->calendar->courseid) {
74             $this->url->param('course', $this->calendar->courseid);
75         }
77         $related['type'] = $type;
79         $data = [
80             'url' => $this->url->out(false),
81         ];
83         parent::__construct($data, $related);
84     }
86     protected static function define_properties() {
87         return [
88             'url' => [
89                 'type' => PARAM_URL,
90             ],
91         ];
92     }
94     /**
95      * Return the list of additional properties.
96      *
97      * @return array
98      */
99     protected static function define_other_properties() {
100         return [
101             'courseid' => [
102                 'type' => PARAM_INT,
103             ],
104             'filter_selector' => [
105                 'type' => PARAM_RAW,
106             ],
107             'navigation' => [
108                 'type' => PARAM_RAW,
109             ],
110             'weeks' => [
111                 'type' => week_exporter::read_properties_definition(),
112                 'multiple' => true,
113             ],
114             'daynames' => [
115                 'type' => day_name_exporter::read_properties_definition(),
116                 'multiple' => true,
117             ],
118             'view' => [
119                 'type' => PARAM_ALPHA,
120             ],
121             'time' => [
122                 'type' => PARAM_INT,
123             ],
124             'periodname' => [
125                 // Note: We must use RAW here because the calendar type returns the formatted month name based on a
126                 // calendar format.
127                 'type' => PARAM_RAW,
128             ],
129             'previousperiod' => [
130                 'type' => PARAM_INT,
131             ],
132             'previousperiodname' => [
133                 // Note: We must use RAW here because the calendar type returns the formatted month name based on a
134                 // calendar format.
135                 'type' => PARAM_RAW,
136             ],
137             'nextperiod' => [
138                 'type' => PARAM_INT,
139             ],
140             'nextperiodname' => [
141                 // Note: We must use RAW here because the calendar type returns the formatted month name based on a
142                 // calendar format.
143                 'type' => PARAM_RAW,
144             ],
145             'larrow' => [
146                 // The left arrow defined by the theme.
147                 'type' => PARAM_RAW,
148             ],
149             'rarrow' => [
150                 // The right arrow defined by the theme.
151                 'type' => PARAM_RAW,
152             ],
153         ];
154     }
156     /**
157      * Get the additional values to inject while exporting.
158      *
159      * @param renderer_base $output The renderer.
160      * @return array Keys are the property names, values are their values.
161      */
162     protected function get_other_values(renderer_base $output) {
163         $previousperiod = $this->get_previous_month_timestamp();
164         $nextperiod = $this->get_next_month_timestamp();
166         return [
167             'courseid' => $this->calendar->courseid,
168             'filter_selector' => $this->get_course_filter_selector($output),
169             'navigation' => $this->get_navigation($output),
170             'weeks' => $this->get_weeks($output),
171             'daynames' => $this->get_day_names($output),
172             'view' => 'month',
173             'time' => $this->calendar->time,
174             'periodname' => userdate($this->calendar->time, get_string('strftimemonthyear')),
175             'previousperiod' => $previousperiod,
176             'previousperiodname' => userdate($previousperiod, get_string('strftimemonthyear')),
177             'nextperiod' => $nextperiod,
178             'nextperiodname' => userdate($nextperiod, get_string('strftimemonthyear')),
179             'larrow' => $output->larrow(),
180             'rarrow' => $output->rarrow(),
181         ];
182     }
184     /**
185      * Get the course filter selector.
186      *
187      * @param renderer_base $output
188      * @return string The html code for the course filter selector.
189      */
190     protected function get_course_filter_selector(renderer_base $output) {
191         $content = '';
192         $content .= $output->course_filter_selector($this->url, get_string('detailedmonthviewfor', 'calendar'));
193         if (calendar_user_can_add_event($this->calendar->course)) {
194             $content .= $output->add_event_button($this->calendar->courseid, 0, 0, 0, $this->calendar->time);
195         }
197         return $content;
198     }
200     /**
201      * Get the calendar navigation controls.
202      *
203      * @param renderer_base $output
204      * @return string The html code to the calendar top navigation.
205      */
206     protected function get_navigation(renderer_base $output) {
207         return calendar_top_controls('month', [
208             'id' => $this->calendar->courseid,
209             'time' => $this->calendar->time,
210         ]);
211     }
213     /**
214      * Get the list of day names for display, re-ordered from the first day
215      * of the week.
216      *
217      * @param   renderer_base $output
218      * @return  day_name_exporter[]
219      */
220     protected function get_day_names(renderer_base $output) {
221         $weekdays = $this->related['type']->get_weekdays();
222         $daysinweek = count($weekdays);
224         $daynames = [];
225         for ($i = 0; $i < $daysinweek; $i++) {
226             // Bump the currentdayno and ensure it loops.
227             $dayno = ($i + $this->firstdayofweek + $daysinweek) % $daysinweek;
228             $dayname = new day_name_exporter($dayno, $weekdays[$dayno]);
229             $daynames[] = $dayname->export($output);
230         }
232         return $daynames;
233     }
235     /**
236      * Get the list of week days, ordered into weeks and padded according
237      * to the value of the first day of the week.
238      *
239      * @param renderer_base $output
240      * @return array The list of weeks.
241      */
242     protected function get_weeks(renderer_base $output) {
243         $weeks = [];
244         $alldays = $this->get_days();
246         $daysinweek = count($this->related['type']->get_weekdays());
248         // Calculate which day number is the first, and last day of the week.
249         $firstdayofweek = $this->firstdayofweek;
250         $lastdayofweek = ($firstdayofweek + $daysinweek - 1) % $daysinweek;
252         // The first week is special as it may have padding at the beginning.
253         $day = reset($alldays);
254         $firstdayno = $day['wday'];
256         $prepadding = ($firstdayno + $daysinweek - 1) % $daysinweek;
257         $daysinfirstweek = $daysinweek - $prepadding;
258         $days = array_slice($alldays, 0, $daysinfirstweek);
259         $week = new week_exporter($this->calendar, $days, $prepadding, ($daysinweek - count($days) - $prepadding), $this->related);
260         $weeks[] = $week->export($output);
262         // Now chunk up the remaining day. and turn them into weeks.
263         $daychunks = array_chunk(array_slice($alldays, $daysinfirstweek), $daysinweek);
264         foreach ($daychunks as $days) {
265             $week = new week_exporter($this->calendar, $days, 0, ($daysinweek - count($days)), $this->related);
266             $weeks[] = $week->export($output);
267         }
269         return $weeks;
270     }
272     /**
273      * Get the list of days with the matching date array.
274      *
275      * @return array
276      */
277     protected function get_days() {
278         $date = $this->related['type']->timestamp_to_date_array($this->calendar->time);
279         $monthdays = $this->related['type']->get_num_days_in_month($date['year'], $date['mon']);
281         $days = [];
282         for ($dayno = 1; $dayno <= $monthdays; $dayno++) {
283             // Get the gregorian representation of the day.
284             $timestamp = $this->related['type']->convert_to_timestamp($date['year'], $date['mon'], $dayno);
286             $days[] = $this->related['type']->timestamp_to_date_array($timestamp);
287         }
289         return $days;
290     }
292     /**
293      * Returns a list of objects that are related.
294      *
295      * @return array
296      */
297     protected static function define_related() {
298         return [
299             'events' => '\core_calendar\local\event\entities\event_interface[]',
300             'cache' => '\core_calendar\external\events_related_objects_cache',
301             'type' => '\core_calendar\type_base',
302         ];
303     }
305     /**
306      * Get the previous month timestamp.
307      *
308      * @return int The previous month timestamp.
309      */
310     protected function get_previous_month_timestamp() {
311         $date = $this->related['type']->timestamp_to_date_array($this->calendar->time);
312         $month = calendar_sub_month($date['mon'], $date['year']);
313         $monthtime = $this->related['type']->convert_to_gregorian($month[1], $month[0], 1);
315         return make_timestamp($monthtime['year'], $monthtime['month'], $monthtime['day'], $monthtime['hour'], $monthtime['minute']);
316     }
318     /**
319      * Get the next month timestamp.
320      *
321      * @return int The next month timestamp.
322      */
323     protected function get_next_month_timestamp() {
324         $date = $this->related['type']->timestamp_to_date_array($this->calendar->time);
325         $month = calendar_add_month($date['mon'], $date['year']);
326         $monthtime = $this->related['type']->convert_to_gregorian($month[1], $month[0], 1);
328         return make_timestamp($monthtime['year'], $monthtime['month'], $monthtime['day'], $monthtime['hour'], $monthtime['minute']);
329     }