6ecc4745f4
end. Avoid deprecated strftime function. Got tests to pass in PHP 8.1.
241 lines
8.5 KiB
PHP
241 lines
8.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Shaarli\Helper;
|
|
|
|
use DatePeriod;
|
|
use DateTimeImmutable;
|
|
use Exception;
|
|
use Shaarli\Bookmark\Bookmark;
|
|
use Slim\Http\Request;
|
|
|
|
class DailyPageHelper
|
|
{
|
|
public const MONTH = 'month';
|
|
public const WEEK = 'week';
|
|
public const DAY = 'day';
|
|
|
|
/**
|
|
* Extracts the type of the daily to display from the HTTP request parameters
|
|
*
|
|
* @param Request $request HTTP request
|
|
*
|
|
* @return string month/week/day
|
|
*/
|
|
public static function extractRequestedType(Request $request): string
|
|
{
|
|
if ($request->getQueryParam(static::MONTH) !== null) {
|
|
return static::MONTH;
|
|
} elseif ($request->getQueryParam(static::WEEK) !== null) {
|
|
return static::WEEK;
|
|
}
|
|
|
|
return static::DAY;
|
|
}
|
|
|
|
/**
|
|
* Extracts a DateTimeImmutable from provided HTTP request.
|
|
* If no parameter is provided, we rely on the creation date of the latest provided created bookmark.
|
|
* If the datastore is empty or no bookmark is provided, we use the current date.
|
|
*
|
|
* @param string $type month/week/day
|
|
* @param string|null $requestedDate Input string extracted from the request
|
|
* @param Bookmark|null $latestBookmark Latest bookmark found in the datastore (by date)
|
|
*
|
|
* @return DateTimeImmutable from input or latest bookmark.
|
|
*
|
|
* @throws Exception Type not supported.
|
|
*/
|
|
public static function extractRequestedDateTime(
|
|
string $type,
|
|
?string $requestedDate,
|
|
Bookmark $latestBookmark = null
|
|
): DateTimeImmutable {
|
|
$format = static::getFormatByType($type);
|
|
if (empty($requestedDate)) {
|
|
return $latestBookmark instanceof Bookmark
|
|
? new DateTimeImmutable($latestBookmark->getCreated()->format(\DateTime::ATOM))
|
|
: new DateTimeImmutable()
|
|
;
|
|
}
|
|
|
|
// Don't use today's day of month (github issue #1844)
|
|
if ($type === static::MONTH) {
|
|
$format = '!' . $format;
|
|
}
|
|
|
|
// W is not supported by createFromFormat...
|
|
if ($type === static::WEEK) {
|
|
return (new DateTimeImmutable())
|
|
->setISODate((int) substr($requestedDate, 0, 4), (int) substr($requestedDate, 4, 2))
|
|
;
|
|
}
|
|
|
|
return DateTimeImmutable::createFromFormat($format, $requestedDate);
|
|
}
|
|
|
|
/**
|
|
* Get the DateTime format used by provided type
|
|
* Examples:
|
|
* - day: 20201016 (<year><month><day>)
|
|
* - week: 202041 (<year><week number>)
|
|
* - month: 202010 (<year><month>)
|
|
*
|
|
* @param string $type month/week/day
|
|
*
|
|
* @return string DateTime compatible format
|
|
*
|
|
* @see https://www.php.net/manual/en/datetime.format.php
|
|
*
|
|
* @throws Exception Type not supported.
|
|
*/
|
|
public static function getFormatByType(string $type): string
|
|
{
|
|
switch ($type) {
|
|
case static::MONTH:
|
|
return 'Ym';
|
|
case static::WEEK:
|
|
return 'YW';
|
|
case static::DAY:
|
|
return 'Ymd';
|
|
default:
|
|
throw new Exception('Unsupported daily format type');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the first DateTime of the time period depending on given datetime and type.
|
|
* Note: DateTimeImmutable is required because we rely heavily on DateTime->modify() syntax
|
|
* and we don't want to alter original datetime.
|
|
*
|
|
* @param string $type month/week/day
|
|
* @param DateTimeImmutable $requested DateTime extracted from request input
|
|
* (should come from extractRequestedDateTime)
|
|
*
|
|
* @return \DateTimeInterface First DateTime of the time period
|
|
*
|
|
* @throws Exception Type not supported.
|
|
*/
|
|
public static function getStartDateTimeByType(string $type, DateTimeImmutable $requested): \DateTimeInterface
|
|
{
|
|
switch ($type) {
|
|
case static::MONTH:
|
|
return $requested->modify('first day of this month midnight');
|
|
case static::WEEK:
|
|
return $requested->modify('Monday this week midnight');
|
|
case static::DAY:
|
|
return $requested->modify('Today midnight');
|
|
default:
|
|
throw new Exception('Unsupported daily format type');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the last DateTime of the time period depending on given datetime and type.
|
|
* Note: DateTimeImmutable is required because we rely heavily on DateTime->modify() syntax
|
|
* and we don't want to alter original datetime.
|
|
*
|
|
* @param string $type month/week/day
|
|
* @param DateTimeImmutable $requested DateTime extracted from request input
|
|
* (should come from extractRequestedDateTime)
|
|
*
|
|
* @return \DateTimeInterface Last DateTime of the time period
|
|
*
|
|
* @throws Exception Type not supported.
|
|
*/
|
|
public static function getEndDateTimeByType(string $type, DateTimeImmutable $requested): \DateTimeInterface
|
|
{
|
|
switch ($type) {
|
|
case static::MONTH:
|
|
return $requested->modify('last day of this month 23:59:59');
|
|
case static::WEEK:
|
|
return $requested->modify('Sunday this week 23:59:59');
|
|
case static::DAY:
|
|
return $requested->modify('Today 23:59:59');
|
|
default:
|
|
throw new Exception('Unsupported daily format type');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get localized description of the time period depending on given datetime and type.
|
|
* Example: for a month period, it returns `October, 2020`.
|
|
*
|
|
* @param string $type month/week/day
|
|
* @param \DateTimeImmutable $requested DateTime extracted from request input
|
|
* (should come from extractRequestedDateTime)
|
|
* @param bool $includeRelative Include relative date description (today, yesterday, etc.)
|
|
*
|
|
* @return string Localized time period description
|
|
*
|
|
* @throws Exception Type not supported.
|
|
*/
|
|
public static function getDescriptionByType(
|
|
string $type,
|
|
\DateTimeImmutable $requested,
|
|
bool $includeRelative = true
|
|
): string {
|
|
switch ($type) {
|
|
case static::MONTH:
|
|
return $requested->format('F') . ', ' . $requested->format('Y');
|
|
case static::WEEK:
|
|
$requested = $requested->modify('Monday this week');
|
|
return t('Week') . ' ' . $requested->format('W') . ' (' . format_date($requested, false) . ')';
|
|
case static::DAY:
|
|
$out = '';
|
|
if ($includeRelative && $requested->format('Ymd') === date('Ymd')) {
|
|
$out = t('Today') . ' - ';
|
|
} elseif ($includeRelative && $requested->format('Ymd') === date('Ymd', strtotime('-1 days'))) {
|
|
$out = t('Yesterday') . ' - ';
|
|
}
|
|
return $out . format_date($requested, false);
|
|
default:
|
|
throw new Exception('Unsupported daily format type');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the number of items to display in the RSS feed depending on the given type.
|
|
*
|
|
* @param string $type month/week/day
|
|
*
|
|
* @return int number of elements
|
|
*
|
|
* @throws Exception Type not supported.
|
|
*/
|
|
public static function getRssLengthByType(string $type): int
|
|
{
|
|
switch ($type) {
|
|
case static::MONTH:
|
|
return 12; // 1 year
|
|
case static::WEEK:
|
|
return 26; // ~6 months
|
|
case static::DAY:
|
|
return 30; // ~1 month
|
|
default:
|
|
throw new Exception('Unsupported daily format type');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the number of items to display in the RSS feed depending on the given type.
|
|
*
|
|
* @param string $type month/week/day
|
|
* @param ?DateTimeImmutable $requested Currently only used for UT
|
|
*
|
|
* @return DatePeriod number of elements
|
|
*
|
|
* @throws Exception Type not supported.
|
|
*/
|
|
public static function getCacheDatePeriodByType(string $type, DateTimeImmutable $requested = null): DatePeriod
|
|
{
|
|
$requested = $requested ?? new DateTimeImmutable();
|
|
|
|
return new DatePeriod(
|
|
static::getStartDateTimeByType($type, $requested),
|
|
new \DateInterval('P1D'),
|
|
static::getEndDateTimeByType($type, $requested)
|
|
);
|
|
}
|
|
}
|