Mercurial > hg > rc1
comparison vendor/sabre/vobject/lib/Property/ICalendar/DateTime.php @ 7:430dbd5346f7
vendor sabre as distributed
author | Charlie Root |
---|---|
date | Sat, 13 Jan 2018 09:06:10 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
6:cec75ba50afc | 7:430dbd5346f7 |
---|---|
1 <?php | |
2 | |
3 namespace Sabre\VObject\Property\ICalendar; | |
4 | |
5 use DateTimeZone; | |
6 use Sabre\VObject\Property; | |
7 use Sabre\VObject\DateTimeParser; | |
8 use Sabre\VObject\TimeZoneUtil; | |
9 | |
10 /** | |
11 * DateTime property | |
12 * | |
13 * This object represents DATE-TIME values, as defined here: | |
14 * | |
15 * http://tools.ietf.org/html/rfc5545#section-3.3.4 | |
16 * | |
17 * This particular object has a bit of hackish magic that it may also in some | |
18 * cases represent a DATE value. This is because it's a common usecase to be | |
19 * able to change a DATE-TIME into a DATE. | |
20 * | |
21 * @copyright Copyright (C) 2011-2015 fruux GmbH (https://fruux.com/). | |
22 * @author Evert Pot (http://evertpot.com/) | |
23 * @license http://sabre.io/license/ Modified BSD License | |
24 */ | |
25 class DateTime extends Property { | |
26 | |
27 /** | |
28 * In case this is a multi-value property. This string will be used as a | |
29 * delimiter. | |
30 * | |
31 * @var string|null | |
32 */ | |
33 public $delimiter = ','; | |
34 | |
35 /** | |
36 * Sets a multi-valued property. | |
37 * | |
38 * You may also specify DateTime objects here. | |
39 * | |
40 * @param array $parts | |
41 * @return void | |
42 */ | |
43 public function setParts(array $parts) { | |
44 | |
45 if (isset($parts[0]) && $parts[0] instanceof \DateTime) { | |
46 $this->setDateTimes($parts); | |
47 } else { | |
48 parent::setParts($parts); | |
49 } | |
50 | |
51 } | |
52 | |
53 /** | |
54 * Updates the current value. | |
55 * | |
56 * This may be either a single, or multiple strings in an array. | |
57 * | |
58 * Instead of strings, you may also use DateTime here. | |
59 * | |
60 * @param string|array|\DateTime $value | |
61 * @return void | |
62 */ | |
63 public function setValue($value) { | |
64 | |
65 if (is_array($value) && isset($value[0]) && $value[0] instanceof \DateTime) { | |
66 $this->setDateTimes($value); | |
67 } elseif ($value instanceof \DateTime) { | |
68 $this->setDateTimes(array($value)); | |
69 } else { | |
70 parent::setValue($value); | |
71 } | |
72 | |
73 } | |
74 | |
75 /** | |
76 * Sets a raw value coming from a mimedir (iCalendar/vCard) file. | |
77 * | |
78 * This has been 'unfolded', so only 1 line will be passed. Unescaping is | |
79 * not yet done, but parameters are not included. | |
80 * | |
81 * @param string $val | |
82 * @return void | |
83 */ | |
84 public function setRawMimeDirValue($val) { | |
85 | |
86 $this->setValue(explode($this->delimiter, $val)); | |
87 | |
88 } | |
89 | |
90 /** | |
91 * Returns a raw mime-dir representation of the value. | |
92 * | |
93 * @return string | |
94 */ | |
95 public function getRawMimeDirValue() { | |
96 | |
97 return implode($this->delimiter, $this->getParts()); | |
98 | |
99 } | |
100 | |
101 /** | |
102 * Returns true if this is a DATE-TIME value, false if it's a DATE. | |
103 * | |
104 * @return bool | |
105 */ | |
106 public function hasTime() { | |
107 | |
108 return strtoupper((string)$this['VALUE']) !== 'DATE'; | |
109 | |
110 } | |
111 | |
112 /** | |
113 * Returns true if this is a floating DATE or DATE-TIME. | |
114 * | |
115 * Note that DATE is always floating. | |
116 */ | |
117 public function isFloating() { | |
118 | |
119 return | |
120 !$this->hasTime() || | |
121 ( | |
122 !isset($this['TZID']) && | |
123 strpos($this->getValue(),'Z')===false | |
124 ); | |
125 | |
126 } | |
127 | |
128 /** | |
129 * Returns a date-time value. | |
130 * | |
131 * Note that if this property contained more than 1 date-time, only the | |
132 * first will be returned. To get an array with multiple values, call | |
133 * getDateTimes. | |
134 * | |
135 * If no timezone information is known, because it's either an all-day | |
136 * property or floating time, we will use the DateTimeZone argument to | |
137 * figure out the exact date. | |
138 * | |
139 * @param DateTimeZone $timeZone | |
140 * @return \DateTime | |
141 */ | |
142 public function getDateTime(DateTimeZone $timeZone = null) { | |
143 | |
144 $dt = $this->getDateTimes($timeZone); | |
145 if (!$dt) return null; | |
146 | |
147 return $dt[0]; | |
148 | |
149 } | |
150 | |
151 /** | |
152 * Returns multiple date-time values. | |
153 * | |
154 * If no timezone information is known, because it's either an all-day | |
155 * property or floating time, we will use the DateTimeZone argument to | |
156 * figure out the exact date. | |
157 * | |
158 * @param DateTimeZone $timeZone | |
159 * @return \DateTime[] | |
160 */ | |
161 public function getDateTimes(DateTimeZone $timeZone = null) { | |
162 | |
163 // Does the property have a TZID? | |
164 $tzid = $this['TZID']; | |
165 | |
166 if ($tzid) { | |
167 $timeZone = TimeZoneUtil::getTimeZone((string)$tzid, $this->root); | |
168 } | |
169 | |
170 $dts = array(); | |
171 foreach($this->getParts() as $part) { | |
172 $dts[] = DateTimeParser::parse($part, $timeZone); | |
173 } | |
174 return $dts; | |
175 | |
176 } | |
177 | |
178 /** | |
179 * Sets the property as a DateTime object. | |
180 * | |
181 * @param \DateTime $dt | |
182 * @param bool isFloating If set to true, timezones will be ignored. | |
183 * @return void | |
184 */ | |
185 public function setDateTime(\DateTime $dt, $isFloating = false) { | |
186 | |
187 $this->setDateTimes(array($dt), $isFloating); | |
188 | |
189 } | |
190 | |
191 /** | |
192 * Sets the property as multiple date-time objects. | |
193 * | |
194 * The first value will be used as a reference for the timezones, and all | |
195 * the otehr values will be adjusted for that timezone | |
196 * | |
197 * @param \DateTime[] $dt | |
198 * @param bool isFloating If set to true, timezones will be ignored. | |
199 * @return void | |
200 */ | |
201 public function setDateTimes(array $dt, $isFloating = false) { | |
202 | |
203 $values = array(); | |
204 | |
205 if($this->hasTime()) { | |
206 | |
207 $tz = null; | |
208 $isUtc = false; | |
209 | |
210 foreach($dt as $d) { | |
211 | |
212 if ($isFloating) { | |
213 $values[] = $d->format('Ymd\\THis'); | |
214 continue; | |
215 } | |
216 if (is_null($tz)) { | |
217 $tz = $d->getTimeZone(); | |
218 $isUtc = in_array($tz->getName() , array('UTC', 'GMT', 'Z')); | |
219 if (!$isUtc) { | |
220 $this->offsetSet('TZID', $tz->getName()); | |
221 } | |
222 } else { | |
223 $d->setTimeZone($tz); | |
224 } | |
225 | |
226 if ($isUtc) { | |
227 $values[] = $d->format('Ymd\\THis\\Z'); | |
228 } else { | |
229 $values[] = $d->format('Ymd\\THis'); | |
230 } | |
231 | |
232 } | |
233 if ($isUtc || $isFloating) { | |
234 $this->offsetUnset('TZID'); | |
235 } | |
236 | |
237 } else { | |
238 | |
239 foreach($dt as $d) { | |
240 | |
241 $values[] = $d->format('Ymd'); | |
242 | |
243 } | |
244 $this->offsetUnset('TZID'); | |
245 | |
246 } | |
247 | |
248 $this->value = $values; | |
249 | |
250 } | |
251 | |
252 /** | |
253 * Returns the type of value. | |
254 * | |
255 * This corresponds to the VALUE= parameter. Every property also has a | |
256 * 'default' valueType. | |
257 * | |
258 * @return string | |
259 */ | |
260 public function getValueType() { | |
261 | |
262 return $this->hasTime()?'DATE-TIME':'DATE'; | |
263 | |
264 } | |
265 | |
266 /** | |
267 * Returns the value, in the format it should be encoded for json. | |
268 * | |
269 * This method must always return an array. | |
270 * | |
271 * @return array | |
272 */ | |
273 public function getJsonValue() { | |
274 | |
275 $dts = $this->getDateTimes(); | |
276 $hasTime = $this->hasTime(); | |
277 $isFloating = $this->isFloating(); | |
278 | |
279 $tz = $dts[0]->getTimeZone(); | |
280 $isUtc = $isFloating ? false : in_array($tz->getName() , array('UTC', 'GMT', 'Z')); | |
281 | |
282 return array_map( | |
283 function($dt) use ($hasTime, $isUtc) { | |
284 | |
285 if ($hasTime) { | |
286 return $dt->format('Y-m-d\\TH:i:s') . ($isUtc?'Z':''); | |
287 } else { | |
288 return $dt->format('Y-m-d'); | |
289 } | |
290 | |
291 }, | |
292 $dts | |
293 ); | |
294 | |
295 } | |
296 | |
297 /** | |
298 * Sets the json value, as it would appear in a jCard or jCal object. | |
299 * | |
300 * The value must always be an array. | |
301 * | |
302 * @param array $value | |
303 * @return void | |
304 */ | |
305 public function setJsonValue(array $value) { | |
306 | |
307 // dates and times in jCal have one difference to dates and times in | |
308 // iCalendar. In jCal date-parts are separated by dashes, and | |
309 // time-parts are separated by colons. It makes sense to just remove | |
310 // those. | |
311 $this->setValue( | |
312 array_map( | |
313 function($item) { | |
314 | |
315 return strtr($item, array(':'=>'', '-'=>'')); | |
316 | |
317 }, | |
318 $value | |
319 ) | |
320 ); | |
321 | |
322 } | |
323 /** | |
324 * We need to intercept offsetSet, because it may be used to alter the | |
325 * VALUE from DATE-TIME to DATE or vice-versa. | |
326 * | |
327 * @param string $name | |
328 * @param mixed $value | |
329 * @return void | |
330 */ | |
331 public function offsetSet($name, $value) { | |
332 | |
333 parent::offsetSet($name, $value); | |
334 if (strtoupper($name)!=='VALUE') { | |
335 return; | |
336 } | |
337 | |
338 // This will ensure that dates are correctly encoded. | |
339 $this->setDateTimes($this->getDateTimes()); | |
340 | |
341 } | |
342 | |
343 /** | |
344 * Validates the node for correctness. | |
345 * | |
346 * The following options are supported: | |
347 * Node::REPAIR - May attempt to automatically repair the problem. | |
348 * | |
349 * This method returns an array with detected problems. | |
350 * Every element has the following properties: | |
351 * | |
352 * * level - problem level. | |
353 * * message - A human-readable string describing the issue. | |
354 * * node - A reference to the problematic node. | |
355 * | |
356 * The level means: | |
357 * 1 - The issue was repaired (only happens if REPAIR was turned on) | |
358 * 2 - An inconsequential issue | |
359 * 3 - A severe issue. | |
360 * | |
361 * @param int $options | |
362 * @return array | |
363 */ | |
364 public function validate($options = 0) { | |
365 | |
366 $messages = parent::validate($options); | |
367 $valueType = $this->getValueType(); | |
368 $value = $this->getValue(); | |
369 try { | |
370 switch($valueType) { | |
371 case 'DATE' : | |
372 $foo = DateTimeParser::parseDate($value); | |
373 break; | |
374 case 'DATE-TIME' : | |
375 $foo = DateTimeParser::parseDateTime($value); | |
376 break; | |
377 } | |
378 } catch (\LogicException $e) { | |
379 $messages[] = array( | |
380 'level' => 3, | |
381 'message' => 'The supplied value (' . $value . ') is not a correct ' . $valueType, | |
382 'node' => $this, | |
383 ); | |
384 } | |
385 return $messages; | |
386 | |
387 } | |
388 } |