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 the customcert module for 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
 * This file contains the customcert date range element.
19
 *
20
 * @package    customcertelement_daterange
21
 * @copyright  2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
namespace customcertelement_daterange;
26
 
27
use mod_customcert\element_helper;
28
 
29
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
30
 
31
require_once($CFG->dirroot . '/lib/grade/constants.php');
32
 
33
/**
34
 * The customcert date range element.
35
 *
36
 * @package    customcertelement_daterange
37
 * @copyright  2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
38
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39
 */
40
class element extends \mod_customcert\element {
41
 
42
    /**
43
     * Max recurring period in seconds.
44
     */
45
    const MAX_RECURRING_PERIOD = 31556926; // 12 months.
46
 
47
    /**
48
     * Current year placeholder string.
49
     */
50
    const CURRENT_YEAR_PLACEHOLDER = '{{current_year}}';
51
 
52
    /**
53
     * First year in a date range placeholder string.
54
     */
55
    const RANGE_FIRST_YEAR_PLACEHOLDER = '{{range_first_year}}';
56
 
57
    /**
58
     * Last year in a date range placeholder string.
59
     */
60
    const RANGE_LAST_YEAR_PLACEHOLDER = '{{range_last_year}}';
61
 
62
    /**
63
     * First year in a date range placeholder string.
64
     */
65
    const RECUR_RANGE_FIRST_YEAR_PLACEHOLDER = '{{recurring_range_first_year}}';
66
 
67
    /**
68
     * Last year in a date range placeholder string.
69
     */
70
    const RECUR_RANGE_LAST_YEAR_PLACEHOLDER = '{{recurring_range_last_year}}';
71
 
72
    /**
73
     * A year in the user's date.
74
     */
75
    const DATE_YEAR_PLACEHOLDER = '{{date_year}}';
76
 
77
    /**
78
     * Date - Issue
79
     */
80
    const DATE_ISSUE = -1;
81
 
82
    /**
83
     * Date - Completion
84
     */
85
    const DATE_COMPLETION = -2;
86
 
87
    /**
88
     * Date - Course start
89
     */
90
    const DATE_COURSE_START = -3;
91
 
92
    /**
93
     * Date - Course end
94
     */
95
    const DATE_COURSE_END = -4;
96
 
97
    /**
98
     * Date - Course grade date
99
     */
100
    const DATE_COURSE_GRADE = -5;
101
 
102
    /**
103
     * Date - Course current date
104
     */
105
    const DATE_CURRENT_DATE = -6;
106
 
107
    /**
108
     * This function renders the form elements when adding a customcert element.
109
     *
110
     * @param \MoodleQuickForm $mform the edit form instance
111
     */
112
    public function render_form_elements($mform) {
113
        global $COURSE;
114
 
115
        // Get the possible date options.
116
        $dateoptions = [];
117
        $dateoptions[self::DATE_ISSUE] = get_string('issueddate', 'customcertelement_daterange');
118
        $dateoptions[self::DATE_CURRENT_DATE] = get_string('currentdate', 'customcertelement_daterange');
119
        $dateoptions[self::DATE_COMPLETION] = get_string('completiondate', 'customcertelement_daterange');
120
        $dateoptions[self::DATE_COURSE_START] = get_string('coursestartdate', 'customcertelement_daterange');
121
        $dateoptions[self::DATE_COURSE_END] = get_string('courseenddate', 'customcertelement_daterange');
122
        $dateoptions[self::DATE_COURSE_GRADE] = get_string('coursegradedate', 'customcertelement_daterange');
123
 
124
        $dateoptions = $dateoptions + element_helper::get_grade_items($COURSE);
125
 
126
        $mform->addElement('select', 'dateitem', get_string('dateitem', 'customcertelement_daterange'), $dateoptions);
127
        $mform->addHelpButton('dateitem', 'dateitem', 'customcertelement_daterange');
128
 
129
        parent::render_form_elements($mform);
130
 
131
        $mform->addElement('header', 'dateranges', get_string('dateranges', 'customcertelement_daterange'));
132
        $mform->addElement('static', 'help', '', get_string('help', 'customcertelement_daterange'));
133
        $mform->addElement('static', 'placeholders', '', get_string('placeholders', 'customcertelement_daterange'));
134
 
135
        $mform->addElement('text', 'fallbackstring', get_string('fallbackstring', 'customcertelement_daterange'));
136
        $mform->addHelpButton('fallbackstring', 'fallbackstring', 'customcertelement_daterange');
137
        $mform->setType('fallbackstring', PARAM_NOTAGS);
138
 
139
        if (empty($this->get_decoded_data()->dateranges)) {
140
            $repeats = 1;
141
        } else {
142
            $repeats = count($this->get_decoded_data()->dateranges);
143
        }
144
 
145
        $ranges = [];
146
 
147
        $ranges[] = $mform->createElement('html', '<hr>');
148
 
149
        $ranges[] = $mform->createElement(
150
            'date_selector',
151
            'startdate',
152
            get_string('start', 'customcertelement_daterange')
153
        );
154
 
155
        $ranges[] = $mform->createElement(
156
            'date_selector',
157
            'enddate',
158
            get_string('end', 'customcertelement_daterange')
159
        );
160
 
161
        $ranges[] = $mform->createElement(
162
            'checkbox',
163
            'recurring',
164
            get_string('recurring', 'customcertelement_daterange')
165
        );
166
 
167
        $ranges[] = $mform->createElement(
168
            'text',
169
            'datestring',
170
            get_string('datestring', 'customcertelement_daterange'),
171
            ['class' => 'datestring']
172
        );
173
 
174
        $ranges[] = $mform->createElement(
175
            'advcheckbox',
176
            'rangedelete',
177
            get_string('setdeleted', 'customcertelement_daterange'),
178
            '',
179
            [],
180
            [0, 1]
181
        );
182
 
183
        $rangeoptions = [];
184
        $rangeoptions['startdate']['type'] = PARAM_INT;
185
        $rangeoptions['enddate']['type'] = PARAM_INT;
186
        $rangeoptions['recurring']['type'] = PARAM_INT;
187
        $rangeoptions['recurring']['helpbutton'] = ['recurring', 'customcertelement_daterange'];
188
        $rangeoptions['datestring']['type'] = PARAM_NOTAGS;
189
        $rangeoptions['rangedelete']['type'] = PARAM_BOOL;
190
 
191
        $addstring = get_string('addrange', 'customcertelement_daterange');
192
        $this->get_edit_element_form()->repeat_elements($ranges, $repeats, $rangeoptions, 'repeats', 'add', 1, $addstring, true);
193
    }
194
 
195
    /**
196
     * A helper function to build consistent form element name.
197
     *
198
     * @param string $name
199
     * @param string $num
200
     *
201
     * @return string
202
     */
203
    protected function build_element_name($name, $num) {
204
        return $name . '[' . $num . ']';
205
    }
206
 
207
    /**
208
     * Get decoded data stored in DB.
209
     *
210
     * @return \stdClass
211
     */
212
    protected function get_decoded_data() {
213
        if ($this->get_data()) {
214
            return json_decode($this->get_data());
215
        }
216
    }
217
 
218
    /**
219
     * Sets the data on the form when editing an element.
220
     *
221
     * @param \MoodleQuickForm $mform the edit form instance
222
     */
223
    public function definition_after_data($mform) {
224
        if (!empty($this->get_data()) && !$mform->isSubmitted()) {
225
            $element = $mform->getElement('dateitem');
226
            $element->setValue($this->get_decoded_data()->dateitem);
227
 
228
            $element = $mform->getElement('fallbackstring');
229
            $element->setValue($this->get_decoded_data()->fallbackstring);
230
 
231
            foreach ($this->get_decoded_data()->dateranges as $key => $range) {
232
                $mform->setDefault($this->build_element_name('startdate', $key), $range->startdate);
233
                $mform->setDefault($this->build_element_name('enddate', $key), $range->enddate);
234
                $mform->setDefault($this->build_element_name('datestring', $key), $range->datestring);
235
                $mform->setDefault($this->build_element_name('recurring', $key), $range->recurring);
236
            }
237
        }
238
 
239
        parent::definition_after_data($mform);
240
    }
241
 
242
    /**
243
     * Performs validation on the element values.
244
     *
245
     * @param array $data the submitted data
246
     * @param array $files the submitted files
247
     * @return array the validation errors
248
     */
249
    public function validate_form_elements($data, $files) {
250
        $errors = parent::validate_form_elements($data, $files);
251
 
252
        // Check if at least one range is set.
253
        $error = get_string('error:atleastone', 'customcertelement_daterange');
254
 
255
        for ($i = 0; $i < $data['repeats']; $i++) {
256
            if (empty($data['rangedelete'][$i])) {
257
                $error = '';
258
            }
259
        }
260
 
261
        if (!empty($error)) {
262
            $errors['help'] = $error;
263
        }
264
 
265
        // Check that datestring is set dataranges what aren't need to be deleted.
266
        for ($i = 0; $i < $data['repeats']; $i++) {
267
            // Skip elements that needs to be deleted.
268
            if (!empty($data['rangedelete'][$i])) {
269
                continue;
270
            }
271
 
272
            if (empty($data['datestring'][$i])) {
273
                $name = $this->build_element_name('datestring', $i);
274
                $errors[$name] = get_string('error:datestring', 'customcertelement_daterange');
275
            }
276
 
277
            // Check that end date is correctly set.
278
            if ( $data['startdate'][$i] >= $data['enddate'][$i] ) {
279
                $errors[$this->build_element_name('enddate', $i)] = get_string('error:enddate', 'customcertelement_daterange');
280
            }
281
 
282
            $rangeperiod = $data['enddate'][$i] - $data['startdate'][$i];
283
 
284
            // Check that recurring dateranges are not longer than 12 months.
285
            if (!empty($data['recurring'][$i]) && $rangeperiod >= self::MAX_RECURRING_PERIOD ) {
286
                $errors[$this->build_element_name('enddate', $i)] = get_string('error:recurring', 'customcertelement_daterange');
287
            }
288
        }
289
 
290
        return $errors;
291
    }
292
 
293
    /**
294
     * This will handle how form data will be saved into the data column in the
295
     * customcert_elements table.
296
     *
297
     * @param \stdClass $data the form data
298
     * @return string the json encoded array
299
     */
300
    public function save_unique_data($data) {
301
        $arrtostore = [
302
            'dateitem' => $data->dateitem,
303
            'fallbackstring' => $data->fallbackstring,
304
            'dateranges' => [],
305
        ];
306
 
307
        for ($i = 0; $i < $data->repeats; $i++) {
308
            if (empty($data->rangedelete[$i])) {
309
                $arrtostore['dateranges'][] = [
310
                    'startdate' => $data->startdate[$i],
311
                    'enddate' => $data->enddate[$i],
312
                    'datestring' => $data->datestring[$i],
313
                    'recurring' => !empty($data->recurring[$i]),
314
                ];
315
            }
316
        }
317
 
318
        // Encode these variables before saving into the DB.
319
        return json_encode($arrtostore);
320
    }
321
 
322
    /**
323
     * Handles rendering the element on the pdf.
324
     *
325
     * @param \pdf $pdf the pdf object
326
     * @param bool $preview true if it is a preview, false otherwise
327
     * @param \stdClass $user the user we are rendering this for
328
     */
329
    public function render($pdf, $preview, $user) {
330
        global $DB;
331
 
332
        // If there is no element data, we have nothing to display.
333
        if (empty($this->get_data())) {
334
            return;
335
        }
336
 
337
        $courseid = element_helper::get_courseid($this->id);
338
        $dateitem = $this->get_decoded_data()->dateitem;
339
 
340
        // If we are previewing this certificate then just show a demonstration date.
341
        if ($preview) {
342
            $date = time();
343
        } else {
344
            // Get the page.
345
            $page = $DB->get_record('customcert_pages', ['id' => $this->get_pageid()], '*', MUST_EXIST);
346
            // Get the customcert this page belongs to.
347
            $customcert = $DB->get_record('customcert', ['templateid' => $page->templateid], '*', MUST_EXIST);
348
            // Now we can get the issue for this user.
349
            $issue = $DB->get_record('customcert_issues', ['userid' => $user->id, 'customcertid' => $customcert->id],
350
                '*', MUST_EXIST);
351
 
352
            switch ($dateitem) {
353
                case self::DATE_ISSUE:
354
                    $date = $issue->timecreated;
355
                    break;
356
 
357
                case self::DATE_CURRENT_DATE:
358
                    $date = time();
359
                    break;
360
 
361
                case self::DATE_COMPLETION:
362
                    // Get the last completion date.
363
                    $sql = "SELECT MAX(c.timecompleted) as timecompleted
364
                          FROM {course_completions} c
365
                         WHERE c.userid = :userid
366
                           AND c.course = :courseid";
367
                    if ($timecompleted = $DB->get_record_sql($sql, ['userid' => $issue->userid, 'courseid' => $courseid])) {
368
                        if (!empty($timecompleted->timecompleted)) {
369
                            $date = $timecompleted->timecompleted;
370
                        }
371
                    }
372
                    break;
373
 
374
                case self::DATE_COURSE_START:
375
                    $date = $DB->get_field('course', 'startdate', ['id' => $courseid]);
376
                    break;
377
 
378
                case self::DATE_COURSE_END:
379
                    $date = $DB->get_field('course', 'enddate', ['id' => $courseid]);
380
                    break;
381
 
382
                case self::DATE_COURSE_GRADE:
383
                    $grade = element_helper::get_course_grade_info(
384
                        $courseid,
385
                        GRADE_DISPLAY_TYPE_DEFAULT, $user->id
386
                    );
387
                    if ($grade && !empty($grade->get_dategraded())) {
388
                        $date = $grade->get_dategraded();
389
                    }
390
                    break;
391
 
392
                default:
393
                    if (strpos($dateitem, 'gradeitem:') === 0) {
394
                        $gradeitemid = substr($dateitem, 10);
395
                        $grade = element_helper::get_grade_item_info(
396
                            $gradeitemid,
397
                            $dateitem,
398
                            $user->id
399
                        );
400
                    } else {
401
                        $grade = element_helper::get_mod_grade_info(
402
                            $dateitem,
403
                            GRADE_DISPLAY_TYPE_DEFAULT,
404
                            $user->id
405
                        );
406
                    }
407
                    if ($grade && !empty($grade->get_dategraded())) {
408
                        $date = $grade->get_dategraded();
409
                    }
410
                    break;
411
            }
412
        }
413
 
414
        // Ensure that a date has been set.
415
        if (!empty($date)) {
416
            element_helper::render_content($pdf, $this, $this->get_daterange_string($date));
417
        }
418
    }
419
 
420
    /**
421
     * Get daterange string.
422
     *
423
     * @param int $date Unix stamp date.
424
     *
425
     * @return string
426
     */
427
    protected function get_daterange_string($date) {
428
        $matchedrange = null;
429
        $outputstring = '';
430
        $formatdata = [];
431
        $formatdata['date'] = $date;
432
 
433
        foreach ($this->get_decoded_data()->dateranges as $key => $range) {
434
            if ($this->is_recurring_range($range)) {
435
                if ($matchedrange = $this->get_matched_recurring_range($date, $range)) {
436
                    $outputstring = $matchedrange->datestring;
437
                    $formatdata['range'] = $range;
438
                    $formatdata['recurringrange'] = $matchedrange;
439
                    break;
440
                }
441
            } else {
442
                if ($this->is_date_in_range($date, $range)) {
443
                    $outputstring = $range->datestring;
444
                    $formatdata['range'] = $range;
445
                    break;
446
                }
447
            }
448
        }
449
 
450
        if (empty($outputstring) && !empty($this->get_decoded_data()->fallbackstring)) {
451
            $outputstring = $this->get_decoded_data()->fallbackstring;
452
        }
453
 
454
        return $this->format_date_string($outputstring, $formatdata);
455
    }
456
 
457
    /**
458
     * Returns whether or not a range is recurring.
459
     *
460
     * @param \stdClass $range Range object.
461
     *
462
     * @return bool
463
     */
464
    protected function is_recurring_range(\stdClass $range) {
465
        return !empty($range->recurring);
466
    }
467
 
468
    /**
469
     * Check if the provided date is in the date range.
470
     *
471
     * @param int $date Unix timestamp date to check.
472
     * @param \stdClass $range Range object.
473
     *
474
     * @return bool
475
     */
476
    protected function is_date_in_range($date, \stdClass $range) {
477
        return ($date >= $range->startdate && $date <= $range->enddate);
478
    }
479
 
480
    /**
481
     * Check if provided date is in the recurring date range.
482
     *
483
     * @param int $date Unix timestamp date to check.
484
     * @param \stdClass $range Range object.
485
     *
486
     * @return bool
487
     */
488
    protected function is_date_in_recurring_range($date, \stdClass $range) {
489
        $intdate = $this->build_number_from_date($date);
490
        $intstart = $this->build_number_from_date($range->startdate);
491
        $intend = $this->build_number_from_date($range->enddate);
492
 
493
        if (!$this->has_turn_of_the_year($range)) {
494
            if ($intdate >= $intstart && $intdate <= $intend) {
495
                return true;
496
            }
497
        } else {
498
            if ($intdate >= $intstart && $intdate >= $intend) {
499
                return true;
500
            }
501
 
502
            if ($intdate <= $intstart && $intdate <= $intend) {
503
                return true;
504
            }
505
        }
506
 
507
        return false;
508
    }
509
 
510
    /**
511
     * Check if provided recurring range has a turn of the year.
512
     *
513
     * @param \stdClass $reccurringrange Range object.
514
     *
515
     * @return bool
516
     */
517
    protected function has_turn_of_the_year(\stdClass $reccurringrange) {
518
        return date('Y', $reccurringrange->startdate) != date('Y', $reccurringrange->enddate);
519
    }
520
 
521
    /**
522
     * Check if provided date is in the start year of the recurring range with a turn of the year.
523
     *
524
     * @param int $date Unix timestamp date to check.
525
     * @param \stdClass $range Range object.
526
     *
527
     * @return bool
528
     */
529
    protected function in_start_year($date, \stdClass $range) {
530
        $intdate = $this->build_number_from_date($date);
531
        $intstart = $this->build_number_from_date($range->startdate);
532
        $intend = $this->build_number_from_date($range->enddate);
533
 
534
        return $intdate >= $intstart && $intdate >= $intend;
535
    }
536
 
537
    /**
538
     * Check if provided date is in the end year of the recurring range with a turn of the year.
539
     *
540
     * @param int $date Unix timestamp date to check.
541
     * @param \stdClass $range Range object.
542
     *
543
     * @return bool
544
     */
545
    protected function in_end_year($date, \stdClass $range) {
546
        $intdate = $this->build_number_from_date($date);
547
        $intstart = $this->build_number_from_date($range->startdate);
548
        $intend = $this->build_number_from_date($range->enddate);
549
 
550
        return $intdate <= $intstart && $intdate <= $intend;
551
    }
552
 
553
    /**
554
     * Return matched recurring date range.
555
     *
556
     * As recurring date ranges do not depend on the year,
557
     * we will use a date's year to build a new matched recurring date range with
558
     * start year and end year. This is required to replace placeholders like range_first_year and range_last_year.
559
     *
560
     * @param int $date Unix timestamp date to check.
561
     * @param \stdClass $range Range object.
562
     *
563
     * @return \stdClass || null
564
     */
565
    protected function get_matched_recurring_range($date, \stdClass $range) {
566
        if (!$this->is_date_in_recurring_range($date, $range)) {
567
            return null;
568
        }
569
 
570
        $matchedrage = clone $range;
571
 
572
        if ($this->has_turn_of_the_year($matchedrage)) {
573
 
574
            if ($this->in_start_year($date, $matchedrage)) {
575
                $startyear = date('Y', $date);
576
                $endyear = $startyear + 1;
577
                $matchedrage->startdate = strtotime(date('d.m.', $matchedrage->startdate) . $startyear);
578
                $matchedrage->enddate = strtotime(date('d.m.', $matchedrage->enddate) . $endyear);
579
 
580
                return $matchedrage;
581
            }
582
 
583
            if ($this->in_end_year($date, $matchedrage)) {
584
                $endyear = date('Y', $date);
585
                $startyear = $endyear - 1;
586
                $matchedrage->startdate = strtotime(date('d.m.', $matchedrage->startdate) . $startyear);
587
                $matchedrage->enddate = strtotime(date('d.m.', $matchedrage->enddate) . $endyear);
588
 
589
                return $matchedrage;
590
            }
591
        } else {
592
            $matchedrage->startdate = strtotime(date('d.m.', $matchedrage->startdate) . date('Y', $date));
593
            $matchedrage->enddate = strtotime(date('d.m.', $matchedrage->enddate) . date('Y', $date));
594
 
595
            return $matchedrage;
596
        }
597
 
598
        return null;
599
    }
600
 
601
    /**
602
     * Build number representation of the provided date.
603
     *
604
     * @param int $date Unix timestamp date to check.
605
     *
606
     * @return int
607
     */
608
    protected function build_number_from_date($date) {
609
        return (int)date('md', $date);
610
    }
611
 
612
    /**
613
     * Format date string based on different types of placeholders.
614
     *
615
     * @param string $datestring The date string
616
     * @param array $formatdata A list of format data.
617
     *
618
     * @return string
619
     */
620
    protected function format_date_string($datestring, array $formatdata) {
621
        foreach ($this->get_placeholders() as $search => $replace) {
622
            $datestring = str_replace($search, $replace, $datestring);
623
        }
624
 
625
        if (!empty($formatdata['date'])) {
626
            foreach ($this->get_date_placeholders($formatdata['date']) as $search => $replace) {
627
                $datestring = str_replace($search, $replace, $datestring);
628
            }
629
        }
630
 
631
        if (!empty($formatdata['range'])) {
632
            foreach ($this->get_range_placeholders($formatdata['range']) as $search => $replace) {
633
                $datestring = str_replace($search, $replace, $datestring);
634
            }
635
        }
636
 
637
        if (!empty($formatdata['recurringrange'])) {
638
            foreach ($this->get_recurring_range_placeholders($formatdata['recurringrange']) as $search => $replace) {
639
                $datestring = str_replace($search, $replace, $datestring);
640
            }
641
        }
642
 
643
        return $datestring;
644
    }
645
 
646
    /**
647
     * Return a list of placeholders to replace in date string as search => $replace pairs.
648
     *
649
     * @return array
650
     */
651
    protected function get_placeholders() {
652
        return [
653
            self::CURRENT_YEAR_PLACEHOLDER => date('Y', time()),
654
        ];
655
    }
656
 
657
    /**
658
     * Return a list of user's date related placeholders to replace in date string as search => $replace pairs.
659
 
660
     * @param int $date Unix timestamp date to check.
661
     *
662
     * @return array
663
     */
664
    protected function get_date_placeholders($date) {
665
        return [
666
            self::DATE_YEAR_PLACEHOLDER => date('Y', $date),
667
        ];
668
    }
669
 
670
    /**
671
     * Return a list of range related placeholders to replace in date string as search => $replace pairs.
672
     *
673
     * @param \stdClass $range
674
     *
675
     * @return array
676
     */
677
    protected function get_range_placeholders(\stdClass $range) {
678
        return [
679
            self::RANGE_FIRST_YEAR_PLACEHOLDER => date('Y', $range->startdate),
680
            self::RANGE_LAST_YEAR_PLACEHOLDER => date('Y', $range->enddate),
681
        ];
682
    }
683
 
684
    /**
685
     * Return a list of recurring range s placeholders to replace in date string as search => $replace pairs.
686
     *
687
     * @param \stdClass $range
688
     *
689
     * @return array
690
     */
691
    protected function get_recurring_range_placeholders(\stdClass $range) {
692
        return [
693
            self::RECUR_RANGE_FIRST_YEAR_PLACEHOLDER => date('Y', $range->startdate),
694
            self::RECUR_RANGE_LAST_YEAR_PLACEHOLDER => date('Y', $range->enddate),
695
        ];
696
    }
697
 
698
    /**
699
     * Render the element in html.
700
     *
701
     * This function is used to render the element when we are using the
702
     * drag and drop interface to position it.
703
     *
704
     * @return string the html
705
     */
706
    public function render_html() {
707
        // If there is no element data, we have nothing to display.
708
        if (empty($this->get_data())) {
709
            return;
710
        }
711
 
712
        return element_helper::render_html_content($this, get_string('preview', 'customcertelement_daterange', $this->get_name()));
713
    }
714
 
715
    /**
716
     * This function is responsible for handling the restoration process of the element.
717
     *
718
     * We will want to update the course module the date element is pointing to as it will
719
     * have changed in the course restore.
720
     *
721
     * @param \restore_customcert_activity_task $restore
722
     */
723
    public function after_restore($restore) {
724
        global $DB;
725
 
726
        $dateinfo = json_decode($this->get_data());
727
 
728
        $isgradeitem = false;
729
        $oldid = $dateinfo->dateitem;
730
        if (str_starts_with($dateinfo->dateitem, 'gradeitem:')) {
731
            $isgradeitem = true;
732
            $oldid = str_replace('gradeitem:', '', $dateinfo->dateitem);
733
        }
734
 
735
        $itemname = $isgradeitem ? 'grade_item' : 'course_module';
736
        if ($newitem = \restore_dbops::get_backup_ids_record($restore->get_restoreid(), $itemname, $oldid)) {
737
            $dateinfo->dateitem = '';
738
            if ($isgradeitem) {
739
                $dateinfo->dateitem = 'gradeitem:';
740
            }
741
            $dateinfo->dateitem = $dateinfo->dateitem . $newitem->newitemid;
742
            $DB->set_field('customcert_elements', 'data', $this->save_unique_data($dateinfo), ['id' => $this->get_id()]);
743
        }
744
    }
745
}