7
|
1 <?php
|
|
2
|
|
3 namespace Sabre\VObject;
|
|
4
|
|
5 use
|
|
6 ArrayObject;
|
|
7
|
|
8 /**
|
|
9 * VObject Parameter
|
|
10 *
|
|
11 * This class represents a parameter. A parameter is always tied to a property.
|
|
12 * In the case of:
|
|
13 * DTSTART;VALUE=DATE:20101108
|
|
14 * VALUE=DATE would be the parameter name and value.
|
|
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 Parameter extends Node {
|
|
21
|
|
22 /**
|
|
23 * Parameter name
|
|
24 *
|
|
25 * @var string
|
|
26 */
|
|
27 public $name;
|
|
28
|
|
29 /**
|
|
30 * vCard 2.1 allows parameters to be encoded without a name.
|
|
31 *
|
|
32 * We can deduce the parameter name based on it's value.
|
|
33 *
|
|
34 * @var bool
|
|
35 */
|
|
36 public $noName = false;
|
|
37
|
|
38 /**
|
|
39 * Parameter value
|
|
40 *
|
|
41 * @var string
|
|
42 */
|
|
43 protected $value;
|
|
44
|
|
45 /**
|
|
46 * Sets up the object.
|
|
47 *
|
|
48 * It's recommended to use the create:: factory method instead.
|
|
49 *
|
|
50 * @param string $name
|
|
51 * @param string $value
|
|
52 */
|
|
53 public function __construct(Document $root, $name, $value = null) {
|
|
54
|
|
55 $this->name = strtoupper($name);
|
|
56 $this->root = $root;
|
|
57 if (is_null($name)) {
|
|
58 $this->noName = true;
|
|
59 $this->name = static::guessParameterNameByValue($value);
|
|
60 }
|
|
61
|
|
62 // If guessParameterNameByValue() returns an empty string
|
|
63 // above, we're actually dealing with a parameter that has no value.
|
|
64 // In that case we have to move the value to the name.
|
|
65 if ($this->name === '') {
|
|
66 $this->noName = false;
|
|
67 $this->name = strtoupper($value);
|
|
68 } else {
|
|
69 $this->setValue($value);
|
|
70 }
|
|
71
|
|
72 }
|
|
73
|
|
74 /**
|
|
75 * Try to guess property name by value, can be used for vCard 2.1 nameless parameters.
|
|
76 *
|
|
77 * Figuring out what the name should have been. Note that a ton of
|
|
78 * these are rather silly in 2014 and would probably rarely be
|
|
79 * used, but we like to be complete.
|
|
80 *
|
|
81 * @param string $value
|
|
82 * @return string
|
|
83 */
|
|
84 public static function guessParameterNameByValue($value) {
|
|
85 switch(strtoupper($value)) {
|
|
86
|
|
87 // Encodings
|
|
88 case '7-BIT' :
|
|
89 case 'QUOTED-PRINTABLE' :
|
|
90 case 'BASE64' :
|
|
91 $name = 'ENCODING';
|
|
92 break;
|
|
93
|
|
94 // Common types
|
|
95 case 'WORK' :
|
|
96 case 'HOME' :
|
|
97 case 'PREF' :
|
|
98
|
|
99 // Delivery Label Type
|
|
100 case 'DOM' :
|
|
101 case 'INTL' :
|
|
102 case 'POSTAL' :
|
|
103 case 'PARCEL' :
|
|
104
|
|
105 // Telephone types
|
|
106 case 'VOICE' :
|
|
107 case 'FAX' :
|
|
108 case 'MSG' :
|
|
109 case 'CELL' :
|
|
110 case 'PAGER' :
|
|
111 case 'BBS' :
|
|
112 case 'MODEM' :
|
|
113 case 'CAR' :
|
|
114 case 'ISDN' :
|
|
115 case 'VIDEO' :
|
|
116
|
|
117 // EMAIL types (lol)
|
|
118 case 'AOL' :
|
|
119 case 'APPLELINK' :
|
|
120 case 'ATTMAIL' :
|
|
121 case 'CIS' :
|
|
122 case 'EWORLD' :
|
|
123 case 'INTERNET' :
|
|
124 case 'IBMMAIL' :
|
|
125 case 'MCIMAIL' :
|
|
126 case 'POWERSHARE' :
|
|
127 case 'PRODIGY' :
|
|
128 case 'TLX' :
|
|
129 case 'X400' :
|
|
130
|
|
131 // Photo / Logo format types
|
|
132 case 'GIF' :
|
|
133 case 'CGM' :
|
|
134 case 'WMF' :
|
|
135 case 'BMP' :
|
|
136 case 'DIB' :
|
|
137 case 'PICT' :
|
|
138 case 'TIFF' :
|
|
139 case 'PDF ':
|
|
140 case 'PS' :
|
|
141 case 'JPEG' :
|
|
142 case 'MPEG' :
|
|
143 case 'MPEG2' :
|
|
144 case 'AVI' :
|
|
145 case 'QTIME' :
|
|
146
|
|
147 // Sound Digital Audio Type
|
|
148 case 'WAVE' :
|
|
149 case 'PCM' :
|
|
150 case 'AIFF' :
|
|
151
|
|
152 // Key types
|
|
153 case 'X509' :
|
|
154 case 'PGP' :
|
|
155 $name = 'TYPE';
|
|
156 break;
|
|
157
|
|
158 // Value types
|
|
159 case 'INLINE' :
|
|
160 case 'URL' :
|
|
161 case 'CONTENT-ID' :
|
|
162 case 'CID' :
|
|
163 $name = 'VALUE';
|
|
164 break;
|
|
165
|
|
166 default:
|
|
167 $name = '';
|
|
168 }
|
|
169
|
|
170 return $name;
|
|
171 }
|
|
172
|
|
173 /**
|
|
174 * Updates the current value.
|
|
175 *
|
|
176 * This may be either a single, or multiple strings in an array.
|
|
177 *
|
|
178 * @param string|array $value
|
|
179 * @return void
|
|
180 */
|
|
181 public function setValue($value) {
|
|
182
|
|
183 $this->value = $value;
|
|
184
|
|
185 }
|
|
186
|
|
187 /**
|
|
188 * Returns the current value
|
|
189 *
|
|
190 * This method will always return a string, or null. If there were multiple
|
|
191 * values, it will automatically concatinate them (separated by comma).
|
|
192 *
|
|
193 * @return string|null
|
|
194 */
|
|
195 public function getValue() {
|
|
196
|
|
197 if (is_array($this->value)) {
|
|
198 return implode(',' , $this->value);
|
|
199 } else {
|
|
200 return $this->value;
|
|
201 }
|
|
202
|
|
203 }
|
|
204
|
|
205 /**
|
|
206 * Sets multiple values for this parameter.
|
|
207 *
|
|
208 * @param array $value
|
|
209 * @return void
|
|
210 */
|
|
211 public function setParts(array $value) {
|
|
212
|
|
213 $this->value = $value;
|
|
214
|
|
215 }
|
|
216
|
|
217 /**
|
|
218 * Returns all values for this parameter.
|
|
219 *
|
|
220 * If there were no values, an empty array will be returned.
|
|
221 *
|
|
222 * @return array
|
|
223 */
|
|
224 public function getParts() {
|
|
225
|
|
226 if (is_array($this->value)) {
|
|
227 return $this->value;
|
|
228 } elseif (is_null($this->value)) {
|
|
229 return array();
|
|
230 } else {
|
|
231 return array($this->value);
|
|
232 }
|
|
233
|
|
234 }
|
|
235
|
|
236 /**
|
|
237 * Adds a value to this parameter
|
|
238 *
|
|
239 * If the argument is specified as an array, all items will be added to the
|
|
240 * parameter value list.
|
|
241 *
|
|
242 * @param string|array $part
|
|
243 * @return void
|
|
244 */
|
|
245 public function addValue($part) {
|
|
246
|
|
247 if (is_null($this->value)) {
|
|
248 $this->value = $part;
|
|
249 } else {
|
|
250 $this->value = array_merge((array)$this->value, (array)$part);
|
|
251 }
|
|
252
|
|
253 }
|
|
254
|
|
255 /**
|
|
256 * Checks if this parameter contains the specified value.
|
|
257 *
|
|
258 * This is a case-insensitive match. It makes sense to call this for for
|
|
259 * instance the TYPE parameter, to see if it contains a keyword such as
|
|
260 * 'WORK' or 'FAX'.
|
|
261 *
|
|
262 * @param string $value
|
|
263 * @return bool
|
|
264 */
|
|
265 public function has($value) {
|
|
266
|
|
267 return in_array(
|
|
268 strtolower($value),
|
|
269 array_map('strtolower', (array)$this->value)
|
|
270 );
|
|
271
|
|
272 }
|
|
273
|
|
274 /**
|
|
275 * Turns the object back into a serialized blob.
|
|
276 *
|
|
277 * @return string
|
|
278 */
|
|
279 public function serialize() {
|
|
280
|
|
281 $value = $this->getParts();
|
|
282
|
|
283 if (count($value)===0) {
|
|
284 return $this->name . '=';
|
|
285 }
|
|
286
|
|
287 if ($this->root->getDocumentType() === Document::VCARD21 && $this->noName) {
|
|
288
|
|
289 return implode(';', $value);
|
|
290
|
|
291 }
|
|
292
|
|
293 return $this->name . '=' . array_reduce(
|
|
294 $value,
|
|
295 function($out, $item) {
|
|
296
|
|
297 if (!is_null($out)) $out.=',';
|
|
298
|
|
299 // If there's no special characters in the string, we'll use the simple
|
|
300 // format.
|
|
301 //
|
|
302 // The list of special characters is defined as:
|
|
303 //
|
|
304 // Any character except CONTROL, DQUOTE, ";", ":", ","
|
|
305 //
|
|
306 // by the iCalendar spec:
|
|
307 // https://tools.ietf.org/html/rfc5545#section-3.1
|
|
308 //
|
|
309 // And we add ^ to that because of:
|
|
310 // https://tools.ietf.org/html/rfc6868
|
|
311 //
|
|
312 // But we've found that iCal (7.0, shipped with OSX 10.9)
|
|
313 // severaly trips on + characters not being quoted, so we
|
|
314 // added + as well.
|
|
315 if (!preg_match('#(?: [\n":;\^,\+] )#x', $item)) {
|
|
316 return $out.$item;
|
|
317 } else {
|
|
318 // Enclosing in double-quotes, and using RFC6868 for encoding any
|
|
319 // special characters
|
|
320 $out.='"' . strtr(
|
|
321 $item,
|
|
322 array(
|
|
323 '^' => '^^',
|
|
324 "\n" => '^n',
|
|
325 '"' => '^\'',
|
|
326 )
|
|
327 ) . '"';
|
|
328 return $out;
|
|
329 }
|
|
330
|
|
331 }
|
|
332 );
|
|
333
|
|
334 }
|
|
335
|
|
336 /**
|
|
337 * This method returns an array, with the representation as it should be
|
|
338 * encoded in json. This is used to create jCard or jCal documents.
|
|
339 *
|
|
340 * @return array
|
|
341 */
|
|
342 public function jsonSerialize() {
|
|
343
|
|
344 return $this->value;
|
|
345
|
|
346 }
|
|
347
|
|
348 /**
|
|
349 * Called when this object is being cast to a string
|
|
350 *
|
|
351 * @return string
|
|
352 */
|
|
353 public function __toString() {
|
|
354
|
|
355 return (string)$this->getValue();
|
|
356
|
|
357 }
|
|
358
|
|
359 /**
|
|
360 * Returns the iterator for this object
|
|
361 *
|
|
362 * @return ElementList
|
|
363 */
|
|
364 public function getIterator() {
|
|
365
|
|
366 if (!is_null($this->iterator))
|
|
367 return $this->iterator;
|
|
368
|
|
369 return $this->iterator = new ArrayObject((array)$this->value);
|
|
370
|
|
371 }
|
|
372
|
|
373 }
|