7
|
1 <?php
|
|
2
|
|
3 namespace Sabre\VObject\Property\VCard;
|
|
4
|
|
5 use
|
|
6 Sabre\VObject\DateTimeParser,
|
|
7 Sabre\VObject\Property\Text,
|
|
8 Sabre\VObject\Property,
|
|
9 DateTime;
|
|
10
|
|
11 /**
|
|
12 * DateAndOrTime property
|
|
13 *
|
|
14 * This object encodes DATE-AND-OR-TIME values.
|
|
15 *
|
|
16 * @copyright Copyright (C) 2011-2015 fruux GmbH (https://fruux.com/).
|
|
17 * @author Evert Pot (http://evertpot.com/)
|
|
18 * @license http://sabre.io/license/ Modified BSD License
|
|
19 */
|
|
20 class DateAndOrTime extends Property {
|
|
21
|
|
22 /**
|
|
23 * Field separator
|
|
24 *
|
|
25 * @var null|string
|
|
26 */
|
|
27 public $delimiter = null;
|
|
28
|
|
29 /**
|
|
30 * Returns the type of value.
|
|
31 *
|
|
32 * This corresponds to the VALUE= parameter. Every property also has a
|
|
33 * 'default' valueType.
|
|
34 *
|
|
35 * @return string
|
|
36 */
|
|
37 public function getValueType() {
|
|
38
|
|
39 return "DATE-AND-OR-TIME";
|
|
40
|
|
41 }
|
|
42
|
|
43 /**
|
|
44 * Sets a multi-valued property.
|
|
45 *
|
|
46 * You may also specify DateTime objects here.
|
|
47 *
|
|
48 * @param array $parts
|
|
49 * @return void
|
|
50 */
|
|
51 public function setParts(array $parts) {
|
|
52
|
|
53 if (count($parts)>1) {
|
|
54 throw new \InvalidArgumentException('Only one value allowed');
|
|
55 }
|
|
56 if (isset($parts[0]) && $parts[0] instanceof \DateTime) {
|
|
57 $this->setDateTime($parts[0]);
|
|
58 } else {
|
|
59 parent::setParts($parts);
|
|
60 }
|
|
61
|
|
62 }
|
|
63
|
|
64 /**
|
|
65 * Updates the current value.
|
|
66 *
|
|
67 * This may be either a single, or multiple strings in an array.
|
|
68 *
|
|
69 * Instead of strings, you may also use DateTime here.
|
|
70 *
|
|
71 * @param string|array|\DateTime $value
|
|
72 * @return void
|
|
73 */
|
|
74 public function setValue($value) {
|
|
75
|
|
76 if ($value instanceof \DateTime) {
|
|
77 $this->setDateTime($value);
|
|
78 } else {
|
|
79 parent::setValue($value);
|
|
80 }
|
|
81
|
|
82 }
|
|
83
|
|
84 /**
|
|
85 * Sets the property as a DateTime object.
|
|
86 *
|
|
87 * @param \DateTime $dt
|
|
88 * @return void
|
|
89 */
|
|
90 public function setDateTime(\DateTime $dt) {
|
|
91
|
|
92 $values = array();
|
|
93
|
|
94 $tz = null;
|
|
95 $isUtc = false;
|
|
96
|
|
97 $tz = $dt->getTimeZone();
|
|
98 $isUtc = in_array($tz->getName() , array('UTC', 'GMT', 'Z'));
|
|
99
|
|
100 if ($isUtc) {
|
|
101 $value = $dt->format('Ymd\\THis\\Z');
|
|
102 } else {
|
|
103 // Calculating the offset.
|
|
104 $value = $dt->format('Ymd\\THisO');
|
|
105 }
|
|
106
|
|
107 $this->value = $value;
|
|
108
|
|
109 }
|
|
110
|
|
111 /**
|
|
112 * Returns a date-time value.
|
|
113 *
|
|
114 * Note that if this property contained more than 1 date-time, only the
|
|
115 * first will be returned. To get an array with multiple values, call
|
|
116 * getDateTimes.
|
|
117 *
|
|
118 * If no time was specified, we will always use midnight (in the default
|
|
119 * timezone) as the time.
|
|
120 *
|
|
121 * If parts of the date were omitted, such as the year, we will grab the
|
|
122 * current values for those. So at the time of writing, if the year was
|
|
123 * omitted, we would have filled in 2014.
|
|
124 *
|
|
125 * @return \DateTime
|
|
126 */
|
|
127 public function getDateTime() {
|
|
128
|
|
129 $dts = array();
|
|
130 $now = new DateTime();
|
|
131
|
|
132 $tzFormat = $now->getTimezone()->getOffset($now)===0?'\\Z':'O';
|
|
133 $nowParts = DateTimeParser::parseVCardDateTime($now->format('Ymd\\This' . $tzFormat));
|
|
134
|
|
135 $value = $this->getValue();
|
|
136
|
|
137 $dateParts = DateTimeParser::parseVCardDateTime($this->getValue());
|
|
138
|
|
139 // This sets all the missing parts to the current date/time.
|
|
140 // So if the year was missing for a birthday, we're making it 'this
|
|
141 // year'.
|
|
142 foreach($dateParts as $k=>$v) {
|
|
143 if (is_null($v)) {
|
|
144 $dateParts[$k] = $nowParts[$k];
|
|
145 }
|
|
146 }
|
|
147 return new DateTime("$dateParts[year]-$dateParts[month]-$dateParts[date] $dateParts[hour]:$dateParts[minute]:$dateParts[second] $dateParts[timezone]");
|
|
148
|
|
149 }
|
|
150
|
|
151 /**
|
|
152 * Returns the value, in the format it should be encoded for json.
|
|
153 *
|
|
154 * This method must always return an array.
|
|
155 *
|
|
156 * @return array
|
|
157 */
|
|
158 public function getJsonValue() {
|
|
159
|
|
160 $parts = DateTimeParser::parseVCardDateTime($this->getValue());
|
|
161
|
|
162 $dateStr = '';
|
|
163
|
|
164 // Year
|
|
165 if (!is_null($parts['year'])) {
|
|
166 $dateStr.=$parts['year'];
|
|
167
|
|
168 if (!is_null($parts['month'])) {
|
|
169 // If a year and a month is set, we need to insert a separator
|
|
170 // dash.
|
|
171 $dateStr.='-';
|
|
172 }
|
|
173
|
|
174 } else {
|
|
175
|
|
176 if (!is_null($parts['month']) || !is_null($parts['date'])) {
|
|
177 // Inserting two dashes
|
|
178 $dateStr.='--';
|
|
179 }
|
|
180
|
|
181 }
|
|
182
|
|
183 // Month
|
|
184
|
|
185 if (!is_null($parts['month'])) {
|
|
186 $dateStr.=$parts['month'];
|
|
187
|
|
188 if (isset($parts['date'])) {
|
|
189 // If month and date are set, we need the separator dash.
|
|
190 $dateStr.='-';
|
|
191 }
|
|
192 } else {
|
|
193 if (isset($parts['date'])) {
|
|
194 // If the month is empty, and a date is set, we need a 'empty
|
|
195 // dash'
|
|
196 $dateStr.='-';
|
|
197 }
|
|
198 }
|
|
199
|
|
200 // Date
|
|
201 if (!is_null($parts['date'])) {
|
|
202 $dateStr.=$parts['date'];
|
|
203 }
|
|
204
|
|
205
|
|
206 // Early exit if we don't have a time string.
|
|
207 if (is_null($parts['hour']) && is_null($parts['minute']) && is_null($parts['second'])) {
|
|
208 return array($dateStr);
|
|
209 }
|
|
210
|
|
211 $dateStr.='T';
|
|
212
|
|
213 // Hour
|
|
214 if (!is_null($parts['hour'])) {
|
|
215 $dateStr.=$parts['hour'];
|
|
216
|
|
217 if (!is_null($parts['minute'])) {
|
|
218 $dateStr.=':';
|
|
219 }
|
|
220 } else {
|
|
221 // We know either minute or second _must_ be set, so we insert a
|
|
222 // dash for an empty value.
|
|
223 $dateStr.='-';
|
|
224 }
|
|
225
|
|
226 // Minute
|
|
227 if (!is_null($parts['minute'])) {
|
|
228 $dateStr.=$parts['minute'];
|
|
229
|
|
230 if (!is_null($parts['second'])) {
|
|
231 $dateStr.=':';
|
|
232 }
|
|
233 } else {
|
|
234 if (isset($parts['second'])) {
|
|
235 // Dash for empty minute
|
|
236 $dateStr.='-';
|
|
237 }
|
|
238 }
|
|
239
|
|
240 // Second
|
|
241 if (!is_null($parts['second'])) {
|
|
242 $dateStr.=$parts['second'];
|
|
243 }
|
|
244
|
|
245 // Timezone
|
|
246 if (!is_null($parts['timezone'])) {
|
|
247 $dateStr.=$parts['timezone'];
|
|
248 }
|
|
249
|
|
250 return array($dateStr);
|
|
251
|
|
252 }
|
|
253
|
|
254 /**
|
|
255 * Sets a raw value coming from a mimedir (iCalendar/vCard) file.
|
|
256 *
|
|
257 * This has been 'unfolded', so only 1 line will be passed. Unescaping is
|
|
258 * not yet done, but parameters are not included.
|
|
259 *
|
|
260 * @param string $val
|
|
261 * @return void
|
|
262 */
|
|
263 public function setRawMimeDirValue($val) {
|
|
264
|
|
265 $this->setValue($val);
|
|
266
|
|
267 }
|
|
268
|
|
269 /**
|
|
270 * Returns a raw mime-dir representation of the value.
|
|
271 *
|
|
272 * @return string
|
|
273 */
|
|
274 public function getRawMimeDirValue() {
|
|
275
|
|
276 return implode($this->delimiter, $this->getParts());
|
|
277
|
|
278 }
|
|
279
|
|
280 /**
|
|
281 * Validates the node for correctness.
|
|
282 *
|
|
283 * The following options are supported:
|
|
284 * Node::REPAIR - May attempt to automatically repair the problem.
|
|
285 *
|
|
286 * This method returns an array with detected problems.
|
|
287 * Every element has the following properties:
|
|
288 *
|
|
289 * * level - problem level.
|
|
290 * * message - A human-readable string describing the issue.
|
|
291 * * node - A reference to the problematic node.
|
|
292 *
|
|
293 * The level means:
|
|
294 * 1 - The issue was repaired (only happens if REPAIR was turned on)
|
|
295 * 2 - An inconsequential issue
|
|
296 * 3 - A severe issue.
|
|
297 *
|
|
298 * @param int $options
|
|
299 * @return array
|
|
300 */
|
|
301 public function validate($options = 0) {
|
|
302
|
|
303 $messages = parent::validate($options);
|
|
304 $value = $this->getValue();
|
|
305 try {
|
|
306 DateTimeParser::parseVCardDateTime($value);
|
|
307 } catch (\InvalidArgumentException $e) {
|
|
308 $messages[] = array(
|
|
309 'level' => 3,
|
|
310 'message' => 'The supplied value (' . $value . ') is not a correct DATE-AND-OR-TIME property',
|
|
311 'node' => $this,
|
|
312 );
|
|
313 }
|
|
314 return $messages;
|
|
315
|
|
316 }
|
|
317 }
|