Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 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
namespace core_calendar\output;
18
 
19
Use DateTimeInterface;
20
use DateTimeImmutable;
21
use core\output\templatable;
22
use core\output\renderable;
23
use core\output\renderer_base;
24
use core\url;
25
 
26
/**
27
 * Class humantimeperiod.
28
 *
29
 * This class is used to render a time period as a human readable date.
30
 * The main difference between userdate and this class is that this class
31
 * will render the date as "Today", "Yesterday", "Tomorrow" if the date is
32
 * close to the current date. Also, it will add styling if the date
33
 * is near.
34
 *
35
 * @package    core_calendar
36
 * @copyright  2025 Amaia Anabitarte <amaia@moodle.com>
37
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38
 */
39
class humantimeperiod implements renderable, templatable {
40
 
41
    /** @var int|null Number of seconds that indicates a nearby date. Default to DAYSECS. Use null for no indication. */
42
    protected $near = DAYSECS;
43
 
44
    /** @var url|null URL to link the date to. */
45
    protected ?url $link = null;
46
 
47
    /** @var string|null An optional date format to apply. */
48
    protected ?string $langtimeformat = null;
49
 
50
    /** @var bool Whether to use human common words or not. */
51
    protected bool $userelatives = true;
52
 
53
    /**
54
     * Class constructor.
55
     *
56
     * @param DateTimeImmutable $startdatetime The starting timestamp.
57
     * @param DateTimeImmutable|null $enddatetime The ending timestamp.
58
     */
59
    protected function __construct(
60
        /** @var DateTimeImmutable $startdatetime The starting date time. */
61
        protected DateTimeImmutable $startdatetime,
62
        /** @var DateTimeImmutable|null $enddatetime The ending date time. */
63
        protected ?DateTimeImmutable $enddatetime,
64
    ) {
65
    }
66
 
67
    /**
68
     * Creates a new humantimeperiod instance from a timestamp.
69
     *
70
     * @param int $starttimestamp The starting timestamp.
71
     * @param int|null $endtimestamp The ending timestamp.
72
     * @param int|null $near The number of seconds that indicates a nearby date. Default to DAYSECS, use null for no indication.
73
     * @param url|null $link URL to link the date to.
74
     * @param string|null $langtimeformat Lang date and time format to use to format the date.
75
     * @param bool $userelatives Whether to use human common words or not.
76
     * @return humantimeperiod The new instance.
77
     */
78
    public static function create_from_timestamp(
79
        int $starttimestamp,
80
        ?int $endtimestamp,
81
        ?int $near = DAYSECS,
82
        ?url $link = null,
83
        ?string $langtimeformat = null,
84
        bool $userelatives = true,
85
    ): self {
86
 
87
        return self::create_from_datetime(
88
            (new DateTimeImmutable("@{$starttimestamp}")),
89
            $endtimestamp ? (new DateTimeImmutable("@{$endtimestamp}")) : null,
90
            $near,
91
            $link,
92
            $langtimeformat,
93
            $userelatives
94
        );
95
    }
96
 
97
    /**
98
     * Creates a new humantimeperiod instance from a datetime.
99
     *
100
     * @param DateTimeInterface $startdatetime The starting datetime.
101
     * @param DateTimeInterface|null $enddatetime The ending datetime.
102
     * @param int|null $near The number of seconds that indicates a nearby date. Default to DAYSECS, use null for no indication.
103
     * @param url|null $link URL to link the date to.
104
     * @param string|null $langtimeformat Lang date and time format to use to format the date.
105
     * @param bool $userelatives Whether to use human common words or not.
106
     * @return humantimeperiod The new instance.
107
     */
108
    public static function create_from_datetime(
109
        DateTimeInterface $startdatetime,
110
        ?DateTimeInterface $enddatetime,
111
        ?int $near = DAYSECS,
112
        ?url $link = null,
113
        ?string $langtimeformat = null,
114
        bool $userelatives = true,
115
    ): self {
116
 
117
        // Always use an Immutable object to ensure that the value does not change externally before it is rendered.
118
        if (!($startdatetime instanceof DateTimeImmutable)) {
119
            $startdatetime = DateTimeImmutable::createFromInterface($startdatetime);
120
        }
121
        if ($enddatetime != null && !($enddatetime instanceof DateTimeImmutable)) {
122
            $enddatetime = DateTimeImmutable::createFromInterface($enddatetime);
123
        }
124
 
125
        return (new self($startdatetime, $enddatetime))
126
            ->set_near_limit($near)
127
            ->set_link($link)
128
            ->set_lang_time_format($langtimeformat)
129
            ->set_use_relatives($userelatives);
130
    }
131
 
132
    /**
133
     * Sets the number of seconds within which a date is considered near.
134
     *
135
     * @param int|null $near The number of seconds within which a date is considered near.
136
     * @return humantimeperiod The instance.
137
     */
138
    public function set_near_limit(?int $near): self {
139
        $this->near = $near;
140
        return $this;
141
    }
142
 
143
    /**
144
     * Sets the link for the date. If null, no link will be added.
145
     *
146
     * @param url|null $link The link for the date.
147
     * @return humantimeperiod The instance.
148
     */
149
    public function set_link(?url $link): self {
150
        $this->link = $link;
151
        return $this;
152
    }
153
 
154
    /**
155
     * Sets an optional date format to apply.
156
     *
157
     * @param string|null $langtimeformat Lang date and time format to use to format the date.
158
     * @return humantimeperiod The instance.
159
     */
160
    public function set_lang_time_format(?string $langtimeformat): self {
161
        $this->langtimeformat = $langtimeformat;
162
        return $this;
163
    }
164
 
165
    /**
166
     * Sets whether to use human relative terminology.
167
     *
168
     * @param bool $userelatives Whether to use human relative terminology.
169
     * @return humantimeperiod The instance.
170
     */
171
    public function set_use_relatives(bool $userelatives): self {
172
        $this->userelatives = $userelatives;
173
        return $this;
174
    }
175
 
176
    #[\Override]
177
    public function export_for_template(renderer_base $output): array {
178
        $period = $this->format_period();
179
        return [
180
            'startdate' => $period['startdate']->export_for_template($output),
181
            'enddate' => $period['enddate'] ? $period['enddate']->export_for_template($output) : null,
182
        ];
183
    }
184
 
185
    /**
186
     * Format a time periods based on 2 dates.
187
     *
188
     * @return array An array of one or two humandate elements.
189
     */
190
    private function format_period(): array {
191
 
192
        $linkstart = null;
193
        $linkend = null;
194
        if ($this->link) {
195
            $linkstart = new url($this->link, ['view' => 'day', 'time' => $this->startdatetime->getTimestamp()]);
196
            $linkend = new url($this->link, ['view' => 'day', 'time' => $this->enddatetime->getTimestamp()]);
197
        }
198
 
199
        $startdate = humandate::create_from_datetime(
200
            datetime: $this->startdatetime,
201
            near: $this->near,
202
            link: $linkstart,
203
            langtimeformat: $this->langtimeformat,
204
            userelatives: $this->userelatives
205
        );
206
 
207
        if ($this->enddatetime == null || $this->startdatetime == $this->enddatetime) {
208
            return [
209
                'startdate' => $startdate,
210
                'enddate' => null,
211
            ];
212
        }
213
 
214
        // Get the midnight of the day the event will start.
215
        $usermidnightstart = usergetmidnight($this->startdatetime->getTimestamp());
216
        // Get the midnight of the day the event will end.
217
        $usermidnightend = usergetmidnight($this->enddatetime->getTimestamp());
218
        // Check if we will still be on the same day.
219
        $issameday = ($usermidnightstart == $usermidnightend);
220
 
221
        $enddate = humandate::create_from_datetime(
222
            datetime: $this->enddatetime,
223
            near: $this->near,
224
            timeonly: $issameday,
225
            link: $linkend,
226
            langtimeformat: $this->langtimeformat,
227
            userelatives: $this->userelatives
228
        );
229
 
230
        return [
231
            'startdate' => $startdate,
232
            'enddate' => $enddate,
233
        ];
234
    }
235
}