1<?php
2
3namespace Sabre\VObject;
4
5use Sabre\Xml;
6
7/**
8 * A node is the root class for every element in an iCalendar of vCard object.
9 *
10 * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
11 * @author Evert Pot (http://evertpot.com/)
12 * @license http://sabre.io/license/ Modified BSD License
13 */
14abstract class Node implements \IteratorAggregate, \ArrayAccess, \Countable, \JsonSerializable, Xml\XmlSerializable
15{
16    /**
17     * The following constants are used by the validate() method.
18     *
19     * If REPAIR is set, the validator will attempt to repair any broken data
20     * (if possible).
21     */
22    const REPAIR = 1;
23
24    /**
25     * If this option is set, the validator will operate on the vcards on the
26     * assumption that the vcards need to be valid for CardDAV.
27     *
28     * This means for example that the UID is required, whereas it is not for
29     * regular vcards.
30     */
31    const PROFILE_CARDDAV = 2;
32
33    /**
34     * If this option is set, the validator will operate on iCalendar objects
35     * on the assumption that the vcards need to be valid for CalDAV.
36     *
37     * This means for example that calendars can only contain objects with
38     * identical component types and UIDs.
39     */
40    const PROFILE_CALDAV = 4;
41
42    /**
43     * Reference to the parent object, if this is not the top object.
44     *
45     * @var Node
46     */
47    public $parent;
48
49    /**
50     * Iterator override.
51     *
52     * @var ElementList
53     */
54    protected $iterator = null;
55
56    /**
57     * The root document.
58     *
59     * @var Component
60     */
61    protected $root;
62
63    /**
64     * Serializes the node into a mimedir format.
65     *
66     * @return string
67     */
68    abstract public function serialize();
69
70    /**
71     * This method returns an array, with the representation as it should be
72     * encoded in JSON. This is used to create jCard or jCal documents.
73     *
74     * @return array
75     */
76    abstract public function jsonSerialize();
77
78    /**
79     * This method serializes the data into XML. This is used to create xCard or
80     * xCal documents.
81     *
82     * @param Xml\Writer $writer XML writer
83     */
84    abstract public function xmlSerialize(Xml\Writer $writer);
85
86    /**
87     * Call this method on a document if you're done using it.
88     *
89     * It's intended to remove all circular references, so PHP can easily clean
90     * it up.
91     */
92    public function destroy()
93    {
94        $this->parent = null;
95        $this->root = null;
96    }
97
98    /* {{{ IteratorAggregator interface */
99
100    /**
101     * Returns the iterator for this object.
102     *
103     * @return ElementList
104     */
105    public function getIterator()
106    {
107        if (!is_null($this->iterator)) {
108            return $this->iterator;
109        }
110
111        return new ElementList([$this]);
112    }
113
114    /**
115     * Sets the overridden iterator.
116     *
117     * Note that this is not actually part of the iterator interface
118     *
119     * @param ElementList $iterator
120     */
121    public function setIterator(ElementList $iterator)
122    {
123        $this->iterator = $iterator;
124    }
125
126    /**
127     * Validates the node for correctness.
128     *
129     * The following options are supported:
130     *   Node::REPAIR - May attempt to automatically repair the problem.
131     *
132     * This method returns an array with detected problems.
133     * Every element has the following properties:
134     *
135     *  * level - problem level.
136     *  * message - A human-readable string describing the issue.
137     *  * node - A reference to the problematic node.
138     *
139     * The level means:
140     *   1 - The issue was repaired (only happens if REPAIR was turned on)
141     *   2 - An inconsequential issue
142     *   3 - A severe issue.
143     *
144     * @param int $options
145     *
146     * @return array
147     */
148    public function validate($options = 0)
149    {
150        return [];
151    }
152
153    /* }}} */
154
155    /* {{{ Countable interface */
156
157    /**
158     * Returns the number of elements.
159     *
160     * @return int
161     */
162    public function count()
163    {
164        $it = $this->getIterator();
165
166        return $it->count();
167    }
168
169    /* }}} */
170
171    /* {{{ ArrayAccess Interface */
172
173    /**
174     * Checks if an item exists through ArrayAccess.
175     *
176     * This method just forwards the request to the inner iterator
177     *
178     * @param int $offset
179     *
180     * @return bool
181     */
182    public function offsetExists($offset)
183    {
184        $iterator = $this->getIterator();
185
186        return $iterator->offsetExists($offset);
187    }
188
189    /**
190     * Gets an item through ArrayAccess.
191     *
192     * This method just forwards the request to the inner iterator
193     *
194     * @param int $offset
195     *
196     * @return mixed
197     */
198    public function offsetGet($offset)
199    {
200        $iterator = $this->getIterator();
201
202        return $iterator->offsetGet($offset);
203    }
204
205    /**
206     * Sets an item through ArrayAccess.
207     *
208     * This method just forwards the request to the inner iterator
209     *
210     * @param int   $offset
211     * @param mixed $value
212     */
213    public function offsetSet($offset, $value)
214    {
215        $iterator = $this->getIterator();
216        $iterator->offsetSet($offset, $value);
217
218        // @codeCoverageIgnoreStart
219    //
220    // This method always throws an exception, so we ignore the closing
221    // brace
222    }
223
224    // @codeCoverageIgnoreEnd
225
226    /**
227     * Sets an item through ArrayAccess.
228     *
229     * This method just forwards the request to the inner iterator
230     *
231     * @param int $offset
232     */
233    public function offsetUnset($offset)
234    {
235        $iterator = $this->getIterator();
236        $iterator->offsetUnset($offset);
237
238        // @codeCoverageIgnoreStart
239    //
240    // This method always throws an exception, so we ignore the closing
241    // brace
242    }
243
244    // @codeCoverageIgnoreEnd
245
246    /* }}} */
247}
248