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 $derivedLocale = strtolower($lang) . $localeSeparator . strtoupper($lang); 52 } else { 53 $derivedLocale = $lang; 54 } 55 $newLocale = setlocale(LC_TIME, $lang, $derivedLocale); 56 if ($newLocale === false) { 57 $newLocale = setlocale(LC_TIME, $lang); 58 /** @noinspection PhpStatementHasEmptyBodyInspection */ 59 if ($newLocale === false) { 60 /** 61 * Not the good algorithm as we come here 62 * everytime on linux. 63 * strftime is deprecated, we should change this code then 64 * 65 */ 66 // throw new ExceptionBadSyntax("The language ($lang) / locale ($derivedLocale) is not available as locale on the server. You can't then format the value ($date) in this language."); 67 } 68 } 69 } 70 $date = syntax_plugin_combo_variable::replaceVariablesWithValuesFromContext($date); 71 $timeStamp = Iso8601Date::createFromString($date)->getDateTime()->getTimestamp(); 72 $formatted = strftime($format, $timeStamp); 73 if ($formatted === false) { 74 if ($lang === null) { 75 $lang = ""; 76 } 77 throw new ExceptionBadSyntax("Unable to format the date ($date) with the format ($format) and lang ($lang)"); 78 } 79 return $formatted; 80 } finally { 81 /** 82 * Restore the locale 83 */ 84 setlocale(LC_ALL, $actualLocale); 85 } 86 87 } 88 89 public static function handleEnterAndSpecial() 90 { 91 LogUtility::warning("The date component has been deprecated for the date variable", DateTag::CANONICAL); 92 } 93 94 public static function renderHtml(TagAttributes $tagAttributes): string 95 { 96 /** 97 * Locale 98 */ 99 $lang = $tagAttributes->getComponentAttributeValue(Lang::PROPERTY_NAME); 100 101 /** 102 * The format 103 */ 104 $format = $tagAttributes->getValue(DateTag::FORMAT_ATTRIBUTE, DateTag::DEFAULT_FORMAT); 105 /** 106 * The date 107 */ 108 $defaultDateTime = Iso8601Date::createFromNow()->toString(); 109 $date = $tagAttributes->getComponentAttributeValue(DateTag::DATE_ATTRIBUTE, $defaultDateTime); 110 try { 111 return DateTag::formatDateString($date, $format, $lang); 112 } catch (ExceptionBadSyntax $e) { 113 $message = "Error while formatting a date. Error: {$e->getMessage()}"; 114 LogUtility::error($message, DateTag::CANONICAL); 115 return LogUtility::wrapInRedForHtml($message); 116 } 117 } 118 119 public static function handleExit(\Doku_Handler $handler) 120 { 121 $callStack = CallStack::createFromHandler($handler); 122 $openingTag = $callStack->moveToPreviousCorrespondingOpeningCall(); 123 $call = $callStack->next(); 124 if ($call !== false) { 125 $date = $call->getCapturedContent(); 126 $openingTag->addAttribute(DateTag::DATE_ATTRIBUTE, $date); 127 $callStack->deleteActualCallAndPrevious(); 128 } 129 } 130} 131