7
|
1 <?php
|
|
2
|
|
3 namespace Sabre\VObject;
|
|
4
|
|
5 /**
|
|
6 * Document
|
|
7 *
|
|
8 * A document is just like a component, except that it's also the top level
|
|
9 * element.
|
|
10 *
|
|
11 * Both a VCALENDAR and a VCARD are considered documents.
|
|
12 *
|
|
13 * This class also provides a registry for document types.
|
|
14 *
|
|
15 * @copyright Copyright (C) 2011-2015 fruux GmbH (https://fruux.com/).
|
|
16 * @author Evert Pot (http://evertpot.com/)
|
|
17 * @license http://sabre.io/license/ Modified BSD License
|
|
18 */
|
|
19 abstract class Document extends Component {
|
|
20
|
|
21 /**
|
|
22 * Unknown document type
|
|
23 */
|
|
24 const UNKNOWN = 1;
|
|
25
|
|
26 /**
|
|
27 * vCalendar 1.0
|
|
28 */
|
|
29 const VCALENDAR10 = 2;
|
|
30
|
|
31 /**
|
|
32 * iCalendar 2.0
|
|
33 */
|
|
34 const ICALENDAR20 = 3;
|
|
35
|
|
36 /**
|
|
37 * vCard 2.1
|
|
38 */
|
|
39 const VCARD21 = 4;
|
|
40
|
|
41 /**
|
|
42 * vCard 3.0
|
|
43 */
|
|
44 const VCARD30 = 5;
|
|
45
|
|
46 /**
|
|
47 * vCard 4.0
|
|
48 */
|
|
49 const VCARD40 = 6;
|
|
50
|
|
51 /**
|
|
52 * The default name for this component.
|
|
53 *
|
|
54 * This should be 'VCALENDAR' or 'VCARD'.
|
|
55 *
|
|
56 * @var string
|
|
57 */
|
|
58 static public $defaultName;
|
|
59
|
|
60 /**
|
|
61 * List of properties, and which classes they map to.
|
|
62 *
|
|
63 * @var array
|
|
64 */
|
|
65 static public $propertyMap = array();
|
|
66
|
|
67 /**
|
|
68 * List of components, along with which classes they map to.
|
|
69 *
|
|
70 * @var array
|
|
71 */
|
|
72 static public $componentMap = array();
|
|
73
|
|
74 /**
|
|
75 * List of value-types, and which classes they map to.
|
|
76 *
|
|
77 * @var array
|
|
78 */
|
|
79 static public $valueMap = array();
|
|
80
|
|
81 /**
|
|
82 * Creates a new document.
|
|
83 *
|
|
84 * We're changing the default behavior slightly here. First, we don't want
|
|
85 * to have to specify a name (we already know it), and we want to allow
|
|
86 * children to be specified in the first argument.
|
|
87 *
|
|
88 * But, the default behavior also works.
|
|
89 *
|
|
90 * So the two sigs:
|
|
91 *
|
|
92 * new Document(array $children = array(), $defaults = true);
|
|
93 * new Document(string $name, array $children = array(), $defaults = true)
|
|
94 *
|
|
95 * @return void
|
|
96 */
|
|
97 public function __construct() {
|
|
98
|
|
99 $args = func_get_args();
|
|
100 if (count($args)===0 || is_array($args[0])) {
|
|
101 array_unshift($args, $this, static::$defaultName);
|
|
102 call_user_func_array(array('parent', '__construct'), $args);
|
|
103 } else {
|
|
104 array_unshift($args, $this);
|
|
105 call_user_func_array(array('parent', '__construct'), $args);
|
|
106 }
|
|
107
|
|
108 }
|
|
109
|
|
110 /**
|
|
111 * Returns the current document type.
|
|
112 *
|
|
113 * @return void
|
|
114 */
|
|
115 public function getDocumentType() {
|
|
116
|
|
117 return self::UNKNOWN;
|
|
118
|
|
119 }
|
|
120
|
|
121 /**
|
|
122 * Creates a new component or property.
|
|
123 *
|
|
124 * If it's a known component, we will automatically call createComponent.
|
|
125 * otherwise, we'll assume it's a property and call createProperty instead.
|
|
126 *
|
|
127 * @param string $name
|
|
128 * @param string $arg1,... Unlimited number of args
|
|
129 * @return mixed
|
|
130 */
|
|
131 public function create($name) {
|
|
132
|
|
133 if (isset(static::$componentMap[strtoupper($name)])) {
|
|
134
|
|
135 return call_user_func_array(array($this,'createComponent'), func_get_args());
|
|
136
|
|
137 } else {
|
|
138
|
|
139 return call_user_func_array(array($this,'createProperty'), func_get_args());
|
|
140
|
|
141 }
|
|
142
|
|
143 }
|
|
144
|
|
145 /**
|
|
146 * Creates a new component
|
|
147 *
|
|
148 * This method automatically searches for the correct component class, based
|
|
149 * on its name.
|
|
150 *
|
|
151 * You can specify the children either in key=>value syntax, in which case
|
|
152 * properties will automatically be created, or you can just pass a list of
|
|
153 * Component and Property object.
|
|
154 *
|
|
155 * By default, a set of sensible values will be added to the component. For
|
|
156 * an iCalendar object, this may be something like CALSCALE:GREGORIAN. To
|
|
157 * ensure that this does not happen, set $defaults to false.
|
|
158 *
|
|
159 * @param string $name
|
|
160 * @param array $children
|
|
161 * @param bool $defaults
|
|
162 * @return Component
|
|
163 */
|
|
164 public function createComponent($name, array $children = null, $defaults = true) {
|
|
165
|
|
166 $name = strtoupper($name);
|
|
167 $class = 'Sabre\\VObject\\Component';
|
|
168
|
|
169 if (isset(static::$componentMap[$name])) {
|
|
170 $class=static::$componentMap[$name];
|
|
171 }
|
|
172 if (is_null($children)) $children = array();
|
|
173 return new $class($this, $name, $children, $defaults);
|
|
174
|
|
175 }
|
|
176
|
|
177 /**
|
|
178 * Factory method for creating new properties
|
|
179 *
|
|
180 * This method automatically searches for the correct property class, based
|
|
181 * on its name.
|
|
182 *
|
|
183 * You can specify the parameters either in key=>value syntax, in which case
|
|
184 * parameters will automatically be created, or you can just pass a list of
|
|
185 * Parameter objects.
|
|
186 *
|
|
187 * @param string $name
|
|
188 * @param mixed $value
|
|
189 * @param array $parameters
|
|
190 * @param string $valueType Force a specific valuetype, such as URI or TEXT
|
|
191 * @return Property
|
|
192 */
|
|
193 public function createProperty($name, $value = null, array $parameters = null, $valueType = null) {
|
|
194
|
|
195 // If there's a . in the name, it means it's prefixed by a groupname.
|
|
196 if (($i=strpos($name,'.'))!==false) {
|
|
197 $group = substr($name, 0, $i);
|
|
198 $name = strtoupper(substr($name, $i+1));
|
|
199 } else {
|
|
200 $name = strtoupper($name);
|
|
201 $group = null;
|
|
202 }
|
|
203
|
|
204 $class = null;
|
|
205
|
|
206 if ($valueType) {
|
|
207 // The valueType argument comes first to figure out the correct
|
|
208 // class.
|
|
209 $class = $this->getClassNameForPropertyValue($valueType);
|
|
210 }
|
|
211
|
|
212 if (is_null($class) && isset($parameters['VALUE'])) {
|
|
213 // If a VALUE parameter is supplied, we should use that.
|
|
214 $class = $this->getClassNameForPropertyValue($parameters['VALUE']);
|
|
215 }
|
|
216 if (is_null($class)) {
|
|
217 $class = $this->getClassNameForPropertyName($name);
|
|
218 }
|
|
219 if (is_null($parameters)) $parameters = array();
|
|
220
|
|
221 return new $class($this, $name, $value, $parameters, $group);
|
|
222
|
|
223 }
|
|
224
|
|
225 /**
|
|
226 * This method returns a full class-name for a value parameter.
|
|
227 *
|
|
228 * For instance, DTSTART may have VALUE=DATE. In that case we will look in
|
|
229 * our valueMap table and return the appropriate class name.
|
|
230 *
|
|
231 * This method returns null if we don't have a specialized class.
|
|
232 *
|
|
233 * @param string $valueParam
|
|
234 * @return void
|
|
235 */
|
|
236 public function getClassNameForPropertyValue($valueParam) {
|
|
237
|
|
238 $valueParam = strtoupper($valueParam);
|
|
239 if (isset(static::$valueMap[$valueParam])) {
|
|
240 return static::$valueMap[$valueParam];
|
|
241 }
|
|
242
|
|
243 }
|
|
244
|
|
245 /**
|
|
246 * Returns the default class for a property name.
|
|
247 *
|
|
248 * @param string $propertyName
|
|
249 * @return string
|
|
250 */
|
|
251 public function getClassNameForPropertyName($propertyName) {
|
|
252
|
|
253 if (isset(static::$propertyMap[$propertyName])) {
|
|
254 return static::$propertyMap[$propertyName];
|
|
255 } else {
|
|
256 return 'Sabre\\VObject\\Property\\Unknown';
|
|
257 }
|
|
258
|
|
259 }
|
|
260
|
|
261 }
|