]> git.immae.eu Git - github/shaarli/Shaarli.git/blobdiff - application/helper/DailyPageHelper.php
Merge branch 'master' into v0.12
[github/shaarli/Shaarli.git] / application / helper / DailyPageHelper.php
diff --git a/application/helper/DailyPageHelper.php b/application/helper/DailyPageHelper.php
new file mode 100644 (file)
index 0000000..5fabc90
--- /dev/null
@@ -0,0 +1,208 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Shaarli\Helper;
+
+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()
+            ;
+        }
+
+        // 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)
+     *
+     * @return string Localized time period description
+     *
+     * @throws \Exception Type not supported.
+     */
+    public static function getDescriptionByType(string $type, \DateTimeImmutable $requested): 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 ($requested->format('Ymd') === date('Ymd')) {
+                    $out = t('Today') . ' - ';
+                } elseif ($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');
+        }
+    }
+}