1 <?php
2
3 /**
4 * String formatter class.
5 *
6 * @package redaxo\core
7 */
8 abstract class rex_formatter
9 {
10 /**
11 * It's not allowed to create instances of this class.
12 */
13 private function __construct()
14 {
15 }
16
17 /**
18 * Formats a string by the given format type.
19 *
20 * @param string $value Value
21 * @param string $formatType Format type (any method name of this class)
22 * @param mixed $format For possible values look at the other methods of this class
23 *
24 * @return string
25 *
26 * @throws InvalidArgumentException
27 */
28 public static function format($value, $formatType, $format)
29 {
30 if (!is_callable([self::class, $formatType])) {
31 throw new InvalidArgumentException('Unknown $formatType: "' . $formatType . '"!');
32 }
33 return self::$formatType($value, $format);
34 }
35
36 /**
37 * Formats a string by `date()`.
38 *
39 * @see http://www.php.net/manual/en/function.date.php
40 *
41 * @param string $value Unix timestamp or datetime string for `strtotime`
42 * @param string $format Default format is `d.m.Y`
43 *
44 * @return string
45 */
46 public static function date($value, $format = '')
47 {
48 if (empty($value)) {
49 return '';
50 }
51
52 if ($format == '') {
53 $format = 'd.m.Y';
54 }
55
56 return date($format, self::getTimestamp($value));
57 }
58
59 /**
60 * Formats a string by `strftime()`.
61 *
62 * @see http://www.php.net/manual/en/function.strftime.php
63 *
64 * @param string $value Unix timestamp or datetime string for `strtotime`
65 * @param string $format Possible values are format strings like in `strftime` or "date" or "datetime", default is "date"
66 *
67 * @return string
68 */
69 public static function strftime($value, $format = '')
70 {
71 if (empty($value)) {
72 return '';
73 }
74
75 if ($format == '' || $format == 'date') {
76 // Default REX-Dateformat
77 $format = rex_i18n::msg('dateformat');
78 } elseif ($format == 'datetime') {
79 // Default REX-Datetimeformat
80 $format = rex_i18n::msg('datetimeformat');
81 } elseif ($format == 'time') {
82 // Default REX-Timeformat
83 $format = rex_i18n::msg('timeformat');
84 }
85 return strftime($format, self::getTimestamp($value));
86 }
87
88 /**
89 * Formats a string by `number_format()`.
90 *
91 * @see http://www.php.net/manual/en/function.number-format.php
92 *
93 * @param string $value Value
94 * @param array $format Array with number of decimals, decimals point and thousands separator, default is `array(2, ',', ' ')`
95 *
96 * @return string
97 */
98 public static function number($value, $format = [])
99 {
100 if (!is_array($format)) {
101 $format = [];
102 }
103
104 // Kommastellen
105 if (!isset($format[0])) {
106 $format[0] = 2;
107 }
108 // Dezimal Trennzeichen
109 if (!isset($format[1])) {
110 $format[1] = ',';
111 }
112 // Tausender Trennzeichen
113 if (!isset($format[2])) {
114 $format[2] = ' ';
115 }
116 return number_format($value, $format[0], $format[1], $format[2]);
117 }
118
119 /**
120 * Formats a string as bytes.
121 *
122 * @param string $value Value
123 * @param array $format Same as {@link rex_formatter::number()}
124 *
125 * @return string
126 */
127 public static function bytes($value, $format = [])
128 {
129 $units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
130 $unit_index = 0;
131 while (($value / 1024) >= 1) {
132 $value /= 1024;
133 ++$unit_index;
134 }
135
136 if (isset($format[0])) {
137 $z = (int) ($value * pow(10, $precision = (int) ($format[0])));
138 for ($i = 0; $i < (int) $precision; ++$i) {
139 if (($z % 10) == 0) {
140 $format[0] = (int) ($format[0]) - 1;
141 $z = (int) ($z / 10);
142 } else {
143 break;
144 }
145 }
146 }
147
148 return self::number($value, $format) . ' ' . $units[$unit_index];
149 }
150
151 /**
152 * Formats a string by `sprintf()`.
153 *
154 * @see http://www.php.net/manual/en/function.sprintf.php
155 *
156 * @param string $value Value
157 * @param string $format
158 *
159 * @return string
160 */
161 public static function sprintf($value, $format = '')
162 {
163 if ($format == '') {
164 $format = '%s';
165 }
166 return sprintf($format, $value);
167 }
168
169 /**
170 * Formats a string by `nl2br`.
171 *
172 * @see http://www.php.net/manual/en/function.nl2br.php
173 *
174 * @param string $value Value
175 *
176 * @return string
177 */
178 public static function nl2br($value)
179 {
180 return nl2br($value);
181 }
182
183 /**
184 * Truncates a string.
185 *
186 * @param string $value Value
187 * @param array $format Default format is `array('length' => 80, 'etc' => '...', 'break_words' => false)`
188 *
189 * @return string
190 */
191 public static function truncate($value, $format = [])
192 {
193 if (!is_array($format)) {
194 $format = [];
195 }
196
197 // Max-String-laenge
198 if (empty($format['length'])) {
199 $format['length'] = 80;
200 }
201
202 // ETC
203 if (empty($format['etc'])) {
204 $format['etc'] = '...';
205 }
206
207 // Break-Words?
208 if (empty($format['break_words'])) {
209 $format['break_words'] = false;
210 }
211
212 if (mb_strlen($value) > $format['length']) {
213 $format['length'] -= mb_strlen($format['etc']);
214 if (!$format['break_words']) {
215 $value = preg_replace('/\s+?(\S+)?$/', '', substr($value, 0, $format['length'] + 1));
216 }
217
218 return substr($value, 0, $format['length']) . $format['etc'];
219 }
220
221 return $value;
222 }
223
224 /**
225 * Avoid widows in a string.
226 *
227 * @param string $value
228 *
229 * @return string
230 */
231 public static function widont($value)
232 {
233 // Sollte ein Wort allein auf einer Zeile vorkommen, wird dies unterbunden
234 $value = rtrim($value);
235 $space = strrpos($value, ' ');
236 if ($space !== false) {
237 $value = substr($value, 0, $space) . ' ' . substr($value, $space + 1);
238 }
239 return $value;
240 }
241
242 /**
243 * Formats a version string by `sprintf()`.
244 *
245 * @see http://www.php.net/manual/en/function.sprintf.php
246 *
247 * @param string $value Version
248 * @param string $format Version format, e.g. "%s.%s"
249 *
250 * @return string
251 */
252 public static function version($value, $format)
253 {
254 return vsprintf($format, rex_string::versionSplit($value));
255 }
256
257 /**
258 * Formats a string as link.
259 *
260 * @param string $value URL
261 * @param array $format Array with link attributes and params
262 *
263 * @return string Link
264 */
265 public static function url($value, $format = [])
266 {
267 if (empty($value)) {
268 return '';
269 }
270
271 if (!is_array($format)) {
272 $format = [];
273 }
274
275 // Linkattribute
276 if (empty($format['attr'])) {
277 $format['attr'] = '';
278 }
279 // Linkparameter (z.b. subject=Hallo Sir)
280 if (empty($format['params'])) {
281 $format['params'] = '';
282 } else {
283 if (strstr($format['params'], '?') != $format['params']) {
284 $format['params'] = '?' . $format['params'];
285 }
286 }
287 // Protokoll
288 if (!preg_match('@((ht|f)tps?|telnet|redaxo)://@', $value)) {
289 $value = 'http://' . $value;
290 }
291
292 return '<a href="' . rex_escape($value . $format['params']) . '"' . $format['attr'] . '>' . rex_escape($value) . '</a>';
293 }
294
295 /**
296 * Formats a string as email link.
297 *
298 * @param string $value Email
299 * @param array $format Array with link attributes and params
300 *
301 * @return string Email link
302 */
303 public static function email($value, $format = [])
304 {
305 if (!is_array($format)) {
306 $format = [];
307 }
308
309 // Linkattribute
310 if (empty($format['attr'])) {
311 $format['attr'] = '';
312 }
313 // Linkparameter (z.b. subject=Hallo Sir)
314 if (empty($format['params'])) {
315 $format['params'] = '';
316 } else {
317 if (strstr($format['params'], '?') != $format['params']) {
318 $format['params'] = '?' . $format['params'];
319 }
320 }
321 // Url formatierung
322 return '<a href="mailto:' . rex_escape($value . $format['params']) . '"' . $format['attr'] . '>' . rex_escape($value) . '</a>';
323 }
324
325 /**
326 * Formats a string by a custom callable.
327 *
328 * @param string $value Value
329 * @param callable|array $format A callable or an array of a callable and additional params
330 *
331 * @return string
332 *
333 * @throws rex_exception
334 */
335 public static function custom($value, $format)
336 {
337 if (!is_callable($format)) {
338 if (!is_callable($format[0])) {
339 throw new rex_exception('Unable to find callable ' . $format[0] . ' for custom format!');
340 }
341
342 $params = [];
343 $params['subject'] = $value;
344 if (is_array($format[1])) {
345 $params = array_merge($format[1], $params);
346 } else {
347 $params['params'] = $format[1];
348 }
349 // $format ist in der Form
350 // array(Name des Callables, Weitere Parameter)
351 return call_user_func($format[0], $params);
352 }
353
354 return call_user_func($format, $value);
355 }
356
357 private static function getTimestamp($value)
358 {
359 if (is_numeric($value)) {
360 return $value;
361 }
362
363 return strtotime($value);
364 }
365 }
366