PageRenderTime 40ms CodeModel.GetById 2ms app.highlight 29ms RepoModel.GetById 1ms app.codeStats 0ms

/class.phpwsdlclient.php

http://php-wsdl-creator.googlecode.com/
PHP | 692 lines | 410 code | 18 blank | 264 comment | 59 complexity | 899e3aab9528f04b00e6e9449b1cbb58 MD5 | raw file
  1<?php
  2
  3/*
  4PhpWsdl - Generate WSDL from PHP
  5Copyright (C) 2011  Andreas Müller-Saala, wan24.de 
  6
  7This program is free software; you can redistribute it and/or modify it under 
  8the terms of the GNU General Public License as published by the Free Software 
  9Foundation; either version 3 of the License, or (at your option) any later 
 10version. 
 11
 12This program is distributed in the hope that it will be useful, but WITHOUT 
 13ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
 14FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 
 15
 16You should have received a copy of the GNU General Public License along with 
 17this program; if not, see <http://www.gnu.org/licenses/>.
 18*/
 19
 20if(basename($_SERVER['SCRIPT_FILENAME'])==basename(__FILE__))
 21	exit;
 22
 23// To use PhpWsdlClient, you need to load it seperatly from PhpWsdl. Or you 
 24// just load this class and let it autoload PhpWsdl
 25
 26require_once(dirname(__FILE__).'/class.phpwsdl.php');
 27
 28/**
 29 * A SOAP client class for PhpWsdl
 30 * 
 31 * @author Andreas Müller-Saala, wan24.de
 32 * @version 2.4
 33 */
 34class PhpWsdlClient{
 35	/**
 36	 * The version number
 37	 * 
 38	 * @var string
 39	 */
 40	public static $VERSION='2.4';
 41	/**
 42	 * Parse a method
 43	 * 1: Type
 44	 * 2: Method
 45	 * 3: Parameters
 46	 * 
 47	 * @var string
 48	 */
 49	public static $methodRx='/^([^\s]+)\s+([^\(]+)\(([^\)]+)?\).*$/';
 50	/**
 51	 * Parse a type
 52	 * 1: Type
 53	 * 2: Name
 54	 * 
 55	 * @var string
 56	 */
 57	public static $typeRx='/^([^\s]+)\s([^\[|\{|\s]+)([\[|\{|\s].*$)?/s';
 58	/**
 59	 * Parse an element
 60	 * 1: Type
 61	 * 2: Name
 62	 * 
 63	 * @var string
 64	 */
 65	public static $elementRx='/^\s*([^\s]+)\s+([^\s|;]+);.*$/';
 66	/**
 67	 * The WSDL URI
 68	 * 
 69	 * @var string
 70	 */
 71	public $WsdlUri;
 72	/**
 73	 * The PHP SoapClient object
 74	 * 
 75	 * @var SoapClient
 76	 */
 77	public $Client=null;
 78	/**
 79	 * SOAP call options
 80	 * 
 81	 * @var array
 82	 */
 83	public $Options;
 84	/**
 85	 * SOAP call request headers
 86	 * 
 87	 * @var array
 88	 */
 89	public $RequestHeaders;
 90	/**
 91	 * PHP SoapClient options array
 92	 * 
 93	 * @var array
 94	 */
 95	public $ClientOptions;
 96	/**
 97	 * The webservice name
 98	 * 
 99	 * @var string
100	 */
101	public $ServiceName=null;
102	/**
103	 * The SOAP endpoint
104	 * 
105	 * @var string
106	 */
107	public $EndPoint=null;
108	/**
109	 * The SOAP namespace
110	 * 
111	 * @var string
112	 */
113	public $NameSpace=null;
114	/**
115	 * A PhpWsdl object
116	 * 
117	 * @var PhpWsdl
118	 */
119	public $Server=null;
120	/**
121	 * The WSDL
122	 * 
123	 * @var string
124	 */
125	public $WSDL=null;
126	/**
127	 * A list of warnings
128	 * 
129	 * @var string[]
130	 */
131	public $Warnings=Array();
132	/**
133	 * The http Auth username for fetching the WSDL (and sending SOAP requests, if PhpWsdlClient->UseSoapHttpAuth is TRUE)
134	 * If you need a different login for SOAP requests, use the PhpWsdlClient->ClientOptions array for the SOAP request 
135	 * authentification values (login/password)
136	 * 
137	 * @var string
138	 */
139	public $HttpUser=null;
140	/**
141	 * The http Auth password
142	 * 
143	 * @var string
144	 */
145	public $HttpPassword=null;
146	/**
147	 * Use http Auth for SOAP requests, too? If FALSE, the login will only be used to fetch the WSDL from the given URI
148	 * 
149	 * @var boolean
150	 */
151	public $UseSoapHttpAuth=true;
152	/**
153	 * Enable debugging of the RAW request/response?
154	 * 
155	 * @var boolean
156	 */
157	public $Debugging=false;
158	/**
159	 * Encode parameters?
160	 * Note: This will only work if it's possible to build a PhpWsdl object from the target webservice WSDL
161	 * 
162	 * @var boolean
163	 */
164	public $EncodeParameters=false;
165	
166	/**
167	 * Constructor
168	 * 
169	 * @param string $wsdlUri The WSDL URI
170	 * @param array $options SOAP call options (default: NULL)
171	 * @param array $requestHeaders SOAP call request headers (default: NULL)
172	 */
173	public function PhpWsdlClient($wsdlUri,$options=null,$requestHeaders=null,$clientOptions=Array()){
174		PhpWsdl::Debug('New PhpWsdlClient '.$wsdlUri);
175		$this->WsdlUri=$wsdlUri;
176		$this->Options=$options;
177		$this->RequestHeaders=$requestHeaders;
178		$this->ClientOptions=array_merge(
179			Array(
180				'soap_version'	=>	SOAP_1_1|SOAP_1_2,
181				'encoding'		=>	'UTF-8',
182				'compression'	=>	SOAP_COMPRESSION_ACCEPT|SOAP_COMPRESSION_GZIP|9,
183				'connection_timeout'=>5
184			),
185			$clientOptions
186		);
187		$this->GetWsdlFromCache();
188	}
189	
190	/**
191	 * Fetch the WSDL (supports http Auth if CURL is enabled)
192	 * 
193	 * @param string $wsdlUri The WSDL URI or NULL to use the PhpWsdlClient->WaslUri property (default: NULL)
194	 * @param array $options The CURL options (default: array)
195	 * @return string The WSDL XML
196	 */
197	public function FetchWsdl($wsdlUri=null,$options=Array()){
198		if(is_null($wsdlUri))
199			$wsdlUri=$this->WsdlUri;
200		PhpWsdl::Debug('Fetch WSDL from '.$wsdlUri);
201		if(!is_file($wsdlUri)&&function_exists('curl_init')&&!is_null($this->HttpUser)){
202			// Fetch with http Auth (credits to faebu :)
203			PhpWsdl::Debug('Try CURL for http Auth');
204            $ch=curl_init();
205            $credit=$this->HttpUser.':'.$this->HttpPassword;
206            curl_setopt_array($ch,array_merge(
207            	Array(
208            		CURLOPT_URL				=>	$wsdlUri,
209            		CURLOPT_HTTPAUTH		=>	CURLAUTH_BASIC,
210            		CURLOPT_USERPWD			=>	$credit,
211            		CURLOPT_TIMEOUT			=>	10,
212            		CURLOPT_RETURNTRANSFER	=>	1
213            	),
214            	$options
215            ));
216            $wsdl=curl_exec($ch);
217            if($wsdl===false){
218            	PhpWsdl::Debug('WARNING: Could not fetch WSDL with CURL: '.curl_error($ch));
219            	@curl_close($ch);
220            }else{
221	            curl_close($ch);
222	            return $wsdl;
223            }
224		}
225		// Fetch without authentification
226		return file_get_contents($wsdlUri);
227	}
228	
229	/**
230	 * Do a SOAP request
231	 * 
232	 * @param string $method The method name
233	 * @param array $param The method parameters
234	 * @param array $options The call options (default: array)
235	 * @param array $requestHeaders The request headers (default: array)
236	 * @return mixed The server response
237	 */
238	public function DoRequest($method,$param,$options=Array(),$requestHeaders=Array()){
239		PhpWsdl::Debug('Sending request '.$method);
240		$options=array_merge($this->Options,$options);
241		$requestHeaders=array_merge($this->RequestHeaders,$requestHeaders);
242		$client=$this->GetClient();
243		if($this->EncodeParameters){
244			$server=$this->CreateServerFromWsdl();
245			$m=$server->GetMethod($method);
246			if(!is_null($m)){
247				PhpWsdl::Debug('Encode parameters');
248				$temp=Array();
249				$i=-1;
250				$len=sizeof($param);
251				while(++$i<$len)
252					$temp[]=PhpWsdl::DoEncoding($m->Param[$i]->Type,$param[$i],true,$server);
253				$param=$temp;
254			}else{
255				PhpWsdl::Debug('Can not encode parameters because the method was not found');
256			}
257		}
258		$res=$client->__soapCall($method,$param,$options,$requestHeaders);
259		if(is_soap_fault($res))
260			PhpWsdl::Debug('SOAP error #'.$res->faultcode.': '.$res->faultstring);
261		if($this->Debugging){
262			PhpWsdl::Debug('Parameters: '.print_r($param,true));
263			PhpWsdl::Debug('Options: '.print_r($options,true));
264			PhpWsdl::Debug('Headers: '.print_r($requestHeaders,true));
265			PhpWsdl::Debug('Result: '.print_r($res,true));
266			PhpWsdl::Debug('Request: '.$client->__getLastRequest());
267			PhpWsdl::Debug('Request headers: '.$client->__getLastRequestHeaders());
268			PhpWsdl::Debug('Response: '.$client->__getLastResponse());
269			PhpWsdl::Debug('Response headers: '.$client->__getLastResponseHeaders());
270		}
271		return $res;
272	}
273	
274	/**
275	 * Get the PHP SoapClient object
276	 * 
277	 * @param string $uri The WSDL URI or NULL to use the PhpWsdlClient->WsdlUri property (default: NULL)
278	 * @param array $options The additional PHP SoapClient options (default: array)
279	 * @return SoapClient The PHP SoapClient object
280	 */
281	public function GetClient($uri=null,$options=Array()){
282		if(is_null($this->Client)){
283			if(is_null($uri))
284				$uri=$this->WsdlUri;
285			PhpWsdl::Debug('Create a PHP SoapClient object in PhpWsdlClient from '.$uri);
286			if(!is_null(PhpWsdl::$CacheFolder)){
287				$wsdlFile=$this->GetCacheFileName($uri);
288				if(!is_null($this->GetWsdlFromCache($wsdlFile))){
289					PhpWsdl::Debug('Use cached WSDL from '.$wsdlFile);
290					$uri=$wsdlFile;
291				}else{
292					$wsdl=$this->FetchWsdl($uri);
293					if($wsdl!==false)
294						if($this->WriteWsdlToCache($wsdl,$uri,$wsdlFile,true)){
295							PhpWsdl::Debug('Using cached WSDL from '.$wsdlFile);
296							$uri=$wsdlFile;
297						}
298				}
299			}
300			if(
301				!is_null($this->HttpUser)&&
302				!isset($this->ClientOptions['login'])&&
303				!isset($options['login'])&&
304				$this->UseSoapHttpAuth
305			){
306				PhpWsdl::Debug('Using http Auth options');
307				$options['login']=$this->HttpUser;
308				$options['password']=$this->HttpPassword;
309			}
310			if($this->Debugging){
311				PhpWsdl::Debug('Debugging enabled');
312				$options['trace']=true;
313			}
314			$this->Client=new SoapClient($uri,array_merge(
315				$this->ClientOptions,
316				$options
317			));
318		}
319		return $this->Client;
320	}
321	
322	/**
323	 * Create/Fill a PhpWsdl object from WSDL
324	 * 
325	 * @param PhpWsdl An existing PhpWsdl object (default: NULL)
326	 * @return PhpWsdl The PhpWsdl object
327	 */
328	public function CreateServerFromWsdl($soap=null){
329		PhpWsdl::Debug('Create/Fill a PhpWsdl object from WSDL');
330		if(is_null($soap)){
331			if(!is_null($this->Server)){
332				PhpWsdl::Debug('Return existing object');
333				return $this->Server;
334			}
335			$soap=PhpWsdl::CreateInstance();
336		}else{
337			PhpWsdl::Debug('Use existing object');
338		}
339		if(!is_null($soap->GetWsdlFromCache())){
340			PhpWsdl::Debug('Server created from cached values');
341			if(is_null($this->Server))
342				$this->Server=$soap;
343			return $soap;
344		}
345		// Configuration
346		$soap->WsdlUri=$this->WsdlUri;
347		$this->ParseWsdl();
348		if(!is_null($this->ServiceName))
349			$soap->Name=$this->ServiceName;
350		if(!is_null($this->NameSpace))
351			$soap->NameSpace=$this->NameSpace;
352		$client=$this->GetClient();
353		// Methods
354		$fnc=$client->__getFunctions();
355		$i=-1;
356		$len=sizeof($fnc);
357		while(++$i<$len){
358			$f=$fnc[$i];
359			list(
360				$type,
361				$method,
362				$temp
363			)=explode("\t",preg_replace(self::$methodRx,"$1\t$2\t$3",$f));
364			PhpWsdl::Debug('Found method #'.$i.' '.$method);
365			if(!is_null($soap->GetMethod($method))){
366				$this->Warn('WARNING: Double method detected!');
367				continue;
368			}
369			$m=new PhpWsdlMethod($method);
370			$temp=explode(' ',$temp);
371			$pLen=sizeof($temp);
372			for($j=0;$j<$pLen-1;$j++){
373				list(
374					$t,
375					$n
376				)=Array(
377					$temp[$j],
378					$temp[$j+1]
379				);
380				PhpWsdl::Debug('Found parameter #'.$j.' '.$n.' type of '.$t);
381				$m->Param[]=new PhpWsdlParam(substr($n,1),$t);
382			}
383			if($type!='void')
384				$m->Return=new PhpWsdlParam('return',$type);
385			$soap->Methods[]=$m;
386		}
387		// Types
388		$typ=$client->__getTypes();
389		$i=-1;
390		$len=sizeof($typ);
391		while(++$i<$len){
392			$t=$typ[$i];
393			list(
394				$type,
395				$name
396			)=explode("\t",preg_replace(self::$typeRx,"$1\t$2",$t));
397			PhpWsdl::Debug('Found type #'.$i.' '.$name.' type of '.$type);
398			if(!is_null($soap->GetType($name))){
399				$this->Warn('WARNING: Double type detected!');
400				continue;
401			}
402			$arr=strpos($t,'[]')>-1;
403			$enum=!$arr&&strpos($t,'{')<0;
404			if($arr){
405				PhpWsdl::Debug('Array type');
406				$y=new PhpWsdlComplex($name);
407				$y->Type=$type;
408				$y->IsArray=true;
409				$soap->Types[]=$y;
410			}else if(!$enum&&$type=='struct'){
411				PhpWsdl::Debug('Complex type');
412				// Note: Inherited types are not supported since the PHP SoapClient object doesn't provide parent class 
413				// informations of a complex type, so PhpWsdlClient doesn't support inherited complex types at all!
414				$el=Array();
415				$temp=explode("\n",$t);
416				$j=0;
417				$eLen=sizeof($temp)-1;
418				while(++$j<$eLen){
419					list(
420						$p,
421						$n
422					)=explode("\t",preg_replace(self::$elementRx,"$1\t$2",$temp[$j]),2);
423					PhpWsdl::Debug('Found element #'.$j.' '.$n.' type of '.$p);
424					$el[]=new PhpWsdlElement($n,$p);
425				}
426				$y=new PhpWsdlComplex($name,$el);
427				$y->IsArray=false;
428				$soap->Types[]=$y;
429			}else if($enum){
430				PhpWsdl::Debug('Enumeration');
431				PhpWsdl::Debug('WARNING: Enumeration values are unknown!');
432				$y=new PhpWsdlEnum($name,$type);
433				$soap->Types[]=$y;
434			}else{
435				$this->Warn('WARNING: Could not create type '.$t);
436			}
437		}
438		if(is_null($this->Server))
439			$this->Server=$soap;
440		return $soap;
441	}
442	
443	/**
444	 * Parse the WSDL for webservice name, namespace and endpoint URI
445	 */
446	public function ParseWsdl(){
447		if(!is_null($this->ServiceName)&&!is_null($this->EndPoint)&&!is_null($this->NameSpace))
448			return;
449		PhpWsdl::Debug('Parse WSDL');
450		$wsdl=$this->WSDL;
451		$writeCache=false;
452		if(is_null($wsdl)){
453			$wsdl=$this->FetchWsdl();
454			if($wsdl===false)
455				throw(new Exception('Could not fetch WSDL'));
456			$writeCache=true;
457		}
458		$xml=new DOMDocument();
459		if(!$xml->loadXML($wsdl))
460			throw(new Exception('Invalid WSDL'));
461		$x=new DOMXPath($xml);
462		// Namespace
463		$temp=$x->query("/*[local-name()='definitions']/@targetNamespace");
464		if($temp->length>0){
465			$temp=$temp->item(0);
466			PhpWsdl::Debug('Namespace '.$temp->value);
467			$this->NameSpace=$temp->value;
468		}else{
469			$this->Warn('WARNING: No namespace found');
470		}
471		// Webservice name
472		$temp=$x->query("/*[local-name()='definitions']/*[local-name()='service']/@name");
473		if($temp->length>0){
474			$temp=$temp->item(0);
475			PhpWsdl::Debug('Name '.$temp->value);
476			$this->ServiceName=$temp->value;
477		}else{
478			$this->Warn('WARNING: No name found');
479		}
480		// Endpoint URI
481		$temp=$x->query("/*[local-name()='definitions']/*[local-name()='service']/*[local-name()='port']/*[local-name()='address']/@location");
482		if($temp->length>0){
483			$temp=$temp->item(0);
484			PhpWsdl::Debug('Endpoint '.$temp->value);
485			$this->EndPoint=$temp->value;
486		}else{
487			$this->Warn('WARNING: No endpoint found');
488		}
489		// Caching
490		$this->WriteWsdlToCache($wsdl,null,null,$writeCache);
491	}
492	
493	/**
494	 * Create a PHP SOAP client for this webservice
495	 * 
496	 * @param string $filename Name of the file to save the PHP code (default: NULL)
497	 * @param array $options The options array for the PhpWsdl->OutputPhp method (default: array)
498	 * @return string The UTF-8 encoded PHP code of the SOAP client
499	 */
500	public function CreatePhpSoapClient($filename=null,$options=Array()){
501		$php=$this->CreateServerFromWsdl()->OutputPhp(false,false,$options);
502		if(!is_null($filename))
503			if(file_put_contents($filename,$php)===false)
504				PhpWsdl::Debug('Could not write file '.$filename);
505		return $php;
506	}
507	
508	/**
509	 * Add a warning message
510	 * 
511	 * @param string $str The message
512	 */
513	private function Warn($str){
514		$this->Warnings[]=$str;
515		PhpWsdl::Debug($str);
516	}
517	
518	/**
519	 * Get the cache filename
520	 * 
521	 * @param string $wsdluri The WSDL URI or NULL to use the PhpWsdlAjax->WsdlUri property (default: NULL)
522	 * @return string The cache filename or NULL, if caching is disabled
523	 */
524	public function GetCacheFileName($wsdluri=null){
525		$data=Array(
526			'client'		=>	$this,
527			'wsdluri'		=>	$wsdluri,
528			'filename'		=>	(is_null(PhpWsdl::$CacheFolder))?null:PhpWsdl::$CacheFolder.'/client-'.sha1((is_null($wsdluri))?$this->WsdlUri:$wsdluri).'.wsdl'
529		);
530		PhpWsdl::CallHook(
531			'ClientCacheFileNameHook',
532			$data
533		);
534		return $data['filename'];
535	}
536
537	/**
538	 * Determine if the cache file exists
539	 * 
540	 * @param string $file The WSDL cache filename or NULL to use the default (default: NULL)
541	 * @return boolean Are the cache files present?
542	 */
543	public function CacheFileExists($file=null){
544		if(is_null($file))
545			$file=$this->GetCacheFileName();
546		PhpWsdl::Debug('Check cache file exists '.$file);
547		return file_exists($file)&&file_exists($file.'.cache');
548	}
549	
550	/**
551	 * Determine if the existing cache files are still valid
552	 * 
553	 * @param string $file The WSDL cache filename or NULL to use the default (default: NULL)
554	 * @return boolean Valid?
555	 */
556	public function IsCacheValid($file=null){
557		PhpWsdl::Debug('Check cache valid');
558		if(is_null($file))
559			$file=$this->GetCacheFileName();
560		if(!$this->CacheFileExists($file))
561			return false;
562		return PhpWsdl::$CacheTime<0||time()-file_get_contents($file.'.cache')<=PhpWsdl::$CacheTime;
563	}
564	
565	/**
566	 * Get the WSDL from the cache
567	 * 
568	 * @param string $file The WSDL cache filename or NULL to use the default (default: NULL)
569	 * @param boolean $force Force this even if the cache is timed out? (default: FALSE)
570	 * @param boolean $nounserialize Don't unserialize the PhpWsdl* objects? (default: FALSE)
571	 * @return string The cached WSDL
572	 */
573	public function GetWsdlFromCache($file=null,$force=false,$nounserialize=false){
574		PhpWsdl::Debug('Get WSDL from cache');
575		if(!is_null($this->WSDL))
576			return $this->WSDL;
577		if(is_null($file))
578			$file=$this->GetCacheFileName();
579		if(!$force){
580			if(!$this->IsCacheValid($file))
581				return null;
582		}else if(!$this->CacheFileExists($file)){
583			return null;
584		}
585		$this->WSDL=file_get_contents($file);
586		if(!$nounserialize){
587			PhpWsdl::Debug('Unserialize data');
588			$data=unserialize(file_get_contents($file.'.obj'));
589			$this->ServiceName=$data['servicename'];
590			$this->EndPoint=$data['endpoint'];
591			$this->NameSpace=$data['namespace'];
592			PhpWsdl::CallHook(
593				'ClientReadCacheHook',
594				Array(
595					'client'		=>	$this,
596					'data'			=>	&$data
597				)
598			);
599			if($data['version']!=self::$VERSION){
600				PhpWsdl::Debug('Could not use cache from version '.$data['version']);
601				$this->ServiceName=null;
602				$this->EndPoint=null;
603				$this->NameSpace=null;
604				$this->WSDL=null;
605				return null;
606			}
607		}
608		return $this->WSDL;
609	}
610	
611	/**
612	 * Write WSDL to cache
613	 * 
614	 * @param string $wsdl The UTF-8 encoded WSDL string (default: NULL)
615	 * @param string $wsdluri The SOAP WSDL URI or NULL to use the default (default: NULL)
616	 * @param string $file The target filename or NULL to use the default (default: NULL)
617	 * @param boolean $force Force refresh (default: FALSE)
618	 * @return boolean Succeed?
619	 */
620	public function WriteWsdlToCache($wsdl=null,$wsdluri=null,$file=null,$force=false){
621		PhpWsdl::Debug('Write WSDL to the cache');
622		if(is_null($wsdluri))
623			$wsdluri=$this->WsdlUri;
624		if($wsdluri==$this->WsdlUri&&!is_null($wsdl))
625			$this->WSDL=$wsdl;
626		if(is_null($wsdl)){
627			if(is_null($this->WSDL)){
628				PhpWsdl::Debug('No WSDL');
629				return false;// WSDL not defined
630			}
631			$wsdl=$this->WSDL;
632		}
633		if(is_null($file)){
634			$file=$this->GetCacheFileName($wsdluri);
635			if(is_null($file)){
636				PhpWsdl::Debug('No cache file');
637				return false;// No cache file
638			}
639		}
640		$temp=substr($file,0,1);
641		if($temp!='/'&&$temp!='.'){
642			if(is_null(PhpWsdl::$CacheFolder)){
643				PhpWsdl::Debug('No cache folder');
644				return false;// No cache folder
645			}
646			$file=PhpWsdl::$CacheFolder.'/'.$file;
647		}
648		if(!$force)
649			if($this->IsCacheValid($file)){
650				PhpWsdl::Debug('Cache is still valid');
651				return true;// Existing cache is still valid
652			}
653		PhpWsdl::Debug('Write to '.$file);
654		if(file_put_contents($file,$wsdl)===false){
655			PhpWsdl::Debug('Could not write to cache');
656			return false;// Error writing to cache
657		}
658		if(file_put_contents($file.'.cache',time())===false){
659			PhpWsdl::Debug('Could not write cache time file');
660			return false;// Error writing to cache
661		}
662		$data=Array(
663			'version'		=>	self::$VERSION,
664			'servicename'	=>	$this->ServiceName,
665			'endpoint'		=>	$this->EndPoint,
666			'namespace'		=>	$this->NameSpace
667		);
668		PhpWsdl::CallHook(
669			'ClientWriteCacheHook',
670			Array(
671				'client'		=>	$this,
672				'data'			=>	&$data
673			)
674		);
675		if(file_put_contents($file.'.obj',serialize($data))===false){
676			PhpWsdl::Debug('Could not write serialized cache');
677			return false;
678		}
679		return true;
680	}
681	
682	/**
683	 * SOAP method call proxy method
684	 * 
685	 * @param string $method The method name
686	 * @param array $param The method parameters
687	 * @return mixed The server response
688	 */
689	public function __call($method,$param){
690		return $this->DoRequest($method,$param);
691	}
692}