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