PluginProbe
The Innovative Form Builder – IvyForms / 1.5
The Innovative Form Builder – IvyForms v1.5
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
ivyforms / backend / src / Common / Helpers / DateTimeHelper / DateTimeFormatter.php

DateTimeFormatter.php in The Innovative Form Builder – IvyForms 1.5, at backend/src/Common/Helpers/DateTimeHelper/DateTimeFormatter.php

216 lines 7.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace IvyForms\Common\Helpers\DateTimeHelper;
4
5 use DateTimeImmutable;
6
7 /**
8 * Handles formatting of combined date-time values for display.
9 */
10 class DateTimeFormatter
11 {
12 /**
13 * Format stored datetime values for frontend display.
14 * Supports both single timestamps and comma-separated range values.
15 *
16 * @param mixed $value Stored field value
17 * @return string Formatted datetime value
18 */
19 public static function formatDateTimeValue($value): string
20 {
21 if ($value === null || $value === '') {
22 return '';
23 }
24
25 $valueString = trim((string) $value);
26 if ($valueString === '') {
27 return '';
28 }
29
30 if (strpos($valueString, ',') !== false) {
31 return self::formatRangeParts($valueString);
32 }
33
34 return self::formatSinglePart($valueString);
35 }
36
37 /**
38 * Format a stored datetime value using the field's configured date/time format.
39 * Handles single values and comma-separated range values.
40 *
41 * @param mixed $value Stored field value (timestamp, canonical string, or comma-separated range)
42 * @param string $dateFormat JS-style date format token (e.g. MM/DD/YYYY, DD.MM.YYYY, YYYY-MM-DD)
43 * @param string $timeFormat Time format key: 'ampm', '24h', 'ampm-s', or '24h-s'
44 * @return string
45 */
46 public static function formatDateTimeWithOptions(
47 $value,
48 string $dateFormat,
49 string $timeFormat
50 ): string {
51 $valueString = trim((string) $value);
52 if ($valueString === '') {
53 return '';
54 }
55
56 if (strpos($valueString, ',') !== false) {
57 return self::buildSubRangesWithOptions($valueString, $dateFormat, $timeFormat);
58 }
59
60 return self::formatSingleWithOptions($valueString, $dateFormat, $timeFormat);
61 }
62
63 /**
64 * Format comma-separated range parts for default display.
65 *
66 * @param string $valueString Comma-separated value string
67 * @return string Formatted range
68 */
69 private static function formatRangeParts(string $valueString): string
70 {
71 $parts = array_values(array_filter(array_map('trim', explode(',', $valueString))));
72 $subRanges = [];
73 $count = count($parts);
74 for ($i = 0; $i < $count; $i += 2) {
75 $start = self::formatSinglePart($parts[$i]);
76 if ($start === '') {
77 continue;
78 }
79 $end = isset($parts[$i + 1]) ? self::formatSinglePart($parts[$i + 1]) : '';
80 $subRanges[] = ($end !== '' && $end !== $start) ? $start . ' - ' . $end : $start;
81 }
82 return implode(', ', $subRanges);
83 }
84
85 /**
86 * Format comma-separated parts as paired sub-ranges using configured date/time format.
87 *
88 * @param string $valueString Non-empty comma-separated value string
89 * @param string $dateFormat JS-style date format token
90 * @param string $timeFormat Time format key
91 * @return string
92 */
93 private static function buildSubRangesWithOptions(
94 string $valueString,
95 string $dateFormat,
96 string $timeFormat
97 ): string {
98 $parts = array_values(array_filter(array_map('trim', explode(',', $valueString))));
99 $subRanges = [];
100 $count = count($parts);
101 for ($i = 0; $i < $count; $i += 2) {
102 $start = self::formatSingleWithOptions($parts[$i], $dateFormat, $timeFormat);
103 if ($start === '') {
104 continue;
105 }
106 $end = isset($parts[$i + 1])
107 ? self::formatSingleWithOptions($parts[$i + 1], $dateFormat, $timeFormat)
108 : '';
109 $subRanges[] = ($end !== '' && $end !== $start) ? $start . ' - ' . $end : $start;
110 }
111 return implode(', ', $subRanges);
112 }
113
114 /**
115 * Format a single timestamp or canonical string for default display.
116 *
117 * @param string $part Single value
118 * @return string Formatted datetime string
119 */
120 private static function formatSinglePart(string $part): string
121 {
122 return is_numeric($part)
123 ? self::timestampToDateTime((int) $part)
124 : self::formatDateTimeSeparator($part);
125 }
126
127 /**
128 * Format a single datetime part using configured date/time format.
129 *
130 * @param string $part Single value (timestamp or canonical string)
131 * @param string $dateFormat JS-style date format token
132 * @param string $timeFormat Time format key
133 * @return string Formatted datetime string
134 */
135 private static function formatSingleWithOptions(
136 string $part,
137 string $dateFormat,
138 string $timeFormat
139 ): string {
140 if ($part === '') {
141 return '';
142 }
143
144 $timestamp = is_numeric($part) ? (int) $part : DateTimeHelper::dateTimeToTimestamp($part);
145
146 if ($timestamp === null) {
147 return self::formatDateTimeSeparator($part);
148 }
149
150 try {
151 $timezone = DateTimeHelper::getWpTimezone();
152 $dateTime = (new DateTimeImmutable('@' . $timestamp))->setTimezone($timezone);
153 } catch (\Throwable $exception) {
154 return self::formatDateTimeSeparator($part);
155 }
156
157 return $dateTime->format(self::buildPhpDateTimeFormat($dateFormat, $timeFormat));
158 }
159
160 /**
161 * Build a combined PHP date-time format string from JS-style tokens and a time format key.
162 *
163 * @param string $dateFormat JS-style date format (e.g. DD.MM.YYYY)
164 * @param string $timeFormat Time format key: 'ampm', '24h', 'ampm-s', or '24h-s'
165 * @return string PHP date() compatible format
166 */
167 private static function buildPhpDateTimeFormat(string $dateFormat, string $timeFormat): string
168 {
169 $phpDateFormat = str_replace(
170 ['YYYY', 'MM', 'DD'],
171 ['Y', 'm', 'd'],
172 $dateFormat ?: 'Y-m-d'
173 );
174
175 $timeFormatMap = [
176 'ampm' => 'g:i A',
177 'ampm-s' => 'g:i:s A',
178 '24h' => 'H:i',
179 '24h-s' => 'H:i:s',
180 ];
181
182 $phpTimeFormat = $timeFormatMap[$timeFormat] ?? 'H:i';
183
184 return $phpDateFormat . ' ' . $phpTimeFormat;
185 }
186
187 /**
188 * Format Unix timestamp back to datetime string.
189 * Includes seconds when the timestamp has a non-zero seconds component.
190 *
191 * @param int $timestamp Unix timestamp
192 * @return string Formatted datetime string
193 */
194 private static function timestampToDateTime(int $timestamp): string
195 {
196 $timezone = DateTimeHelper::getWpTimezone();
197 $dateTime = new DateTimeImmutable('@' . $timestamp);
198 $dateTime = $dateTime->setTimezone($timezone);
199
200 $format = ((int) $dateTime->format('s') > 0) ? 'Y-m-d H:i:s' : 'Y-m-d H:i';
201
202 return $dateTime->format($format);
203 }
204
205 /**
206 * Normalize display spacing around the datetime separator.
207 *
208 * @param string $value Raw datetime string
209 * @return string Datetime string with spaced separator
210 */
211 private static function formatDateTimeSeparator(string $value): string
212 {
213 return (string) preg_replace('/\s*\|\s*/', ' ', $value);
214 }
215 }
216