1<?php
2
3namespace Sabre\VObject\Component;
4
5use Sabre\VObject;
6
7/**
8 * The Available sub-component.
9 *
10 * This component adds functionality to a component, specific for AVAILABLE
11 * components.
12 *
13 * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
14 * @author Ivan Enderlin
15 * @license http://sabre.io/license/ Modified BSD License
16 */
17class Available extends VObject\Component
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        }
39
40        return [$effectiveStart, $effectiveEnd];
41    }
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,
64
65            'DTEND' => '?',
66            'DURATION' => '?',
67
68            'CREATED' => '?',
69            'DESCRIPTION' => '?',
70            'LAST-MODIFIED' => '?',
71            'RECURRENCE-ID' => '?',
72            'RRULE' => '?',
73            'SUMMARY' => '?',
74
75            'CATEGORIES' => '*',
76            'COMMENT' => '*',
77            'CONTACT' => '*',
78            'EXDATE' => '*',
79            'RDATE' => '*',
80
81            'AVAILABLE' => '*',
82        ];
83    }
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);
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        }
120
121        return $result;
122    }
123}
124