Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 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 */
26
require_once 'SOAP/Base.php';
27
 
28
/**
29
 * @package SOAP
30
 */
31
class 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
}