Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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 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
 */
24
 
25
namespace core_calendar\external;
26
 
27
defined('MOODLE_INTERNAL') || die();
28
 
29
use core\external\exporter;
30
use renderer_base;
31
use moodle_url;
32
 
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 {
41
 
42
    /** @var int Number of calendar instances displayed. */
43
    protected static $calendarinstances = 0;
44
 
45
    /** @var int This calendar instance's ID. */
46
    protected $calendarinstanceid = 0;
47
 
48
    /**
49
     * @var \calendar_information $calendar The calendar to be rendered.
50
     */
51
    protected $calendar;
52
 
53
    /**
54
     * @var int $firstdayofweek The first day of the week.
55
     */
56
    protected $firstdayofweek;
57
 
58
    /**
59
     * @var moodle_url $url The URL for the events page.
60
     */
61
    protected $url;
62
 
63
    /**
64
     * @var bool $includenavigation Whether navigation should be included on the output.
65
     */
66
    protected $includenavigation = true;
67
 
68
    /**
69
     * @var bool $initialeventsloaded Whether the events have been loaded for this month.
70
     */
71
    protected $initialeventsloaded = true;
72
 
73
    /**
74
     * @var bool $showcoursefilter Whether to render the course filter selector as well.
75
     */
76
    protected $showcoursefilter = false;
77
 
78
    /**
79
     * Constructor for month_exporter.
80
     *
81
     * @param \calendar_information $calendar The calendar being represented
82
     * @param \core_calendar\type_base $type The calendar type (e.g. Gregorian)
83
     * @param array $related The related information
84
     */
85
    public function __construct(\calendar_information $calendar, \core_calendar\type_base $type, $related) {
86
        // Increment the calendar instances count on initialisation.
87
        self::$calendarinstances++;
88
        // Assign this instance an ID based on the latest calendar instances count.
89
        $this->calendarinstanceid = self::$calendarinstances;
90
        $this->calendar = $calendar;
91
        $this->firstdayofweek = $type->get_starting_weekday();
92
 
93
        $this->url = new moodle_url('/calendar/view.php', [
94
                'view' => 'month',
95
                'time' => $calendar->time,
96
            ]);
97
 
98
        if ($this->calendar->course && SITEID !== $this->calendar->course->id) {
99
            $this->url->param('course', $this->calendar->course->id);
100
        } else if ($this->calendar->categoryid) {
101
            $this->url->param('category', $this->calendar->categoryid);
102
        }
103
 
104
        $related['type'] = $type;
105
 
106
        $data = [
107
            'url' => $this->url->out(false),
108
        ];
109
 
110
        parent::__construct($data, $related);
111
    }
112
 
113
    protected static function define_properties() {
114
        return [
115
            'url' => [
116
                'type' => PARAM_URL,
117
            ],
118
        ];
119
    }
120
 
121
    /**
122
     * Return the list of additional properties.
123
     *
124
     * @return array
125
     */
126
    protected static function define_other_properties() {
127
        return [
128
            'courseid' => [
129
                'type' => PARAM_INT,
130
            ],
131
            'categoryid' => [
132
                'type' => PARAM_INT,
133
                'optional' => true,
134
                'default' => 0,
135
            ],
136
            'filter_selector' => [
137
                'type' => PARAM_RAW,
138
                'optional' => true,
139
            ],
140
            'weeks' => [
141
                'type' => week_exporter::read_properties_definition(),
142
                'multiple' => true,
143
            ],
144
            'daynames' => [
145
                'type' => day_name_exporter::read_properties_definition(),
146
                'multiple' => true,
147
            ],
148
            'view' => [
149
                'type' => PARAM_ALPHA,
150
            ],
151
            'date' => [
152
                'type' => date_exporter::read_properties_definition(),
153
            ],
154
            'periodname' => [
155
                // Note: We must use RAW here because the calendar type returns the formatted month name based on a
156
                // calendar format.
157
                'type' => PARAM_RAW,
158
            ],
159
            'includenavigation' => [
160
                'type' => PARAM_BOOL,
161
                'default' => true,
162
            ],
163
            // Tracks whether the first set of events have been loaded and provided
164
            // to the exporter.
165
            'initialeventsloaded' => [
166
                'type' => PARAM_BOOL,
167
                'default' => true,
168
            ],
169
            'previousperiod' => [
170
                'type' => date_exporter::read_properties_definition(),
171
            ],
172
            'previousperiodlink' => [
173
                'type' => PARAM_URL,
174
            ],
175
            'previousperiodname' => [
176
                // Note: We must use RAW here because the calendar type returns the formatted month name based on a
177
                // calendar format.
178
                'type' => PARAM_RAW,
179
            ],
180
            'nextperiod' => [
181
                'type' => date_exporter::read_properties_definition(),
182
            ],
183
            'nextperiodname' => [
184
                // Note: We must use RAW here because the calendar type returns the formatted month name based on a
185
                // calendar format.
186
                'type' => PARAM_RAW,
187
            ],
188
            'nextperiodlink' => [
189
                'type' => PARAM_URL,
190
            ],
191
            'larrow' => [
192
                // The left arrow defined by the theme.
193
                'type' => PARAM_RAW,
194
            ],
195
            'rarrow' => [
196
                // The right arrow defined by the theme.
197
                'type' => PARAM_RAW,
198
            ],
199
            'defaulteventcontext' => [
200
                'type' => PARAM_INT,
201
                'default' => 0,
202
            ],
203
            'calendarinstanceid' => [
204
                'type' => PARAM_INT,
205
                'default' => 0,
206
            ],
207
            'viewingmonth' => [
208
                'type' => PARAM_BOOL,
209
                'default' => true,
210
            ],
211
            'showviewselector' => [
212
                'type' => PARAM_BOOL,
213
                'default' => true,
214
            ],
215
            'viewinginblock' => [
216
                'type' => PARAM_BOOL,
217
                'default' => false,
218
            ],
219
        ];
220
    }
221
 
222
    /**
223
     * Get the additional values to inject while exporting.
224
     *
225
     * @param renderer_base $output The renderer.
226
     * @return array Keys are the property names, values are their values.
227
     */
228
    protected function get_other_values(renderer_base $output) {
229
        $previousperiod = $this->get_previous_month_data();
230
        $nextperiod = $this->get_next_month_data();
231
        $date = $this->related['type']->timestamp_to_date_array($this->calendar->time);
232
 
233
        $nextperiodlink = new moodle_url($this->url);
234
        $nextperiodlink->param('time', $nextperiod[0]);
235
 
236
        $previousperiodlink = new moodle_url($this->url);
237
        $previousperiodlink->param('time', $previousperiod[0]);
238
 
239
        $viewmode = $this->calendar->get_viewmode() ?? 'month';
240
 
241
        $return = [
242
            'courseid' => $this->calendar->courseid,
243
            'weeks' => $this->get_weeks($output),
244
            'daynames' => $this->get_day_names($output),
245
            'view' => $viewmode,
246
            'date' => (new date_exporter($date))->export($output),
247
            'periodname' => userdate($this->calendar->time, get_string('strftimemonthyear')),
248
            'previousperiod' => (new date_exporter($previousperiod))->export($output),
249
            'previousperiodname' => userdate($previousperiod[0], get_string('strftimemonth')),
250
            'previousperiodlink' => $previousperiodlink->out(false),
251
            'nextperiod' => (new date_exporter($nextperiod))->export($output),
252
            'nextperiodname' => userdate($nextperiod[0], get_string('strftimemonth')),
253
            'nextperiodlink' => $nextperiodlink->out(false),
254
            'larrow' => $output->larrow(),
255
            'rarrow' => $output->rarrow(),
256
            'includenavigation' => $this->includenavigation,
257
            'initialeventsloaded' => $this->initialeventsloaded,
258
            'calendarinstanceid' => $this->calendarinstanceid,
259
            'showviewselector' => $viewmode === 'month',
260
            'viewinginblock' => $viewmode === 'monthblock',
261
        ];
262
 
263
        if ($this->showcoursefilter) {
264
            $return['filter_selector'] = $this->get_course_filter_selector($output);
265
        }
266
 
267
        if ($context = $this->get_default_add_context()) {
268
            $return['defaulteventcontext'] = $context->id;
269
        }
270
 
271
        if ($this->calendar->categoryid) {
272
            $return['categoryid'] = $this->calendar->categoryid;
273
        }
274
 
275
        return $return;
276
    }
277
 
278
    /**
279
     * Get the course filter selector.
280
     *
281
     * @param renderer_base $output
282
     * @return string The html code for the course filter selector.
283
     */
284
    protected function get_course_filter_selector(renderer_base $output) {
285
        $content = '';
286
        $content .= $output->course_filter_selector($this->url, '', $this->calendar->course->id, $this->calendarinstanceid);
287
 
288
        return $content;
289
    }
290
 
291
    /**
292
     * Get the list of day names for display, re-ordered from the first day
293
     * of the week.
294
     *
295
     * @param   renderer_base $output
296
     * @return  day_name_exporter[]
297
     */
298
    protected function get_day_names(renderer_base $output) {
299
        $weekdays = $this->related['type']->get_weekdays();
300
        $daysinweek = count($weekdays);
301
 
302
        $daynames = [];
303
        for ($i = 0; $i < $daysinweek; $i++) {
304
            // Bump the currentdayno and ensure it loops.
305
            $dayno = ($i + $this->firstdayofweek + $daysinweek) % $daysinweek;
306
            $dayname = new day_name_exporter($dayno, $weekdays[$dayno]);
307
            $daynames[] = $dayname->export($output);
308
        }
309
 
310
        return $daynames;
311
    }
312
 
313
    /**
314
     * Get the list of week days, ordered into weeks and padded according
315
     * to the value of the first day of the week.
316
     *
317
     * @param renderer_base $output
318
     * @return array The list of weeks.
319
     */
320
    protected function get_weeks(renderer_base $output) {
321
        $weeks = [];
322
        $alldays = $this->get_days();
323
 
324
        $daysinweek = count($this->related['type']->get_weekdays());
325
 
326
        // Calculate which day number is the first, and last day of the week.
327
        $firstdayofweek = $this->firstdayofweek;
328
 
329
        // The first week is special as it may have padding at the beginning.
330
        $day = reset($alldays);
331
        $firstdayno = $day['wday'];
332
 
333
        $prepadding = ($firstdayno + $daysinweek - $firstdayofweek) % $daysinweek;
334
        $daysinfirstweek = $daysinweek - $prepadding;
335
        $days = array_slice($alldays, 0, $daysinfirstweek);
336
        $week = new week_exporter($this->calendar, $days, $prepadding, ($daysinweek - count($days) - $prepadding), $this->related);
337
        $weeks[] = $week->export($output);
338
 
339
        // Now chunk up the remaining day. and turn them into weeks.
340
        $daychunks = array_chunk(array_slice($alldays, $daysinfirstweek), $daysinweek);
341
        foreach ($daychunks as $days) {
342
            $week = new week_exporter($this->calendar, $days, 0, ($daysinweek - count($days)), $this->related);
343
            $weeks[] = $week->export($output);
344
        }
345
 
346
        return $weeks;
347
    }
348
 
349
    /**
350
     * Get the list of days with the matching date array.
351
     *
352
     * @return array
353
     */
354
    protected function get_days() {
355
        $date = $this->related['type']->timestamp_to_date_array($this->calendar->time);
356
        $monthdays = $this->related['type']->get_num_days_in_month($date['year'], $date['mon']);
357
 
358
        $days = [];
359
        for ($dayno = 1; $dayno <= $monthdays; $dayno++) {
360
            // Get the gregorian representation of the day.
361
            $timestamp = $this->related['type']->convert_to_timestamp($date['year'], $date['mon'], $dayno);
362
 
363
            $days[] = $this->related['type']->timestamp_to_date_array($timestamp);
364
        }
365
 
366
        return $days;
367
    }
368
 
369
    /**
370
     * Returns a list of objects that are related.
371
     *
372
     * @return array
373
     */
374
    protected static function define_related() {
375
        return [
376
            'events' => '\core_calendar\local\event\entities\event_interface[]',
377
            'cache' => '\core_calendar\external\events_related_objects_cache',
378
            'type' => '\core_calendar\type_base',
379
        ];
380
    }
381
 
382
    /**
383
     * Get the current month timestamp.
384
     *
385
     * @return int The month timestamp.
386
     */
387
    protected function get_month_data() {
388
        $date = $this->related['type']->timestamp_to_date_array($this->calendar->time);
389
        $monthtime = $this->related['type']->convert_to_gregorian($date['year'], $date['month'], 1);
390
 
391
        return make_timestamp($monthtime['year'], $monthtime['month']);
392
    }
393
 
394
    /**
395
     * Get the previous month timestamp.
396
     *
397
     * @return int The previous month timestamp.
398
     */
399
    protected function get_previous_month_data() {
400
        $type = $this->related['type'];
401
        $date = $type->timestamp_to_date_array($this->calendar->time);
402
        list($date['mon'], $date['year']) = $type->get_prev_month($date['year'], $date['mon']);
403
        $time = $type->convert_to_timestamp($date['year'], $date['mon'], 1);
404
 
405
        return $type->timestamp_to_date_array($time);
406
    }
407
 
408
    /**
409
     * Get the next month timestamp.
410
     *
411
     * @return int The next month timestamp.
412
     */
413
    protected function get_next_month_data() {
414
        $type = $this->related['type'];
415
        $date = $type->timestamp_to_date_array($this->calendar->time);
416
        list($date['mon'], $date['year']) = $type->get_next_month($date['year'], $date['mon']);
417
        $time = $type->convert_to_timestamp($date['year'], $date['mon'], 1);
418
 
419
        return $type->timestamp_to_date_array($time);
420
    }
421
 
422
    /**
423
     * Set whether the navigation should be shown.
424
     *
425
     * @param   bool    $include
426
     * @return  $this
427
     */
428
    public function set_includenavigation($include) {
429
        $this->includenavigation = $include;
430
 
431
        return $this;
432
    }
433
 
434
    /**
435
     * Set whether the initial events have already been loaded and
436
     * provided to the exporter.
437
     *
438
     * @param   bool    $loaded
439
     * @return  $this
440
     */
441
    public function set_initialeventsloaded(bool $loaded) {
442
        $this->initialeventsloaded = $loaded;
443
 
444
        return $this;
445
    }
446
 
447
    /**
448
     * Set whether the course filter selector should be shown.
449
     *
450
     * @param   bool    $show
451
     * @return  $this
452
     */
453
    public function set_showcoursefilter(bool $show) {
454
        $this->showcoursefilter = $show;
455
 
456
        return $this;
457
    }
458
 
459
    /**
460
     * Get the default context for use when adding a new event.
461
     *
462
     * @return null|\context
463
     */
464
    protected function get_default_add_context() {
465
        if (calendar_user_can_add_event($this->calendar->course)) {
466
            return \context_course::instance($this->calendar->course->id);
467
        }
468
 
469
        return null;
470
    }
471
}