[BUGFIX] Correctly treat relative date specification in date-VH
[Packages/TYPO3.CMS.git] / typo3 / sysext / fluid / Classes / ViewHelpers / Format / DateViewHelper.php
1 <?php
2 namespace TYPO3\CMS\Fluid\ViewHelpers\Format;
3
4 /* *
5 * This script is backported from the TYPO3 Flow package "TYPO3.Fluid". *
6 * *
7 * It is free software; you can redistribute it and/or modify it under *
8 * the terms of the GNU Lesser General Public License, either version 3 *
9 * of the License, or (at your option) any later version. *
10 * *
11 * The TYPO3 project - inspiring people to share! *
12 * */
13
14 use TYPO3\CMS\Core\Utility\MathUtility;
15 use TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface;
16 use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
17 use TYPO3\CMS\Fluid\Core\ViewHelper\Exception;
18 use TYPO3\CMS\Fluid\Core\ViewHelper\Facets\CompilableInterface;
19
20 /**
21 * Formats a \DateTime object.
22 *
23 * = Examples =
24 *
25 * <code title="Defaults">
26 * <f:format.date>{dateObject}</f:format.date>
27 * </code>
28 * <output>
29 * 1980-12-13
30 * (depending on the current date)
31 * </output>
32 *
33 * <code title="Custom date format">
34 * <f:format.date format="H:i">{dateObject}</f:format.date>
35 * </code>
36 * <output>
37 * 01:23
38 * (depending on the current time)
39 * </output>
40 *
41 * <code title="Relative date with given time">
42 * <f:format.date format="Y" base="{dateObject}">-1 year</f:format.date>
43 * </code>
44 * <output>
45 * 2016
46 * (assuming dateObject is in 2017)
47 * </output>
48 *
49 * <code title="strtotime string">
50 * <f:format.date format="d.m.Y - H:i:s">+1 week 2 days 4 hours 2 seconds</f:format.date>
51 * </code>
52 * <output>
53 * 13.12.1980 - 21:03:42
54 * (depending on the current time, see http://www.php.net/manual/en/function.strtotime.php)
55 * </output>
56 *
57 * <code title="Localized dates using strftime date format">
58 * <f:format.date format="%d. %B %Y">{dateObject}</f:format.date>
59 * </code>
60 * <output>
61 * 13. Dezember 1980
62 * (depending on the current date and defined locale. In the example you see the 1980-12-13 in a german locale)
63 * </output>
64 *
65 * <code title="Inline notation">
66 * {f:format.date(date: dateObject)}
67 * </code>
68 * <output>
69 * 1980-12-13
70 * (depending on the value of {dateObject})
71 * </output>
72 *
73 * <code title="Inline notation (2nd variant)">
74 * {dateObject -> f:format.date()}
75 * </code>
76 * <output>
77 * 1980-12-13
78 * (depending on the value of {dateObject})
79 * </output>
80 *
81 * @api
82 */
83 class DateViewHelper extends AbstractViewHelper implements CompilableInterface {
84
85 /**
86 * @var bool
87 */
88 protected $escapingInterceptorEnabled = FALSE;
89
90 /**
91 * Render the supplied DateTime object as a formatted date.
92 *
93 * @param mixed $date either a DateTime object or a string that is accepted by DateTime constructor
94 * @param string $format Format String which is taken to format the Date/Time
95 * @param mixed $base A base time (a DateTime object or a string) used if $date is a relative date specification. Defaults to current time.
96 *
97 * @return string Formatted date
98 * @throws Exception
99 * @api
100 */
101 public function render($date = NULL, $format = '', $base = NULL) {
102 return static::renderStatic(
103 array(
104 'date' => $date,
105 'format' => $format,
106 'base' => $base
107 ),
108 $this->buildRenderChildrenClosure(),
109 $this->renderingContext
110 );
111 }
112
113 /**
114 * @param array $arguments
115 * @param \Closure $renderChildrenClosure
116 * @param RenderingContextInterface $renderingContext
117 *
118 * @return string
119 * @throws Exception
120 */
121 static public function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) {
122 $date = $arguments['date'];
123 $format = $arguments['format'];
124 $base = $arguments['base'] === NULL ? time() : $arguments['base'];
125 if ($format === '') {
126 $format = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] ?: 'Y-m-d';
127 }
128
129 if ($date === NULL) {
130 $date = $renderChildrenClosure();
131 if ($date === NULL) {
132 return '';
133 }
134 }
135 if (!$date instanceof \DateTime) {
136 try {
137 $base = $base instanceof \DateTime ? $base->format('U') : strtotime((MathUtility::canBeInterpretedAsInteger($base) ? '@' : '') . $base);
138 $dateTimestamp = strtotime((MathUtility::canBeInterpretedAsInteger($date) ? '@' : '') . $date, $base);
139 $date = new \DateTime('@' . $dateTimestamp);
140 $date->setTimezone(new \DateTimeZone(date_default_timezone_get()));
141 } catch (\Exception $exception) {
142 throw new Exception('"' . $date . '" could not be parsed by \DateTime constructor.', 1241722579);
143 }
144 }
145
146 if (strpos($format, '%') !== FALSE) {
147 return strftime($format, $date->format('U'));
148 } else {
149 return $date->format($format);
150 }
151 }
152
153 }