1<?php 2 3namespace Sabre\DAV\Xml\Request; 4 5use Sabre\Xml\Element; 6use Sabre\Xml\Reader; 7use Sabre\Xml\Writer; 8 9/** 10 * WebDAV PROPPATCH request parser. 11 * 12 * This class parses the {DAV:}propertyupdate request, as defined in: 13 * 14 * https://tools.ietf.org/html/rfc4918#section-14.20 15 * 16 * @copyright Copyright (C) fruux GmbH (https://fruux.com/) 17 * @author Evert Pot (http://www.rooftopsolutions.nl/) 18 * @license http://sabre.io/license/ Modified BSD License 19 */ 20class PropPatch implements Element { 21 22 /** 23 * The list of properties that will be updated and removed. 24 * 25 * If a property will be removed, it's value will be set to null. 26 * 27 * @var array 28 */ 29 public $properties = []; 30 31 /** 32 * The xmlSerialize method is called during xml writing. 33 * 34 * Use the $writer argument to write its own xml serialization. 35 * 36 * An important note: do _not_ create a parent element. Any element 37 * implementing XmlSerializable should only ever write what's considered 38 * its 'inner xml'. 39 * 40 * The parent of the current element is responsible for writing a 41 * containing element. 42 * 43 * This allows serializers to be re-used for different element names. 44 * 45 * If you are opening new elements, you must also close them again. 46 * 47 * @param Writer $writer 48 * @return void 49 */ 50 function xmlSerialize(Writer $writer) { 51 52 foreach ($this->properties as $propertyName => $propertyValue) { 53 54 if (is_null($propertyValue)) { 55 $writer->startElement("{DAV:}remove"); 56 $writer->write(['{DAV:}prop' => [$propertyName => $propertyValue]]); 57 $writer->endElement(); 58 } else { 59 $writer->startElement("{DAV:}set"); 60 $writer->write(['{DAV:}prop' => [$propertyName => $propertyValue]]); 61 $writer->endElement(); 62 } 63 64 } 65 66 } 67 68 /** 69 * The deserialize method is called during xml parsing. 70 * 71 * This method is called statically, this is because in theory this method 72 * may be used as a type of constructor, or factory method. 73 * 74 * Often you want to return an instance of the current class, but you are 75 * free to return other data as well. 76 * 77 * You are responsible for advancing the reader to the next element. Not 78 * doing anything will result in a never-ending loop. 79 * 80 * If you just want to skip parsing for this element altogether, you can 81 * just call $reader->next(); 82 * 83 * $reader->parseInnerTree() will parse the entire sub-tree, and advance to 84 * the next element. 85 * 86 * @param Reader $reader 87 * @return mixed 88 */ 89 static function xmlDeserialize(Reader $reader) { 90 91 $self = new self(); 92 93 $elementMap = $reader->elementMap; 94 $elementMap['{DAV:}prop'] = 'Sabre\DAV\Xml\Element\Prop'; 95 $elementMap['{DAV:}set'] = 'Sabre\Xml\Element\KeyValue'; 96 $elementMap['{DAV:}remove'] = 'Sabre\Xml\Element\KeyValue'; 97 98 $elems = $reader->parseInnerTree($elementMap); 99 100 foreach ($elems as $elem) { 101 if ($elem['name'] === '{DAV:}set') { 102 $self->properties = array_merge($self->properties, $elem['value']['{DAV:}prop']); 103 } 104 if ($elem['name'] === '{DAV:}remove') { 105 106 // Ensuring there are no values. 107 foreach ($elem['value']['{DAV:}prop'] as $remove => $value) { 108 $self->properties[$remove] = null; 109 } 110 111 } 112 } 113 114 return $self; 115 116 } 117 118} 119