[Pkg-owncloud-commits] [php-sabredav] 76/148: Automatically mapping complex property values to Complex class.

David Prévot taffit at moszumanska.debian.org
Wed Apr 15 01:37:18 UTC 2015


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository php-sabredav.

commit 989eed4f86d95ebc488adb46430c355e26f62c6e
Author: Evert Pot <me at evertpot.com>
Date:   Fri Mar 20 19:04:53 2015 -0400

    Automatically mapping complex property values to Complex class.
---
 lib/CalDAV/Xml/Request/MkCalendar.php        |   5 +-
 lib/DAV/Xml/Element/Prop.php                 | 124 +++++++++++++++++++++++++++
 lib/DAV/Xml/Property/Complex.php             |  91 ++++++++++++++++++++
 lib/DAV/Xml/Request/MkCol.php                |   7 +-
 lib/DAV/Xml/Request/PropFind.php             |   8 +-
 lib/DAV/Xml/Request/PropPatch.php            |   7 +-
 lib/DAV/Xml/Request/SyncCollectionReport.php |   9 +-
 lib/DAV/Xml/Response/MultiStatus.php         |   4 +-
 lib/DAV/Xml/Service.php                      |   3 -
 9 files changed, 249 insertions(+), 9 deletions(-)

diff --git a/lib/CalDAV/Xml/Request/MkCalendar.php b/lib/CalDAV/Xml/Request/MkCalendar.php
index 69dcced..41a162a 100644
--- a/lib/CalDAV/Xml/Request/MkCalendar.php
+++ b/lib/CalDAV/Xml/Request/MkCalendar.php
@@ -61,7 +61,10 @@ class MkCalendar implements XmlDeserializable {
 
         $self = new self();
 
-        $elems = $reader->parseInnerTree();
+        $elementMap = $reader->elementMap;
+        $elementMap['{DAV:}prop']   = 'Sabre\DAV\Xml\Element\Prop';
+        $elementMap['{DAV:}set']    = 'Sabre\Xml\Element\KeyValue';
+        $elems = $reader->parseInnerTree($elementMap);
 
         foreach($elems as $elem) {
             if ($elem['name'] === '{DAV:}set') {
diff --git a/lib/DAV/Xml/Element/Prop.php b/lib/DAV/Xml/Element/Prop.php
new file mode 100644
index 0000000..1ee02cb
--- /dev/null
+++ b/lib/DAV/Xml/Element/Prop.php
@@ -0,0 +1,124 @@
+<?php
+
+namespace Sabre\DAV\Xml\Element;
+
+use
+    Sabre\DAV\Xml\Property\Complex,
+    Sabre\Xml\XmlDeserializable,
+    Sabre\Xml\Reader;
+
+/**
+ * This class is responsible for decoding the {DAV:}prop element as it appears
+ * in {DAV:}property-update.
+ *
+ * This class doesn't return an instance of itself. It just returns a
+ * key->value array.
+ *
+ * @copyright Copyright (C) 2007-2015 fruux GmbH. (https://fruux.com/)
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
+ */
+class Prop implements XmlDeserializable {
+
+    /**
+     * The deserialize method is called during xml parsing.
+     *
+     * This method is called statictly, this is because in theory this method
+     * may be used as a type of constructor, or factory method.
+     *
+     * Often you want to return an instance of the current class, but you are
+     * free to return other data as well.
+     *
+     * You are responsible for advancing the reader to the next element. Not
+     * doing anything will result in a never-ending loop.
+     *
+     * If you just want to skip parsing for this element altogether, you can
+     * just call $reader->next();
+     *
+     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+     * the next element.
+     *
+     * @param Reader $reader
+     * @return mixed
+     */
+    static function xmlDeserialize(Reader $reader) {
+
+        // If there's no children, we don't do anything.
+        if ($reader->isEmptyElement) {
+            $reader->next();
+            return [];
+        }
+
+        $values = [];
+
+        $reader->read();
+        do {
+
+            if ($reader->nodeType === Reader::ELEMENT) {
+
+                $clark = $reader->getClark();
+                $values[$clark] = self::parseCurrentElement($reader)['value'];
+
+            } else {
+                $reader->read();
+            }
+
+        } while ($reader->nodeType !== Reader::END_ELEMENT);
+
+        $reader->read();
+
+        return $values;
+
+    }
+
+    /**
+     * This function behaves similar to Sabre\Xml\Reader::parseCurrentElement,
+     * but instead of creating deep xml array structures, it will turn any
+     * top-level element it doesn't recognize into either a string, or an
+     * XmlFragment class.
+     *
+     * This method returns arn array with 3 properties:
+     *   * name - A clark-notation XML element name.
+     *   * value - The parsed value.
+     *   * attributes - A key-value list of attributes.
+     *
+     * @return array
+     */
+    static private function parseCurrentElement(Reader $reader) {
+
+        $name = $reader->getClark();
+
+        $attributes = [];
+
+        if ($reader->hasAttributes) {
+            $attributes = $reader->parseAttributes();
+        }
+
+        if (array_key_exists($name, $reader->elementMap)) {
+            $deserializer = $reader->elementMap[$name];
+            if (is_subclass_of($deserializer, 'Sabre\\Xml\\XmlDeserializable')) {
+                $value = call_user_func( [ $deserializer, 'xmlDeserialize' ], $reader);
+            } elseif (is_callable($deserializer)) {
+                $value = call_user_func($deserializer, $reader);
+            } else {
+                $type = gettype($deserializer);
+                if ($type==='string') {
+                    $type.=' (' . $deserializer . ')';
+                } elseif ($type==='object') {
+                    $type.=' (' . get_class($deserializer) . ')';
+                }
+                throw new \LogicException('Could not use this type as a deserializer: ' . $type );
+            }
+        } else {
+            $value = Complex::xmlDeserialize($reader);
+        }
+
+        return [
+            'name' => $name,
+            'value' => $value,
+            'attributes' => $attributes,
+        ];
+
+    }
+
+}
diff --git a/lib/DAV/Xml/Property/Complex.php b/lib/DAV/Xml/Property/Complex.php
new file mode 100644
index 0000000..7d14b4c
--- /dev/null
+++ b/lib/DAV/Xml/Property/Complex.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace Sabre\DAV\Xml\Property;
+
+use
+    Sabre\Xml\Element\XmlFragment,
+    Sabre\Xml\Reader;
+
+/**
+ * This class represents a 'complex' property that didn't have a default
+ * decoder.
+ *
+ * It's basically a container for an xml snippet.
+ *
+ * @copyright Copyright (C) 2007-2015 fruux GmbH. (https://fruux.com/)
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
+ */
+class Complex extends XmlFragment {
+
+    /**
+     * The deserialize method is called during xml parsing.
+     *
+     * This method is called statictly, this is because in theory this method
+     * may be used as a type of constructor, or factory method.
+     *
+     * Often you want to return an instance of the current class, but you are
+     * free to return other data as well.
+     *
+     * You are responsible for advancing the reader to the next element. Not
+     * doing anything will result in a never-ending loop.
+     *
+     * If you just want to skip parsing for this element altogether, you can
+     * just call $reader->next();
+     *
+     * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+     * the next element.
+     *
+     * @param Reader $reader
+     * @return mixed
+     */
+    static function xmlDeserialize(Reader $reader) {
+
+        $xml = $reader->readInnerXml();
+
+        if ($reader->nodeType === Reader::ELEMENT && $reader->isEmptyElement) {
+            // Easy!
+            $reader->next();
+            return null;
+        }
+        // Now we have a copy of the inner xml, we need to traverse it to get
+        // all the strings. If there's no non-string data, we just return the
+        // string, otherwise we return an instance of this class.
+        $reader->read();
+
+        $nonText = false;
+        $text = '';
+
+        while(true) {
+
+            switch($reader->nodeType) {
+                case Reader::ELEMENT :
+                    $nonText = true;
+                    $reader->next();
+                    continue 2;
+                case Reader::TEXT :
+                case Reader::CDATA :
+                    $text.=$reader->value;
+                    break;
+                case Reader::END_ELEMENT :
+                    break 2;
+            }
+            $reader->read();
+
+        }
+
+        // Make sure we advance the cursor one step further.
+        $reader->read();
+
+        if ($nonText) {
+            $new = new self($xml);
+            return $new;
+        } else {
+            return $text;
+        }
+
+    }
+
+
+}
+
diff --git a/lib/DAV/Xml/Request/MkCol.php b/lib/DAV/Xml/Request/MkCol.php
index d9236d6..30fd14a 100644
--- a/lib/DAV/Xml/Request/MkCol.php
+++ b/lib/DAV/Xml/Request/MkCol.php
@@ -62,7 +62,12 @@ class MkCol implements XmlDeserializable {
 
         $self = new self();
 
-        $elems = $reader->parseInnerTree();
+        $elementMap = $reader->elementMap;
+        $elementMap['{DAV:}prop']   = 'Sabre\DAV\Xml\Element\Prop';
+        $elementMap['{DAV:}set']    = 'Sabre\Xml\Element\KeyValue';
+        $elementMap['{DAV:}remove'] = 'Sabre\Xml\Element\KeyValue';
+
+        $elems = $reader->parseInnerTree($elementMap);
 
         foreach($elems as $elem) {
             if ($elem['name'] === '{DAV:}set') {
diff --git a/lib/DAV/Xml/Request/PropFind.php b/lib/DAV/Xml/Request/PropFind.php
index cadfbc6..ee5b3f1 100644
--- a/lib/DAV/Xml/Request/PropFind.php
+++ b/lib/DAV/Xml/Request/PropFind.php
@@ -58,11 +58,14 @@ class PropFind implements XmlDeserializable {
 
         $self = new self();
 
+        $reader->pushContext();
+        $reader->elementMap['{DAV:}prop'] = 'Sabre\Xml\Element\Elements';
+
         foreach(KeyValue::xmlDeserialize($reader) as $k=>$v) {
 
             switch($k) {
                 case '{DAV:}prop' :
-                    $self->properties = array_keys($v);
+                    $self->properties = $v;
                     break;
                 case '{DAV:}allprop' :
                     $self->allProp = true;
@@ -70,6 +73,9 @@ class PropFind implements XmlDeserializable {
             }
 
         }
+
+        $reader->popContext();
+
         return $self;
 
     }
diff --git a/lib/DAV/Xml/Request/PropPatch.php b/lib/DAV/Xml/Request/PropPatch.php
index c080a44..fef8c4d 100644
--- a/lib/DAV/Xml/Request/PropPatch.php
+++ b/lib/DAV/Xml/Request/PropPatch.php
@@ -52,7 +52,12 @@ class PropPatch implements XmlDeserializable {
 
         $self = new self();
 
-        $elems = $reader->parseInnerTree();
+        $elementMap = $reader->elementMap;
+        $elementMap['{DAV:}prop']   = 'Sabre\DAV\Xml\Element\Prop';
+        $elementMap['{DAV:}set']    = 'Sabre\Xml\Element\KeyValue';
+        $elementMap['{DAV:}remove'] = 'Sabre\Xml\Element\KeyValue';
+
+        $elems = $reader->parseInnerTree($elementMap);
 
         foreach($elems as $elem) {
             if ($elem['name'] === '{DAV:}set') {
diff --git a/lib/DAV/Xml/Request/SyncCollectionReport.php b/lib/DAV/Xml/Request/SyncCollectionReport.php
index 8725b04..035d2ba 100644
--- a/lib/DAV/Xml/Request/SyncCollectionReport.php
+++ b/lib/DAV/Xml/Request/SyncCollectionReport.php
@@ -73,8 +73,15 @@ class SyncCollectionReport implements XmlDeserializable {
 
         $self = new self();
 
+        $elementMap = $reader->elementMap;
+
+        $reader->pushContext();
+
+        $reader->elementMap['{DAV:}prop']   = 'Sabre\Xml\Element\Elements';
         $elems = KeyValue::xmlDeserialize($reader);
 
+        $reader->popContext();
+
         $required = [
             '{DAV:}sync-token',
             '{DAV:}prop',
@@ -87,7 +94,7 @@ class SyncCollectionReport implements XmlDeserializable {
         }
 
 
-        $self->properties = array_keys($elems['{DAV:}prop']);
+        $self->properties = $elems['{DAV:}prop'];
         $self->syncToken = $elems['{DAV:}sync-token'];
 
         if (isset($elems['{DAV:}limit'])) {
diff --git a/lib/DAV/Xml/Response/MultiStatus.php b/lib/DAV/Xml/Response/MultiStatus.php
index 2f157ce..0c46dc0 100644
--- a/lib/DAV/Xml/Response/MultiStatus.php
+++ b/lib/DAV/Xml/Response/MultiStatus.php
@@ -118,7 +118,9 @@ class MultiStatus implements Element {
      */
     static function xmlDeserialize(Reader $reader) {
 
-        $elements = $reader->parseInnerTree();
+        $elementMap = $reader->elementMap;
+        $elementMap['{DAV:}prop'] = 'Sabre\\DAV\\Xml\\Element\\Prop';
+        $elements = $reader->parseInnerTree($elementMap);
 
         $responses = [];
         $syncToken = null;
diff --git a/lib/DAV/Xml/Service.php b/lib/DAV/Xml/Service.php
index a24c713..45f5e6b 100644
--- a/lib/DAV/Xml/Service.php
+++ b/lib/DAV/Xml/Service.php
@@ -21,9 +21,6 @@ class Service extends \Sabre\Xml\Service {
         '{DAV:}multistatus' => 'Sabre\\DAV\\Xml\\Response\\MultiStatus',
         '{DAV:}response'    => 'Sabre\\DAV\\Xml\\Element\\Response',
         '{DAV:}propstat'    => 'Sabre\\Xml\\Element\\KeyValue',
-        '{DAV:}prop'        => 'Sabre\\Xml\\Element\\KeyValue',
-        '{DAV:}set'         => 'Sabre\\Xml\\Element\\KeyValue',
-        '{DAV:}remove'      => 'Sabre\\Xml\\Element\\KeyValue',
 
         // Requests
         '{DAV:}propfind'        => 'Sabre\\DAV\\Xml\\Request\\PropFind',

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/php-sabredav.git



More information about the Pkg-owncloud-commits mailing list