From 159233ba0b9d3f06b59e55236130b89853c789d3 Mon Sep 17 00:00:00 2001 From: Evert Pot Date: Wed, 2 Sep 2015 13:38:31 +0200 Subject: [PATCH 1/3] When properties appear in propstat with no value, don't call deserializers. --- lib/DAV/Xml/Element/Response.php | 39 ++++++++++++ lib/DAV/Xml/Service.php | 1 - tests/Sabre/DAV/Xml/Element/ResponseTest.php | 67 ++++++++++++++++++++ 3 files changed, 106 insertions(+), 1 deletion(-) diff --git a/lib/DAV/Xml/Element/Response.php b/lib/DAV/Xml/Element/Response.php index 3df962f87e..a5cc1b387d 100644 --- a/lib/DAV/Xml/Element/Response.php +++ b/lib/DAV/Xml/Element/Response.php @@ -161,7 +161,46 @@ function xmlSerialize(Writer $writer) { */ static function xmlDeserialize(Reader $reader) { + $reader->pushContext(); + + $reader->elementMap['{DAV:}propstat'] = 'Sabre\\Xml\\Element\\KeyValue'; + + // We are overriding the parser for {DAV:}prop. This deserializer is + // almost identical to the one for Sabre\Xml\Element\KeyValue. + // + // The difference is that if there are any child-elements inside of + // {DAV:}prop, that have no value, normally any deserializers are + // called. But we don't want this, because a singlular element without + // child-elements implies 'no value' in {DAV:}prop, so we want to skip + // deserializers and just set null for those. + $reader->elementMap['{DAV:}prop'] = function(Reader $reader) { + + if ($reader->isEmptyElement) { + $reader->next(); + return []; + } + $values = []; + $reader->read(); + do { + if ($reader->nodeType === Reader::ELEMENT) { + $clark = $reader->getClark(); + + if ($reader->isEmptyElement) { + $values[$clark] = null; + $reader->next(); + } else { + $values[$clark] = $reader->parseCurrentElement()['value']; + } + } else { + $reader->read(); + } + } while ($reader->nodeType !== Reader::END_ELEMENT); + $reader->read(); + return $values; + + }; $elems = $reader->parseInnerTree(); + $reader->popContext(); $href = null; $propertyLists = []; diff --git a/lib/DAV/Xml/Service.php b/lib/DAV/Xml/Service.php index b74fcd1a8f..53cf4143b3 100644 --- a/lib/DAV/Xml/Service.php +++ b/lib/DAV/Xml/Service.php @@ -20,7 +20,6 @@ class Service extends \Sabre\Xml\Service { public $elementMap = [ '{DAV:}multistatus' => 'Sabre\\DAV\\Xml\\Response\\MultiStatus', '{DAV:}response' => 'Sabre\\DAV\\Xml\\Element\\Response', - '{DAV:}propstat' => 'Sabre\\Xml\\Element\\KeyValue', // Requests '{DAV:}propfind' => 'Sabre\\DAV\\Xml\\Request\\PropFind', diff --git a/tests/Sabre/DAV/Xml/Element/ResponseTest.php b/tests/Sabre/DAV/Xml/Element/ResponseTest.php index 47387fd208..fb069c43cf 100644 --- a/tests/Sabre/DAV/Xml/Element/ResponseTest.php +++ b/tests/Sabre/DAV/Xml/Element/ResponseTest.php @@ -179,4 +179,71 @@ function testSerializeBreak() { } + function testDeserializeComplexProperty() { + + $xml = ' + + /uri + + + hello + + HTTP/1.1 200 OK + + +'; + + $result = $this->parse($xml, [ + '{DAV:}response' => 'Sabre\DAV\Xml\Element\Response', + '{DAV:}foo' => function($reader) { + + $reader->next(); + return 'world'; + }, + ]); + $this->assertEquals( + new Response('/uri', [ + '200' => [ + '{DAV:}foo' => 'world', + ] + ]), + $result['value'] + ); + + } + + /** + * In the case of {DAV:}prop, a deserializer should never get called, if + * the property element is empty. + */ + function testDeserializeComplexPropertyEmpty() { + + $xml = ' + + /uri + + + + + HTTP/1.1 404 Not Found + + +'; + + $result = $this->parse($xml, [ + '{DAV:}response' => 'Sabre\DAV\Xml\Element\Response', + '{DAV:}foo' => function($reader) { + throw new \LogicException('This should never happned'); + }, + ]); + $this->assertEquals( + new Response('/uri', [ + '404' => [ + '{DAV:}foo' => null + ] + ]), + $result['value'] + ); + + } } From 4b538fee33ebf3546732cb8f6793f6704caede41 Mon Sep 17 00:00:00 2001 From: Evert Pot Date: Wed, 2 Sep 2015 13:52:14 +0200 Subject: [PATCH 2/3] Typo --- tests/Sabre/DAV/Xml/Element/ResponseTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Sabre/DAV/Xml/Element/ResponseTest.php b/tests/Sabre/DAV/Xml/Element/ResponseTest.php index fb069c43cf..8ca4bee436 100644 --- a/tests/Sabre/DAV/Xml/Element/ResponseTest.php +++ b/tests/Sabre/DAV/Xml/Element/ResponseTest.php @@ -233,7 +233,7 @@ function testDeserializeComplexPropertyEmpty() { $result = $this->parse($xml, [ '{DAV:}response' => 'Sabre\DAV\Xml\Element\Response', '{DAV:}foo' => function($reader) { - throw new \LogicException('This should never happned'); + throw new \LogicException('This should never happen'); }, ]); $this->assertEquals( From baa117f23fe53c8b5d98c115a850bd5a5445069b Mon Sep 17 00:00:00 2001 From: Dominik Tobschall Date: Wed, 2 Sep 2015 16:07:52 +0200 Subject: [PATCH 3/3] typo --- lib/DAV/Xml/Element/Response.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/DAV/Xml/Element/Response.php b/lib/DAV/Xml/Element/Response.php index a5cc1b387d..c9d73bdd5e 100644 --- a/lib/DAV/Xml/Element/Response.php +++ b/lib/DAV/Xml/Element/Response.php @@ -170,7 +170,7 @@ static function xmlDeserialize(Reader $reader) { // // The difference is that if there are any child-elements inside of // {DAV:}prop, that have no value, normally any deserializers are - // called. But we don't want this, because a singlular element without + // called. But we don't want this, because a singular element without // child-elements implies 'no value' in {DAV:}prop, so we want to skip // deserializers and just set null for those. $reader->elementMap['{DAV:}prop'] = function(Reader $reader) {