1*a1a3b679SAndreas Boehler<?php 2*a1a3b679SAndreas Boehler 3*a1a3b679SAndreas Boehlernamespace Sabre\DAV\Xml\Element; 4*a1a3b679SAndreas Boehler 5*a1a3b679SAndreas Boehleruse Sabre\DAV\Xml\Property\Complex; 6*a1a3b679SAndreas Boehleruse Sabre\Xml\XmlDeserializable; 7*a1a3b679SAndreas Boehleruse Sabre\Xml\Reader; 8*a1a3b679SAndreas Boehler 9*a1a3b679SAndreas Boehler/** 10*a1a3b679SAndreas Boehler * This class is responsible for decoding the {DAV:}prop element as it appears 11*a1a3b679SAndreas Boehler * in {DAV:}property-update. 12*a1a3b679SAndreas Boehler * 13*a1a3b679SAndreas Boehler * This class doesn't return an instance of itself. It just returns a 14*a1a3b679SAndreas Boehler * key->value array. 15*a1a3b679SAndreas Boehler * 16*a1a3b679SAndreas Boehler * @copyright Copyright (C) 2007-2015 fruux GmbH. (https://fruux.com/) 17*a1a3b679SAndreas Boehler * @author Evert Pot (http://evertpot.com/) 18*a1a3b679SAndreas Boehler * @license http://sabre.io/license/ Modified BSD License 19*a1a3b679SAndreas Boehler */ 20*a1a3b679SAndreas Boehlerclass Prop implements XmlDeserializable { 21*a1a3b679SAndreas Boehler 22*a1a3b679SAndreas Boehler /** 23*a1a3b679SAndreas Boehler * The deserialize method is called during xml parsing. 24*a1a3b679SAndreas Boehler * 25*a1a3b679SAndreas Boehler * This method is called statictly, this is because in theory this method 26*a1a3b679SAndreas Boehler * may be used as a type of constructor, or factory method. 27*a1a3b679SAndreas Boehler * 28*a1a3b679SAndreas Boehler * Often you want to return an instance of the current class, but you are 29*a1a3b679SAndreas Boehler * free to return other data as well. 30*a1a3b679SAndreas Boehler * 31*a1a3b679SAndreas Boehler * You are responsible for advancing the reader to the next element. Not 32*a1a3b679SAndreas Boehler * doing anything will result in a never-ending loop. 33*a1a3b679SAndreas Boehler * 34*a1a3b679SAndreas Boehler * If you just want to skip parsing for this element altogether, you can 35*a1a3b679SAndreas Boehler * just call $reader->next(); 36*a1a3b679SAndreas Boehler * 37*a1a3b679SAndreas Boehler * $reader->parseInnerTree() will parse the entire sub-tree, and advance to 38*a1a3b679SAndreas Boehler * the next element. 39*a1a3b679SAndreas Boehler * 40*a1a3b679SAndreas Boehler * @param Reader $reader 41*a1a3b679SAndreas Boehler * @return mixed 42*a1a3b679SAndreas Boehler */ 43*a1a3b679SAndreas Boehler static function xmlDeserialize(Reader $reader) { 44*a1a3b679SAndreas Boehler 45*a1a3b679SAndreas Boehler // If there's no children, we don't do anything. 46*a1a3b679SAndreas Boehler if ($reader->isEmptyElement) { 47*a1a3b679SAndreas Boehler $reader->next(); 48*a1a3b679SAndreas Boehler return []; 49*a1a3b679SAndreas Boehler } 50*a1a3b679SAndreas Boehler 51*a1a3b679SAndreas Boehler $values = []; 52*a1a3b679SAndreas Boehler 53*a1a3b679SAndreas Boehler $reader->read(); 54*a1a3b679SAndreas Boehler do { 55*a1a3b679SAndreas Boehler 56*a1a3b679SAndreas Boehler if ($reader->nodeType === Reader::ELEMENT) { 57*a1a3b679SAndreas Boehler 58*a1a3b679SAndreas Boehler $clark = $reader->getClark(); 59*a1a3b679SAndreas Boehler $values[$clark] = self::parseCurrentElement($reader)['value']; 60*a1a3b679SAndreas Boehler 61*a1a3b679SAndreas Boehler } else { 62*a1a3b679SAndreas Boehler $reader->read(); 63*a1a3b679SAndreas Boehler } 64*a1a3b679SAndreas Boehler 65*a1a3b679SAndreas Boehler } while ($reader->nodeType !== Reader::END_ELEMENT); 66*a1a3b679SAndreas Boehler 67*a1a3b679SAndreas Boehler $reader->read(); 68*a1a3b679SAndreas Boehler 69*a1a3b679SAndreas Boehler return $values; 70*a1a3b679SAndreas Boehler 71*a1a3b679SAndreas Boehler } 72*a1a3b679SAndreas Boehler 73*a1a3b679SAndreas Boehler /** 74*a1a3b679SAndreas Boehler * This function behaves similar to Sabre\Xml\Reader::parseCurrentElement, 75*a1a3b679SAndreas Boehler * but instead of creating deep xml array structures, it will turn any 76*a1a3b679SAndreas Boehler * top-level element it doesn't recognize into either a string, or an 77*a1a3b679SAndreas Boehler * XmlFragment class. 78*a1a3b679SAndreas Boehler * 79*a1a3b679SAndreas Boehler * This method returns arn array with 2 properties: 80*a1a3b679SAndreas Boehler * * name - A clark-notation XML element name. 81*a1a3b679SAndreas Boehler * * value - The parsed value. 82*a1a3b679SAndreas Boehler * 83*a1a3b679SAndreas Boehler * @param Reader $reader 84*a1a3b679SAndreas Boehler * @return array 85*a1a3b679SAndreas Boehler */ 86*a1a3b679SAndreas Boehler private static function parseCurrentElement(Reader $reader) { 87*a1a3b679SAndreas Boehler 88*a1a3b679SAndreas Boehler $name = $reader->getClark(); 89*a1a3b679SAndreas Boehler 90*a1a3b679SAndreas Boehler if (array_key_exists($name, $reader->elementMap)) { 91*a1a3b679SAndreas Boehler $deserializer = $reader->elementMap[$name]; 92*a1a3b679SAndreas Boehler if (is_subclass_of($deserializer, 'Sabre\\Xml\\XmlDeserializable')) { 93*a1a3b679SAndreas Boehler $value = call_user_func([ $deserializer, 'xmlDeserialize' ], $reader); 94*a1a3b679SAndreas Boehler } elseif (is_callable($deserializer)) { 95*a1a3b679SAndreas Boehler $value = call_user_func($deserializer, $reader); 96*a1a3b679SAndreas Boehler } else { 97*a1a3b679SAndreas Boehler $type = gettype($deserializer); 98*a1a3b679SAndreas Boehler if ($type === 'string') { 99*a1a3b679SAndreas Boehler $type .= ' (' . $deserializer . ')'; 100*a1a3b679SAndreas Boehler } elseif ($type === 'object') { 101*a1a3b679SAndreas Boehler $type .= ' (' . get_class($deserializer) . ')'; 102*a1a3b679SAndreas Boehler } 103*a1a3b679SAndreas Boehler throw new \LogicException('Could not use this type as a deserializer: ' . $type); 104*a1a3b679SAndreas Boehler } 105*a1a3b679SAndreas Boehler } else { 106*a1a3b679SAndreas Boehler $value = Complex::xmlDeserialize($reader); 107*a1a3b679SAndreas Boehler } 108*a1a3b679SAndreas Boehler 109*a1a3b679SAndreas Boehler return [ 110*a1a3b679SAndreas Boehler 'name' => $name, 111*a1a3b679SAndreas Boehler 'value' => $value, 112*a1a3b679SAndreas Boehler ]; 113*a1a3b679SAndreas Boehler 114*a1a3b679SAndreas Boehler } 115*a1a3b679SAndreas Boehler 116*a1a3b679SAndreas Boehler} 117