MDL-69521 core: Move all comments in code from 4.0 to 3.10
[moodle.git] / calendar / classes / external / calendar_event_exporter.php
CommitLineData
64ff737a
AN
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 * Contains event class for displaying a calendar event.
19 *
20 * @package core_calendar
21 * @copyright 2017 Ryan Wyllie <ryan@moodle.com>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25namespace core_calendar\external;
26
27defined('MOODLE_INTERNAL') || die();
28
c56dd950 29use \core_calendar\local\event\container;
64ff737a
AN
30use \core_course\external\course_summary_exporter;
31use \renderer_base;
63b13467 32require_once($CFG->dirroot . '/course/lib.php');
64ff737a
AN
33/**
34 * Class for displaying a calendar event.
35 *
36 * @package core_calendar
37 * @copyright 2017 Ryan Wyllie <ryan@moodle.com>
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 */
40class calendar_event_exporter extends event_exporter_base {
41
42 /**
43 * Return the list of additional properties.
44 *
45 * @return array
46 */
47 protected static function define_other_properties() {
1652934f
RW
48
49 $values = parent::define_other_properties();
50 $values['url'] = ['type' => PARAM_URL];
c8b6e9ab
AN
51 $values['islastday'] = [
52 'type' => PARAM_BOOL,
53 'default' => false,
54 ];
c8b6e9ab
AN
55 $values['popupname'] = [
56 'type' => PARAM_RAW,
57 ];
c56dd950
RW
58 $values['mindaytimestamp'] = [
59 'type' => PARAM_INT,
60 'optional' => true
61 ];
62 $values['mindayerror'] = [
63 'type' => PARAM_TEXT,
64 'optional' => true
65 ];
66 $values['maxdaytimestamp'] = [
67 'type' => PARAM_INT,
68 'optional' => true
69 ];
70 $values['maxdayerror'] = [
71 'type' => PARAM_TEXT,
72 'optional' => true
73 ];
6688ae2b
RW
74 $values['draggable'] = [
75 'type' => PARAM_BOOL,
76 'default' => false
77 ];
1652934f
RW
78
79 return $values;
64ff737a
AN
80 }
81
82 /**
83 * Get the additional values to inject while exporting.
84 *
85 * @param renderer_base $output The renderer.
86 * @return array Keys are the property names, values are their values.
87 */
88 protected function get_other_values(renderer_base $output) {
c8b6e9ab
AN
89 global $CFG;
90
64ff737a 91 $values = parent::get_other_values($output);
63b13467 92 $event = $this->event;
bb4691ec
RW
93 $course = $this->related['course'];
94 $hascourse = !empty($course);
64ff737a 95
6688ae2b
RW
96 // By default all events that can be edited are
97 // draggable.
98 $values['draggable'] = $values['canedit'];
99
63b13467
SL
100 if ($moduleproxy = $event->get_course_module()) {
101 $modulename = $moduleproxy->get('modname');
102 $moduleid = $moduleproxy->get('id');
103 $url = new \moodle_url(sprintf('/mod/%s/view.php', $modulename), ['id' => $moduleid]);
64ff737a 104
63b13467
SL
105 // Build edit event url for action events.
106 $params = array('update' => $moduleid, 'return' => true, 'sesskey' => sesskey());
107 $editurl = new \moodle_url('/course/mod.php', $params);
108 $values['editurl'] = $editurl->out(false);
d0e56d84
AN
109 } else if ($event->get_type() == 'category') {
110 $url = $event->get_category()->get_proxied_instance()->get_view_link();
63b13467 111 } else {
bb4691ec 112 $url = course_get_url($hascourse ? $course : SITEID);
63b13467 113 }
c56dd950 114
63b13467 115 $values['url'] = $url->out(false);
c8b6e9ab
AN
116 $values['islastday'] = false;
117 $today = $this->related['type']->timestamp_to_date_array($this->related['today']);
118
119 $values['popupname'] = $this->event->get_name();
120
121 $times = $this->event->get_times();
122 if ($duration = $times->get_duration()) {
123 $enddate = $this->related['type']->timestamp_to_date_array($times->get_end_time()->getTimestamp());
124 $values['islastday'] = true;
125 $values['islastday'] = $values['islastday'] && $enddate['year'] == $today['year'];
126 $values['islastday'] = $values['islastday'] && $enddate['mon'] == $today['mon'];
127 $values['islastday'] = $values['islastday'] && $enddate['mday'] == $today['mday'];
128 }
129
130 $subscription = $this->event->get_subscription();
131 if ($subscription && !empty($subscription->get('id')) && $CFG->calendar_showicalsource) {
132 $a = (object) [
133 'name' => $values['popupname'],
134 'source' => $subscription->get('name'),
135 ];
136 $values['popupname'] = get_string('namewithsource', 'calendar', $a);
137 } else {
138 if ($values['islastday']) {
139 $startdate = $this->related['type']->timestamp_to_date_array($times->get_start_time()->getTimestamp());
140 $samedate = true;
141 $samedate = $samedate && $startdate['mon'] == $enddate['mon'];
142 $samedate = $samedate && $startdate['year'] == $enddate['year'];
143 $samedate = $samedate && $startdate['mday'] == $enddate['mday'];
144
145 if (!$samedate) {
146 $values['popupname'] = get_string('eventendtimewrapped', 'calendar', $values['popupname']);
147 }
148 }
149 }
150
5ba6507e
AN
151 // Include category name into the event name, if applicable.
152 $proxy = $this->event->get_category();
153 if ($proxy && $proxy->get('id')) {
154 $category = $proxy->get_proxied_instance();
155 $eventnameparams = (object) [
156 'name' => $values['popupname'],
157 'category' => $category->get_formatted_name(),
158 ];
159 $values['popupname'] = get_string('eventnameandcategory', 'calendar', $eventnameparams);
160 }
161
c8b6e9ab 162 // Include course's shortname into the event name, if applicable.
bb4691ec 163 if ($hascourse && $course->id !== SITEID) {
c8b6e9ab
AN
164 $eventnameparams = (object) [
165 'name' => $values['popupname'],
6b024885 166 'course' => $values['course']->shortname,
c8b6e9ab
AN
167 ];
168 $values['popupname'] = get_string('eventnameandcourse', 'calendar', $eventnameparams);
169 }
170
c56dd950
RW
171 if ($event->get_course_module()) {
172 $values = array_merge($values, $this->get_module_timestamp_limits($event));
b0e5f229
SR
173 } else if ($hascourse && $course->id != SITEID && empty($event->get_group())) {
174 // This is a course event.
175 $values = array_merge($values, $this->get_course_timestamp_limits($event));
c56dd950
RW
176 }
177
64ff737a
AN
178 return $values;
179 }
180
181 /**
182 * Returns a list of objects that are related.
183 *
184 * @return array
185 */
186 protected static function define_related() {
187 $related = parent::define_related();
188 $related['daylink'] = \moodle_url::class;
c8b6e9ab
AN
189 $related['type'] = '\core_calendar\type_base';
190 $related['today'] = 'int';
3152de6a 191 $related['moduleinstance'] = 'stdClass?';
64ff737a
AN
192
193 return $related;
194 }
c8b6e9ab
AN
195
196 /**
197 * Return the normalised event type.
198 * Activity events are normalised to be course events.
199 *
200 * @return string
201 */
202 public function get_calendar_event_type() {
70569dad
AN
203 if ($this->event->get_course_module()) {
204 return 'course';
c8b6e9ab
AN
205 }
206
70569dad 207 return $this->event->get_type();
c8b6e9ab 208 }
c56dd950 209
b0e5f229
SR
210 /**
211 * Return the set of minimum and maximum date timestamp values
212 * for the given event.
213 *
214 * @param event_interface $event
215 * @return array
216 */
217 protected function get_course_timestamp_limits($event) {
218 $values = [];
219 $mapper = container::get_event_mapper();
220 $starttime = $event->get_times()->get_start_time();
221
222 list($min, $max) = component_callback(
223 'core_course',
224 'core_calendar_get_valid_event_timestart_range',
225 [$mapper->from_event_to_legacy_event($event), $event->get_course()->get_proxied_instance()],
226 [false, false]
227 );
228
229 // The callback will return false for either of the
230 // min or max cutoffs to indicate that there are no
231 // valid timestart values. In which case the event is
232 // not draggable.
233 if ($min === false || $max === false) {
234 return ['draggable' => false];
235 }
236
237 if ($min) {
238 $values = array_merge($values, $this->get_timestamp_min_limit($starttime, $min));
239 }
240
241 if ($max) {
242 $values = array_merge($values, $this->get_timestamp_max_limit($starttime, $max));
243 }
244
245 return $values;
246 }
247
c56dd950
RW
248 /**
249 * Return the set of minimum and maximum date timestamp values
250 * for the given event.
251 *
252 * @param event_interface $event
253 * @return array
254 */
255 protected function get_module_timestamp_limits($event) {
256 $values = [];
257 $mapper = container::get_event_mapper();
258 $starttime = $event->get_times()->get_start_time();
478b1d19 259 $modname = $event->get_course_module()->get('modname');
3152de6a 260 $moduleinstance = $this->related['moduleinstance'];
c56dd950
RW
261
262 list($min, $max) = component_callback(
478b1d19 263 'mod_' . $modname,
c56dd950 264 'core_calendar_get_valid_event_timestart_range',
478b1d19 265 [$mapper->from_event_to_legacy_event($event), $moduleinstance],
6688ae2b 266 [false, false]
c56dd950
RW
267 );
268
6688ae2b
RW
269 // The callback will return false for either of the
270 // min or max cutoffs to indicate that there are no
271 // valid timestart values. In which case the event is
272 // not draggable.
273 if ($min === false || $max === false) {
274 return ['draggable' => false];
275 }
276
c56dd950 277 if ($min) {
084d5ee4 278 $values = array_merge($values, $this->get_timestamp_min_limit($starttime, $min));
c56dd950
RW
279 }
280
281 if ($max) {
084d5ee4 282 $values = array_merge($values, $this->get_timestamp_max_limit($starttime, $max));
c56dd950
RW
283 }
284
285 return $values;
286 }
287
288 /**
289 * Get the correct minimum midnight day limit based on the event start time
084d5ee4 290 * and the minimum timestamp limit of what the event belongs to.
c56dd950
RW
291 *
292 * @param DateTimeInterface $starttime The event start time
293 * @param array $min The module's minimum limit for the event
084d5ee4 294 * @return array Returns an array with mindaytimestamp and mindayerror keys.
c56dd950 295 */
084d5ee4 296 protected function get_timestamp_min_limit(\DateTimeInterface $starttime, $min) {
c56dd950
RW
297 // We need to check that the minimum valid time is earlier in the
298 // day than the current event time so that if the user drags and drops
299 // the event to this day (which changes the date but not the time) it
300 // will result in a valid time start for the event.
301 //
302 // For example:
303 // An event that starts on 2017-01-10 08:00 with a minimum cutoff
304 // of 2017-01-05 09:00 means that 2017-01-05 is not a valid start day
305 // for the drag and drop because it would result in the event start time
306 // being set to 2017-01-05 08:00, which is invalid. Instead the minimum
307 // valid start day would be 2017-01-06.
308 $values = [];
309 $timestamp = $min[0];
310 $errorstring = $min[1];
311 $mindate = (new \DateTimeImmutable())->setTimestamp($timestamp);
312 $minstart = $mindate->setTime(
313 $starttime->format('H'),
314 $starttime->format('i'),
315 $starttime->format('s')
316 );
317 $midnight = usergetmidnight($timestamp);
318
319 if ($mindate <= $minstart) {
320 $values['mindaytimestamp'] = $midnight;
321 } else {
322 $tomorrow = (new \DateTime())->setTimestamp($midnight)->modify('+1 day');
323 $values['mindaytimestamp'] = $tomorrow->getTimestamp();
324 }
325
326 // Get the human readable error message to display if the min day
327 // timestamp is violated.
328 $values['mindayerror'] = $errorstring;
329 return $values;
330 }
331
332 /**
333 * Get the correct maximum midnight day limit based on the event start time
084d5ee4 334 * and the maximum timestamp limit of what the event belongs to.
c56dd950
RW
335 *
336 * @param DateTimeInterface $starttime The event start time
337 * @param array $max The module's maximum limit for the event
084d5ee4 338 * @return array Returns an array with maxdaytimestamp and maxdayerror keys.
c56dd950 339 */
084d5ee4 340 protected function get_timestamp_max_limit(\DateTimeInterface $starttime, $max) {
c56dd950
RW
341 // We're doing a similar calculation here as we are for the minimum
342 // day timestamp. See the explanation above.
084d5ee4 343 $values = [];
c56dd950
RW
344 $timestamp = $max[0];
345 $errorstring = $max[1];
346 $maxdate = (new \DateTimeImmutable())->setTimestamp($timestamp);
347 $maxstart = $maxdate->setTime(
348 $starttime->format('H'),
349 $starttime->format('i'),
350 $starttime->format('s')
351 );
352 $midnight = usergetmidnight($timestamp);
353
354 if ($maxdate >= $maxstart) {
355 $values['maxdaytimestamp'] = $midnight;
356 } else {
357 $yesterday = (new \DateTime())->setTimestamp($midnight)->modify('-1 day');
358 $values['maxdaytimestamp'] = $yesterday->getTimestamp();
359 }
360
361 // Get the human readable error message to display if the max day
362 // timestamp is violated.
363 $values['maxdayerror'] = $errorstring;
364 return $values;
365 }
084d5ee4
SR
366
367 /**
368 * Get the correct minimum midnight day limit based on the event start time
369 * and the module's minimum timestamp limit.
370 *
371 * @deprecated since Moodle 3.6. Please use get_timestamp_min_limit().
709b46db 372 * @todo final deprecation. To be removed in Moodle 3.10
084d5ee4
SR
373 * @param DateTimeInterface $starttime The event start time
374 * @param array $min The module's minimum limit for the event
375 * @return array Returns an array with mindaytimestamp and mindayerror keys.
376 */
377 protected function get_module_timestamp_min_limit(\DateTimeInterface $starttime, $min) {
378 debugging('get_module_timestamp_min_limit() has been deprecated. Please call get_timestamp_min_limit() instead.',
379 DEBUG_DEVELOPER);
380 return $this->get_timestamp_min_limit($starttime, $min);
381 }
382
383 /**
384 * Get the correct maximum midnight day limit based on the event start time
385 * and the module's maximum timestamp limit.
386 *
387 * @deprecated since Moodle 3.6. Please use get_timestamp_max_limit().
709b46db 388 * @todo final deprecation. To be removed in Moodle 3.10
084d5ee4
SR
389 * @param DateTimeInterface $starttime The event start time
390 * @param array $max The module's maximum limit for the event
391 * @return array Returns an array with maxdaytimestamp and maxdayerror keys.
392 */
393 protected function get_module_timestamp_max_limit(\DateTimeInterface $starttime, $max) {
394 debugging('get_module_timestamp_max_limit() has been deprecated. Please call get_timestamp_max_limit() instead.',
395 DEBUG_DEVELOPER);
396 return $this->get_timestamp_max_limit($starttime, $max);
397 }
64ff737a 398}