ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
XML.php
Go to the documentation of this file.
1<?php
2
4
10use Sabre\Xml as SabreXml;
11
21class XML extends Parser {
22
23 const XCAL_NAMESPACE = 'urn:ietf:params:xml:ns:icalendar-2.0';
24 const XCARD_NAMESPACE = 'urn:ietf:params:xml:ns:vcard-4.0';
25
31 protected $input;
32
38 private $pointer;
39
45 protected $root;
46
57 function __construct($input = null, $options = 0) {
58
59 if (0 === $options) {
60 $options = parent::OPTION_FORGIVING;
61 }
62
63 parent::__construct($input, $options);
64
65 }
66
77 function parse($input = null, $options = 0) {
78
79 if (!is_null($input)) {
80 $this->setInput($input);
81 }
82
83 if (0 !== $options) {
84 $this->options = $options;
85 }
86
87 if (is_null($this->input)) {
88 throw new EofException('End of input stream, or no input supplied');
89 }
90
91 switch ($this->input['name']) {
92
93 case '{' . self::XCAL_NAMESPACE . '}icalendar':
94 $this->root = new VCalendar([], false);
95 $this->pointer = &$this->input['value'][0];
96 $this->parseVCalendarComponents($this->root);
97 break;
98
99 case '{' . self::XCARD_NAMESPACE . '}vcards':
100 foreach ($this->input['value'] as &$vCard) {
101
102 $this->root = new VCard(['version' => '4.0'], false);
103 $this->pointer = &$vCard;
104 $this->parseVCardComponents($this->root);
105
106 // We just parse the first <vcard /> element.
107 break;
108
109 }
110 break;
111
112 default:
113 throw new ParseException('Unsupported XML standard');
114
115 }
116
117 return $this->root;
118 }
119
127 protected function parseVCalendarComponents(Component $parentComponent) {
128
129 foreach ($this->pointer['value'] ?: [] as $children) {
130
131 switch (static::getTagName($children['name'])) {
132
133 case 'properties':
134 $this->pointer = &$children['value'];
135 $this->parseProperties($parentComponent);
136 break;
137
138 case 'components':
139 $this->pointer = &$children;
140 $this->parseComponent($parentComponent);
141 break;
142 }
143 }
144
145 }
146
154 protected function parseVCardComponents(Component $parentComponent) {
155
156 $this->pointer = &$this->pointer['value'];
157 $this->parseProperties($parentComponent);
158
159 }
160
169 protected function parseProperties(Component $parentComponent, $propertyNamePrefix = '') {
170
171 foreach ($this->pointer ?: [] as $xmlProperty) {
172
173 list($namespace, $tagName) = SabreXml\Service::parseClarkNotation($xmlProperty['name']);
174
175 $propertyName = $tagName;
176 $propertyValue = [];
177 $propertyParameters = [];
178 $propertyType = 'text';
179
180 // A property which is not part of the standard.
181 if ($namespace !== self::XCAL_NAMESPACE
182 && $namespace !== self::XCARD_NAMESPACE) {
183
184 $propertyName = 'xml';
185 $value = '<' . $tagName . ' xmlns="' . $namespace . '"';
186
187 foreach ($xmlProperty['attributes'] as $attributeName => $attributeValue) {
188 $value .= ' ' . $attributeName . '="' . str_replace('"', '\"', $attributeValue) . '"';
189 }
190
191 $value .= '>' . $xmlProperty['value'] . '</' . $tagName . '>';
192
193 $propertyValue = [$value];
194
195 $this->createProperty(
196 $parentComponent,
197 $propertyName,
198 $propertyParameters,
199 $propertyType,
200 $propertyValue
201 );
202
203 continue;
204 }
205
206 // xCard group.
207 if ($propertyName === 'group') {
208
209 if (!isset($xmlProperty['attributes']['name'])) {
210 continue;
211 }
212
213 $this->pointer = &$xmlProperty['value'];
214 $this->parseProperties(
215 $parentComponent,
216 strtoupper($xmlProperty['attributes']['name']) . '.'
217 );
218
219 continue;
220
221 }
222
223 // Collect parameters.
224 foreach ($xmlProperty['value'] as $i => $xmlPropertyChild) {
225
226 if (!is_array($xmlPropertyChild)
227 || 'parameters' !== static::getTagName($xmlPropertyChild['name']))
228 continue;
229
230 $xmlParameters = $xmlPropertyChild['value'];
231
232 foreach ($xmlParameters as $xmlParameter) {
233
234 $propertyParameterValues = [];
235
236 foreach ($xmlParameter['value'] as $xmlParameterValues) {
237 $propertyParameterValues[] = $xmlParameterValues['value'];
238 }
239
240 $propertyParameters[static::getTagName($xmlParameter['name'])]
241 = implode(',', $propertyParameterValues);
242
243 }
244
245 array_splice($xmlProperty['value'], $i, 1);
246
247 }
248
249 $propertyNameExtended = ($this->root instanceof VCalendar
250 ? 'xcal'
251 : 'xcard') . ':' . $propertyName;
252
253 switch ($propertyNameExtended) {
254
255 case 'xcal:geo':
256 $propertyType = 'float';
257 $propertyValue['latitude'] = 0;
258 $propertyValue['longitude'] = 0;
259
260 foreach ($xmlProperty['value'] as $xmlRequestChild) {
261 $propertyValue[static::getTagName($xmlRequestChild['name'])]
262 = $xmlRequestChild['value'];
263 }
264 break;
265
266 case 'xcal:request-status':
267 $propertyType = 'text';
268
269 foreach ($xmlProperty['value'] as $xmlRequestChild) {
270 $propertyValue[static::getTagName($xmlRequestChild['name'])]
271 = $xmlRequestChild['value'];
272 }
273 break;
274
275 case 'xcal:freebusy':
276 $propertyType = 'freebusy';
277 // We don't break because we only want to set
278 // another property type.
279
280 case 'xcal:categories':
281 case 'xcal:resources':
282 case 'xcal:exdate':
283 foreach ($xmlProperty['value'] as $specialChild) {
284 $propertyValue[static::getTagName($specialChild['name'])]
285 = $specialChild['value'];
286 }
287 break;
288
289 case 'xcal:rdate':
290 $propertyType = 'date-time';
291
292 foreach ($xmlProperty['value'] as $specialChild) {
293
294 $tagName = static::getTagName($specialChild['name']);
295
296 if ('period' === $tagName) {
297
298 $propertyParameters['value'] = 'PERIOD';
299 $propertyValue[] = implode('/', $specialChild['value']);
300
301 }
302 else {
303 $propertyValue[] = $specialChild['value'];
304 }
305 }
306 break;
307
308 default:
309 $propertyType = static::getTagName($xmlProperty['value'][0]['name']);
310
311 foreach ($xmlProperty['value'] as $value) {
312 $propertyValue[] = $value['value'];
313 }
314
315 if ('date' === $propertyType) {
316 $propertyParameters['value'] = 'DATE';
317 }
318 break;
319 }
320
321 $this->createProperty(
322 $parentComponent,
323 $propertyNamePrefix . $propertyName,
324 $propertyParameters,
325 $propertyType,
326 $propertyValue
327 );
328
329 }
330
331 }
332
340 protected function parseComponent(Component $parentComponent) {
341
342 $components = $this->pointer['value'] ?: [];
343
344 foreach ($components as $component) {
345
346 $componentName = static::getTagName($component['name']);
347 $currentComponent = $this->root->createComponent(
348 $componentName,
349 null,
350 false
351 );
352
353 $this->pointer = &$component;
354 $this->parseVCalendarComponents($currentComponent);
355
356 $parentComponent->add($currentComponent);
357
358 }
359
360 }
361
373 protected function createProperty(Component $parentComponent, $name, $parameters, $type, $value) {
374
375 $property = $this->root->createProperty(
376 $name,
377 null,
378 $parameters,
379 $type
380 );
381 $parentComponent->add($property);
382 $property->setXmlValue($value);
383
384 }
385
393 function setInput($input) {
394
395 if (is_resource($input)) {
396 $input = stream_get_contents($input);
397 }
398
399 if (is_string($input)) {
400
401 $reader = new SabreXml\Reader();
402 $reader->elementMap['{' . self::XCAL_NAMESPACE . '}period']
403 = 'Sabre\VObject\Parser\XML\Element\KeyValue';
404 $reader->elementMap['{' . self::XCAL_NAMESPACE . '}recur']
405 = 'Sabre\VObject\Parser\XML\Element\KeyValue';
406 $reader->xml($input);
407 $input = $reader->parse();
408
409 }
410
411 $this->input = $input;
412
413 }
414
422 protected static function getTagName($clarkedTagName) {
423
424 list(, $tagName) = SabreXml\Service::parseClarkNotation($clarkedTagName);
425 return $tagName;
426
427 }
428}
An exception for terminatinating execution or to throw for unit testing.
The VCalendar component.
Definition: VCalendar.php:23
The VCard component.
Definition: VCard.php:18
add()
Adds a new property or component, and returns the new item.
Definition: Component.php:109
Exception thrown by parser when the end of the stream has been reached, before this was expected.
Exception thrown by Reader if an invalid object was attempted to be parsed.
Abstract parser.
Definition: Parser.php:14
XML Parser.
Definition: XML.php:21
parseComponent(Component $parentComponent)
Parse a component.
Definition: XML.php:340
createProperty(Component $parentComponent, $name, $parameters, $type, $value)
Create a property.
Definition: XML.php:373
setInput($input)
Sets the input data.
Definition: XML.php:393
static getTagName($clarkedTagName)
Get tag name from a Clark notation.
Definition: XML.php:422
parse($input=null, $options=0)
Parse xCal or xCard.
Definition: XML.php:77
parseVCalendarComponents(Component $parentComponent)
Parse a xCalendar component.
Definition: XML.php:127
parseVCardComponents(Component $parentComponent)
Parse a xCard component.
Definition: XML.php:154
__construct($input=null, $options=0)
Creates the parser.
Definition: XML.php:57
parseProperties(Component $parentComponent, $propertyNamePrefix='')
Parse xCalendar and xCard properties.
Definition: XML.php:169
The Reader class expands upon PHP's built-in XMLReader.
Definition: Reader.php:20
static parseClarkNotation($str)
Parses a clark-notation string, and returns the namespace and element name components.
Definition: Service.php:274
$i
Definition: disco.tpl.php:19
if($err=$client->getError()) $namespace
input
Definition: langcheck.php:166
$type