Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * WsdlGenerator file.
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the BSD License.
7
 *
8
 * Copyright(c) 2005 by Marcus Nyeholt. All rights reserved.
9
 *
10
 * To contact the author write to {@link mailto:tanus@users.sourceforge.net Marcus Nyeholt}
11
 * This file is part of the PRADO framework from {@link http://www.xisc.com}
12
 *
13
 * @author Marcus Nyeholt		<tanus@users.sourceforge.net>
14
 * @version $Id: WsdlGenerator.php 2393 2008-03-07 17:12:19Z xue $
15
 * @package System.Web.Services.SOAP
16
 */
17
 
18
require_once(dirname(__FILE__).'/Wsdl.php');
19
require_once(dirname(__FILE__).'/WsdlMessage.php');
20
require_once(dirname(__FILE__).'/WsdlOperation.php');
21
 
22
/**
23
 * Generator for the wsdl.
24
 * Special thanks to Cristian Losada for implementing the Complex Types section of the WSDL.
25
 * @author 		Marcus Nyeholt		<tanus@users.sourceforge.net>
26
 * @author 		Cristian Losada		<cristian@teaxul.com>
27
 * @version 	$Revision$
28
 */
29
class WsdlGenerator
30
{
31
	/**
32
	 * The instance.
33
	 * var		WsdlGenerator
34
	 */
35
	private static $instance;
36
 
37
	/**
38
	 * The name of this service (the classname)
39
	 * @var 	string
40
	 */
41
	private $serviceName = '';
42
 
43
	/**
44
	 * The complex types to use in the wsdl
45
	 * @var 	Array
46
	 */
47
	private $types = array();
48
 
49
	/**
50
	 * The operations available in this wsdl
51
	 * @var 	ArrayObject
52
	 */
53
	private $operations;
54
 
55
	/**
56
	 * The wsdl object.
57
	 * @var 	object
58
	 */
59
	private $wsdlDocument;
60
 
61
	/**
62
	 * The actual wsdl string
63
	 * @var 	string
64
	 */
65
	private $wsdl = '';
66
 
67
	/**
68
	 * The singleton instance for the generator
69
	 */
70
	public static function getInstance()
71
	{
72
		if (is_null(self::$instance)) {
73
			self::$instance = new WsdlGenerator();
74
		}
75
		return self::$instance;
76
	}
77
 
78
	/**
79
	 * Get the Wsdl generated
80
	 * @return 	string		The Wsdl for this wsdl
81
	 */
82
	public function getWsdl()
83
	{
84
		return $this->wsdl;
85
	}
86
 
87
	/**
88
	 * Generates WSDL for a passed in class, and saves it in the current object. The
89
	 * WSDL can then be retrieved by calling
90
	 * @param 	string		$className		The name of the class to generate for
91
	 * @param 	string		$serviceUri		The URI of the service that handles this WSDL
92
	 * @param string $encoding character encoding.
93
	 * @return 	void
94
	 */
95
	public function generateWsdl($className, $serviceUri='',$encoding='')
96
	{
97
		$this->wsdlDocument = new Wsdl($className, $serviceUri, $encoding);
98
 
99
		$classReflect = new ReflectionClass($className);
100
		$methods = $classReflect->getMethods();
101
 
102
		foreach ($methods as $method) {
103
			// Only process public methods
104
			if ($method->isPublic()) {
105
				$this->processMethod($method);
106
			}
107
		}
108
 
109
		foreach($this->types as $type => $elements) {
110
			$this->wsdlDocument->addComplexType($type, $elements);
111
		}
112
 
113
		$this->wsdl = $this->wsdlDocument->getWsdl();
114
	}
115
 
116
	/**
117
	 * Static method that generates and outputs the generated wsdl
118
	 * @param 		string		$className		The name of the class to export
119
	 * @param 		string		$serviceUri		The URI of the service that handles this WSDL
120
	 * @param string $encoding character encoding.
121
	 */
122
	public static function generate($className, $serviceUri='', $encoding='')
123
	{
124
		$generator = WsdlGenerator::getInstance();
125
		$generator->generateWsdl($className, $serviceUri,$encoding);
126
		//header('Content-type: text/xml');
127
		return $generator->getWsdl();
128
		//exit();
129
 
130
	}
131
 
132
	/**
133
	 * Process a method found in the passed in class.
134
	 * @param 		ReflectionMethod		$method		The method to process
135
	 */
136
	protected function processMethod(ReflectionMethod $method)
137
	{
138
		$comment = $method->getDocComment();
139
		if (strpos($comment, '@soapmethod') === false) {
140
			return;
141
		}
142
		$comment = preg_replace("/(^[\\s]*\\/\\*\\*)
143
                                 |(^[\\s]\\*\\/)
144
                                 |(^[\\s]*\\*?\\s)
145
                                 |(^[\\s]*)
146
                                 |(^[\\t]*)/ixm", "", $comment);
147
 
148
	    $comment = str_replace("\r", "", $comment);
149
	    $comment = preg_replace("/([\\t])+/", "\t", $comment);
150
	    $commentLines = explode("\n", $comment);
151
 
152
		$methodDoc = '';
153
		$params = array();
154
		$return = array();
155
		$gotDesc = false;
156
		$gotParams = false;
157
 
158
		foreach ($commentLines as $line) {
159
			if ($line == '') continue;
160
			if ($line{0} == '@') {
161
				$gotDesc = true;
162
				if (preg_match('/^@param\s+([\w\[\]()]+)\s+\$([\w()]+)\s*(.*)/i', $line, $match)) {
163
					$param = array();
164
					$param['type'] = $this->convertType($match[1]);
165
					$param['name'] = $match[2];
166
					$param['desc'] = $match[3];
167
					$params[] = $param;
168
				}
169
				else if (preg_match('/^@return\s+([\w\[\]()]+)\s*(.*)/i', $line, $match)) {
170
					$gotParams = true;
171
					$return['type'] = $this->convertType($match[1]);
172
					$return['desc'] = $match[2];
173
					$return['name'] = 'return';
174
				}
175
			}
176
			else {
177
				if (!$gotDesc) {
178
					$methodDoc .= trim($line);
179
				}
180
				else if (!$gotParams) {
181
					$params[count($params)-1]['desc'] .= trim($line);
182
				}
183
				else {
184
					if ($line == '*/') continue;
185
					$return['desc'] .= trim($line);
186
				}
187
			}
188
		}
189
 
190
		$methodName = $method->getName();
191
		$operation = new WsdlOperation($methodName, $methodDoc);
192
 
193
		$operation->setInputMessage(new WsdlMessage($methodName.'Request', $params));
194
		$operation->setOutputMessage(new WsdlMessage($methodName.'Response', array($return)));
195
 
196
		$this->wsdlDocument->addOperation($operation);
197
 
198
	}
199
 
200
	/**
201
	 * Converts from a PHP type into a WSDL type. This is borrowed from
202
	 * Cerebral Cortex (let me know and I'll remove asap).
203
	 *
204
	 * TODO: date and dateTime
205
	 * @param 		string		$type		The php type to convert
206
	 * @return 		string					The XSD type.
207
	 */
208
	private function convertType($type)
209
	{
210
		 switch ($type) {
211
             case 'string':
212
             case 'str':
213
                 return 'xsd:string';
214
                 break;
215
             case 'int':
216
             case 'integer':
217
                 return 'xsd:int';
218
                 break;
219
             case 'float':
220
             case 'double':
221
                 return 'xsd:float';
222
                 break;
223
             case 'boolean':
224
             case 'bool':
225
                 return 'xsd:boolean';
226
                 break;
227
             case 'date':
228
                 return 'xsd:date';
229
                 break;
230
             case 'time':
231
                 return 'xsd:time';
232
                 break;
233
             case 'dateTime':
234
                 return 'xsd:dateTime';
235
                 break;
236
             case 'array':
237
                 return 'soap-enc:Array';
238
                 break;
239
             case 'object':
240
                 return 'xsd:struct';
241
                 break;
242
             case 'mixed':
243
                 return 'xsd:anyType';
244
                 break;
245
             case 'void':
246
                 return '';
247
             default:
248
             	 if(strpos($type, '[]'))  // if it is an array
249
             	 {
250
             	 	$className = substr($type, 0, strlen($type) - 2);
251
             	 	$type = $className . 'Array';
252
             	 	$this->types[$type] = '';
253
             	 	$this->convertType($className);
254
             	 }
255
             	 else
256
             	 {
257
             	 	 if(!isset($this->types[$type]))
258
	             		$this->extractClassProperties($type);
259
             	 }
260
                 return 'tns:' . $type;
261
         }
262
	}
263
 
264
	/**
265
	 * Extract the type and the name of all properties of the $className class and saves it in the $types array
266
	 * This method extract properties from PHPDoc formatted comments for variables. Unfortunately the reflectionproperty
267
	 * class doesn't have a getDocComment method to extract comments about it, so we have to extract the information
268
	 * about the variables manually. Thanks heaps to Cristian Losada for implementing this.
269
	 * @param string $className The name of the class
270
	 */
271
	private function extractClassProperties($className)
272
	{
273
		/**
274
		 * modified by Qiang Xue, Jan. 2, 2007
275
		 * Using Reflection's DocComment to obtain property definitions
276
		 * DocComment is available since PHP 5.1
277
		 */
278
		$reflection = new ReflectionClass($className);
279
		$properties = $reflection->getProperties();
280
		foreach($properties as $property)
281
		{
282
			$comment = $property->getDocComment();
283
			if(strpos($comment, '@soapproperty') !== false)
284
			{
285
				if (preg_match('/@var\s+(\w+(\[\])?)\s+\$(\w+)/mi', $comment, $match)) {
286
					$param = array();
287
					$param['type'] = $this->convertType($match[1]);
288
					$param['name'] = $match[3];
289
					$this->types[$className][] = $param;
290
				}
291
			}
292
		}
293
	}
294
}
295
?>