ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
VCard.php
Go to the documentation of this file.
1<?php
2
4
6use Sabre\Xml;
7
18class VCard extends VObject\Document {
19
27 static $defaultName = 'VCARD';
28
34 private $version = null;
35
41 static $componentMap = [
42 'VCARD' => 'Sabre\\VObject\\Component\\VCard',
43 ];
44
50 static $valueMap = [
51 'BINARY' => 'Sabre\\VObject\\Property\\Binary',
52 'BOOLEAN' => 'Sabre\\VObject\\Property\\Boolean',
53 'CONTENT-ID' => 'Sabre\\VObject\\Property\\FlatText', // vCard 2.1 only
54 'DATE' => 'Sabre\\VObject\\Property\\VCard\\Date',
55 'DATE-TIME' => 'Sabre\\VObject\\Property\\VCard\\DateTime',
56 'DATE-AND-OR-TIME' => 'Sabre\\VObject\\Property\\VCard\\DateAndOrTime', // vCard only
57 'FLOAT' => 'Sabre\\VObject\\Property\\FloatValue',
58 'INTEGER' => 'Sabre\\VObject\\Property\\IntegerValue',
59 'LANGUAGE-TAG' => 'Sabre\\VObject\\Property\\VCard\\LanguageTag',
60 'TIMESTAMP' => 'Sabre\\VObject\\Property\\VCard\\TimeStamp',
61 'TEXT' => 'Sabre\\VObject\\Property\\Text',
62 'TIME' => 'Sabre\\VObject\\Property\\Time',
63 'UNKNOWN' => 'Sabre\\VObject\\Property\\Unknown', // jCard / jCal-only.
64 'URI' => 'Sabre\\VObject\\Property\\Uri',
65 'URL' => 'Sabre\\VObject\\Property\\Uri', // vCard 2.1 only
66 'UTC-OFFSET' => 'Sabre\\VObject\\Property\\UtcOffset',
67 ];
68
74 static $propertyMap = [
75
76 // vCard 2.1 properties and up
77 'N' => 'Sabre\\VObject\\Property\\Text',
78 'FN' => 'Sabre\\VObject\\Property\\FlatText',
79 'PHOTO' => 'Sabre\\VObject\\Property\\Binary',
80 'BDAY' => 'Sabre\\VObject\\Property\\VCard\\DateAndOrTime',
81 'ADR' => 'Sabre\\VObject\\Property\\Text',
82 'LABEL' => 'Sabre\\VObject\\Property\\FlatText', // Removed in vCard 4.0
83 'TEL' => 'Sabre\\VObject\\Property\\FlatText',
84 'EMAIL' => 'Sabre\\VObject\\Property\\FlatText',
85 'MAILER' => 'Sabre\\VObject\\Property\\FlatText', // Removed in vCard 4.0
86 'GEO' => 'Sabre\\VObject\\Property\\FlatText',
87 'TITLE' => 'Sabre\\VObject\\Property\\FlatText',
88 'ROLE' => 'Sabre\\VObject\\Property\\FlatText',
89 'LOGO' => 'Sabre\\VObject\\Property\\Binary',
90 // 'AGENT' => 'Sabre\\VObject\\Property\\', // Todo: is an embedded vCard. Probably rare, so
91 // not supported at the moment
92 'ORG' => 'Sabre\\VObject\\Property\\Text',
93 'NOTE' => 'Sabre\\VObject\\Property\\FlatText',
94 'REV' => 'Sabre\\VObject\\Property\\VCard\\TimeStamp',
95 'SOUND' => 'Sabre\\VObject\\Property\\FlatText',
96 'URL' => 'Sabre\\VObject\\Property\\Uri',
97 'UID' => 'Sabre\\VObject\\Property\\FlatText',
98 'VERSION' => 'Sabre\\VObject\\Property\\FlatText',
99 'KEY' => 'Sabre\\VObject\\Property\\FlatText',
100 'TZ' => 'Sabre\\VObject\\Property\\Text',
101
102 // vCard 3.0 properties
103 'CATEGORIES' => 'Sabre\\VObject\\Property\\Text',
104 'SORT-STRING' => 'Sabre\\VObject\\Property\\FlatText',
105 'PRODID' => 'Sabre\\VObject\\Property\\FlatText',
106 'NICKNAME' => 'Sabre\\VObject\\Property\\Text',
107 'CLASS' => 'Sabre\\VObject\\Property\\FlatText', // Removed in vCard 4.0
108
109 // rfc2739 properties
110 'FBURL' => 'Sabre\\VObject\\Property\\Uri',
111 'CAPURI' => 'Sabre\\VObject\\Property\\Uri',
112 'CALURI' => 'Sabre\\VObject\\Property\\Uri',
113 'CALADRURI' => 'Sabre\\VObject\\Property\\Uri',
114
115 // rfc4770 properties
116 'IMPP' => 'Sabre\\VObject\\Property\\Uri',
117
118 // vCard 4.0 properties
119 'SOURCE' => 'Sabre\\VObject\\Property\\Uri',
120 'XML' => 'Sabre\\VObject\\Property\\FlatText',
121 'ANNIVERSARY' => 'Sabre\\VObject\\Property\\VCard\\DateAndOrTime',
122 'CLIENTPIDMAP' => 'Sabre\\VObject\\Property\\Text',
123 'LANG' => 'Sabre\\VObject\\Property\\VCard\\LanguageTag',
124 'GENDER' => 'Sabre\\VObject\\Property\\Text',
125 'KIND' => 'Sabre\\VObject\\Property\\FlatText',
126 'MEMBER' => 'Sabre\\VObject\\Property\\Uri',
127 'RELATED' => 'Sabre\\VObject\\Property\\Uri',
128
129 // rfc6474 properties
130 'BIRTHPLACE' => 'Sabre\\VObject\\Property\\FlatText',
131 'DEATHPLACE' => 'Sabre\\VObject\\Property\\FlatText',
132 'DEATHDATE' => 'Sabre\\VObject\\Property\\VCard\\DateAndOrTime',
133
134 // rfc6715 properties
135 'EXPERTISE' => 'Sabre\\VObject\\Property\\FlatText',
136 'HOBBY' => 'Sabre\\VObject\\Property\\FlatText',
137 'INTEREST' => 'Sabre\\VObject\\Property\\FlatText',
138 'ORG-DIRECTORY' => 'Sabre\\VObject\\Property\\FlatText',
139
140 ];
141
147 function getDocumentType() {
148
149 if (!$this->version) {
150
151 $version = (string)$this->VERSION;
152
153 switch ($version) {
154 case '2.1' :
155 $this->version = self::VCARD21;
156 break;
157 case '3.0' :
158 $this->version = self::VCARD30;
159 break;
160 case '4.0' :
161 $this->version = self::VCARD40;
162 break;
163 default :
164 // We don't want to cache the version if it's unknown,
165 // because we might get a version property in a bit.
166 return self::UNKNOWN;
167 }
168 }
169
170 return $this->version;
171
172 }
173
188 function convert($target) {
189
190 $converter = new VObject\VCardConverter();
191 return $converter->convert($this, $target);
192
193 }
194
201
224 function validate($options = 0) {
225
226 $warnings = [];
227
228 $versionMap = [
229 self::VCARD21 => '2.1',
230 self::VCARD30 => '3.0',
231 self::VCARD40 => '4.0',
232 ];
233
234 $version = $this->select('VERSION');
235 if (count($version) === 1) {
236 $version = (string)$this->VERSION;
237 if ($version !== '2.1' && $version !== '3.0' && $version !== '4.0') {
238 $warnings[] = [
239 'level' => 3,
240 'message' => 'Only vcard version 4.0 (RFC6350), version 3.0 (RFC2426) or version 2.1 (icm-vcard-2.1) are supported.',
241 'node' => $this,
242 ];
243 if ($options & self::REPAIR) {
244 $this->VERSION = $versionMap[self::DEFAULT_VERSION];
245 }
246 }
247 if ($version === '2.1' && ($options & self::PROFILE_CARDDAV)) {
248 $warnings[] = [
249 'level' => 3,
250 'message' => 'CardDAV servers are not allowed to accept vCard 2.1.',
251 'node' => $this,
252 ];
253 }
254
255 }
256 $uid = $this->select('UID');
257 if (count($uid) === 0) {
258 if ($options & self::PROFILE_CARDDAV) {
259 // Required for CardDAV
260 $warningLevel = 3;
261 $message = 'vCards on CardDAV servers MUST have a UID property.';
262 } else {
263 // Not required for regular vcards
264 $warningLevel = 2;
265 $message = 'Adding a UID to a vCard property is recommended.';
266 }
267 if ($options & self::REPAIR) {
268 $this->UID = VObject\UUIDUtil::getUUID();
269 $warningLevel = 1;
270 }
271 $warnings[] = [
272 'level' => $warningLevel,
273 'message' => $message,
274 'node' => $this,
275 ];
276 }
277
278 $fn = $this->select('FN');
279 if (count($fn) !== 1) {
280
281 $repaired = false;
282 if (($options & self::REPAIR) && count($fn) === 0) {
283 // We're going to try to see if we can use the contents of the
284 // N property.
285 if (isset($this->N)) {
286 $value = explode(';', (string)$this->N);
287 if (isset($value[1]) && $value[1]) {
288 $this->FN = $value[1] . ' ' . $value[0];
289 } else {
290 $this->FN = $value[0];
291 }
292 $repaired = true;
293
294 // Otherwise, the ORG property may work
295 } elseif (isset($this->ORG)) {
296 $this->FN = (string)$this->ORG;
297 $repaired = true;
298
299 // Otherwise, the EMAIL property may work
300 } elseif (isset($this->EMAIL)) {
301 $this->FN = (string)$this->EMAIL;
302 $repaired = true;
303 }
304
305 }
306 $warnings[] = [
307 'level' => $repaired ? 1 : 3,
308 'message' => 'The FN property must appear in the VCARD component exactly 1 time',
309 'node' => $this,
310 ];
311 }
312
313 return array_merge(
314 parent::validate($options),
316 );
317
318 }
319
336
337 return [
338 'ADR' => '*',
339 'ANNIVERSARY' => '?',
340 'BDAY' => '?',
341 'CALADRURI' => '*',
342 'CALURI' => '*',
343 'CATEGORIES' => '*',
344 'CLIENTPIDMAP' => '*',
345 'EMAIL' => '*',
346 'FBURL' => '*',
347 'IMPP' => '*',
348 'GENDER' => '?',
349 'GEO' => '*',
350 'KEY' => '*',
351 'KIND' => '?',
352 'LANG' => '*',
353 'LOGO' => '*',
354 'MEMBER' => '*',
355 'N' => '?',
356 'NICKNAME' => '*',
357 'NOTE' => '*',
358 'ORG' => '*',
359 'PHOTO' => '*',
360 'PRODID' => '?',
361 'RELATED' => '*',
362 'REV' => '?',
363 'ROLE' => '*',
364 'SOUND' => '*',
365 'SOURCE' => '*',
366 'TEL' => '*',
367 'TITLE' => '*',
368 'TZ' => '*',
369 'URL' => '*',
370 'VERSION' => '1',
371 'XML' => '*',
372
373 // FN is commented out, because it's already handled by the
374 // validate function, which may also try to repair it.
375 // 'FN' => '+',
376 'UID' => '?',
377 ];
378
379 }
380
395 function preferred($propertyName) {
396
397 $preferred = null;
398 $lastPref = 101;
399 foreach ($this->select($propertyName) as $field) {
400
401 $pref = 101;
402 if (isset($field['TYPE']) && $field['TYPE']->has('PREF')) {
403 $pref = 1;
404 } elseif (isset($field['PREF'])) {
405 $pref = $field['PREF']->getValue();
406 }
407
408 if ($pref < $lastPref || is_null($preferred)) {
409 $preferred = $field;
410 $lastPref = $pref;
411 }
412
413 }
414 return $preferred;
415
416 }
417
429 function getByType($propertyName, $type) {
430 foreach ($this->select($propertyName) as $field) {
431 if (isset($field['TYPE']) && $field['TYPE']->has($type)) {
432 return $field;
433 }
434 }
435 }
436
442 protected function getDefaults() {
443
444 return [
445 'VERSION' => '4.0',
446 'PRODID' => '-//Sabre//Sabre VObject ' . VObject\Version::VERSION . '//EN',
447 'UID' => 'sabre-vobject-' . VObject\UUIDUtil::getUUID(),
448 ];
449
450 }
451
458 function jsonSerialize() {
459
460 // A vcard does not have sub-components, so we're overriding this
461 // method to remove that array element.
462 $properties = [];
463
464 foreach ($this->children() as $child) {
465 $properties[] = $child->jsonSerialize();
466 }
467
468 return [
469 strtolower($this->name),
470 $properties,
471 ];
472
473 }
474
483 function xmlSerialize(Xml\Writer $writer) {
484
485 $propertiesByGroup = [];
486
487 foreach ($this->children() as $property) {
488
489 $group = $property->group;
490
491 if (!isset($propertiesByGroup[$group])) {
492 $propertiesByGroup[$group] = [];
493 }
494
495 $propertiesByGroup[$group][] = $property;
496
497 }
498
499 $writer->startElement(strtolower($this->name));
500
501 foreach ($propertiesByGroup as $group => $properties) {
502
503 if (!empty($group)) {
504
505 $writer->startElement('group');
506 $writer->writeAttribute('name', strtolower($group));
507
508 }
509
510 foreach ($properties as $property) {
511 switch ($property->name) {
512
513 case 'VERSION':
514 continue;
515
516 case 'XML':
517 $value = $property->getParts();
518 $fragment = new Xml\Element\XmlFragment($value[0]);
519 $writer->write($fragment);
520 break;
521
522 default:
523 $property->xmlSerialize($writer);
524 break;
525
526 }
527 }
528
529 if (!empty($group)) {
530 $writer->endElement();
531 }
532
533 }
534
535 $writer->endElement();
536
537 }
538
546 function getClassNameForPropertyName($propertyName) {
547
548 $className = parent::getClassNameForPropertyName($propertyName);
549
550 // In vCard 4, BINARY no longer exists, and we need URI instead.
551 if ($className == 'Sabre\\VObject\\Property\\Binary' && $this->getDocumentType() === self::VCARD40) {
552 return 'Sabre\\VObject\\Property\\Uri';
553 }
554 return $className;
555
556 }
557
558}
An exception for terminatinating execution or to throw for unit testing.
The VCard component.
Definition: VCard.php:18
validate($options=0)
Validates the node for correctness.
Definition: VCard.php:224
getDefaults()
This method should return a list of default property values.
Definition: VCard.php:442
preferred($propertyName)
Returns a preferred field.
Definition: VCard.php:395
getClassNameForPropertyName($propertyName)
Returns the default class for a property name.
Definition: VCard.php:546
const DEFAULT_VERSION
VCards with version 2.1, 3.0 and 4.0 are found.
Definition: VCard.php:200
convert($target)
Converts the document to a different vcard version.
Definition: VCard.php:188
jsonSerialize()
This method returns an array, with the representation as it should be encoded in json.
Definition: VCard.php:458
xmlSerialize(Xml\Writer $writer)
This method serializes the data into XML.
Definition: VCard.php:483
getByType($propertyName, $type)
Returns a property with a specific TYPE value (ADR, TEL, or EMAIL).
Definition: VCard.php:429
getDocumentType()
Returns the current document type.
Definition: VCard.php:147
children()
Returns a flat list of all the properties and components in this component.
Definition: Component.php:187
select($name)
Returns an array with elements that match the specified name.
Definition: Component.php:231
const VCARD30
vCard 3.0.
Definition: Document.php:44
const UNKNOWN
Unknown document type.
Definition: Document.php:24
const VCARD21
vCard 2.1.
Definition: Document.php:39
const VCARD40
vCard 4.0.
Definition: Document.php:49
count()
Returns the number of elements.
Definition: Node.php:177
static getUUID()
Returns a pseudo-random v4 UUID.
Definition: UUIDUtil.php:27
This utility converts vcards from one version to another.
const VERSION
Full version number.
Definition: Version.php:17
iCalendar/vCard/jCal/jCard/xCal/xCard writer object.
Definition: Writer.php:17
The XmlFragment element allows you to extract a portion of your xml tree, and get a well-formed xml s...
Definition: XmlFragment.php:23
catch(Exception $e) $message
$target
Definition: test.php:19
$type