source: branches/version-2_11-dev/data/module/SOAP/Disco.php @ 21299

Revision 21299, 15.3 KB checked in by Seasoft, 12 years ago (diff)

#1521 (PEAR::SOAP 配布と異なる部分がある)

  • 新しいバージョンの配布ファイルを上書きすることで解決

#1522 (PEAR::SOAP をバージョンアップ)

  • 0.11.0 -> 0.12.0
  • Property svn:eol-style set to LF
  • Property svn:mime-type set to text/x-httpd-php; charset=UTF-8
Line 
1<?php
2/**
3 * This file contains the code for the DISCO server, providing DISO and WSDL
4 * services.
5 *
6 * PHP versions 4 and 5
7 *
8 * LICENSE: This source file is subject to version 2.02 of the PHP license,
9 * that is bundled with this package in the file LICENSE, and is available at
10 * through the world-wide-web at http://www.php.net/license/2_02.txt.  If you
11 * did not receive a copy of the PHP license and are unable to obtain it
12 * through the world-wide-web, please send a note to license@php.net so we can
13 * mail you a copy immediately.
14 *
15 * @category   Web Services
16 * @package    SOAP
17 * @author     Dmitri Vinogradov <dimitri@vinogradov.de>
18 * @author     Chuck Hagenbuch <chuck@horde.org>
19 * @author     Jan Schneider <jan@horde.org>
20 * @copyright  2003-2005 The PHP Group
21 * @license    http://www.php.net/license/2_02.txt  PHP License 2.02
22 * @link       http://pear.php.net/package/SOAP
23 */
24
25/** SOAP_Base */
26require_once 'SOAP/Base.php';
27
28/**
29 * @package SOAP
30 */
31class SOAP_DISCO_Server extends SOAP_Base_Object {
32
33    var $namespaces     = array(SCHEMA_WSDL => 'wsdl', SCHEMA_SOAP => 'soap');
34    var $import_ns      = array();
35    var $wsdl           = '';
36    var $disco          = '';
37    var $_wsdl          = array();
38    var $_disco         = array();
39    var $_service_name  = '';
40    var $_service_ns    = '';
41    var $_service_desc  = '';
42    var $_portname      = '';
43    var $_bindingname   = '';
44    var $soap_server    = NULL;
45
46
47    function SOAP_DISCO_Server($soap_server, $service_name, $service_desc = '',
48                               $import_ns = null)
49    {
50        parent::SOAP_Base_Object('Server');
51
52        if ( !is_object($soap_server)
53            || !get_class($soap_server) == 'soap_server') return;
54
55        $this->_service_name = $service_name;
56        $this->_service_ns = "urn:$service_name";
57        $this->_service_desc = $service_desc;
58        $this->import_ns = isset($import_ns) ? $import_ns : $this->import_ns;
59        $this->soap_server = $soap_server;
60        $this->host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
61    }
62
63    function getDISCO()
64    {
65        $this->_generate_DISCO();
66        return $this->disco;
67    }
68
69    function getWSDL()
70    {
71        $this->_generate_WSDL();
72        return $this->wsdl;
73    }
74
75    function _generate_DISCO()
76    {
77        // DISCO
78        $this->_disco['disco:discovery']['attr']['xmlns:disco'] = SCHEMA_DISCO;
79        $this->_disco['disco:discovery']['attr']['xmlns:scl'] = SCHEMA_DISCO_SCL;
80        $this->_disco['disco:discovery']['scl:contractRef']['attr']['ref'] =
81            (array_key_exists('HTTPS', $_SERVER) && $_SERVER['HTTPS'] == 'on')
82            ? 'https://' . $this->host . $_SERVER['PHP_SELF'] . '?wsdl'
83            : 'http://'  . $this->host . $_SERVER['PHP_SELF'] . '?wsdl';
84
85        // generate disco xml
86        $this->_generate_DISCO_XML($this->_disco);
87    }
88
89    function _generate_WSDL()
90    {
91        // WSDL
92        if (is_array($this->soap_server->_namespaces)) {
93            // need to get: typens, xsd & SOAP-ENC
94            $flipped = array_flip($this->soap_server->_namespaces);
95            $this->namespaces[$this->_service_ns] = 'tns';
96            $this->namespaces[$flipped['xsd']] = 'xsd';
97            $this->namespaces[$flipped[SOAP_BASE::SOAPENCPrefix()]] = SOAP_BASE::SOAPENCPrefix();
98        }
99
100        // DEFINITIONS
101        $this->_wsdl['definitions']['attr']['name'] = $this->_service_name;
102        $this->_wsdl['definitions']['attr']['targetNamespace'] = $this->_service_ns;
103        foreach ($this->namespaces as $ns => $prefix) {
104            $this->_wsdl['definitions']['attr']['xmlns:' . $prefix] = $ns;
105        }
106        $this->_wsdl['definitions']['attr']['xmlns'] = SCHEMA_WSDL;
107
108        // Import namespaces. Seems to not work yet: wsdl.exe fom .NET can't
109        // handle imported complete wsdl-definitions.
110        if (count($this->import_ns)) {
111            $i = 0;
112            foreach ($this->import_ns as $_ns => $_location) {
113                $this->_wsdl['definitions']['import'][$i]['attr']['location'] = $_location;
114                $this->_wsdl['definitions']['import'][$i]['attr']['namespace'] = $_ns;
115                $i++;
116            }
117        }
118        $this->_wsdl['definitions']['types']['attr']['xmlns']='http://schemas.xmlsoap.org/wsdl/';
119        $this->_wsdl['definitions']['types']['schema']=array();
120
121        // Placeholder for messages
122        $this->_wsdl['definitions']['message'] = array();
123
124        // PORTTYPE-NAME
125        $this->_portname = $this->_service_name . 'Port';
126        $this->_wsdl['definitions']['portType']['attr']['name'] = $this->_portname;
127
128        // BINDING-NAME
129        $this->_bindingname = $this->_service_name . 'Binding';
130        $this->_wsdl['definitions']['binding']['attr']['name'] = $this->_bindingname;
131        $this->_wsdl['definitions']['binding']['attr']['type'] = 'tns:' . $this->_portname;
132        $this->_wsdl['definitions']['binding']['soap:binding']['attr']['style'] = 'rpc';
133        $this->_wsdl['definitions']['binding']['soap:binding']['attr']['transport'] = SCHEMA_SOAP_HTTP;
134
135        // SERVICE
136        $this->_wsdl['definitions']['service']['attr']['name'] = $this->_service_name . 'Service';
137        $this->_wsdl['definitions']['service']['documentation']['attr'] = '';
138        $this->_wsdl['definitions']['service']['documentation'] = htmlentities($this->_service_desc);
139        $this->_wsdl['definitions']['service']['port']['attr']['name'] = $this->_portname;
140        $this->_wsdl['definitions']['service']['port']['attr']['binding'] = 'tns:' . $this->_bindingname;
141        $this->_wsdl['definitions']['service']['port']['soap:address']['attr']['location'] =
142            (array_key_exists('HTTPS', $_SERVER) && $_SERVER['HTTPS'] == 'on')
143            ? 'https://' . $this->host . $_SERVER['PHP_SELF']
144            : 'http://'  . $this->host . $_SERVER['PHP_SELF'];
145
146        //
147        $dispatch_keys = array_keys($this->soap_server->dispatch_objects);
148        $dc = count($dispatch_keys);
149        for ($di = 0; $di < $dc; $di++) {
150            $namespace = $dispatch_keys[$di];
151            $namespace_objects =& $this->soap_server->dispatch_objects[$namespace];
152            $oc = count($namespace_objects);
153            for ($oi = 0; $oi < $oc; $oi++) {
154                $object = $namespace_objects[$oi];
155                // types definitions
156                $this->addSchemaFromMap($object->__typedef);
157                // MESSAGES
158                $this->addMethodsFromMap($object->__dispatch_map, $namespace, get_class($object));
159            }
160        }
161        if (isset($this->soap_server->dispatch_map)) {
162            $this->addMethodsFromMap($this->soap_server->dispatch_map, $namespace);
163        }
164
165        // generate wsdl
166        $this->_generate_WSDL_XML();
167    }
168
169    function &_getSchema($namespace)
170    {
171        // SCHEMA
172        $c = count($this->_wsdl['definitions']['types']['schema']);
173        for($i = 0; $i < $c; $i++) {
174            if ($this->_wsdl['definitions']['types']['schema'][$i]['attr']['targetNamespace'] == $namespace) {
175                return $this->_wsdl['definitions']['types']['schema'][$i];
176            }
177        }
178
179        // don't have this namespace
180        $schema = array();
181        $schema['attr'] = array();
182        $schema['complexType'] = array();
183        $schema['attr']['xmlns'] = array_search('xsd',$this->namespaces);
184        $schema['attr']['targetNamespace'] = $namespace;
185        $this->_wsdl['definitions']['types']['schema'][] =& $schema;
186
187        return $schema;
188    }
189
190    function addSchemaFromMap(&$map)
191    {
192        if (!$map) {
193            return;
194        }
195
196        foreach ($map as $_type_name => $_type_def) {
197            list($typens,$type) = $this->_getTypeNs($_type_name);
198            if ($typens == 'xsd') {
199                // cannot add to xsd, lets use method_namespace
200                $typens = 'tns';
201            }
202            $schema =& $this->_getSchema(array_search($typens, $this->namespaces));
203            if (!$this->_ifComplexTypeExists($schema['complexType'], $type)) {
204                $ctype =& $schema['complexType'][];
205                $ctype['attr']['name'] = $type;
206                foreach ($_type_def as $_varname => $_vartype) {
207                    if (!is_int($_varname)) {
208                        list($_vartypens,$_vartype) = $this->_getTypeNs($_vartype);
209                        $ctype['all']['attr'] = '';
210                        $el =& $ctype['all']['element'][];
211                        $el['attr']['name'] = $_varname;
212                        $el['attr']['type'] = $_vartypens . ':' . $_vartype;
213                    } else {
214                        $ctype['complexContent']['attr'] = '';
215                        $ctype['complexContent']['restriction']['attr']['base'] = SOAP_BASE::SOAPENCPrefix().':Array';
216                        foreach ($_vartype as $array_type) {
217                            list($_vartypens, $_vartype) = $this->_getTypeNs($array_type);
218                            $ctype['complexContent']['restriction']['attribute']['attr']['ref'] = SOAP_BASE::SOAPENCPrefix().':arrayType';
219                            $ctype['complexContent']['restriction']['attribute']['attr']['wsdl:arrayType'] = $_vartypens . ':' . $_vartype . '[]';
220                        }
221                    }
222                }
223            }
224        }
225    }
226
227    function addMethodsFromMap(&$map, $namespace, $classname = null)
228    {
229        if (!$map) {
230            return;
231        }
232
233        foreach ($map as $method_name => $method_types) {
234            if (array_key_exists('namespace', $method_types)) {
235                $method_namespace = $method_types['namespace'];
236            } else {
237                $method_namespace = $namespace;
238            }
239
240            // INPUT
241            $input_message = array('attr' => array('name' => $method_name . 'Request'));
242            if (isset($method_types['in']) && is_array($method_types['in'])) {
243                foreach ($method_types['in'] as $name => $type) {
244                    list($typens, $type) = $this->_getTypeNs($type);
245                    $part = array();
246                    $part['attr']['name'] = $name;
247                    $part['attr']['type'] = $typens . ':' . $type;
248                    $input_message['part'][] = $part;
249                }
250            }
251            $this->_wsdl['definitions']['message'][] = $input_message;
252
253            // OUTPUT
254            $output_message = array('attr' => array('name' => $method_name . 'Response'));
255            if (isset($method_types['out']) && is_array($method_types['out'])) {
256                foreach ($method_types['out'] as $name => $type) {
257                    list($typens, $type) = $this->_getTypeNs($type);
258                    $part = array();
259                    $part['attr']['name'] = $name;
260                    $part['attr']['type'] = $typens . ':' . $type;
261                    $output_message['part'][] = $part;
262                }
263            }
264            $this->_wsdl['definitions']['message'][] = $output_message;
265
266            // PORTTYPES
267            $operation = array();
268            $operation['attr']['name'] = $method_name;
269            // INPUT
270            $operation['input']['attr']['message'] = 'tns:' . $input_message['attr']['name'];
271            // OUTPUT
272            $operation['output']['attr']['message'] = 'tns:' . $output_message['attr']['name'];
273            $this->_wsdl['definitions']['portType']['operation'][] = $operation;
274
275            // BINDING
276            $binding = array();
277            $binding['attr']['name'] = $method_name;
278            $action = $method_namespace . '#' . ($classname ? $classname . '#' : '') . $method_name;
279            $binding['soap:operation']['attr']['soapAction'] = $action;
280            // INPUT
281            $binding['input']['attr'] = '';
282            $binding['input']['soap:body']['attr']['use'] = 'encoded';
283            $binding['input']['soap:body']['attr']['namespace'] = $method_namespace;
284            $binding['input']['soap:body']['attr']['encodingStyle'] = SOAP_SCHEMA_ENCODING;
285            // OUTPUT
286            $binding['output']['attr'] = '';
287            $binding['output']['soap:body']['attr']['use'] = 'encoded';
288            $binding['output']['soap:body']['attr']['namespace'] = $method_namespace;
289            $binding['output']['soap:body']['attr']['encodingStyle'] = SOAP_SCHEMA_ENCODING;
290            $this->_wsdl['definitions']['binding']['operation'][] = $binding;
291        }
292    }
293
294    function _generate_DISCO_XML($disco_array)
295    {
296        $disco = '<?xml version="1.0"?>';
297        foreach ($disco_array as $key => $val) {
298            $disco .= $this->_arrayToNode($key,$val);
299        }
300        $this->disco = $disco;
301    }
302
303    function _generate_WSDL_XML()
304    {
305        $wsdl = '<?xml version="1.0"?>';
306        foreach ($this->_wsdl as $key => $val) {
307            $wsdl .= $this->_arrayToNode($key, $val);
308        }
309        $this->wsdl = $wsdl;
310    }
311
312    function _arrayToNode($node_name = '', $array)
313    {
314        $return = '';
315        if (is_array($array)) {
316            // we have a node if there's key 'attr'
317            if (array_key_exists('attr',$array)) {
318                $return .= "<$node_name";
319                if (is_array($array['attr'])) {
320                    foreach ($array['attr'] as $attr_name => $attr_value) {
321                        $return .= " $attr_name=\"$attr_value\"";
322                    }
323                }
324
325                // unset 'attr' and proceed other childs...
326                unset($array['attr']);
327
328                if (count($array) > 0) {
329                    $i = 0;
330                    foreach ($array as $child_node_name => $child_node_value) {
331                        $return .= $i == 0 ? ">\n" : '';
332                        $return .= $this->_arrayToNode($child_node_name,$child_node_value);
333                        $i++;
334                    }
335                    $return .= "</$node_name>\n";
336                } else {
337                    $return .= " />\n";
338                }
339            } else {
340                // we have no 'attr' key in array - so it's list of nodes with
341                // the same name ...
342                foreach ($array as $child_node_name => $child_node_value) {
343                    $return .= $this->_arrayToNode($node_name,$child_node_value);
344                }
345            }
346        } else {
347            // $array is not an array
348            if ($array !='') {
349                // and its not empty
350                $return .= "<$node_name>$array</$node_name>\n";
351            } else {
352                // and its empty...
353                $return .= "<$node_name />\n";
354            }
355        }
356        return $return;
357    }
358
359    function _getTypeNs($type)
360    {
361        preg_match_all("'\{(.*)\}'sm", $type, $m);
362        if (isset($m[1][0]) && $m[1][0] != '') {
363            if (!array_key_exists($m[1][0],$this->namespaces)) {
364                $ns_pref = 'ns' . count($this->namespaces);
365                $this->namespaces[$m[1][0]] = $ns_pref;
366                $this->_wsdl['definitions']['attr']['xmlns:' . $ns_pref] = $m[1][0];
367            }
368            $typens = $this->namespaces[$m[1][0]];
369            $type = ereg_replace($m[0][0],'',$type);
370        } else {
371            $typens = 'xsd';
372        }
373        return array($typens,$type);
374    }
375
376    function _ifComplexTypeExists($typesArray, $type_name)
377    {
378        if (is_array($typesArray)) {
379            foreach ($typesArray as $type_data) {
380                if ($type_data['attr']['name'] == $type_name) {
381                    return true;
382                }
383            }
384        }
385        return false;
386    }
387}
Note: See TracBrowser for help on using the repository browser.