]> git.immae.eu Git - github/shaarli/Shaarli.git/blob - application/helper/DailyPageHelper.php
05f95812a279825b5b31372d4e4761d424189f5e
[github/shaarli/Shaarli.git] / application / helper / DailyPageHelper.php
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Shaarli\Helper;
6
7 use DatePeriod;
8 use DateTimeImmutable;
9 use Exception;
10 use Shaarli\Bookmark\Bookmark;
11 use Slim\Http\Request;
12
13 class DailyPageHelper
14 {
15 public const MONTH = 'month';
16 public const WEEK = 'week';
17 public const DAY = 'day';
18
19 /**
20 * Extracts the type of the daily to display from the HTTP request parameters
21 *
22 * @param Request $request HTTP request
23 *
24 * @return string month/week/day
25 */
26 public static function extractRequestedType(Request $request): string
27 {
28 if ($request->getQueryParam(static::MONTH) !== null) {
29 return static::MONTH;
30 } elseif ($request->getQueryParam(static::WEEK) !== null) {
31 return static::WEEK;
32 }
33
34 return static::DAY;
35 }
36
37 /**
38 * Extracts a DateTimeImmutable from provided HTTP request.
39 * If no parameter is provided, we rely on the creation date of the latest provided created bookmark.
40 * If the datastore is empty or no bookmark is provided, we use the current date.
41 *
42 * @param string $type month/week/day
43 * @param string|null $requestedDate Input string extracted from the request
44 * @param Bookmark|null $latestBookmark Latest bookmark found in the datastore (by date)
45 *
46 * @return DateTimeImmutable from input or latest bookmark.
47 *
48 * @throws Exception Type not supported.
49 */
50 public static function extractRequestedDateTime(
51 string $type,
52 ?string $requestedDate,
53 Bookmark $latestBookmark = null
54 ): DateTimeImmutable {
55 $format = static::getFormatByType($type);
56 if (empty($requestedDate)) {
57 return $latestBookmark instanceof Bookmark
58 ? new DateTimeImmutable($latestBookmark->getCreated()->format(\DateTime::ATOM))
59 : new DateTimeImmutable()
60 ;
61 }
62
63 // W is not supported by createFromFormat...
64 if ($type === static::WEEK) {
65 return (new DateTimeImmutable())
66 ->setISODate((int) substr($requestedDate, 0, 4), (int) substr($requestedDate, 4, 2))
67 ;
68 }
69
70 return DateTimeImmutable::createFromFormat($format, $requestedDate);
71 }
72
73 /**
74 * Get the DateTime format used by provided type
75 * Examples:
76 * - day: 20201016 (<year><month><day>)
77 * - week: 202041 (<year><week number>)
78 * - month: 202010 (<year><month>)
79 *
80 * @param string $type month/week/day
81 *
82 * @return string DateTime compatible format
83 *
84 * @see https://www.php.net/manual/en/datetime.format.php
85 *
86 * @throws Exception Type not supported.
87 */
88 public static function getFormatByType(string $type): string
89 {
90 switch ($type) {
91 case static::MONTH:
92 return 'Ym';
93 case static::WEEK:
94 return 'YW';
95 case static::DAY:
96 return 'Ymd';
97 default:
98 throw new Exception('Unsupported daily format type');
99 }
100 }
101
102 /**
103 * Get the first DateTime of the time period depending on given datetime and type.
104 * Note: DateTimeImmutable is required because we rely heavily on DateTime->modify() syntax
105 * and we don't want to alter original datetime.
106 *
107 * @param string $type month/week/day
108 * @param DateTimeImmutable $requested DateTime extracted from request input
109 * (should come from extractRequestedDateTime)
110 *
111 * @return \DateTimeInterface First DateTime of the time period
112 *
113 * @throws Exception Type not supported.
114 */
115 public static function getStartDateTimeByType(string $type, DateTimeImmutable $requested): \DateTimeInterface
116 {
117 switch ($type) {
118 case static::MONTH:
119 return $requested->modify('first day of this month midnight');
120 case static::WEEK:
121 return $requested->modify('Monday this week midnight');
122 case static::DAY:
123 return $requested->modify('Today midnight');
124 default:
125 throw new Exception('Unsupported daily format type');
126 }
127 }
128
129 /**
130 * Get the last DateTime of the time period depending on given datetime and type.
131 * Note: DateTimeImmutable is required because we rely heavily on DateTime->modify() syntax
132 * and we don't want to alter original datetime.
133 *
134 * @param string $type month/week/day
135 * @param DateTimeImmutable $requested DateTime extracted from request input
136 * (should come from extractRequestedDateTime)
137 *
138 * @return \DateTimeInterface Last DateTime of the time period
139 *
140 * @throws Exception Type not supported.
141 */
142 public static function getEndDateTimeByType(string $type, DateTimeImmutable $requested): \DateTimeInterface
143 {
144 switch ($type) {
145 case static::MONTH:
146 return $requested->modify('last day of this month 23:59:59');
147 case static::WEEK:
148 return $requested->modify('Sunday this week 23:59:59');
149 case static::DAY:
150 return $requested->modify('Today 23:59:59');
151 default:
152 throw new Exception('Unsupported daily format type');
153 }
154 }
155
156 /**
157 * Get localized description of the time period depending on given datetime and type.
158 * Example: for a month period, it returns `October, 2020`.
159 *
160 * @param string $type month/week/day
161 * @param \DateTimeImmutable $requested DateTime extracted from request input
162 * (should come from extractRequestedDateTime)
163 * @param bool $includeRelative Include relative date description (today, yesterday, etc.)
164 *
165 * @return string Localized time period description
166 *
167 * @throws Exception Type not supported.
168 */
169 public static function getDescriptionByType(
170 string $type,
171 \DateTimeImmutable $requested,
172 bool $includeRelative = true
173 ): string {
174 switch ($type) {
175 case static::MONTH:
176 return $requested->format('F') . ', ' . $requested->format('Y');
177 case static::WEEK:
178 $requested = $requested->modify('Monday this week');
179 return t('Week') . ' ' . $requested->format('W') . ' (' . format_date($requested, false) . ')';
180 case static::DAY:
181 $out = '';
182 if ($includeRelative && $requested->format('Ymd') === date('Ymd')) {
183 $out = t('Today') . ' - ';
184 } elseif ($includeRelative && $requested->format('Ymd') === date('Ymd', strtotime('-1 days'))) {
185 $out = t('Yesterday') . ' - ';
186 }
187 return $out . format_date($requested, false);
188 default:
189 throw new Exception('Unsupported daily format type');
190 }
191 }
192
193 /**
194 * Get the number of items to display in the RSS feed depending on the given type.
195 *
196 * @param string $type month/week/day
197 *
198 * @return int number of elements
199 *
200 * @throws Exception Type not supported.
201 */
202 public static function getRssLengthByType(string $type): int
203 {
204 switch ($type) {
205 case static::MONTH:
206 return 12; // 1 year
207 case static::WEEK:
208 return 26; // ~6 months
209 case static::DAY:
210 return 30; // ~1 month
211 default:
212 throw new Exception('Unsupported daily format type');
213 }
214 }
215
216 /**
217 * Get the number of items to display in the RSS feed depending on the given type.
218 *
219 * @param string $type month/week/day
220 * @param ?DateTimeImmutable $requested Currently only used for UT
221 *
222 * @return DatePeriod number of elements
223 *
224 * @throws Exception Type not supported.
225 */
226 public static function getCacheDatePeriodByType(string $type, DateTimeImmutable $requested = null): DatePeriod
227 {
228 $requested = $requested ?? new DateTimeImmutable();
229
230 return new DatePeriod(
231 static::getStartDateTimeByType($type, $requested),
232 new \DateInterval('P1D'),
233 static::getEndDateTimeByType($type, $requested)
234 );
235 }
236 }