1<?php
2
3namespace ComboStrap;
4
5
6use syntax_plugin_combo_variable;
7
8/**
9 * Format a date
10 * @deprecated use the pipline instead
11 */
12class DateTag
13{
14    public const CANONICAL = "variable:date";
15    public const FORMAT_ATTRIBUTE = "format";
16    public const DATE_ATTRIBUTE = "date";
17    public const TAG = "date";
18    /**
19     * https://www.php.net/manual/en/function.strftime.php
20     */
21    public const DEFAULT_FORMAT = "%A, %d %B %Y";
22
23
24    /**
25     * @param string $date
26     * @param string $format
27     * @param string|null $lang
28     * @return string
29     * @throws ExceptionBadSyntax
30     */
31    public static function formatDateString(string $date, string $format = DateTag::DEFAULT_FORMAT, string $lang = null): string
32    {
33        // https://www.php.net/manual/en/function.date.php
34        // To format dates in other languages, you should use the setlocale() and strftime() functions instead of date().
35        $localeSeparator = '_';
36        if ($lang === null) {
37            try {
38                $lang = Lang::createFromRequestedMarkup()->getValueOrDefault();
39            } catch (ExceptionNotFound $e) {
40                // should never happen but yeah
41                LogUtility::error("Internal Error: The requested page was not found. We were unable to get the page language. Defaulting to the site language");
42                $lang = Site::getLang();
43            }
44        }
45        $actualLocale = setlocale(LC_ALL, 0);
46        try {
47            if ($lang !== null && trim($lang) !== "") {
48                // Set local takes several possible locales value
49                // The lang just works fine but the second argument can be seen in the doc
50                if (strlen(trim($lang)) === 2) {
51                    $region = Site::getLanguageRegion();
52                    $derivedLocale = strtolower($region) . $localeSeparator . strtoupper($lang);
53                } else {
54                    $derivedLocale = $lang;
55                }
56                $newLocale = setlocale(LC_TIME, $lang, $derivedLocale);
57                if ($newLocale === false) {
58                    $newLocale = setlocale(LC_TIME, $lang);
59                    if ($newLocale === false) {
60                        LogUtility::warning("The language ($lang) / locale ($derivedLocale) is not available as locale on the server. You can't then format the value ($date) in this language.");
61                    }
62                }
63            }
64            $date = syntax_plugin_combo_variable::replaceVariablesWithValuesFromContext($date);
65            $timeStamp = Iso8601Date::createFromString($date)->getDateTime()->getTimestamp();
66            $formatted = strftime($format, $timeStamp);
67            if ($formatted === false) {
68                if ($lang === null) {
69                    $lang = "";
70                }
71                throw new ExceptionBadSyntax("Unable to format the date ($date) with the format ($format) and lang ($lang)");
72            }
73            return $formatted;
74        } finally {
75            /**
76             * Restore the locale
77             */
78            setlocale(LC_ALL, $actualLocale);
79        }
80
81    }
82
83    public static function handleEnterAndSpecial()
84    {
85        LogUtility::warning("The date component has been deprecated for the date variable", DateTag::CANONICAL);
86    }
87
88    public static function renderHtml(TagAttributes $tagAttributes): string
89    {
90        /**
91         * Locale
92         */
93        $lang = $tagAttributes->getComponentAttributeValue(Lang::PROPERTY_NAME);
94
95        /**
96         * The format
97         */
98        $format = $tagAttributes->getValue(DateTag::FORMAT_ATTRIBUTE, DateTag::DEFAULT_FORMAT);
99        /**
100         * The date
101         */
102        $defaultDateTime = Iso8601Date::createFromNow()->toString();
103        $date = $tagAttributes->getComponentAttributeValue(DateTag::DATE_ATTRIBUTE, $defaultDateTime);
104        try {
105            return DateTag::formatDateString($date, $format, $lang);
106        } catch (ExceptionBadSyntax $e) {
107            $message = "Error while formatting a date. Error: {$e->getMessage()}";
108            LogUtility::error($message, DateTag::CANONICAL);
109            return LogUtility::wrapInRedForHtml($message);
110        }
111    }
112
113    public static function handleExit(\Doku_Handler $handler)
114    {
115        $callStack = CallStack::createFromHandler($handler);
116        $openingTag = $callStack->moveToPreviousCorrespondingOpeningCall();
117        $call = $callStack->next();
118        if ($call !== false) {
119            $date = $call->getCapturedContent();
120            $openingTag->addAttribute(DateTag::DATE_ATTRIBUTE, $date);
121            $callStack->deleteActualCallAndPrevious();
122        }
123    }
124}
125