]> granicus.if.org Git - php/commitdiff
Remplemented support for SplArray using Traversable interface.
authorDmitry Stogov <dmitry@php.net>
Wed, 9 Jan 2008 13:50:17 +0000 (13:50 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 9 Jan 2008 13:50:17 +0000 (13:50 +0000)
ext/soap/php_encoding.c
ext/soap/tests/server031.phpt [new file with mode: 0644]

index ec2ee658af3dd609e498f3f19e8c076181ce98db..7fa330da83ab87315a9856708d5e80a1b5406aa5 100644 (file)
 #include "ext/standard/base64.h"
 #include <libxml/parserInternals.h>
 #include "zend_strtod.h"
-
-#ifdef HAVE_SPL
-# include "ext/spl/spl_array.h"
-#endif
+#include "zend_interfaces.h"
 
 /* zval type decode */
 static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data);
@@ -2176,9 +2173,7 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod
        int dimension = 1;
        int* dims;
        int soap_version;
-#ifdef HAVE_SPL
        zval *array_copy = NULL;
-#endif
        TSRMLS_FETCH();
 
        soap_version = SOAP_GLOBAL(soap_version);
@@ -2198,17 +2193,78 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod
                return xmlParam;
        }
 
-#ifdef HAVE_SPL
-       if (Z_TYPE_P(data) == IS_OBJECT && (instanceof_function(Z_OBJCE_P(data), spl_ce_ArrayObject TSRMLS_CC) || instanceof_function(Z_OBJCE_P(data), spl_ce_ArrayIterator TSRMLS_CC))) {
-               zval getArray;
-            
-               ZVAL_STRING(&getArray, "getArrayCopy", 0);
-               call_user_function_ex(NULL, &data, &getArray, &array_copy, 0, 0, 0, NULL TSRMLS_CC);        
-               if (Z_TYPE_P(array_copy) == IS_ARRAY) {
+       if (Z_TYPE_P(data) == IS_OBJECT && instanceof_function(Z_OBJCE_P(data), zend_ce_traversable TSRMLS_CC)) {
+               zend_object_iterator   *iter;
+               zend_class_entry       *ce = Z_OBJCE_P(data);
+               zval                  **val;
+               zstr                    str_key;
+               uint                    str_key_len;
+               ulong                   int_key;
+               int                     key_type;
+
+               ALLOC_ZVAL(array_copy);
+               INIT_PZVAL(array_copy);
+               array_init(array_copy);
+
+               iter = ce->get_iterator(ce, data, 0 TSRMLS_CC);
+
+               if (EG(exception)) {
+                       goto iterator_done;
+               }
+
+               if (iter->funcs->rewind) {
+                       iter->funcs->rewind(iter TSRMLS_CC);
+                       if (EG(exception)) {
+                               goto iterator_done;
+                       }
+               }
+
+               while (iter->funcs->valid(iter TSRMLS_CC) == SUCCESS) {
+                       if (EG(exception)) {
+                               goto iterator_done;
+                       }
+
+                       iter->funcs->get_current_data(iter, &val TSRMLS_CC);
+                       if (EG(exception)) {
+                               goto iterator_done;
+                       }
+                       if (iter->funcs->get_current_key) {
+                               key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC);
+                               if (EG(exception)) {
+                                       goto iterator_done;
+                               }
+                               switch(key_type) {
+                                       case HASH_KEY_IS_STRING:
+                                               add_assoc_zval_ex(array_copy, str_key.s, str_key_len, *val);
+                                               efree(str_key.s);
+                                               break;
+                                       case HASH_KEY_IS_UNICODE:
+                                               add_u_assoc_zval_ex(array_copy, IS_UNICODE, str_key, str_key_len, *val);
+                                               efree(str_key.u);
+                                               break;
+                                       case HASH_KEY_IS_LONG:
+                                               add_index_zval(array_copy, int_key, *val);
+                                               break;
+                               }
+                       } else {
+                               add_next_index_zval(array_copy, *val);
+                       }
+                       Z_ADDREF_PP(val);
+
+                       iter->funcs->move_forward(iter TSRMLS_CC);
+                       if (EG(exception)) {
+                               goto iterator_done;
+                       }
+               }
+iterator_done:
+               iter->funcs->dtor(iter TSRMLS_CC);
+               if (EG(exception)) {
+                       zval_ptr_dtor(&array_copy);
+                       array_copy = NULL;
+               } else {
                        data = array_copy;
                }
        }
-#endif
 
        if (Z_TYPE_P(data) == IS_ARRAY) {
                sdlAttributePtr *arrayType;
@@ -2388,11 +2444,9 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod
                }
        }
 
-#ifdef HAVE_SPL
        if (array_copy) {
                zval_ptr_dtor(&array_copy);
        }
-#endif
 
        return xmlParam;
 }
diff --git a/ext/soap/tests/server031.phpt b/ext/soap/tests/server031.phpt
new file mode 100644 (file)
index 0000000..f520f1f
--- /dev/null
@@ -0,0 +1,67 @@
+--TEST--
+SOAP Server 31: Handling classes which implements Iterator
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+class ItemArray implements Iterator {
+       private $a = array();
+
+       public function __construct(array $a) {
+               $this->a = $a;
+       }
+
+    public function rewind()    { return reset($this->a); }
+    public function current()   { return current($this->a); }
+    public function key()       { return key($this->a); }
+    public function next()      { return next($this->a); }
+    public function valid()     { return (current($this->a) !== false); }
+}
+
+class Item {
+    public $text;
+
+       public function __construct($n) {
+               $this->text = 'text'.$n;
+       }
+}
+
+class handlerClass {
+    public function getItems()
+    {
+        return new ItemArray(array(
+                       new Item(0),
+                       new Item(1),
+                       new Item(2),
+                       new Item(3),
+                       new Item(4),
+                       new Item(5),
+                       new Item(6),
+                       new Item(7),
+                       new Item(8),
+                       new Item(9)
+               ));
+    }
+}
+
+$server = new SoapServer(dirname(__FILE__)."/server030.wsdl");
+$server->setClass('handlerClass');
+
+$HTTP_RAW_POST_DATA = <<<EOF
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<SOAP-ENV:Envelope
+  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
+  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
+  <SOAP-ENV:Body>
+    <getItems/>
+  </SOAP-ENV:Body>
+</SOAP-ENV:Envelope>
+EOF;
+
+$server->handle($HTTP_RAW_POST_DATA);
+echo "ok\n";
+?>
+--EXPECT--
+<?xml version="1.0" encoding="UTF-8"?>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://testuri.org" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:getItemsResponse><getItemsReturn SOAP-ENC:arrayType="ns1:Item[10]" xsi:type="ns1:ItemArray"><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text0</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text1</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text2</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text3</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text4</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text5</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text6</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text7</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text8</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text9</text></item></getItemsReturn></ns1:getItemsResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
+ok