Completed
Branch develop (fc1aaa)
by
unknown
18:31
created
htdocs/includes/sabre/sabre/vobject/lib/Component/VCard.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -50,7 +50,7 @@
 block discarded – undo
50 50
     public static $valueMap = [
51 51
         'BINARY' => VObject\Property\Binary::class,
52 52
         'BOOLEAN' => VObject\Property\Boolean::class,
53
-        'CONTENT-ID' => VObject\Property\FlatText::class,   // vCard 2.1 only
53
+        'CONTENT-ID' => VObject\Property\FlatText::class, // vCard 2.1 only
54 54
         'DATE' => VObject\Property\VCard\Date::class,
55 55
         'DATE-TIME' => VObject\Property\VCard\DateTime::class,
56 56
         'DATE-AND-OR-TIME' => VObject\Property\VCard\DateAndOrTime::class, // vCard only
Please login to merge, or discard this patch.
Indentation   +521 added lines, -521 removed lines patch added patch discarded remove patch
@@ -17,525 +17,525 @@
 block discarded – undo
17 17
  */
18 18
 class VCard extends VObject\Document
19 19
 {
20
-    /**
21
-     * The default name for this component.
22
-     *
23
-     * This should be 'VCALENDAR' or 'VCARD'.
24
-     *
25
-     * @var string
26
-     */
27
-    public static $defaultName = 'VCARD';
28
-
29
-    /**
30
-     * Caching the version number.
31
-     *
32
-     * @var int
33
-     */
34
-    private $version = null;
35
-
36
-    /**
37
-     * This is a list of components, and which classes they should map to.
38
-     *
39
-     * @var array
40
-     */
41
-    public static $componentMap = [
42
-        'VCARD' => VCard::class,
43
-    ];
44
-
45
-    /**
46
-     * List of value-types, and which classes they map to.
47
-     *
48
-     * @var array
49
-     */
50
-    public static $valueMap = [
51
-        'BINARY' => VObject\Property\Binary::class,
52
-        'BOOLEAN' => VObject\Property\Boolean::class,
53
-        'CONTENT-ID' => VObject\Property\FlatText::class,   // vCard 2.1 only
54
-        'DATE' => VObject\Property\VCard\Date::class,
55
-        'DATE-TIME' => VObject\Property\VCard\DateTime::class,
56
-        'DATE-AND-OR-TIME' => VObject\Property\VCard\DateAndOrTime::class, // vCard only
57
-        'FLOAT' => VObject\Property\FloatValue::class,
58
-        'INTEGER' => VObject\Property\IntegerValue::class,
59
-        'LANGUAGE-TAG' => VObject\Property\VCard\LanguageTag::class,
60
-        'PHONE-NUMBER' => VObject\Property\VCard\PhoneNumber::class, // vCard 3.0 only
61
-        'TIMESTAMP' => VObject\Property\VCard\TimeStamp::class,
62
-        'TEXT' => VObject\Property\Text::class,
63
-        'TIME' => VObject\Property\Time::class,
64
-        'UNKNOWN' => VObject\Property\Unknown::class, // jCard / jCal-only.
65
-        'URI' => VObject\Property\Uri::class,
66
-        'URL' => VObject\Property\Uri::class, // vCard 2.1 only
67
-        'UTC-OFFSET' => VObject\Property\UtcOffset::class,
68
-    ];
69
-
70
-    /**
71
-     * List of properties, and which classes they map to.
72
-     *
73
-     * @var array
74
-     */
75
-    public static $propertyMap = [
76
-        // vCard 2.1 properties and up
77
-        'N' => VObject\Property\Text::class,
78
-        'FN' => VObject\Property\FlatText::class,
79
-        'PHOTO' => VObject\Property\Binary::class,
80
-        'BDAY' => VObject\Property\VCard\DateAndOrTime::class,
81
-        'ADR' => VObject\Property\Text::class,
82
-        'LABEL' => VObject\Property\FlatText::class, // Removed in vCard 4.0
83
-        'TEL' => VObject\Property\FlatText::class,
84
-        'EMAIL' => VObject\Property\FlatText::class,
85
-        'MAILER' => VObject\Property\FlatText::class, // Removed in vCard 4.0
86
-        'GEO' => VObject\Property\FlatText::class,
87
-        'TITLE' => VObject\Property\FlatText::class,
88
-        'ROLE' => VObject\Property\FlatText::class,
89
-        'LOGO' => VObject\Property\Binary::class,
90
-        // 'AGENT'   => 'Sabre\\VObject\\Property\\',      // Todo: is an embedded vCard. Probably rare, so
91
-                                 // not supported at the moment
92
-        'ORG' => VObject\Property\Text::class,
93
-        'NOTE' => VObject\Property\FlatText::class,
94
-        'REV' => VObject\Property\VCard\TimeStamp::class,
95
-        'SOUND' => VObject\Property\FlatText::class,
96
-        'URL' => VObject\Property\Uri::class,
97
-        'UID' => VObject\Property\FlatText::class,
98
-        'VERSION' => VObject\Property\FlatText::class,
99
-        'KEY' => VObject\Property\FlatText::class,
100
-        'TZ' => VObject\Property\Text::class,
101
-
102
-        // vCard 3.0 properties
103
-        'CATEGORIES' => VObject\Property\Text::class,
104
-        'SORT-STRING' => VObject\Property\FlatText::class,
105
-        'PRODID' => VObject\Property\FlatText::class,
106
-        'NICKNAME' => VObject\Property\Text::class,
107
-        'CLASS' => VObject\Property\FlatText::class, // Removed in vCard 4.0
108
-
109
-        // rfc2739 properties
110
-        'FBURL' => VObject\Property\Uri::class,
111
-        'CAPURI' => VObject\Property\Uri::class,
112
-        'CALURI' => VObject\Property\Uri::class,
113
-        'CALADRURI' => VObject\Property\Uri::class,
114
-
115
-        // rfc4770 properties
116
-        'IMPP' => VObject\Property\Uri::class,
117
-
118
-        // vCard 4.0 properties
119
-        'SOURCE' => VObject\Property\Uri::class,
120
-        'XML' => VObject\Property\FlatText::class,
121
-        'ANNIVERSARY' => VObject\Property\VCard\DateAndOrTime::class,
122
-        'CLIENTPIDMAP' => VObject\Property\Text::class,
123
-        'LANG' => VObject\Property\VCard\LanguageTag::class,
124
-        'GENDER' => VObject\Property\Text::class,
125
-        'KIND' => VObject\Property\FlatText::class,
126
-        'MEMBER' => VObject\Property\Uri::class,
127
-        'RELATED' => VObject\Property\Uri::class,
128
-
129
-        // rfc6474 properties
130
-        'BIRTHPLACE' => VObject\Property\FlatText::class,
131
-        'DEATHPLACE' => VObject\Property\FlatText::class,
132
-        'DEATHDATE' => VObject\Property\VCard\DateAndOrTime::class,
133
-
134
-        // rfc6715 properties
135
-        'EXPERTISE' => VObject\Property\FlatText::class,
136
-        'HOBBY' => VObject\Property\FlatText::class,
137
-        'INTEREST' => VObject\Property\FlatText::class,
138
-        'ORG-DIRECTORY' => VObject\Property\FlatText::class,
139
-    ];
140
-
141
-    /**
142
-     * Returns the current document type.
143
-     *
144
-     * @return int
145
-     */
146
-    public function getDocumentType()
147
-    {
148
-        if (!$this->version) {
149
-            $version = (string) $this->VERSION;
150
-
151
-            switch ($version) {
152
-                case '2.1':
153
-                    $this->version = self::VCARD21;
154
-                    break;
155
-                case '3.0':
156
-                    $this->version = self::VCARD30;
157
-                    break;
158
-                case '4.0':
159
-                    $this->version = self::VCARD40;
160
-                    break;
161
-                default:
162
-                    // We don't want to cache the version if it's unknown,
163
-                    // because we might get a version property in a bit.
164
-                    return self::UNKNOWN;
165
-            }
166
-        }
167
-
168
-        return $this->version;
169
-    }
170
-
171
-    /**
172
-     * Converts the document to a different vcard version.
173
-     *
174
-     * Use one of the VCARD constants for the target. This method will return
175
-     * a copy of the vcard in the new version.
176
-     *
177
-     * At the moment the only supported conversion is from 3.0 to 4.0.
178
-     *
179
-     * If input and output version are identical, a clone is returned.
180
-     *
181
-     * @param int $target
182
-     *
183
-     * @return VCard
184
-     */
185
-    public function convert($target)
186
-    {
187
-        $converter = new VObject\VCardConverter();
188
-
189
-        return $converter->convert($this, $target);
190
-    }
191
-
192
-    /**
193
-     * VCards with version 2.1, 3.0 and 4.0 are found.
194
-     *
195
-     * If the VCARD doesn't know its version, 2.1 is assumed.
196
-     */
197
-    const DEFAULT_VERSION = self::VCARD21;
198
-
199
-    /**
200
-     * Validates the node for correctness.
201
-     *
202
-     * The following options are supported:
203
-     *   Node::REPAIR - May attempt to automatically repair the problem.
204
-     *
205
-     * This method returns an array with detected problems.
206
-     * Every element has the following properties:
207
-     *
208
-     *  * level - problem level.
209
-     *  * message - A human-readable string describing the issue.
210
-     *  * node - A reference to the problematic node.
211
-     *
212
-     * The level means:
213
-     *   1 - The issue was repaired (only happens if REPAIR was turned on)
214
-     *   2 - An inconsequential issue
215
-     *   3 - A severe issue.
216
-     *
217
-     * @param int $options
218
-     *
219
-     * @return array
220
-     */
221
-    public function validate($options = 0)
222
-    {
223
-        $warnings = [];
224
-
225
-        $versionMap = [
226
-            self::VCARD21 => '2.1',
227
-            self::VCARD30 => '3.0',
228
-            self::VCARD40 => '4.0',
229
-        ];
230
-
231
-        $version = $this->select('VERSION');
232
-        if (1 === count($version)) {
233
-            $version = (string) $this->VERSION;
234
-            if ('2.1' !== $version && '3.0' !== $version && '4.0' !== $version) {
235
-                $warnings[] = [
236
-                    'level' => 3,
237
-                    'message' => 'Only vcard version 4.0 (RFC6350), version 3.0 (RFC2426) or version 2.1 (icm-vcard-2.1) are supported.',
238
-                    'node' => $this,
239
-                ];
240
-                if ($options & self::REPAIR) {
241
-                    $this->VERSION = $versionMap[self::DEFAULT_VERSION];
242
-                }
243
-            }
244
-            if ('2.1' === $version && ($options & self::PROFILE_CARDDAV)) {
245
-                $warnings[] = [
246
-                    'level' => 3,
247
-                    'message' => 'CardDAV servers are not allowed to accept vCard 2.1.',
248
-                    'node' => $this,
249
-                ];
250
-            }
251
-        }
252
-        $uid = $this->select('UID');
253
-        if (0 === count($uid)) {
254
-            if ($options & self::PROFILE_CARDDAV) {
255
-                // Required for CardDAV
256
-                $warningLevel = 3;
257
-                $message = 'vCards on CardDAV servers MUST have a UID property.';
258
-            } else {
259
-                // Not required for regular vcards
260
-                $warningLevel = 2;
261
-                $message = 'Adding a UID to a vCard property is recommended.';
262
-            }
263
-            if ($options & self::REPAIR) {
264
-                $this->UID = VObject\UUIDUtil::getUUID();
265
-                $warningLevel = 1;
266
-            }
267
-            $warnings[] = [
268
-                'level' => $warningLevel,
269
-                'message' => $message,
270
-                'node' => $this,
271
-            ];
272
-        }
273
-
274
-        $fn = $this->select('FN');
275
-        if (1 !== count($fn)) {
276
-            $repaired = false;
277
-            if (($options & self::REPAIR) && 0 === count($fn)) {
278
-                // We're going to try to see if we can use the contents of the
279
-                // N property.
280
-                if (isset($this->N)) {
281
-                    $value = explode(';', (string) $this->N);
282
-                    if (isset($value[1]) && $value[1]) {
283
-                        $this->FN = $value[1].' '.$value[0];
284
-                    } else {
285
-                        $this->FN = $value[0];
286
-                    }
287
-                    $repaired = true;
288
-
289
-                // Otherwise, the ORG property may work
290
-                } elseif (isset($this->ORG)) {
291
-                    $this->FN = (string) $this->ORG;
292
-                    $repaired = true;
293
-
294
-                // Otherwise, the NICKNAME property may work
295
-                } elseif (isset($this->NICKNAME)) {
296
-                    $this->FN = (string) $this->NICKNAME;
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
-            $warnings[] = [
306
-                'level' => $repaired ? 1 : 3,
307
-                'message' => 'The FN property must appear in the VCARD component exactly 1 time',
308
-                'node' => $this,
309
-            ];
310
-        }
311
-
312
-        return array_merge(
313
-            parent::validate($options),
314
-            $warnings
315
-        );
316
-    }
317
-
318
-    /**
319
-     * A simple list of validation rules.
320
-     *
321
-     * This is simply a list of properties, and how many times they either
322
-     * must or must not appear.
323
-     *
324
-     * Possible values per property:
325
-     *   * 0 - Must not appear.
326
-     *   * 1 - Must appear exactly once.
327
-     *   * + - Must appear at least once.
328
-     *   * * - Can appear any number of times.
329
-     *   * ? - May appear, but not more than once.
330
-     *
331
-     * @var array
332
-     */
333
-    public function getValidationRules()
334
-    {
335
-        return [
336
-            'ADR' => '*',
337
-            'ANNIVERSARY' => '?',
338
-            'BDAY' => '?',
339
-            'CALADRURI' => '*',
340
-            'CALURI' => '*',
341
-            'CATEGORIES' => '*',
342
-            'CLIENTPIDMAP' => '*',
343
-            'EMAIL' => '*',
344
-            'FBURL' => '*',
345
-            'IMPP' => '*',
346
-            'GENDER' => '?',
347
-            'GEO' => '*',
348
-            'KEY' => '*',
349
-            'KIND' => '?',
350
-            'LANG' => '*',
351
-            'LOGO' => '*',
352
-            'MEMBER' => '*',
353
-            'N' => '?',
354
-            'NICKNAME' => '*',
355
-            'NOTE' => '*',
356
-            'ORG' => '*',
357
-            'PHOTO' => '*',
358
-            'PRODID' => '?',
359
-            'RELATED' => '*',
360
-            'REV' => '?',
361
-            'ROLE' => '*',
362
-            'SOUND' => '*',
363
-            'SOURCE' => '*',
364
-            'TEL' => '*',
365
-            'TITLE' => '*',
366
-            'TZ' => '*',
367
-            'URL' => '*',
368
-            'VERSION' => '1',
369
-            'XML' => '*',
370
-
371
-            // FN is commented out, because it's already handled by the
372
-            // validate function, which may also try to repair it.
373
-            // 'FN'           => '+',
374
-            'UID' => '?',
375
-        ];
376
-    }
377
-
378
-    /**
379
-     * Returns a preferred field.
380
-     *
381
-     * VCards can indicate whether a field such as ADR, TEL or EMAIL is
382
-     * preferred by specifying TYPE=PREF (vcard 2.1, 3) or PREF=x (vcard 4, x
383
-     * being a number between 1 and 100).
384
-     *
385
-     * If neither of those parameters are specified, the first is returned, if
386
-     * a field with that name does not exist, null is returned.
387
-     *
388
-     * @param string $fieldName
389
-     *
390
-     * @return VObject\Property|null
391
-     */
392
-    public function preferred($propertyName)
393
-    {
394
-        $preferred = null;
395
-        $lastPref = 101;
396
-        foreach ($this->select($propertyName) as $field) {
397
-            $pref = 101;
398
-            if (isset($field['TYPE']) && $field['TYPE']->has('PREF')) {
399
-                $pref = 1;
400
-            } elseif (isset($field['PREF'])) {
401
-                $pref = $field['PREF']->getValue();
402
-            }
403
-
404
-            if ($pref < $lastPref || is_null($preferred)) {
405
-                $preferred = $field;
406
-                $lastPref = $pref;
407
-            }
408
-        }
409
-
410
-        return $preferred;
411
-    }
412
-
413
-    /**
414
-     * Returns a property with a specific TYPE value (ADR, TEL, or EMAIL).
415
-     *
416
-     * This function will return null if the property does not exist. If there are
417
-     * multiple properties with the same TYPE value, only one will be returned.
418
-     *
419
-     * @param string $propertyName
420
-     * @param string $type
421
-     *
422
-     * @return VObject\Property|null
423
-     */
424
-    public function getByType($propertyName, $type)
425
-    {
426
-        foreach ($this->select($propertyName) as $field) {
427
-            if (isset($field['TYPE']) && $field['TYPE']->has($type)) {
428
-                return $field;
429
-            }
430
-        }
431
-    }
432
-
433
-    /**
434
-     * This method should return a list of default property values.
435
-     *
436
-     * @return array
437
-     */
438
-    protected function getDefaults()
439
-    {
440
-        return [
441
-            'VERSION' => '4.0',
442
-            'PRODID' => '-//Sabre//Sabre VObject '.VObject\Version::VERSION.'//EN',
443
-            'UID' => 'sabre-vobject-'.VObject\UUIDUtil::getUUID(),
444
-        ];
445
-    }
446
-
447
-    /**
448
-     * This method returns an array, with the representation as it should be
449
-     * encoded in json. This is used to create jCard or jCal documents.
450
-     *
451
-     * @return array
452
-     */
453
-    #[\ReturnTypeWillChange]
454
-    public function jsonSerialize()
455
-    {
456
-        // A vcard does not have sub-components, so we're overriding this
457
-        // method to remove that array element.
458
-        $properties = [];
459
-
460
-        foreach ($this->children() as $child) {
461
-            $properties[] = $child->jsonSerialize();
462
-        }
463
-
464
-        return [
465
-            strtolower($this->name),
466
-            $properties,
467
-        ];
468
-    }
469
-
470
-    /**
471
-     * This method serializes the data into XML. This is used to create xCard or
472
-     * xCal documents.
473
-     *
474
-     * @param Xml\Writer $writer XML writer
475
-     */
476
-    public function xmlSerialize(Xml\Writer $writer): void
477
-    {
478
-        $propertiesByGroup = [];
479
-
480
-        foreach ($this->children() as $property) {
481
-            $group = $property->group;
482
-
483
-            if (!isset($propertiesByGroup[$group])) {
484
-                $propertiesByGroup[$group] = [];
485
-            }
486
-
487
-            $propertiesByGroup[$group][] = $property;
488
-        }
489
-
490
-        $writer->startElement(strtolower($this->name));
491
-
492
-        foreach ($propertiesByGroup as $group => $properties) {
493
-            if (!empty($group)) {
494
-                $writer->startElement('group');
495
-                $writer->writeAttribute('name', strtolower($group));
496
-            }
497
-
498
-            foreach ($properties as $property) {
499
-                switch ($property->name) {
500
-                    case 'VERSION':
501
-                        break;
502
-
503
-                    case 'XML':
504
-                        $value = $property->getParts();
505
-                        $fragment = new Xml\Element\XmlFragment($value[0]);
506
-                        $writer->write($fragment);
507
-                        break;
508
-
509
-                    default:
510
-                        $property->xmlSerialize($writer);
511
-                        break;
512
-                }
513
-            }
514
-
515
-            if (!empty($group)) {
516
-                $writer->endElement();
517
-            }
518
-        }
519
-
520
-        $writer->endElement();
521
-    }
522
-
523
-    /**
524
-     * Returns the default class for a property name.
525
-     *
526
-     * @param string $propertyName
527
-     *
528
-     * @return string
529
-     */
530
-    public function getClassNameForPropertyName($propertyName)
531
-    {
532
-        $className = parent::getClassNameForPropertyName($propertyName);
533
-
534
-        // In vCard 4, BINARY no longer exists, and we need URI instead.
535
-        if (VObject\Property\Binary::class == $className && self::VCARD40 === $this->getDocumentType()) {
536
-            return VObject\Property\Uri::class;
537
-        }
538
-
539
-        return $className;
540
-    }
20
+	/**
21
+	 * The default name for this component.
22
+	 *
23
+	 * This should be 'VCALENDAR' or 'VCARD'.
24
+	 *
25
+	 * @var string
26
+	 */
27
+	public static $defaultName = 'VCARD';
28
+
29
+	/**
30
+	 * Caching the version number.
31
+	 *
32
+	 * @var int
33
+	 */
34
+	private $version = null;
35
+
36
+	/**
37
+	 * This is a list of components, and which classes they should map to.
38
+	 *
39
+	 * @var array
40
+	 */
41
+	public static $componentMap = [
42
+		'VCARD' => VCard::class,
43
+	];
44
+
45
+	/**
46
+	 * List of value-types, and which classes they map to.
47
+	 *
48
+	 * @var array
49
+	 */
50
+	public static $valueMap = [
51
+		'BINARY' => VObject\Property\Binary::class,
52
+		'BOOLEAN' => VObject\Property\Boolean::class,
53
+		'CONTENT-ID' => VObject\Property\FlatText::class,   // vCard 2.1 only
54
+		'DATE' => VObject\Property\VCard\Date::class,
55
+		'DATE-TIME' => VObject\Property\VCard\DateTime::class,
56
+		'DATE-AND-OR-TIME' => VObject\Property\VCard\DateAndOrTime::class, // vCard only
57
+		'FLOAT' => VObject\Property\FloatValue::class,
58
+		'INTEGER' => VObject\Property\IntegerValue::class,
59
+		'LANGUAGE-TAG' => VObject\Property\VCard\LanguageTag::class,
60
+		'PHONE-NUMBER' => VObject\Property\VCard\PhoneNumber::class, // vCard 3.0 only
61
+		'TIMESTAMP' => VObject\Property\VCard\TimeStamp::class,
62
+		'TEXT' => VObject\Property\Text::class,
63
+		'TIME' => VObject\Property\Time::class,
64
+		'UNKNOWN' => VObject\Property\Unknown::class, // jCard / jCal-only.
65
+		'URI' => VObject\Property\Uri::class,
66
+		'URL' => VObject\Property\Uri::class, // vCard 2.1 only
67
+		'UTC-OFFSET' => VObject\Property\UtcOffset::class,
68
+	];
69
+
70
+	/**
71
+	 * List of properties, and which classes they map to.
72
+	 *
73
+	 * @var array
74
+	 */
75
+	public static $propertyMap = [
76
+		// vCard 2.1 properties and up
77
+		'N' => VObject\Property\Text::class,
78
+		'FN' => VObject\Property\FlatText::class,
79
+		'PHOTO' => VObject\Property\Binary::class,
80
+		'BDAY' => VObject\Property\VCard\DateAndOrTime::class,
81
+		'ADR' => VObject\Property\Text::class,
82
+		'LABEL' => VObject\Property\FlatText::class, // Removed in vCard 4.0
83
+		'TEL' => VObject\Property\FlatText::class,
84
+		'EMAIL' => VObject\Property\FlatText::class,
85
+		'MAILER' => VObject\Property\FlatText::class, // Removed in vCard 4.0
86
+		'GEO' => VObject\Property\FlatText::class,
87
+		'TITLE' => VObject\Property\FlatText::class,
88
+		'ROLE' => VObject\Property\FlatText::class,
89
+		'LOGO' => VObject\Property\Binary::class,
90
+		// 'AGENT'   => 'Sabre\\VObject\\Property\\',      // Todo: is an embedded vCard. Probably rare, so
91
+								 // not supported at the moment
92
+		'ORG' => VObject\Property\Text::class,
93
+		'NOTE' => VObject\Property\FlatText::class,
94
+		'REV' => VObject\Property\VCard\TimeStamp::class,
95
+		'SOUND' => VObject\Property\FlatText::class,
96
+		'URL' => VObject\Property\Uri::class,
97
+		'UID' => VObject\Property\FlatText::class,
98
+		'VERSION' => VObject\Property\FlatText::class,
99
+		'KEY' => VObject\Property\FlatText::class,
100
+		'TZ' => VObject\Property\Text::class,
101
+
102
+		// vCard 3.0 properties
103
+		'CATEGORIES' => VObject\Property\Text::class,
104
+		'SORT-STRING' => VObject\Property\FlatText::class,
105
+		'PRODID' => VObject\Property\FlatText::class,
106
+		'NICKNAME' => VObject\Property\Text::class,
107
+		'CLASS' => VObject\Property\FlatText::class, // Removed in vCard 4.0
108
+
109
+		// rfc2739 properties
110
+		'FBURL' => VObject\Property\Uri::class,
111
+		'CAPURI' => VObject\Property\Uri::class,
112
+		'CALURI' => VObject\Property\Uri::class,
113
+		'CALADRURI' => VObject\Property\Uri::class,
114
+
115
+		// rfc4770 properties
116
+		'IMPP' => VObject\Property\Uri::class,
117
+
118
+		// vCard 4.0 properties
119
+		'SOURCE' => VObject\Property\Uri::class,
120
+		'XML' => VObject\Property\FlatText::class,
121
+		'ANNIVERSARY' => VObject\Property\VCard\DateAndOrTime::class,
122
+		'CLIENTPIDMAP' => VObject\Property\Text::class,
123
+		'LANG' => VObject\Property\VCard\LanguageTag::class,
124
+		'GENDER' => VObject\Property\Text::class,
125
+		'KIND' => VObject\Property\FlatText::class,
126
+		'MEMBER' => VObject\Property\Uri::class,
127
+		'RELATED' => VObject\Property\Uri::class,
128
+
129
+		// rfc6474 properties
130
+		'BIRTHPLACE' => VObject\Property\FlatText::class,
131
+		'DEATHPLACE' => VObject\Property\FlatText::class,
132
+		'DEATHDATE' => VObject\Property\VCard\DateAndOrTime::class,
133
+
134
+		// rfc6715 properties
135
+		'EXPERTISE' => VObject\Property\FlatText::class,
136
+		'HOBBY' => VObject\Property\FlatText::class,
137
+		'INTEREST' => VObject\Property\FlatText::class,
138
+		'ORG-DIRECTORY' => VObject\Property\FlatText::class,
139
+	];
140
+
141
+	/**
142
+	 * Returns the current document type.
143
+	 *
144
+	 * @return int
145
+	 */
146
+	public function getDocumentType()
147
+	{
148
+		if (!$this->version) {
149
+			$version = (string) $this->VERSION;
150
+
151
+			switch ($version) {
152
+				case '2.1':
153
+					$this->version = self::VCARD21;
154
+					break;
155
+				case '3.0':
156
+					$this->version = self::VCARD30;
157
+					break;
158
+				case '4.0':
159
+					$this->version = self::VCARD40;
160
+					break;
161
+				default:
162
+					// We don't want to cache the version if it's unknown,
163
+					// because we might get a version property in a bit.
164
+					return self::UNKNOWN;
165
+			}
166
+		}
167
+
168
+		return $this->version;
169
+	}
170
+
171
+	/**
172
+	 * Converts the document to a different vcard version.
173
+	 *
174
+	 * Use one of the VCARD constants for the target. This method will return
175
+	 * a copy of the vcard in the new version.
176
+	 *
177
+	 * At the moment the only supported conversion is from 3.0 to 4.0.
178
+	 *
179
+	 * If input and output version are identical, a clone is returned.
180
+	 *
181
+	 * @param int $target
182
+	 *
183
+	 * @return VCard
184
+	 */
185
+	public function convert($target)
186
+	{
187
+		$converter = new VObject\VCardConverter();
188
+
189
+		return $converter->convert($this, $target);
190
+	}
191
+
192
+	/**
193
+	 * VCards with version 2.1, 3.0 and 4.0 are found.
194
+	 *
195
+	 * If the VCARD doesn't know its version, 2.1 is assumed.
196
+	 */
197
+	const DEFAULT_VERSION = self::VCARD21;
198
+
199
+	/**
200
+	 * Validates the node for correctness.
201
+	 *
202
+	 * The following options are supported:
203
+	 *   Node::REPAIR - May attempt to automatically repair the problem.
204
+	 *
205
+	 * This method returns an array with detected problems.
206
+	 * Every element has the following properties:
207
+	 *
208
+	 *  * level - problem level.
209
+	 *  * message - A human-readable string describing the issue.
210
+	 *  * node - A reference to the problematic node.
211
+	 *
212
+	 * The level means:
213
+	 *   1 - The issue was repaired (only happens if REPAIR was turned on)
214
+	 *   2 - An inconsequential issue
215
+	 *   3 - A severe issue.
216
+	 *
217
+	 * @param int $options
218
+	 *
219
+	 * @return array
220
+	 */
221
+	public function validate($options = 0)
222
+	{
223
+		$warnings = [];
224
+
225
+		$versionMap = [
226
+			self::VCARD21 => '2.1',
227
+			self::VCARD30 => '3.0',
228
+			self::VCARD40 => '4.0',
229
+		];
230
+
231
+		$version = $this->select('VERSION');
232
+		if (1 === count($version)) {
233
+			$version = (string) $this->VERSION;
234
+			if ('2.1' !== $version && '3.0' !== $version && '4.0' !== $version) {
235
+				$warnings[] = [
236
+					'level' => 3,
237
+					'message' => 'Only vcard version 4.0 (RFC6350), version 3.0 (RFC2426) or version 2.1 (icm-vcard-2.1) are supported.',
238
+					'node' => $this,
239
+				];
240
+				if ($options & self::REPAIR) {
241
+					$this->VERSION = $versionMap[self::DEFAULT_VERSION];
242
+				}
243
+			}
244
+			if ('2.1' === $version && ($options & self::PROFILE_CARDDAV)) {
245
+				$warnings[] = [
246
+					'level' => 3,
247
+					'message' => 'CardDAV servers are not allowed to accept vCard 2.1.',
248
+					'node' => $this,
249
+				];
250
+			}
251
+		}
252
+		$uid = $this->select('UID');
253
+		if (0 === count($uid)) {
254
+			if ($options & self::PROFILE_CARDDAV) {
255
+				// Required for CardDAV
256
+				$warningLevel = 3;
257
+				$message = 'vCards on CardDAV servers MUST have a UID property.';
258
+			} else {
259
+				// Not required for regular vcards
260
+				$warningLevel = 2;
261
+				$message = 'Adding a UID to a vCard property is recommended.';
262
+			}
263
+			if ($options & self::REPAIR) {
264
+				$this->UID = VObject\UUIDUtil::getUUID();
265
+				$warningLevel = 1;
266
+			}
267
+			$warnings[] = [
268
+				'level' => $warningLevel,
269
+				'message' => $message,
270
+				'node' => $this,
271
+			];
272
+		}
273
+
274
+		$fn = $this->select('FN');
275
+		if (1 !== count($fn)) {
276
+			$repaired = false;
277
+			if (($options & self::REPAIR) && 0 === count($fn)) {
278
+				// We're going to try to see if we can use the contents of the
279
+				// N property.
280
+				if (isset($this->N)) {
281
+					$value = explode(';', (string) $this->N);
282
+					if (isset($value[1]) && $value[1]) {
283
+						$this->FN = $value[1].' '.$value[0];
284
+					} else {
285
+						$this->FN = $value[0];
286
+					}
287
+					$repaired = true;
288
+
289
+				// Otherwise, the ORG property may work
290
+				} elseif (isset($this->ORG)) {
291
+					$this->FN = (string) $this->ORG;
292
+					$repaired = true;
293
+
294
+				// Otherwise, the NICKNAME property may work
295
+				} elseif (isset($this->NICKNAME)) {
296
+					$this->FN = (string) $this->NICKNAME;
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
+			$warnings[] = [
306
+				'level' => $repaired ? 1 : 3,
307
+				'message' => 'The FN property must appear in the VCARD component exactly 1 time',
308
+				'node' => $this,
309
+			];
310
+		}
311
+
312
+		return array_merge(
313
+			parent::validate($options),
314
+			$warnings
315
+		);
316
+	}
317
+
318
+	/**
319
+	 * A simple list of validation rules.
320
+	 *
321
+	 * This is simply a list of properties, and how many times they either
322
+	 * must or must not appear.
323
+	 *
324
+	 * Possible values per property:
325
+	 *   * 0 - Must not appear.
326
+	 *   * 1 - Must appear exactly once.
327
+	 *   * + - Must appear at least once.
328
+	 *   * * - Can appear any number of times.
329
+	 *   * ? - May appear, but not more than once.
330
+	 *
331
+	 * @var array
332
+	 */
333
+	public function getValidationRules()
334
+	{
335
+		return [
336
+			'ADR' => '*',
337
+			'ANNIVERSARY' => '?',
338
+			'BDAY' => '?',
339
+			'CALADRURI' => '*',
340
+			'CALURI' => '*',
341
+			'CATEGORIES' => '*',
342
+			'CLIENTPIDMAP' => '*',
343
+			'EMAIL' => '*',
344
+			'FBURL' => '*',
345
+			'IMPP' => '*',
346
+			'GENDER' => '?',
347
+			'GEO' => '*',
348
+			'KEY' => '*',
349
+			'KIND' => '?',
350
+			'LANG' => '*',
351
+			'LOGO' => '*',
352
+			'MEMBER' => '*',
353
+			'N' => '?',
354
+			'NICKNAME' => '*',
355
+			'NOTE' => '*',
356
+			'ORG' => '*',
357
+			'PHOTO' => '*',
358
+			'PRODID' => '?',
359
+			'RELATED' => '*',
360
+			'REV' => '?',
361
+			'ROLE' => '*',
362
+			'SOUND' => '*',
363
+			'SOURCE' => '*',
364
+			'TEL' => '*',
365
+			'TITLE' => '*',
366
+			'TZ' => '*',
367
+			'URL' => '*',
368
+			'VERSION' => '1',
369
+			'XML' => '*',
370
+
371
+			// FN is commented out, because it's already handled by the
372
+			// validate function, which may also try to repair it.
373
+			// 'FN'           => '+',
374
+			'UID' => '?',
375
+		];
376
+	}
377
+
378
+	/**
379
+	 * Returns a preferred field.
380
+	 *
381
+	 * VCards can indicate whether a field such as ADR, TEL or EMAIL is
382
+	 * preferred by specifying TYPE=PREF (vcard 2.1, 3) or PREF=x (vcard 4, x
383
+	 * being a number between 1 and 100).
384
+	 *
385
+	 * If neither of those parameters are specified, the first is returned, if
386
+	 * a field with that name does not exist, null is returned.
387
+	 *
388
+	 * @param string $fieldName
389
+	 *
390
+	 * @return VObject\Property|null
391
+	 */
392
+	public function preferred($propertyName)
393
+	{
394
+		$preferred = null;
395
+		$lastPref = 101;
396
+		foreach ($this->select($propertyName) as $field) {
397
+			$pref = 101;
398
+			if (isset($field['TYPE']) && $field['TYPE']->has('PREF')) {
399
+				$pref = 1;
400
+			} elseif (isset($field['PREF'])) {
401
+				$pref = $field['PREF']->getValue();
402
+			}
403
+
404
+			if ($pref < $lastPref || is_null($preferred)) {
405
+				$preferred = $field;
406
+				$lastPref = $pref;
407
+			}
408
+		}
409
+
410
+		return $preferred;
411
+	}
412
+
413
+	/**
414
+	 * Returns a property with a specific TYPE value (ADR, TEL, or EMAIL).
415
+	 *
416
+	 * This function will return null if the property does not exist. If there are
417
+	 * multiple properties with the same TYPE value, only one will be returned.
418
+	 *
419
+	 * @param string $propertyName
420
+	 * @param string $type
421
+	 *
422
+	 * @return VObject\Property|null
423
+	 */
424
+	public function getByType($propertyName, $type)
425
+	{
426
+		foreach ($this->select($propertyName) as $field) {
427
+			if (isset($field['TYPE']) && $field['TYPE']->has($type)) {
428
+				return $field;
429
+			}
430
+		}
431
+	}
432
+
433
+	/**
434
+	 * This method should return a list of default property values.
435
+	 *
436
+	 * @return array
437
+	 */
438
+	protected function getDefaults()
439
+	{
440
+		return [
441
+			'VERSION' => '4.0',
442
+			'PRODID' => '-//Sabre//Sabre VObject '.VObject\Version::VERSION.'//EN',
443
+			'UID' => 'sabre-vobject-'.VObject\UUIDUtil::getUUID(),
444
+		];
445
+	}
446
+
447
+	/**
448
+	 * This method returns an array, with the representation as it should be
449
+	 * encoded in json. This is used to create jCard or jCal documents.
450
+	 *
451
+	 * @return array
452
+	 */
453
+	#[\ReturnTypeWillChange]
454
+	public function jsonSerialize()
455
+	{
456
+		// A vcard does not have sub-components, so we're overriding this
457
+		// method to remove that array element.
458
+		$properties = [];
459
+
460
+		foreach ($this->children() as $child) {
461
+			$properties[] = $child->jsonSerialize();
462
+		}
463
+
464
+		return [
465
+			strtolower($this->name),
466
+			$properties,
467
+		];
468
+	}
469
+
470
+	/**
471
+	 * This method serializes the data into XML. This is used to create xCard or
472
+	 * xCal documents.
473
+	 *
474
+	 * @param Xml\Writer $writer XML writer
475
+	 */
476
+	public function xmlSerialize(Xml\Writer $writer): void
477
+	{
478
+		$propertiesByGroup = [];
479
+
480
+		foreach ($this->children() as $property) {
481
+			$group = $property->group;
482
+
483
+			if (!isset($propertiesByGroup[$group])) {
484
+				$propertiesByGroup[$group] = [];
485
+			}
486
+
487
+			$propertiesByGroup[$group][] = $property;
488
+		}
489
+
490
+		$writer->startElement(strtolower($this->name));
491
+
492
+		foreach ($propertiesByGroup as $group => $properties) {
493
+			if (!empty($group)) {
494
+				$writer->startElement('group');
495
+				$writer->writeAttribute('name', strtolower($group));
496
+			}
497
+
498
+			foreach ($properties as $property) {
499
+				switch ($property->name) {
500
+					case 'VERSION':
501
+						break;
502
+
503
+					case 'XML':
504
+						$value = $property->getParts();
505
+						$fragment = new Xml\Element\XmlFragment($value[0]);
506
+						$writer->write($fragment);
507
+						break;
508
+
509
+					default:
510
+						$property->xmlSerialize($writer);
511
+						break;
512
+				}
513
+			}
514
+
515
+			if (!empty($group)) {
516
+				$writer->endElement();
517
+			}
518
+		}
519
+
520
+		$writer->endElement();
521
+	}
522
+
523
+	/**
524
+	 * Returns the default class for a property name.
525
+	 *
526
+	 * @param string $propertyName
527
+	 *
528
+	 * @return string
529
+	 */
530
+	public function getClassNameForPropertyName($propertyName)
531
+	{
532
+		$className = parent::getClassNameForPropertyName($propertyName);
533
+
534
+		// In vCard 4, BINARY no longer exists, and we need URI instead.
535
+		if (VObject\Property\Binary::class == $className && self::VCARD40 === $this->getDocumentType()) {
536
+			return VObject\Property\Uri::class;
537
+		}
538
+
539
+		return $className;
540
+	}
541 541
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Component/VCalendar.php 2 patches
Indentation   +503 added lines, -503 removed lines patch added patch discarded remove patch
@@ -22,507 +22,507 @@
 block discarded – undo
22 22
  */
23 23
 class VCalendar extends VObject\Document
24 24
 {
25
-    /**
26
-     * The default name for this component.
27
-     *
28
-     * This should be 'VCALENDAR' or 'VCARD'.
29
-     *
30
-     * @var string
31
-     */
32
-    public static $defaultName = 'VCALENDAR';
33
-
34
-    /**
35
-     * This is a list of components, and which classes they should map to.
36
-     *
37
-     * @var array
38
-     */
39
-    public static $componentMap = [
40
-        'VCALENDAR' => self::class,
41
-        'VALARM' => VAlarm::class,
42
-        'VEVENT' => VEvent::class,
43
-        'VFREEBUSY' => VFreeBusy::class,
44
-        'VAVAILABILITY' => VAvailability::class,
45
-        'AVAILABLE' => Available::class,
46
-        'VJOURNAL' => VJournal::class,
47
-        'VTIMEZONE' => VTimeZone::class,
48
-        'VTODO' => VTodo::class,
49
-    ];
50
-
51
-    /**
52
-     * List of value-types, and which classes they map to.
53
-     *
54
-     * @var array
55
-     */
56
-    public static $valueMap = [
57
-        'BINARY' => VObject\Property\Binary::class,
58
-        'BOOLEAN' => VObject\Property\Boolean::class,
59
-        'CAL-ADDRESS' => VObject\Property\ICalendar\CalAddress::class,
60
-        'DATE' => VObject\Property\ICalendar\Date::class,
61
-        'DATE-TIME' => VObject\Property\ICalendar\DateTime::class,
62
-        'DURATION' => VObject\Property\ICalendar\Duration::class,
63
-        'FLOAT' => VObject\Property\FloatValue::class,
64
-        'INTEGER' => VObject\Property\IntegerValue::class,
65
-        'PERIOD' => VObject\Property\ICalendar\Period::class,
66
-        'RECUR' => VObject\Property\ICalendar\Recur::class,
67
-        'TEXT' => VObject\Property\Text::class,
68
-        'TIME' => VObject\Property\Time::class,
69
-        'UNKNOWN' => VObject\Property\Unknown::class, // jCard / jCal-only.
70
-        'URI' => VObject\Property\Uri::class,
71
-        'UTC-OFFSET' => VObject\Property\UtcOffset::class,
72
-    ];
73
-
74
-    /**
75
-     * List of properties, and which classes they map to.
76
-     *
77
-     * @var array
78
-     */
79
-    public static $propertyMap = [
80
-        // Calendar properties
81
-        'CALSCALE' => VObject\Property\FlatText::class,
82
-        'METHOD' => VObject\Property\FlatText::class,
83
-        'PRODID' => VObject\Property\FlatText::class,
84
-        'VERSION' => VObject\Property\FlatText::class,
85
-
86
-        // Component properties
87
-        'ATTACH' => VObject\Property\Uri::class,
88
-        'CATEGORIES' => VObject\Property\Text::class,
89
-        'CLASS' => VObject\Property\FlatText::class,
90
-        'COMMENT' => VObject\Property\FlatText::class,
91
-        'DESCRIPTION' => VObject\Property\FlatText::class,
92
-        'GEO' => VObject\Property\FloatValue::class,
93
-        'LOCATION' => VObject\Property\FlatText::class,
94
-        'PERCENT-COMPLETE' => VObject\Property\IntegerValue::class,
95
-        'PRIORITY' => VObject\Property\IntegerValue::class,
96
-        'RESOURCES' => VObject\Property\Text::class,
97
-        'STATUS' => VObject\Property\FlatText::class,
98
-        'SUMMARY' => VObject\Property\FlatText::class,
99
-
100
-        // Date and Time Component Properties
101
-        'COMPLETED' => VObject\Property\ICalendar\DateTime::class,
102
-        'DTEND' => VObject\Property\ICalendar\DateTime::class,
103
-        'DUE' => VObject\Property\ICalendar\DateTime::class,
104
-        'DTSTART' => VObject\Property\ICalendar\DateTime::class,
105
-        'DURATION' => VObject\Property\ICalendar\Duration::class,
106
-        'FREEBUSY' => VObject\Property\ICalendar\Period::class,
107
-        'TRANSP' => VObject\Property\FlatText::class,
108
-
109
-        // Time Zone Component Properties
110
-        'TZID' => VObject\Property\FlatText::class,
111
-        'TZNAME' => VObject\Property\FlatText::class,
112
-        'TZOFFSETFROM' => VObject\Property\UtcOffset::class,
113
-        'TZOFFSETTO' => VObject\Property\UtcOffset::class,
114
-        'TZURL' => VObject\Property\Uri::class,
115
-
116
-        // Relationship Component Properties
117
-        'ATTENDEE' => VObject\Property\ICalendar\CalAddress::class,
118
-        'CONTACT' => VObject\Property\FlatText::class,
119
-        'ORGANIZER' => VObject\Property\ICalendar\CalAddress::class,
120
-        'RECURRENCE-ID' => VObject\Property\ICalendar\DateTime::class,
121
-        'RELATED-TO' => VObject\Property\FlatText::class,
122
-        'URL' => VObject\Property\Uri::class,
123
-        'UID' => VObject\Property\FlatText::class,
124
-
125
-        // Recurrence Component Properties
126
-        'EXDATE' => VObject\Property\ICalendar\DateTime::class,
127
-        'RDATE' => VObject\Property\ICalendar\DateTime::class,
128
-        'RRULE' => VObject\Property\ICalendar\Recur::class,
129
-        'EXRULE' => VObject\Property\ICalendar\Recur::class, // Deprecated since rfc5545
130
-
131
-        // Alarm Component Properties
132
-        'ACTION' => VObject\Property\FlatText::class,
133
-        'REPEAT' => VObject\Property\IntegerValue::class,
134
-        'TRIGGER' => VObject\Property\ICalendar\Duration::class,
135
-
136
-        // Change Management Component Properties
137
-        'CREATED' => VObject\Property\ICalendar\DateTime::class,
138
-        'DTSTAMP' => VObject\Property\ICalendar\DateTime::class,
139
-        'LAST-MODIFIED' => VObject\Property\ICalendar\DateTime::class,
140
-        'SEQUENCE' => VObject\Property\IntegerValue::class,
141
-
142
-        // Request Status
143
-        'REQUEST-STATUS' => VObject\Property\Text::class,
144
-
145
-        // Additions from draft-daboo-valarm-extensions-04
146
-        'ALARM-AGENT' => VObject\Property\Text::class,
147
-        'ACKNOWLEDGED' => VObject\Property\ICalendar\DateTime::class,
148
-        'PROXIMITY' => VObject\Property\Text::class,
149
-        'DEFAULT-ALARM' => VObject\Property\Boolean::class,
150
-
151
-        // Additions from draft-daboo-calendar-availability-05
152
-        'BUSYTYPE' => VObject\Property\Text::class,
153
-    ];
154
-
155
-    /**
156
-     * Returns the current document type.
157
-     *
158
-     * @return int
159
-     */
160
-    public function getDocumentType()
161
-    {
162
-        return self::ICALENDAR20;
163
-    }
164
-
165
-    /**
166
-     * Returns a list of all 'base components'. For instance, if an Event has
167
-     * a recurrence rule, and one instance is overridden, the overridden event
168
-     * will have the same UID, but will be excluded from this list.
169
-     *
170
-     * VTIMEZONE components will always be excluded.
171
-     *
172
-     * @param string $componentName filter by component name
173
-     *
174
-     * @return VObject\Component[]
175
-     */
176
-    public function getBaseComponents($componentName = null)
177
-    {
178
-        $isBaseComponent = function ($component) {
179
-            if (!$component instanceof VObject\Component) {
180
-                return false;
181
-            }
182
-            if ('VTIMEZONE' === $component->name) {
183
-                return false;
184
-            }
185
-            if (isset($component->{'RECURRENCE-ID'})) {
186
-                return false;
187
-            }
188
-
189
-            return true;
190
-        };
191
-
192
-        if ($componentName) {
193
-            // Early exit
194
-            return array_filter(
195
-                $this->select($componentName),
196
-                $isBaseComponent
197
-            );
198
-        }
199
-
200
-        $components = [];
201
-        foreach ($this->children as $childGroup) {
202
-            foreach ($childGroup as $child) {
203
-                if (!$child instanceof Component) {
204
-                    // If one child is not a component, they all are so we skip
205
-                    // the entire group.
206
-                    continue 2;
207
-                }
208
-                if ($isBaseComponent($child)) {
209
-                    $components[] = $child;
210
-                }
211
-            }
212
-        }
213
-
214
-        return $components;
215
-    }
216
-
217
-    /**
218
-     * Returns the first component that is not a VTIMEZONE, and does not have
219
-     * an RECURRENCE-ID.
220
-     *
221
-     * If there is no such component, null will be returned.
222
-     *
223
-     * @param string $componentName filter by component name
224
-     *
225
-     * @return VObject\Component|null
226
-     */
227
-    public function getBaseComponent($componentName = null)
228
-    {
229
-        $isBaseComponent = function ($component) {
230
-            if (!$component instanceof VObject\Component) {
231
-                return false;
232
-            }
233
-            if ('VTIMEZONE' === $component->name) {
234
-                return false;
235
-            }
236
-            if (isset($component->{'RECURRENCE-ID'})) {
237
-                return false;
238
-            }
239
-
240
-            return true;
241
-        };
242
-
243
-        if ($componentName) {
244
-            foreach ($this->select($componentName) as $child) {
245
-                if ($isBaseComponent($child)) {
246
-                    return $child;
247
-                }
248
-            }
249
-
250
-            return null;
251
-        }
252
-
253
-        // Searching all components
254
-        foreach ($this->children as $childGroup) {
255
-            foreach ($childGroup as $child) {
256
-                if ($isBaseComponent($child)) {
257
-                    return $child;
258
-                }
259
-            }
260
-        }
261
-
262
-        return null;
263
-    }
264
-
265
-    /**
266
-     * Expand all events in this VCalendar object and return a new VCalendar
267
-     * with the expanded events.
268
-     *
269
-     * If this calendar object, has events with recurrence rules, this method
270
-     * can be used to expand the event into multiple sub-events.
271
-     *
272
-     * Each event will be stripped from its recurrence information, and only
273
-     * the instances of the event in the specified timerange will be left
274
-     * alone.
275
-     *
276
-     * In addition, this method will cause timezone information to be stripped,
277
-     * and normalized to UTC.
278
-     *
279
-     * @param DateTimeZone $timeZone reference timezone for floating dates and
280
-     *                               times
281
-     *
282
-     * @return VCalendar
283
-     */
284
-    public function expand(DateTimeInterface $start, DateTimeInterface $end, DateTimeZone $timeZone = null)
285
-    {
286
-        $newChildren = [];
287
-        $recurringEvents = [];
288
-
289
-        if (!$timeZone) {
290
-            $timeZone = new DateTimeZone('UTC');
291
-        }
292
-
293
-        $stripTimezones = function (Component $component) use ($timeZone, &$stripTimezones) {
294
-            foreach ($component->children() as $componentChild) {
295
-                if ($componentChild instanceof Property\ICalendar\DateTime && $componentChild->hasTime()) {
296
-                    $dt = $componentChild->getDateTimes($timeZone);
297
-                    // We only need to update the first timezone, because
298
-                    // setDateTimes will match all other timezones to the
299
-                    // first.
300
-                    $dt[0] = $dt[0]->setTimeZone(new DateTimeZone('UTC'));
301
-                    $componentChild->setDateTimes($dt);
302
-                } elseif ($componentChild instanceof Component) {
303
-                    $stripTimezones($componentChild);
304
-                }
305
-            }
306
-
307
-            return $component;
308
-        };
309
-
310
-        foreach ($this->children() as $child) {
311
-            if ($child instanceof Property && 'PRODID' !== $child->name) {
312
-                // We explicitly want to ignore PRODID, because we want to
313
-                // overwrite it with our own.
314
-                $newChildren[] = clone $child;
315
-            } elseif ($child instanceof Component && 'VTIMEZONE' !== $child->name) {
316
-                // We're also stripping all VTIMEZONE objects because we're
317
-                // converting everything to UTC.
318
-                if ('VEVENT' === $child->name && (isset($child->{'RECURRENCE-ID'}) || isset($child->RRULE) || isset($child->RDATE))) {
319
-                    // Handle these a bit later.
320
-                    $uid = (string) $child->UID;
321
-                    if (!$uid) {
322
-                        throw new InvalidDataException('Every VEVENT object must have a UID property');
323
-                    }
324
-                    if (isset($recurringEvents[$uid])) {
325
-                        $recurringEvents[$uid][] = clone $child;
326
-                    } else {
327
-                        $recurringEvents[$uid] = [clone $child];
328
-                    }
329
-                } elseif ('VEVENT' === $child->name && $child->isInTimeRange($start, $end)) {
330
-                    $newChildren[] = $stripTimezones(clone $child);
331
-                }
332
-            }
333
-        }
334
-
335
-        foreach ($recurringEvents as $events) {
336
-            try {
337
-                $it = new EventIterator($events, null, $timeZone);
338
-            } catch (NoInstancesException $e) {
339
-                // This event is recurring, but it doesn't have a single
340
-                // instance. We are skipping this event from the output
341
-                // entirely.
342
-                continue;
343
-            }
344
-            $it->fastForward($start);
345
-
346
-            while ($it->valid() && $it->getDTStart() < $end) {
347
-                if ($it->getDTEnd() > $start) {
348
-                    $newChildren[] = $stripTimezones($it->getEventObject());
349
-                }
350
-                $it->next();
351
-            }
352
-        }
353
-
354
-        return new self($newChildren);
355
-    }
356
-
357
-    /**
358
-     * This method should return a list of default property values.
359
-     *
360
-     * @return array
361
-     */
362
-    protected function getDefaults()
363
-    {
364
-        return [
365
-            'VERSION' => '2.0',
366
-            'PRODID' => '-//Sabre//Sabre VObject '.VObject\Version::VERSION.'//EN',
367
-            'CALSCALE' => 'GREGORIAN',
368
-        ];
369
-    }
370
-
371
-    /**
372
-     * A simple list of validation rules.
373
-     *
374
-     * This is simply a list of properties, and how many times they either
375
-     * must or must not appear.
376
-     *
377
-     * Possible values per property:
378
-     *   * 0 - Must not appear.
379
-     *   * 1 - Must appear exactly once.
380
-     *   * + - Must appear at least once.
381
-     *   * * - Can appear any number of times.
382
-     *   * ? - May appear, but not more than once.
383
-     *
384
-     * @var array
385
-     */
386
-    public function getValidationRules()
387
-    {
388
-        return [
389
-            'PRODID' => 1,
390
-            'VERSION' => 1,
391
-
392
-            'CALSCALE' => '?',
393
-            'METHOD' => '?',
394
-        ];
395
-    }
396
-
397
-    /**
398
-     * Validates the node for correctness.
399
-     *
400
-     * The following options are supported:
401
-     *   Node::REPAIR - May attempt to automatically repair the problem.
402
-     *   Node::PROFILE_CARDDAV - Validate the vCard for CardDAV purposes.
403
-     *   Node::PROFILE_CALDAV - Validate the iCalendar for CalDAV purposes.
404
-     *
405
-     * This method returns an array with detected problems.
406
-     * Every element has the following properties:
407
-     *
408
-     *  * level - problem level.
409
-     *  * message - A human-readable string describing the issue.
410
-     *  * node - A reference to the problematic node.
411
-     *
412
-     * The level means:
413
-     *   1 - The issue was repaired (only happens if REPAIR was turned on).
414
-     *   2 - A warning.
415
-     *   3 - An error.
416
-     *
417
-     * @param int $options
418
-     *
419
-     * @return array
420
-     */
421
-    public function validate($options = 0)
422
-    {
423
-        $warnings = parent::validate($options);
424
-
425
-        if ($ver = $this->VERSION) {
426
-            if ('2.0' !== (string) $ver) {
427
-                $warnings[] = [
428
-                    'level' => 3,
429
-                    'message' => 'Only iCalendar version 2.0 as defined in rfc5545 is supported.',
430
-                    'node' => $this,
431
-                ];
432
-            }
433
-        }
434
-
435
-        $uidList = [];
436
-        $componentsFound = 0;
437
-        $componentTypes = [];
438
-
439
-        foreach ($this->children() as $child) {
440
-            if ($child instanceof Component) {
441
-                ++$componentsFound;
442
-
443
-                if (!in_array($child->name, ['VEVENT', 'VTODO', 'VJOURNAL'])) {
444
-                    continue;
445
-                }
446
-                $componentTypes[] = $child->name;
447
-
448
-                $uid = (string) $child->UID;
449
-                $isMaster = isset($child->{'RECURRENCE-ID'}) ? 0 : 1;
450
-                if (isset($uidList[$uid])) {
451
-                    ++$uidList[$uid]['count'];
452
-                    if ($isMaster && $uidList[$uid]['hasMaster']) {
453
-                        $warnings[] = [
454
-                            'level' => 3,
455
-                            'message' => 'More than one master object was found for the object with UID '.$uid,
456
-                            'node' => $this,
457
-                        ];
458
-                    }
459
-                    $uidList[$uid]['hasMaster'] += $isMaster;
460
-                } else {
461
-                    $uidList[$uid] = [
462
-                        'count' => 1,
463
-                        'hasMaster' => $isMaster,
464
-                    ];
465
-                }
466
-            }
467
-        }
468
-
469
-        if (0 === $componentsFound) {
470
-            $warnings[] = [
471
-                'level' => 3,
472
-                'message' => 'An iCalendar object must have at least 1 component.',
473
-                'node' => $this,
474
-            ];
475
-        }
476
-
477
-        if ($options & self::PROFILE_CALDAV) {
478
-            if (count($uidList) > 1) {
479
-                $warnings[] = [
480
-                    'level' => 3,
481
-                    'message' => 'A calendar object on a CalDAV server may only have components with the same UID.',
482
-                    'node' => $this,
483
-                ];
484
-            }
485
-            if (0 === count($componentTypes)) {
486
-                $warnings[] = [
487
-                    'level' => 3,
488
-                    'message' => 'A calendar object on a CalDAV server must have at least 1 component (VTODO, VEVENT, VJOURNAL).',
489
-                    'node' => $this,
490
-                ];
491
-            }
492
-            if (count(array_unique($componentTypes)) > 1) {
493
-                $warnings[] = [
494
-                    'level' => 3,
495
-                    'message' => 'A calendar object on a CalDAV server may only have 1 type of component (VEVENT, VTODO or VJOURNAL).',
496
-                    'node' => $this,
497
-                ];
498
-            }
499
-
500
-            if (isset($this->METHOD)) {
501
-                $warnings[] = [
502
-                    'level' => 3,
503
-                    'message' => 'A calendar object on a CalDAV server MUST NOT have a METHOD property.',
504
-                    'node' => $this,
505
-                ];
506
-            }
507
-        }
508
-
509
-        return $warnings;
510
-    }
511
-
512
-    /**
513
-     * Returns all components with a specific UID value.
514
-     *
515
-     * @return array
516
-     */
517
-    public function getByUID($uid)
518
-    {
519
-        return array_filter($this->getComponents(), function ($item) use ($uid) {
520
-            if (!$itemUid = $item->select('UID')) {
521
-                return false;
522
-            }
523
-            $itemUid = current($itemUid)->getValue();
524
-
525
-            return $uid === $itemUid;
526
-        });
527
-    }
25
+	/**
26
+	 * The default name for this component.
27
+	 *
28
+	 * This should be 'VCALENDAR' or 'VCARD'.
29
+	 *
30
+	 * @var string
31
+	 */
32
+	public static $defaultName = 'VCALENDAR';
33
+
34
+	/**
35
+	 * This is a list of components, and which classes they should map to.
36
+	 *
37
+	 * @var array
38
+	 */
39
+	public static $componentMap = [
40
+		'VCALENDAR' => self::class,
41
+		'VALARM' => VAlarm::class,
42
+		'VEVENT' => VEvent::class,
43
+		'VFREEBUSY' => VFreeBusy::class,
44
+		'VAVAILABILITY' => VAvailability::class,
45
+		'AVAILABLE' => Available::class,
46
+		'VJOURNAL' => VJournal::class,
47
+		'VTIMEZONE' => VTimeZone::class,
48
+		'VTODO' => VTodo::class,
49
+	];
50
+
51
+	/**
52
+	 * List of value-types, and which classes they map to.
53
+	 *
54
+	 * @var array
55
+	 */
56
+	public static $valueMap = [
57
+		'BINARY' => VObject\Property\Binary::class,
58
+		'BOOLEAN' => VObject\Property\Boolean::class,
59
+		'CAL-ADDRESS' => VObject\Property\ICalendar\CalAddress::class,
60
+		'DATE' => VObject\Property\ICalendar\Date::class,
61
+		'DATE-TIME' => VObject\Property\ICalendar\DateTime::class,
62
+		'DURATION' => VObject\Property\ICalendar\Duration::class,
63
+		'FLOAT' => VObject\Property\FloatValue::class,
64
+		'INTEGER' => VObject\Property\IntegerValue::class,
65
+		'PERIOD' => VObject\Property\ICalendar\Period::class,
66
+		'RECUR' => VObject\Property\ICalendar\Recur::class,
67
+		'TEXT' => VObject\Property\Text::class,
68
+		'TIME' => VObject\Property\Time::class,
69
+		'UNKNOWN' => VObject\Property\Unknown::class, // jCard / jCal-only.
70
+		'URI' => VObject\Property\Uri::class,
71
+		'UTC-OFFSET' => VObject\Property\UtcOffset::class,
72
+	];
73
+
74
+	/**
75
+	 * List of properties, and which classes they map to.
76
+	 *
77
+	 * @var array
78
+	 */
79
+	public static $propertyMap = [
80
+		// Calendar properties
81
+		'CALSCALE' => VObject\Property\FlatText::class,
82
+		'METHOD' => VObject\Property\FlatText::class,
83
+		'PRODID' => VObject\Property\FlatText::class,
84
+		'VERSION' => VObject\Property\FlatText::class,
85
+
86
+		// Component properties
87
+		'ATTACH' => VObject\Property\Uri::class,
88
+		'CATEGORIES' => VObject\Property\Text::class,
89
+		'CLASS' => VObject\Property\FlatText::class,
90
+		'COMMENT' => VObject\Property\FlatText::class,
91
+		'DESCRIPTION' => VObject\Property\FlatText::class,
92
+		'GEO' => VObject\Property\FloatValue::class,
93
+		'LOCATION' => VObject\Property\FlatText::class,
94
+		'PERCENT-COMPLETE' => VObject\Property\IntegerValue::class,
95
+		'PRIORITY' => VObject\Property\IntegerValue::class,
96
+		'RESOURCES' => VObject\Property\Text::class,
97
+		'STATUS' => VObject\Property\FlatText::class,
98
+		'SUMMARY' => VObject\Property\FlatText::class,
99
+
100
+		// Date and Time Component Properties
101
+		'COMPLETED' => VObject\Property\ICalendar\DateTime::class,
102
+		'DTEND' => VObject\Property\ICalendar\DateTime::class,
103
+		'DUE' => VObject\Property\ICalendar\DateTime::class,
104
+		'DTSTART' => VObject\Property\ICalendar\DateTime::class,
105
+		'DURATION' => VObject\Property\ICalendar\Duration::class,
106
+		'FREEBUSY' => VObject\Property\ICalendar\Period::class,
107
+		'TRANSP' => VObject\Property\FlatText::class,
108
+
109
+		// Time Zone Component Properties
110
+		'TZID' => VObject\Property\FlatText::class,
111
+		'TZNAME' => VObject\Property\FlatText::class,
112
+		'TZOFFSETFROM' => VObject\Property\UtcOffset::class,
113
+		'TZOFFSETTO' => VObject\Property\UtcOffset::class,
114
+		'TZURL' => VObject\Property\Uri::class,
115
+
116
+		// Relationship Component Properties
117
+		'ATTENDEE' => VObject\Property\ICalendar\CalAddress::class,
118
+		'CONTACT' => VObject\Property\FlatText::class,
119
+		'ORGANIZER' => VObject\Property\ICalendar\CalAddress::class,
120
+		'RECURRENCE-ID' => VObject\Property\ICalendar\DateTime::class,
121
+		'RELATED-TO' => VObject\Property\FlatText::class,
122
+		'URL' => VObject\Property\Uri::class,
123
+		'UID' => VObject\Property\FlatText::class,
124
+
125
+		// Recurrence Component Properties
126
+		'EXDATE' => VObject\Property\ICalendar\DateTime::class,
127
+		'RDATE' => VObject\Property\ICalendar\DateTime::class,
128
+		'RRULE' => VObject\Property\ICalendar\Recur::class,
129
+		'EXRULE' => VObject\Property\ICalendar\Recur::class, // Deprecated since rfc5545
130
+
131
+		// Alarm Component Properties
132
+		'ACTION' => VObject\Property\FlatText::class,
133
+		'REPEAT' => VObject\Property\IntegerValue::class,
134
+		'TRIGGER' => VObject\Property\ICalendar\Duration::class,
135
+
136
+		// Change Management Component Properties
137
+		'CREATED' => VObject\Property\ICalendar\DateTime::class,
138
+		'DTSTAMP' => VObject\Property\ICalendar\DateTime::class,
139
+		'LAST-MODIFIED' => VObject\Property\ICalendar\DateTime::class,
140
+		'SEQUENCE' => VObject\Property\IntegerValue::class,
141
+
142
+		// Request Status
143
+		'REQUEST-STATUS' => VObject\Property\Text::class,
144
+
145
+		// Additions from draft-daboo-valarm-extensions-04
146
+		'ALARM-AGENT' => VObject\Property\Text::class,
147
+		'ACKNOWLEDGED' => VObject\Property\ICalendar\DateTime::class,
148
+		'PROXIMITY' => VObject\Property\Text::class,
149
+		'DEFAULT-ALARM' => VObject\Property\Boolean::class,
150
+
151
+		// Additions from draft-daboo-calendar-availability-05
152
+		'BUSYTYPE' => VObject\Property\Text::class,
153
+	];
154
+
155
+	/**
156
+	 * Returns the current document type.
157
+	 *
158
+	 * @return int
159
+	 */
160
+	public function getDocumentType()
161
+	{
162
+		return self::ICALENDAR20;
163
+	}
164
+
165
+	/**
166
+	 * Returns a list of all 'base components'. For instance, if an Event has
167
+	 * a recurrence rule, and one instance is overridden, the overridden event
168
+	 * will have the same UID, but will be excluded from this list.
169
+	 *
170
+	 * VTIMEZONE components will always be excluded.
171
+	 *
172
+	 * @param string $componentName filter by component name
173
+	 *
174
+	 * @return VObject\Component[]
175
+	 */
176
+	public function getBaseComponents($componentName = null)
177
+	{
178
+		$isBaseComponent = function ($component) {
179
+			if (!$component instanceof VObject\Component) {
180
+				return false;
181
+			}
182
+			if ('VTIMEZONE' === $component->name) {
183
+				return false;
184
+			}
185
+			if (isset($component->{'RECURRENCE-ID'})) {
186
+				return false;
187
+			}
188
+
189
+			return true;
190
+		};
191
+
192
+		if ($componentName) {
193
+			// Early exit
194
+			return array_filter(
195
+				$this->select($componentName),
196
+				$isBaseComponent
197
+			);
198
+		}
199
+
200
+		$components = [];
201
+		foreach ($this->children as $childGroup) {
202
+			foreach ($childGroup as $child) {
203
+				if (!$child instanceof Component) {
204
+					// If one child is not a component, they all are so we skip
205
+					// the entire group.
206
+					continue 2;
207
+				}
208
+				if ($isBaseComponent($child)) {
209
+					$components[] = $child;
210
+				}
211
+			}
212
+		}
213
+
214
+		return $components;
215
+	}
216
+
217
+	/**
218
+	 * Returns the first component that is not a VTIMEZONE, and does not have
219
+	 * an RECURRENCE-ID.
220
+	 *
221
+	 * If there is no such component, null will be returned.
222
+	 *
223
+	 * @param string $componentName filter by component name
224
+	 *
225
+	 * @return VObject\Component|null
226
+	 */
227
+	public function getBaseComponent($componentName = null)
228
+	{
229
+		$isBaseComponent = function ($component) {
230
+			if (!$component instanceof VObject\Component) {
231
+				return false;
232
+			}
233
+			if ('VTIMEZONE' === $component->name) {
234
+				return false;
235
+			}
236
+			if (isset($component->{'RECURRENCE-ID'})) {
237
+				return false;
238
+			}
239
+
240
+			return true;
241
+		};
242
+
243
+		if ($componentName) {
244
+			foreach ($this->select($componentName) as $child) {
245
+				if ($isBaseComponent($child)) {
246
+					return $child;
247
+				}
248
+			}
249
+
250
+			return null;
251
+		}
252
+
253
+		// Searching all components
254
+		foreach ($this->children as $childGroup) {
255
+			foreach ($childGroup as $child) {
256
+				if ($isBaseComponent($child)) {
257
+					return $child;
258
+				}
259
+			}
260
+		}
261
+
262
+		return null;
263
+	}
264
+
265
+	/**
266
+	 * Expand all events in this VCalendar object and return a new VCalendar
267
+	 * with the expanded events.
268
+	 *
269
+	 * If this calendar object, has events with recurrence rules, this method
270
+	 * can be used to expand the event into multiple sub-events.
271
+	 *
272
+	 * Each event will be stripped from its recurrence information, and only
273
+	 * the instances of the event in the specified timerange will be left
274
+	 * alone.
275
+	 *
276
+	 * In addition, this method will cause timezone information to be stripped,
277
+	 * and normalized to UTC.
278
+	 *
279
+	 * @param DateTimeZone $timeZone reference timezone for floating dates and
280
+	 *                               times
281
+	 *
282
+	 * @return VCalendar
283
+	 */
284
+	public function expand(DateTimeInterface $start, DateTimeInterface $end, DateTimeZone $timeZone = null)
285
+	{
286
+		$newChildren = [];
287
+		$recurringEvents = [];
288
+
289
+		if (!$timeZone) {
290
+			$timeZone = new DateTimeZone('UTC');
291
+		}
292
+
293
+		$stripTimezones = function (Component $component) use ($timeZone, &$stripTimezones) {
294
+			foreach ($component->children() as $componentChild) {
295
+				if ($componentChild instanceof Property\ICalendar\DateTime && $componentChild->hasTime()) {
296
+					$dt = $componentChild->getDateTimes($timeZone);
297
+					// We only need to update the first timezone, because
298
+					// setDateTimes will match all other timezones to the
299
+					// first.
300
+					$dt[0] = $dt[0]->setTimeZone(new DateTimeZone('UTC'));
301
+					$componentChild->setDateTimes($dt);
302
+				} elseif ($componentChild instanceof Component) {
303
+					$stripTimezones($componentChild);
304
+				}
305
+			}
306
+
307
+			return $component;
308
+		};
309
+
310
+		foreach ($this->children() as $child) {
311
+			if ($child instanceof Property && 'PRODID' !== $child->name) {
312
+				// We explicitly want to ignore PRODID, because we want to
313
+				// overwrite it with our own.
314
+				$newChildren[] = clone $child;
315
+			} elseif ($child instanceof Component && 'VTIMEZONE' !== $child->name) {
316
+				// We're also stripping all VTIMEZONE objects because we're
317
+				// converting everything to UTC.
318
+				if ('VEVENT' === $child->name && (isset($child->{'RECURRENCE-ID'}) || isset($child->RRULE) || isset($child->RDATE))) {
319
+					// Handle these a bit later.
320
+					$uid = (string) $child->UID;
321
+					if (!$uid) {
322
+						throw new InvalidDataException('Every VEVENT object must have a UID property');
323
+					}
324
+					if (isset($recurringEvents[$uid])) {
325
+						$recurringEvents[$uid][] = clone $child;
326
+					} else {
327
+						$recurringEvents[$uid] = [clone $child];
328
+					}
329
+				} elseif ('VEVENT' === $child->name && $child->isInTimeRange($start, $end)) {
330
+					$newChildren[] = $stripTimezones(clone $child);
331
+				}
332
+			}
333
+		}
334
+
335
+		foreach ($recurringEvents as $events) {
336
+			try {
337
+				$it = new EventIterator($events, null, $timeZone);
338
+			} catch (NoInstancesException $e) {
339
+				// This event is recurring, but it doesn't have a single
340
+				// instance. We are skipping this event from the output
341
+				// entirely.
342
+				continue;
343
+			}
344
+			$it->fastForward($start);
345
+
346
+			while ($it->valid() && $it->getDTStart() < $end) {
347
+				if ($it->getDTEnd() > $start) {
348
+					$newChildren[] = $stripTimezones($it->getEventObject());
349
+				}
350
+				$it->next();
351
+			}
352
+		}
353
+
354
+		return new self($newChildren);
355
+	}
356
+
357
+	/**
358
+	 * This method should return a list of default property values.
359
+	 *
360
+	 * @return array
361
+	 */
362
+	protected function getDefaults()
363
+	{
364
+		return [
365
+			'VERSION' => '2.0',
366
+			'PRODID' => '-//Sabre//Sabre VObject '.VObject\Version::VERSION.'//EN',
367
+			'CALSCALE' => 'GREGORIAN',
368
+		];
369
+	}
370
+
371
+	/**
372
+	 * A simple list of validation rules.
373
+	 *
374
+	 * This is simply a list of properties, and how many times they either
375
+	 * must or must not appear.
376
+	 *
377
+	 * Possible values per property:
378
+	 *   * 0 - Must not appear.
379
+	 *   * 1 - Must appear exactly once.
380
+	 *   * + - Must appear at least once.
381
+	 *   * * - Can appear any number of times.
382
+	 *   * ? - May appear, but not more than once.
383
+	 *
384
+	 * @var array
385
+	 */
386
+	public function getValidationRules()
387
+	{
388
+		return [
389
+			'PRODID' => 1,
390
+			'VERSION' => 1,
391
+
392
+			'CALSCALE' => '?',
393
+			'METHOD' => '?',
394
+		];
395
+	}
396
+
397
+	/**
398
+	 * Validates the node for correctness.
399
+	 *
400
+	 * The following options are supported:
401
+	 *   Node::REPAIR - May attempt to automatically repair the problem.
402
+	 *   Node::PROFILE_CARDDAV - Validate the vCard for CardDAV purposes.
403
+	 *   Node::PROFILE_CALDAV - Validate the iCalendar for CalDAV purposes.
404
+	 *
405
+	 * This method returns an array with detected problems.
406
+	 * Every element has the following properties:
407
+	 *
408
+	 *  * level - problem level.
409
+	 *  * message - A human-readable string describing the issue.
410
+	 *  * node - A reference to the problematic node.
411
+	 *
412
+	 * The level means:
413
+	 *   1 - The issue was repaired (only happens if REPAIR was turned on).
414
+	 *   2 - A warning.
415
+	 *   3 - An error.
416
+	 *
417
+	 * @param int $options
418
+	 *
419
+	 * @return array
420
+	 */
421
+	public function validate($options = 0)
422
+	{
423
+		$warnings = parent::validate($options);
424
+
425
+		if ($ver = $this->VERSION) {
426
+			if ('2.0' !== (string) $ver) {
427
+				$warnings[] = [
428
+					'level' => 3,
429
+					'message' => 'Only iCalendar version 2.0 as defined in rfc5545 is supported.',
430
+					'node' => $this,
431
+				];
432
+			}
433
+		}
434
+
435
+		$uidList = [];
436
+		$componentsFound = 0;
437
+		$componentTypes = [];
438
+
439
+		foreach ($this->children() as $child) {
440
+			if ($child instanceof Component) {
441
+				++$componentsFound;
442
+
443
+				if (!in_array($child->name, ['VEVENT', 'VTODO', 'VJOURNAL'])) {
444
+					continue;
445
+				}
446
+				$componentTypes[] = $child->name;
447
+
448
+				$uid = (string) $child->UID;
449
+				$isMaster = isset($child->{'RECURRENCE-ID'}) ? 0 : 1;
450
+				if (isset($uidList[$uid])) {
451
+					++$uidList[$uid]['count'];
452
+					if ($isMaster && $uidList[$uid]['hasMaster']) {
453
+						$warnings[] = [
454
+							'level' => 3,
455
+							'message' => 'More than one master object was found for the object with UID '.$uid,
456
+							'node' => $this,
457
+						];
458
+					}
459
+					$uidList[$uid]['hasMaster'] += $isMaster;
460
+				} else {
461
+					$uidList[$uid] = [
462
+						'count' => 1,
463
+						'hasMaster' => $isMaster,
464
+					];
465
+				}
466
+			}
467
+		}
468
+
469
+		if (0 === $componentsFound) {
470
+			$warnings[] = [
471
+				'level' => 3,
472
+				'message' => 'An iCalendar object must have at least 1 component.',
473
+				'node' => $this,
474
+			];
475
+		}
476
+
477
+		if ($options & self::PROFILE_CALDAV) {
478
+			if (count($uidList) > 1) {
479
+				$warnings[] = [
480
+					'level' => 3,
481
+					'message' => 'A calendar object on a CalDAV server may only have components with the same UID.',
482
+					'node' => $this,
483
+				];
484
+			}
485
+			if (0 === count($componentTypes)) {
486
+				$warnings[] = [
487
+					'level' => 3,
488
+					'message' => 'A calendar object on a CalDAV server must have at least 1 component (VTODO, VEVENT, VJOURNAL).',
489
+					'node' => $this,
490
+				];
491
+			}
492
+			if (count(array_unique($componentTypes)) > 1) {
493
+				$warnings[] = [
494
+					'level' => 3,
495
+					'message' => 'A calendar object on a CalDAV server may only have 1 type of component (VEVENT, VTODO or VJOURNAL).',
496
+					'node' => $this,
497
+				];
498
+			}
499
+
500
+			if (isset($this->METHOD)) {
501
+				$warnings[] = [
502
+					'level' => 3,
503
+					'message' => 'A calendar object on a CalDAV server MUST NOT have a METHOD property.',
504
+					'node' => $this,
505
+				];
506
+			}
507
+		}
508
+
509
+		return $warnings;
510
+	}
511
+
512
+	/**
513
+	 * Returns all components with a specific UID value.
514
+	 *
515
+	 * @return array
516
+	 */
517
+	public function getByUID($uid)
518
+	{
519
+		return array_filter($this->getComponents(), function ($item) use ($uid) {
520
+			if (!$itemUid = $item->select('UID')) {
521
+				return false;
522
+			}
523
+			$itemUid = current($itemUid)->getValue();
524
+
525
+			return $uid === $itemUid;
526
+		});
527
+	}
528 528
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -175,7 +175,7 @@  discard block
 block discarded – undo
175 175
      */
176 176
     public function getBaseComponents($componentName = null)
177 177
     {
178
-        $isBaseComponent = function ($component) {
178
+        $isBaseComponent = function($component) {
179 179
             if (!$component instanceof VObject\Component) {
180 180
                 return false;
181 181
             }
@@ -226,7 +226,7 @@  discard block
 block discarded – undo
226 226
      */
227 227
     public function getBaseComponent($componentName = null)
228 228
     {
229
-        $isBaseComponent = function ($component) {
229
+        $isBaseComponent = function($component) {
230 230
             if (!$component instanceof VObject\Component) {
231 231
                 return false;
232 232
             }
@@ -290,7 +290,7 @@  discard block
 block discarded – undo
290 290
             $timeZone = new DateTimeZone('UTC');
291 291
         }
292 292
 
293
-        $stripTimezones = function (Component $component) use ($timeZone, &$stripTimezones) {
293
+        $stripTimezones = function(Component $component) use ($timeZone, &$stripTimezones) {
294 294
             foreach ($component->children() as $componentChild) {
295 295
                 if ($componentChild instanceof Property\ICalendar\DateTime && $componentChild->hasTime()) {
296 296
                     $dt = $componentChild->getDateTimes($timeZone);
@@ -516,7 +516,7 @@  discard block
 block discarded – undo
516 516
      */
517 517
     public function getByUID($uid)
518 518
     {
519
-        return array_filter($this->getComponents(), function ($item) use ($uid) {
519
+        return array_filter($this->getComponents(), function($item) use ($uid) {
520 520
             if (!$itemUid = $item->select('UID')) {
521 521
                 return false;
522 522
             }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Component/VAlarm.php 1 patch
Indentation   +105 added lines, -105 removed lines patch added patch discarded remove patch
@@ -18,121 +18,121 @@
 block discarded – undo
18 18
  */
19 19
 class VAlarm extends VObject\Component
20 20
 {
21
-    /**
22
-     * Returns a DateTime object when this alarm is going to trigger.
23
-     *
24
-     * This ignores repeated alarm, only the first trigger is returned.
25
-     *
26
-     * @return DateTimeImmutable
27
-     */
28
-    public function getEffectiveTriggerTime()
29
-    {
30
-        $trigger = $this->TRIGGER;
31
-        if (!isset($trigger['VALUE']) || 'DURATION' === strtoupper($trigger['VALUE'])) {
32
-            $triggerDuration = VObject\DateTimeParser::parseDuration($this->TRIGGER);
33
-            $related = (isset($trigger['RELATED']) && 'END' == strtoupper($trigger['RELATED'])) ? 'END' : 'START';
21
+	/**
22
+	 * Returns a DateTime object when this alarm is going to trigger.
23
+	 *
24
+	 * This ignores repeated alarm, only the first trigger is returned.
25
+	 *
26
+	 * @return DateTimeImmutable
27
+	 */
28
+	public function getEffectiveTriggerTime()
29
+	{
30
+		$trigger = $this->TRIGGER;
31
+		if (!isset($trigger['VALUE']) || 'DURATION' === strtoupper($trigger['VALUE'])) {
32
+			$triggerDuration = VObject\DateTimeParser::parseDuration($this->TRIGGER);
33
+			$related = (isset($trigger['RELATED']) && 'END' == strtoupper($trigger['RELATED'])) ? 'END' : 'START';
34 34
 
35
-            $parentComponent = $this->parent;
36
-            if ('START' === $related) {
37
-                if ('VTODO' === $parentComponent->name) {
38
-                    $propName = 'DUE';
39
-                } else {
40
-                    $propName = 'DTSTART';
41
-                }
35
+			$parentComponent = $this->parent;
36
+			if ('START' === $related) {
37
+				if ('VTODO' === $parentComponent->name) {
38
+					$propName = 'DUE';
39
+				} else {
40
+					$propName = 'DTSTART';
41
+				}
42 42
 
43
-                $effectiveTrigger = $parentComponent->$propName->getDateTime();
44
-                $effectiveTrigger = $effectiveTrigger->add($triggerDuration);
45
-            } else {
46
-                if ('VTODO' === $parentComponent->name) {
47
-                    $endProp = 'DUE';
48
-                } elseif ('VEVENT' === $parentComponent->name) {
49
-                    $endProp = 'DTEND';
50
-                } else {
51
-                    throw new InvalidDataException('time-range filters on VALARM components are only supported when they are a child of VTODO or VEVENT');
52
-                }
43
+				$effectiveTrigger = $parentComponent->$propName->getDateTime();
44
+				$effectiveTrigger = $effectiveTrigger->add($triggerDuration);
45
+			} else {
46
+				if ('VTODO' === $parentComponent->name) {
47
+					$endProp = 'DUE';
48
+				} elseif ('VEVENT' === $parentComponent->name) {
49
+					$endProp = 'DTEND';
50
+				} else {
51
+					throw new InvalidDataException('time-range filters on VALARM components are only supported when they are a child of VTODO or VEVENT');
52
+				}
53 53
 
54
-                if (isset($parentComponent->$endProp)) {
55
-                    $effectiveTrigger = $parentComponent->$endProp->getDateTime();
56
-                    $effectiveTrigger = $effectiveTrigger->add($triggerDuration);
57
-                } elseif (isset($parentComponent->DURATION)) {
58
-                    $effectiveTrigger = $parentComponent->DTSTART->getDateTime();
59
-                    $duration = VObject\DateTimeParser::parseDuration($parentComponent->DURATION);
60
-                    $effectiveTrigger = $effectiveTrigger->add($duration);
61
-                    $effectiveTrigger = $effectiveTrigger->add($triggerDuration);
62
-                } else {
63
-                    $effectiveTrigger = $parentComponent->DTSTART->getDateTime();
64
-                    $effectiveTrigger = $effectiveTrigger->add($triggerDuration);
65
-                }
66
-            }
67
-        } else {
68
-            $effectiveTrigger = $trigger->getDateTime();
69
-        }
54
+				if (isset($parentComponent->$endProp)) {
55
+					$effectiveTrigger = $parentComponent->$endProp->getDateTime();
56
+					$effectiveTrigger = $effectiveTrigger->add($triggerDuration);
57
+				} elseif (isset($parentComponent->DURATION)) {
58
+					$effectiveTrigger = $parentComponent->DTSTART->getDateTime();
59
+					$duration = VObject\DateTimeParser::parseDuration($parentComponent->DURATION);
60
+					$effectiveTrigger = $effectiveTrigger->add($duration);
61
+					$effectiveTrigger = $effectiveTrigger->add($triggerDuration);
62
+				} else {
63
+					$effectiveTrigger = $parentComponent->DTSTART->getDateTime();
64
+					$effectiveTrigger = $effectiveTrigger->add($triggerDuration);
65
+				}
66
+			}
67
+		} else {
68
+			$effectiveTrigger = $trigger->getDateTime();
69
+		}
70 70
 
71
-        return $effectiveTrigger;
72
-    }
71
+		return $effectiveTrigger;
72
+	}
73 73
 
74
-    /**
75
-     * Returns true or false depending on if the event falls in the specified
76
-     * time-range. This is used for filtering purposes.
77
-     *
78
-     * The rules used to determine if an event falls within the specified
79
-     * time-range is based on the CalDAV specification.
80
-     *
81
-     * @param DateTime $start
82
-     * @param DateTime $end
83
-     *
84
-     * @return bool
85
-     */
86
-    public function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end)
87
-    {
88
-        $effectiveTrigger = $this->getEffectiveTriggerTime();
74
+	/**
75
+	 * Returns true or false depending on if the event falls in the specified
76
+	 * time-range. This is used for filtering purposes.
77
+	 *
78
+	 * The rules used to determine if an event falls within the specified
79
+	 * time-range is based on the CalDAV specification.
80
+	 *
81
+	 * @param DateTime $start
82
+	 * @param DateTime $end
83
+	 *
84
+	 * @return bool
85
+	 */
86
+	public function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end)
87
+	{
88
+		$effectiveTrigger = $this->getEffectiveTriggerTime();
89 89
 
90
-        if (isset($this->DURATION)) {
91
-            $duration = VObject\DateTimeParser::parseDuration($this->DURATION);
92
-            $repeat = (string) $this->REPEAT;
93
-            if (!$repeat) {
94
-                $repeat = 1;
95
-            }
90
+		if (isset($this->DURATION)) {
91
+			$duration = VObject\DateTimeParser::parseDuration($this->DURATION);
92
+			$repeat = (string) $this->REPEAT;
93
+			if (!$repeat) {
94
+				$repeat = 1;
95
+			}
96 96
 
97
-            $period = new \DatePeriod($effectiveTrigger, $duration, (int) $repeat);
97
+			$period = new \DatePeriod($effectiveTrigger, $duration, (int) $repeat);
98 98
 
99
-            foreach ($period as $occurrence) {
100
-                if ($start <= $occurrence && $end > $occurrence) {
101
-                    return true;
102
-                }
103
-            }
99
+			foreach ($period as $occurrence) {
100
+				if ($start <= $occurrence && $end > $occurrence) {
101
+					return true;
102
+				}
103
+			}
104 104
 
105
-            return false;
106
-        } else {
107
-            return $start <= $effectiveTrigger && $end > $effectiveTrigger;
108
-        }
109
-    }
105
+			return false;
106
+		} else {
107
+			return $start <= $effectiveTrigger && $end > $effectiveTrigger;
108
+		}
109
+	}
110 110
 
111
-    /**
112
-     * A simple list of validation rules.
113
-     *
114
-     * This is simply a list of properties, and how many times they either
115
-     * must or must not appear.
116
-     *
117
-     * Possible values per property:
118
-     *   * 0 - Must not appear.
119
-     *   * 1 - Must appear exactly once.
120
-     *   * + - Must appear at least once.
121
-     *   * * - Can appear any number of times.
122
-     *   * ? - May appear, but not more than once.
123
-     *
124
-     * @var array
125
-     */
126
-    public function getValidationRules()
127
-    {
128
-        return [
129
-            'ACTION' => 1,
130
-            'TRIGGER' => 1,
111
+	/**
112
+	 * A simple list of validation rules.
113
+	 *
114
+	 * This is simply a list of properties, and how many times they either
115
+	 * must or must not appear.
116
+	 *
117
+	 * Possible values per property:
118
+	 *   * 0 - Must not appear.
119
+	 *   * 1 - Must appear exactly once.
120
+	 *   * + - Must appear at least once.
121
+	 *   * * - Can appear any number of times.
122
+	 *   * ? - May appear, but not more than once.
123
+	 *
124
+	 * @var array
125
+	 */
126
+	public function getValidationRules()
127
+	{
128
+		return [
129
+			'ACTION' => 1,
130
+			'TRIGGER' => 1,
131 131
 
132
-            'DURATION' => '?',
133
-            'REPEAT' => '?',
132
+			'DURATION' => '?',
133
+			'REPEAT' => '?',
134 134
 
135
-            'ATTACH' => '?',
136
-        ];
137
-    }
135
+			'ATTACH' => '?',
136
+		];
137
+	}
138 138
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Component/VTodo.php 1 patch
Indentation   +151 added lines, -151 removed lines patch added patch discarded remove patch
@@ -16,166 +16,166 @@
 block discarded – undo
16 16
  */
17 17
 class VTodo extends VObject\Component
18 18
 {
19
-    /**
20
-     * Returns true or false depending on if the event falls in the specified
21
-     * time-range. This is used for filtering purposes.
22
-     *
23
-     * The rules used to determine if an event falls within the specified
24
-     * time-range is based on the CalDAV specification.
25
-     *
26
-     * @return bool
27
-     */
28
-    public function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end)
29
-    {
30
-        $dtstart = isset($this->DTSTART) ? $this->DTSTART->getDateTime() : null;
31
-        $duration = isset($this->DURATION) ? VObject\DateTimeParser::parseDuration($this->DURATION) : null;
32
-        $due = isset($this->DUE) ? $this->DUE->getDateTime() : null;
33
-        $completed = isset($this->COMPLETED) ? $this->COMPLETED->getDateTime() : null;
34
-        $created = isset($this->CREATED) ? $this->CREATED->getDateTime() : null;
19
+	/**
20
+	 * Returns true or false depending on if the event falls in the specified
21
+	 * time-range. This is used for filtering purposes.
22
+	 *
23
+	 * The rules used to determine if an event falls within the specified
24
+	 * time-range is based on the CalDAV specification.
25
+	 *
26
+	 * @return bool
27
+	 */
28
+	public function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end)
29
+	{
30
+		$dtstart = isset($this->DTSTART) ? $this->DTSTART->getDateTime() : null;
31
+		$duration = isset($this->DURATION) ? VObject\DateTimeParser::parseDuration($this->DURATION) : null;
32
+		$due = isset($this->DUE) ? $this->DUE->getDateTime() : null;
33
+		$completed = isset($this->COMPLETED) ? $this->COMPLETED->getDateTime() : null;
34
+		$created = isset($this->CREATED) ? $this->CREATED->getDateTime() : null;
35 35
 
36
-        if ($dtstart) {
37
-            if ($duration) {
38
-                $effectiveEnd = $dtstart->add($duration);
36
+		if ($dtstart) {
37
+			if ($duration) {
38
+				$effectiveEnd = $dtstart->add($duration);
39 39
 
40
-                return $start <= $effectiveEnd && $end > $dtstart;
41
-            } elseif ($due) {
42
-                return
43
-                    ($start < $due || $start <= $dtstart) &&
44
-                    ($end > $dtstart || $end >= $due);
45
-            } else {
46
-                return $start <= $dtstart && $end > $dtstart;
47
-            }
48
-        }
49
-        if ($due) {
50
-            return $start < $due && $end >= $due;
51
-        }
52
-        if ($completed && $created) {
53
-            return
54
-                ($start <= $created || $start <= $completed) &&
55
-                ($end >= $created || $end >= $completed);
56
-        }
57
-        if ($completed) {
58
-            return $start <= $completed && $end >= $completed;
59
-        }
60
-        if ($created) {
61
-            return $end > $created;
62
-        }
40
+				return $start <= $effectiveEnd && $end > $dtstart;
41
+			} elseif ($due) {
42
+				return
43
+					($start < $due || $start <= $dtstart) &&
44
+					($end > $dtstart || $end >= $due);
45
+			} else {
46
+				return $start <= $dtstart && $end > $dtstart;
47
+			}
48
+		}
49
+		if ($due) {
50
+			return $start < $due && $end >= $due;
51
+		}
52
+		if ($completed && $created) {
53
+			return
54
+				($start <= $created || $start <= $completed) &&
55
+				($end >= $created || $end >= $completed);
56
+		}
57
+		if ($completed) {
58
+			return $start <= $completed && $end >= $completed;
59
+		}
60
+		if ($created) {
61
+			return $end > $created;
62
+		}
63 63
 
64
-        return true;
65
-    }
64
+		return true;
65
+	}
66 66
 
67
-    /**
68
-     * A simple list of validation rules.
69
-     *
70
-     * This is simply a list of properties, and how many times they either
71
-     * must or must not appear.
72
-     *
73
-     * Possible values per property:
74
-     *   * 0 - Must not appear.
75
-     *   * 1 - Must appear exactly once.
76
-     *   * + - Must appear at least once.
77
-     *   * * - Can appear any number of times.
78
-     *   * ? - May appear, but not more than once.
79
-     *
80
-     * @var array
81
-     */
82
-    public function getValidationRules()
83
-    {
84
-        return [
85
-            'UID' => 1,
86
-            'DTSTAMP' => 1,
67
+	/**
68
+	 * A simple list of validation rules.
69
+	 *
70
+	 * This is simply a list of properties, and how many times they either
71
+	 * must or must not appear.
72
+	 *
73
+	 * Possible values per property:
74
+	 *   * 0 - Must not appear.
75
+	 *   * 1 - Must appear exactly once.
76
+	 *   * + - Must appear at least once.
77
+	 *   * * - Can appear any number of times.
78
+	 *   * ? - May appear, but not more than once.
79
+	 *
80
+	 * @var array
81
+	 */
82
+	public function getValidationRules()
83
+	{
84
+		return [
85
+			'UID' => 1,
86
+			'DTSTAMP' => 1,
87 87
 
88
-            'CLASS' => '?',
89
-            'COMPLETED' => '?',
90
-            'CREATED' => '?',
91
-            'DESCRIPTION' => '?',
92
-            'DTSTART' => '?',
93
-            'GEO' => '?',
94
-            'LAST-MODIFIED' => '?',
95
-            'LOCATION' => '?',
96
-            'ORGANIZER' => '?',
97
-            'PERCENT' => '?',
98
-            'PRIORITY' => '?',
99
-            'RECURRENCE-ID' => '?',
100
-            'SEQUENCE' => '?',
101
-            'STATUS' => '?',
102
-            'SUMMARY' => '?',
103
-            'URL' => '?',
88
+			'CLASS' => '?',
89
+			'COMPLETED' => '?',
90
+			'CREATED' => '?',
91
+			'DESCRIPTION' => '?',
92
+			'DTSTART' => '?',
93
+			'GEO' => '?',
94
+			'LAST-MODIFIED' => '?',
95
+			'LOCATION' => '?',
96
+			'ORGANIZER' => '?',
97
+			'PERCENT' => '?',
98
+			'PRIORITY' => '?',
99
+			'RECURRENCE-ID' => '?',
100
+			'SEQUENCE' => '?',
101
+			'STATUS' => '?',
102
+			'SUMMARY' => '?',
103
+			'URL' => '?',
104 104
 
105
-            'RRULE' => '?',
106
-            'DUE' => '?',
107
-            'DURATION' => '?',
105
+			'RRULE' => '?',
106
+			'DUE' => '?',
107
+			'DURATION' => '?',
108 108
 
109
-            'ATTACH' => '*',
110
-            'ATTENDEE' => '*',
111
-            'CATEGORIES' => '*',
112
-            'COMMENT' => '*',
113
-            'CONTACT' => '*',
114
-            'EXDATE' => '*',
115
-            'REQUEST-STATUS' => '*',
116
-            'RELATED-TO' => '*',
117
-            'RESOURCES' => '*',
118
-            'RDATE' => '*',
119
-        ];
120
-    }
109
+			'ATTACH' => '*',
110
+			'ATTENDEE' => '*',
111
+			'CATEGORIES' => '*',
112
+			'COMMENT' => '*',
113
+			'CONTACT' => '*',
114
+			'EXDATE' => '*',
115
+			'REQUEST-STATUS' => '*',
116
+			'RELATED-TO' => '*',
117
+			'RESOURCES' => '*',
118
+			'RDATE' => '*',
119
+		];
120
+	}
121 121
 
122
-    /**
123
-     * Validates the node for correctness.
124
-     *
125
-     * The following options are supported:
126
-     *   Node::REPAIR - May attempt to automatically repair the problem.
127
-     *
128
-     * This method returns an array with detected problems.
129
-     * Every element has the following properties:
130
-     *
131
-     *  * level - problem level.
132
-     *  * message - A human-readable string describing the issue.
133
-     *  * node - A reference to the problematic node.
134
-     *
135
-     * The level means:
136
-     *   1 - The issue was repaired (only happens if REPAIR was turned on)
137
-     *   2 - An inconsequential issue
138
-     *   3 - A severe issue.
139
-     *
140
-     * @param int $options
141
-     *
142
-     * @return array
143
-     */
144
-    public function validate($options = 0)
145
-    {
146
-        $result = parent::validate($options);
147
-        if (isset($this->DUE) && isset($this->DTSTART)) {
148
-            $due = $this->DUE;
149
-            $dtStart = $this->DTSTART;
122
+	/**
123
+	 * Validates the node for correctness.
124
+	 *
125
+	 * The following options are supported:
126
+	 *   Node::REPAIR - May attempt to automatically repair the problem.
127
+	 *
128
+	 * This method returns an array with detected problems.
129
+	 * Every element has the following properties:
130
+	 *
131
+	 *  * level - problem level.
132
+	 *  * message - A human-readable string describing the issue.
133
+	 *  * node - A reference to the problematic node.
134
+	 *
135
+	 * The level means:
136
+	 *   1 - The issue was repaired (only happens if REPAIR was turned on)
137
+	 *   2 - An inconsequential issue
138
+	 *   3 - A severe issue.
139
+	 *
140
+	 * @param int $options
141
+	 *
142
+	 * @return array
143
+	 */
144
+	public function validate($options = 0)
145
+	{
146
+		$result = parent::validate($options);
147
+		if (isset($this->DUE) && isset($this->DTSTART)) {
148
+			$due = $this->DUE;
149
+			$dtStart = $this->DTSTART;
150 150
 
151
-            if ($due->getValueType() !== $dtStart->getValueType()) {
152
-                $result[] = [
153
-                    'level' => 3,
154
-                    'message' => 'The value type (DATE or DATE-TIME) must be identical for DUE and DTSTART',
155
-                    'node' => $due,
156
-                ];
157
-            } elseif ($due->getDateTime() < $dtStart->getDateTime()) {
158
-                $result[] = [
159
-                    'level' => 3,
160
-                    'message' => 'DUE must occur after DTSTART',
161
-                    'node' => $due,
162
-                ];
163
-            }
164
-        }
151
+			if ($due->getValueType() !== $dtStart->getValueType()) {
152
+				$result[] = [
153
+					'level' => 3,
154
+					'message' => 'The value type (DATE or DATE-TIME) must be identical for DUE and DTSTART',
155
+					'node' => $due,
156
+				];
157
+			} elseif ($due->getDateTime() < $dtStart->getDateTime()) {
158
+				$result[] = [
159
+					'level' => 3,
160
+					'message' => 'DUE must occur after DTSTART',
161
+					'node' => $due,
162
+				];
163
+			}
164
+		}
165 165
 
166
-        return $result;
167
-    }
166
+		return $result;
167
+	}
168 168
 
169
-    /**
170
-     * This method should return a list of default property values.
171
-     *
172
-     * @return array
173
-     */
174
-    protected function getDefaults()
175
-    {
176
-        return [
177
-            'UID' => 'sabre-vobject-'.VObject\UUIDUtil::getUUID(),
178
-            'DTSTAMP' => date('Ymd\\THis\\Z'),
179
-        ];
180
-    }
169
+	/**
170
+	 * This method should return a list of default property values.
171
+	 *
172
+	 * @return array
173
+	 */
174
+	protected function getDefaults()
175
+	{
176
+		return [
177
+			'UID' => 'sabre-vobject-'.VObject\UUIDUtil::getUUID(),
178
+			'DTSTAMP' => date('Ymd\\THis\\Z'),
179
+		];
180
+	}
181 181
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Component/VFreeBusy.php 1 patch
Indentation   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -17,77 +17,77 @@
 block discarded – undo
17 17
  */
18 18
 class VFreeBusy extends VObject\Component
19 19
 {
20
-    /**
21
-     * Checks based on the contained FREEBUSY information, if a timeslot is
22
-     * available.
23
-     *
24
-     * @return bool
25
-     */
26
-    public function isFree(DateTimeInterface $start, DatetimeInterface $end)
27
-    {
28
-        foreach ($this->select('FREEBUSY') as $freebusy) {
29
-            // We are only interested in FBTYPE=BUSY (the default),
30
-            // FBTYPE=BUSY-TENTATIVE or FBTYPE=BUSY-UNAVAILABLE.
31
-            if (isset($freebusy['FBTYPE']) && 'BUSY' !== strtoupper(substr((string) $freebusy['FBTYPE'], 0, 4))) {
32
-                continue;
33
-            }
20
+	/**
21
+	 * Checks based on the contained FREEBUSY information, if a timeslot is
22
+	 * available.
23
+	 *
24
+	 * @return bool
25
+	 */
26
+	public function isFree(DateTimeInterface $start, DatetimeInterface $end)
27
+	{
28
+		foreach ($this->select('FREEBUSY') as $freebusy) {
29
+			// We are only interested in FBTYPE=BUSY (the default),
30
+			// FBTYPE=BUSY-TENTATIVE or FBTYPE=BUSY-UNAVAILABLE.
31
+			if (isset($freebusy['FBTYPE']) && 'BUSY' !== strtoupper(substr((string) $freebusy['FBTYPE'], 0, 4))) {
32
+				continue;
33
+			}
34 34
 
35
-            // The freebusy component can hold more than 1 value, separated by
36
-            // commas.
37
-            $periods = explode(',', (string) $freebusy);
35
+			// The freebusy component can hold more than 1 value, separated by
36
+			// commas.
37
+			$periods = explode(',', (string) $freebusy);
38 38
 
39
-            foreach ($periods as $period) {
40
-                // Every period is formatted as [start]/[end]. The start is an
41
-                // absolute UTC time, the end may be an absolute UTC time, or
42
-                // duration (relative) value.
43
-                list($busyStart, $busyEnd) = explode('/', $period);
39
+			foreach ($periods as $period) {
40
+				// Every period is formatted as [start]/[end]. The start is an
41
+				// absolute UTC time, the end may be an absolute UTC time, or
42
+				// duration (relative) value.
43
+				list($busyStart, $busyEnd) = explode('/', $period);
44 44
 
45
-                $busyStart = VObject\DateTimeParser::parse($busyStart);
46
-                $busyEnd = VObject\DateTimeParser::parse($busyEnd);
47
-                if ($busyEnd instanceof \DateInterval) {
48
-                    $busyEnd = $busyStart->add($busyEnd);
49
-                }
45
+				$busyStart = VObject\DateTimeParser::parse($busyStart);
46
+				$busyEnd = VObject\DateTimeParser::parse($busyEnd);
47
+				if ($busyEnd instanceof \DateInterval) {
48
+					$busyEnd = $busyStart->add($busyEnd);
49
+				}
50 50
 
51
-                if ($start < $busyEnd && $end > $busyStart) {
52
-                    return false;
53
-                }
54
-            }
55
-        }
51
+				if ($start < $busyEnd && $end > $busyStart) {
52
+					return false;
53
+				}
54
+			}
55
+		}
56 56
 
57
-        return true;
58
-    }
57
+		return true;
58
+	}
59 59
 
60
-    /**
61
-     * A simple list of validation rules.
62
-     *
63
-     * This is simply a list of properties, and how many times they either
64
-     * must or must not appear.
65
-     *
66
-     * Possible values per property:
67
-     *   * 0 - Must not appear.
68
-     *   * 1 - Must appear exactly once.
69
-     *   * + - Must appear at least once.
70
-     *   * * - Can appear any number of times.
71
-     *   * ? - May appear, but not more than once.
72
-     *
73
-     * @var array
74
-     */
75
-    public function getValidationRules()
76
-    {
77
-        return [
78
-            'UID' => 1,
79
-            'DTSTAMP' => 1,
60
+	/**
61
+	 * A simple list of validation rules.
62
+	 *
63
+	 * This is simply a list of properties, and how many times they either
64
+	 * must or must not appear.
65
+	 *
66
+	 * Possible values per property:
67
+	 *   * 0 - Must not appear.
68
+	 *   * 1 - Must appear exactly once.
69
+	 *   * + - Must appear at least once.
70
+	 *   * * - Can appear any number of times.
71
+	 *   * ? - May appear, but not more than once.
72
+	 *
73
+	 * @var array
74
+	 */
75
+	public function getValidationRules()
76
+	{
77
+		return [
78
+			'UID' => 1,
79
+			'DTSTAMP' => 1,
80 80
 
81
-            'CONTACT' => '?',
82
-            'DTSTART' => '?',
83
-            'DTEND' => '?',
84
-            'ORGANIZER' => '?',
85
-            'URL' => '?',
81
+			'CONTACT' => '?',
82
+			'DTSTART' => '?',
83
+			'DTEND' => '?',
84
+			'ORGANIZER' => '?',
85
+			'URL' => '?',
86 86
 
87
-            'ATTENDEE' => '*',
88
-            'COMMENT' => '*',
89
-            'FREEBUSY' => '*',
90
-            'REQUEST-STATUS' => '*',
91
-        ];
92
-    }
87
+			'ATTENDEE' => '*',
88
+			'COMMENT' => '*',
89
+			'FREEBUSY' => '*',
90
+			'REQUEST-STATUS' => '*',
91
+		];
92
+	}
93 93
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Component/VEvent.php 1 patch
Indentation   +111 added lines, -111 removed lines patch added patch discarded remove patch
@@ -18,123 +18,123 @@
 block discarded – undo
18 18
  */
19 19
 class VEvent extends VObject\Component
20 20
 {
21
-    /**
22
-     * Returns true or false depending on if the event falls in the specified
23
-     * time-range. This is used for filtering purposes.
24
-     *
25
-     * The rules used to determine if an event falls within the specified
26
-     * time-range is based on the CalDAV specification.
27
-     *
28
-     * @return bool
29
-     */
30
-    public function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end)
31
-    {
32
-        if ($this->RRULE) {
33
-            try {
34
-                $it = new EventIterator($this, null, $start->getTimezone());
35
-            } catch (NoInstancesException $e) {
36
-                // If we've caught this exception, there are no instances
37
-                // for the event that fall into the specified time-range.
38
-                return false;
39
-            }
21
+	/**
22
+	 * Returns true or false depending on if the event falls in the specified
23
+	 * time-range. This is used for filtering purposes.
24
+	 *
25
+	 * The rules used to determine if an event falls within the specified
26
+	 * time-range is based on the CalDAV specification.
27
+	 *
28
+	 * @return bool
29
+	 */
30
+	public function isInTimeRange(DateTimeInterface $start, DateTimeInterface $end)
31
+	{
32
+		if ($this->RRULE) {
33
+			try {
34
+				$it = new EventIterator($this, null, $start->getTimezone());
35
+			} catch (NoInstancesException $e) {
36
+				// If we've caught this exception, there are no instances
37
+				// for the event that fall into the specified time-range.
38
+				return false;
39
+			}
40 40
 
41
-            $it->fastForward($start);
41
+			$it->fastForward($start);
42 42
 
43
-            // We fast-forwarded to a spot where the end-time of the
44
-            // recurrence instance exceeded the start of the requested
45
-            // time-range.
46
-            //
47
-            // If the starttime of the recurrence did not exceed the
48
-            // end of the time range as well, we have a match.
49
-            return $it->getDTStart() < $end && $it->getDTEnd() > $start;
50
-        }
43
+			// We fast-forwarded to a spot where the end-time of the
44
+			// recurrence instance exceeded the start of the requested
45
+			// time-range.
46
+			//
47
+			// If the starttime of the recurrence did not exceed the
48
+			// end of the time range as well, we have a match.
49
+			return $it->getDTStart() < $end && $it->getDTEnd() > $start;
50
+		}
51 51
 
52
-        $effectiveStart = $this->DTSTART->getDateTime($start->getTimezone());
53
-        if (isset($this->DTEND)) {
54
-            // The DTEND property is considered non inclusive. So for a 3 day
55
-            // event in july, dtstart and dtend would have to be July 1st and
56
-            // July 4th respectively.
57
-            //
58
-            // See:
59
-            // http://tools.ietf.org/html/rfc5545#page-54
60
-            $effectiveEnd = $this->DTEND->getDateTime($end->getTimezone());
61
-        } elseif (isset($this->DURATION)) {
62
-            $effectiveEnd = $effectiveStart->add(VObject\DateTimeParser::parseDuration($this->DURATION));
63
-        } elseif (!$this->DTSTART->hasTime()) {
64
-            $effectiveEnd = $effectiveStart->modify('+1 day');
65
-        } else {
66
-            $effectiveEnd = $effectiveStart;
67
-        }
52
+		$effectiveStart = $this->DTSTART->getDateTime($start->getTimezone());
53
+		if (isset($this->DTEND)) {
54
+			// The DTEND property is considered non inclusive. So for a 3 day
55
+			// event in july, dtstart and dtend would have to be July 1st and
56
+			// July 4th respectively.
57
+			//
58
+			// See:
59
+			// http://tools.ietf.org/html/rfc5545#page-54
60
+			$effectiveEnd = $this->DTEND->getDateTime($end->getTimezone());
61
+		} elseif (isset($this->DURATION)) {
62
+			$effectiveEnd = $effectiveStart->add(VObject\DateTimeParser::parseDuration($this->DURATION));
63
+		} elseif (!$this->DTSTART->hasTime()) {
64
+			$effectiveEnd = $effectiveStart->modify('+1 day');
65
+		} else {
66
+			$effectiveEnd = $effectiveStart;
67
+		}
68 68
 
69
-        return
70
-            ($start < $effectiveEnd) && ($end > $effectiveStart)
71
-        ;
72
-    }
69
+		return
70
+			($start < $effectiveEnd) && ($end > $effectiveStart)
71
+		;
72
+	}
73 73
 
74
-    /**
75
-     * This method should return a list of default property values.
76
-     *
77
-     * @return array
78
-     */
79
-    protected function getDefaults()
80
-    {
81
-        return [
82
-            'UID' => 'sabre-vobject-'.VObject\UUIDUtil::getUUID(),
83
-            'DTSTAMP' => gmdate('Ymd\\THis\\Z'),
84
-        ];
85
-    }
74
+	/**
75
+	 * This method should return a list of default property values.
76
+	 *
77
+	 * @return array
78
+	 */
79
+	protected function getDefaults()
80
+	{
81
+		return [
82
+			'UID' => 'sabre-vobject-'.VObject\UUIDUtil::getUUID(),
83
+			'DTSTAMP' => gmdate('Ymd\\THis\\Z'),
84
+		];
85
+	}
86 86
 
87
-    /**
88
-     * A simple list of validation rules.
89
-     *
90
-     * This is simply a list of properties, and how many times they either
91
-     * must or must not appear.
92
-     *
93
-     * Possible values per property:
94
-     *   * 0 - Must not appear.
95
-     *   * 1 - Must appear exactly once.
96
-     *   * + - Must appear at least once.
97
-     *   * * - Can appear any number of times.
98
-     *   * ? - May appear, but not more than once.
99
-     *
100
-     * @var array
101
-     */
102
-    public function getValidationRules()
103
-    {
104
-        $hasMethod = isset($this->parent->METHOD);
87
+	/**
88
+	 * A simple list of validation rules.
89
+	 *
90
+	 * This is simply a list of properties, and how many times they either
91
+	 * must or must not appear.
92
+	 *
93
+	 * Possible values per property:
94
+	 *   * 0 - Must not appear.
95
+	 *   * 1 - Must appear exactly once.
96
+	 *   * + - Must appear at least once.
97
+	 *   * * - Can appear any number of times.
98
+	 *   * ? - May appear, but not more than once.
99
+	 *
100
+	 * @var array
101
+	 */
102
+	public function getValidationRules()
103
+	{
104
+		$hasMethod = isset($this->parent->METHOD);
105 105
 
106
-        return [
107
-            'UID' => 1,
108
-            'DTSTAMP' => 1,
109
-            'DTSTART' => $hasMethod ? '?' : '1',
110
-            'CLASS' => '?',
111
-            'CREATED' => '?',
112
-            'DESCRIPTION' => '?',
113
-            'GEO' => '?',
114
-            'LAST-MODIFIED' => '?',
115
-            'LOCATION' => '?',
116
-            'ORGANIZER' => '?',
117
-            'PRIORITY' => '?',
118
-            'SEQUENCE' => '?',
119
-            'STATUS' => '?',
120
-            'SUMMARY' => '?',
121
-            'TRANSP' => '?',
122
-            'URL' => '?',
123
-            'RECURRENCE-ID' => '?',
124
-            'RRULE' => '?',
125
-            'DTEND' => '?',
126
-            'DURATION' => '?',
106
+		return [
107
+			'UID' => 1,
108
+			'DTSTAMP' => 1,
109
+			'DTSTART' => $hasMethod ? '?' : '1',
110
+			'CLASS' => '?',
111
+			'CREATED' => '?',
112
+			'DESCRIPTION' => '?',
113
+			'GEO' => '?',
114
+			'LAST-MODIFIED' => '?',
115
+			'LOCATION' => '?',
116
+			'ORGANIZER' => '?',
117
+			'PRIORITY' => '?',
118
+			'SEQUENCE' => '?',
119
+			'STATUS' => '?',
120
+			'SUMMARY' => '?',
121
+			'TRANSP' => '?',
122
+			'URL' => '?',
123
+			'RECURRENCE-ID' => '?',
124
+			'RRULE' => '?',
125
+			'DTEND' => '?',
126
+			'DURATION' => '?',
127 127
 
128
-            'ATTACH' => '*',
129
-            'ATTENDEE' => '*',
130
-            'CATEGORIES' => '*',
131
-            'COMMENT' => '*',
132
-            'CONTACT' => '*',
133
-            'EXDATE' => '*',
134
-            'REQUEST-STATUS' => '*',
135
-            'RELATED-TO' => '*',
136
-            'RESOURCES' => '*',
137
-            'RDATE' => '*',
138
-        ];
139
-    }
128
+			'ATTACH' => '*',
129
+			'ATTENDEE' => '*',
130
+			'CATEGORIES' => '*',
131
+			'COMMENT' => '*',
132
+			'CONTACT' => '*',
133
+			'EXDATE' => '*',
134
+			'REQUEST-STATUS' => '*',
135
+			'RELATED-TO' => '*',
136
+			'RESOURCES' => '*',
137
+			'RDATE' => '*',
138
+		];
139
+	}
140 140
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Component/VTimeZone.php 1 patch
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -16,48 +16,48 @@
 block discarded – undo
16 16
  */
17 17
 class VTimeZone extends VObject\Component
18 18
 {
19
-    /**
20
-     * Returns the PHP DateTimeZone for this VTIMEZONE component.
21
-     *
22
-     * If we can't accurately determine the timezone, this method will return
23
-     * UTC.
24
-     *
25
-     * @return \DateTimeZone
26
-     */
27
-    public function getTimeZone()
28
-    {
29
-        return VObject\TimeZoneUtil::getTimeZone((string) $this->TZID, $this->root);
30
-    }
19
+	/**
20
+	 * Returns the PHP DateTimeZone for this VTIMEZONE component.
21
+	 *
22
+	 * If we can't accurately determine the timezone, this method will return
23
+	 * UTC.
24
+	 *
25
+	 * @return \DateTimeZone
26
+	 */
27
+	public function getTimeZone()
28
+	{
29
+		return VObject\TimeZoneUtil::getTimeZone((string) $this->TZID, $this->root);
30
+	}
31 31
 
32
-    /**
33
-     * A simple list of validation rules.
34
-     *
35
-     * This is simply a list of properties, and how many times they either
36
-     * must or must not appear.
37
-     *
38
-     * Possible values per property:
39
-     *   * 0 - Must not appear.
40
-     *   * 1 - Must appear exactly once.
41
-     *   * + - Must appear at least once.
42
-     *   * * - Can appear any number of times.
43
-     *   * ? - May appear, but not more than once.
44
-     *
45
-     * @var array
46
-     */
47
-    public function getValidationRules()
48
-    {
49
-        return [
50
-            'TZID' => 1,
32
+	/**
33
+	 * A simple list of validation rules.
34
+	 *
35
+	 * This is simply a list of properties, and how many times they either
36
+	 * must or must not appear.
37
+	 *
38
+	 * Possible values per property:
39
+	 *   * 0 - Must not appear.
40
+	 *   * 1 - Must appear exactly once.
41
+	 *   * + - Must appear at least once.
42
+	 *   * * - Can appear any number of times.
43
+	 *   * ? - May appear, but not more than once.
44
+	 *
45
+	 * @var array
46
+	 */
47
+	public function getValidationRules()
48
+	{
49
+		return [
50
+			'TZID' => 1,
51 51
 
52
-            'LAST-MODIFIED' => '?',
53
-            'TZURL' => '?',
52
+			'LAST-MODIFIED' => '?',
53
+			'TZURL' => '?',
54 54
 
55
-            // At least 1 STANDARD or DAYLIGHT must appear.
56
-            //
57
-            // The validator is not specific yet to pick this up, so these
58
-            // rules are too loose.
59
-            'STANDARD' => '*',
60
-            'DAYLIGHT' => '*',
61
-        ];
62
-    }
55
+			// At least 1 STANDARD or DAYLIGHT must appear.
56
+			//
57
+			// The validator is not specific yet to pick this up, so these
58
+			// rules are too loose.
59
+			'STANDARD' => '*',
60
+			'DAYLIGHT' => '*',
61
+		];
62
+	}
63 63
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/Component/Available.php 1 patch
Indentation   +95 added lines, -95 removed lines patch added patch discarded remove patch
@@ -16,108 +16,108 @@
 block discarded – undo
16 16
  */
17 17
 class Available extends VObject\Component
18 18
 {
19
-    /**
20
-     * Returns the 'effective start' and 'effective end' of this VAVAILABILITY
21
-     * component.
22
-     *
23
-     * We use the DTSTART and DTEND or DURATION to determine this.
24
-     *
25
-     * The returned value is an array containing DateTimeImmutable instances.
26
-     * If either the start or end is 'unbounded' its value will be null
27
-     * instead.
28
-     *
29
-     * @return array
30
-     */
31
-    public function getEffectiveStartEnd()
32
-    {
33
-        $effectiveStart = $this->DTSTART->getDateTime();
34
-        if (isset($this->DTEND)) {
35
-            $effectiveEnd = $this->DTEND->getDateTime();
36
-        } else {
37
-            $effectiveEnd = $effectiveStart->add(VObject\DateTimeParser::parseDuration($this->DURATION));
38
-        }
19
+	/**
20
+	 * Returns the 'effective start' and 'effective end' of this VAVAILABILITY
21
+	 * component.
22
+	 *
23
+	 * We use the DTSTART and DTEND or DURATION to determine this.
24
+	 *
25
+	 * The returned value is an array containing DateTimeImmutable instances.
26
+	 * If either the start or end is 'unbounded' its value will be null
27
+	 * instead.
28
+	 *
29
+	 * @return array
30
+	 */
31
+	public function getEffectiveStartEnd()
32
+	{
33
+		$effectiveStart = $this->DTSTART->getDateTime();
34
+		if (isset($this->DTEND)) {
35
+			$effectiveEnd = $this->DTEND->getDateTime();
36
+		} else {
37
+			$effectiveEnd = $effectiveStart->add(VObject\DateTimeParser::parseDuration($this->DURATION));
38
+		}
39 39
 
40
-        return [$effectiveStart, $effectiveEnd];
41
-    }
40
+		return [$effectiveStart, $effectiveEnd];
41
+	}
42 42
 
43
-    /**
44
-     * A simple list of validation rules.
45
-     *
46
-     * This is simply a list of properties, and how many times they either
47
-     * must or must not appear.
48
-     *
49
-     * Possible values per property:
50
-     *   * 0 - Must not appear.
51
-     *   * 1 - Must appear exactly once.
52
-     *   * + - Must appear at least once.
53
-     *   * * - Can appear any number of times.
54
-     *   * ? - May appear, but not more than once.
55
-     *
56
-     * @var array
57
-     */
58
-    public function getValidationRules()
59
-    {
60
-        return [
61
-            'UID' => 1,
62
-            'DTSTART' => 1,
63
-            'DTSTAMP' => 1,
43
+	/**
44
+	 * A simple list of validation rules.
45
+	 *
46
+	 * This is simply a list of properties, and how many times they either
47
+	 * must or must not appear.
48
+	 *
49
+	 * Possible values per property:
50
+	 *   * 0 - Must not appear.
51
+	 *   * 1 - Must appear exactly once.
52
+	 *   * + - Must appear at least once.
53
+	 *   * * - Can appear any number of times.
54
+	 *   * ? - May appear, but not more than once.
55
+	 *
56
+	 * @var array
57
+	 */
58
+	public function getValidationRules()
59
+	{
60
+		return [
61
+			'UID' => 1,
62
+			'DTSTART' => 1,
63
+			'DTSTAMP' => 1,
64 64
 
65
-            'DTEND' => '?',
66
-            'DURATION' => '?',
65
+			'DTEND' => '?',
66
+			'DURATION' => '?',
67 67
 
68
-            'CREATED' => '?',
69
-            'DESCRIPTION' => '?',
70
-            'LAST-MODIFIED' => '?',
71
-            'RECURRENCE-ID' => '?',
72
-            'RRULE' => '?',
73
-            'SUMMARY' => '?',
68
+			'CREATED' => '?',
69
+			'DESCRIPTION' => '?',
70
+			'LAST-MODIFIED' => '?',
71
+			'RECURRENCE-ID' => '?',
72
+			'RRULE' => '?',
73
+			'SUMMARY' => '?',
74 74
 
75
-            'CATEGORIES' => '*',
76
-            'COMMENT' => '*',
77
-            'CONTACT' => '*',
78
-            'EXDATE' => '*',
79
-            'RDATE' => '*',
75
+			'CATEGORIES' => '*',
76
+			'COMMENT' => '*',
77
+			'CONTACT' => '*',
78
+			'EXDATE' => '*',
79
+			'RDATE' => '*',
80 80
 
81
-            'AVAILABLE' => '*',
82
-        ];
83
-    }
81
+			'AVAILABLE' => '*',
82
+		];
83
+	}
84 84
 
85
-    /**
86
-     * Validates the node for correctness.
87
-     *
88
-     * The following options are supported:
89
-     *   Node::REPAIR - May attempt to automatically repair the problem.
90
-     *   Node::PROFILE_CARDDAV - Validate the vCard for CardDAV purposes.
91
-     *   Node::PROFILE_CALDAV - Validate the iCalendar for CalDAV purposes.
92
-     *
93
-     * This method returns an array with detected problems.
94
-     * Every element has the following properties:
95
-     *
96
-     *  * level - problem level.
97
-     *  * message - A human-readable string describing the issue.
98
-     *  * node - A reference to the problematic node.
99
-     *
100
-     * The level means:
101
-     *   1 - The issue was repaired (only happens if REPAIR was turned on).
102
-     *   2 - A warning.
103
-     *   3 - An error.
104
-     *
105
-     * @param int $options
106
-     *
107
-     * @return array
108
-     */
109
-    public function validate($options = 0)
110
-    {
111
-        $result = parent::validate($options);
85
+	/**
86
+	 * Validates the node for correctness.
87
+	 *
88
+	 * The following options are supported:
89
+	 *   Node::REPAIR - May attempt to automatically repair the problem.
90
+	 *   Node::PROFILE_CARDDAV - Validate the vCard for CardDAV purposes.
91
+	 *   Node::PROFILE_CALDAV - Validate the iCalendar for CalDAV purposes.
92
+	 *
93
+	 * This method returns an array with detected problems.
94
+	 * Every element has the following properties:
95
+	 *
96
+	 *  * level - problem level.
97
+	 *  * message - A human-readable string describing the issue.
98
+	 *  * node - A reference to the problematic node.
99
+	 *
100
+	 * The level means:
101
+	 *   1 - The issue was repaired (only happens if REPAIR was turned on).
102
+	 *   2 - A warning.
103
+	 *   3 - An error.
104
+	 *
105
+	 * @param int $options
106
+	 *
107
+	 * @return array
108
+	 */
109
+	public function validate($options = 0)
110
+	{
111
+		$result = parent::validate($options);
112 112
 
113
-        if (isset($this->DTEND) && isset($this->DURATION)) {
114
-            $result[] = [
115
-                'level' => 3,
116
-                'message' => 'DTEND and DURATION cannot both be present',
117
-                'node' => $this,
118
-            ];
119
-        }
113
+		if (isset($this->DTEND) && isset($this->DURATION)) {
114
+			$result[] = [
115
+				'level' => 3,
116
+				'message' => 'DTEND and DURATION cannot both be present',
117
+				'node' => $this,
118
+			];
119
+		}
120 120
 
121
-        return $result;
122
-    }
121
+		return $result;
122
+	}
123 123
 }
Please login to merge, or discard this patch.
htdocs/includes/sabre/sabre/vobject/lib/UUIDUtil.php 1 patch
Indentation   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -15,52 +15,52 @@
 block discarded – undo
15 15
  */
16 16
 class UUIDUtil
17 17
 {
18
-    /**
19
-     * Returns a pseudo-random v4 UUID.
20
-     *
21
-     * This function is based on a comment by Andrew Moore on php.net
22
-     *
23
-     * @see http://www.php.net/manual/en/function.uniqid.php#94959
24
-     *
25
-     * @return string
26
-     */
27
-    public static function getUUID()
28
-    {
29
-        return sprintf(
30
-            '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
18
+	/**
19
+	 * Returns a pseudo-random v4 UUID.
20
+	 *
21
+	 * This function is based on a comment by Andrew Moore on php.net
22
+	 *
23
+	 * @see http://www.php.net/manual/en/function.uniqid.php#94959
24
+	 *
25
+	 * @return string
26
+	 */
27
+	public static function getUUID()
28
+	{
29
+		return sprintf(
30
+			'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
31 31
 
32
-            // 32 bits for "time_low"
33
-            mt_rand(0, 0xffff), mt_rand(0, 0xffff),
32
+			// 32 bits for "time_low"
33
+			mt_rand(0, 0xffff), mt_rand(0, 0xffff),
34 34
 
35
-            // 16 bits for "time_mid"
36
-            mt_rand(0, 0xffff),
35
+			// 16 bits for "time_mid"
36
+			mt_rand(0, 0xffff),
37 37
 
38
-            // 16 bits for "time_hi_and_version",
39
-            // four most significant bits holds version number 4
40
-            mt_rand(0, 0x0fff) | 0x4000,
38
+			// 16 bits for "time_hi_and_version",
39
+			// four most significant bits holds version number 4
40
+			mt_rand(0, 0x0fff) | 0x4000,
41 41
 
42
-            // 16 bits, 8 bits for "clk_seq_hi_res",
43
-            // 8 bits for "clk_seq_low",
44
-            // two most significant bits holds zero and one for variant DCE1.1
45
-            mt_rand(0, 0x3fff) | 0x8000,
42
+			// 16 bits, 8 bits for "clk_seq_hi_res",
43
+			// 8 bits for "clk_seq_low",
44
+			// two most significant bits holds zero and one for variant DCE1.1
45
+			mt_rand(0, 0x3fff) | 0x8000,
46 46
 
47
-            // 48 bits for "node"
48
-            mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
49
-        );
50
-    }
47
+			// 48 bits for "node"
48
+			mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
49
+		);
50
+	}
51 51
 
52
-    /**
53
-     * Checks if a string is a valid UUID.
54
-     *
55
-     * @param string $uuid
56
-     *
57
-     * @return bool
58
-     */
59
-    public static function validateUUID($uuid)
60
-    {
61
-        return 0 !== preg_match(
62
-            '/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i',
63
-            $uuid
64
-        );
65
-    }
52
+	/**
53
+	 * Checks if a string is a valid UUID.
54
+	 *
55
+	 * @param string $uuid
56
+	 *
57
+	 * @return bool
58
+	 */
59
+	public static function validateUUID($uuid)
60
+	{
61
+		return 0 !== preg_match(
62
+			'/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i',
63
+			$uuid
64
+		);
65
+	}
66 66
 }
Please login to merge, or discard this patch.