File indexing completed on 2024-12-22 05:37:07
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Soap 0017 * @subpackage AutoDiscover 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 /** 0024 * @see Zend_Server_Interface 0025 */ 0026 // require_once 'Zend/Server/Interface.php'; 0027 /** 0028 * @see Zend_Soap_Wsdl 0029 */ 0030 // require_once 'Zend/Soap/Wsdl.php'; 0031 /** 0032 * @see Zend_Server_Reflection 0033 */ 0034 // require_once 'Zend/Server/Reflection.php'; 0035 /** 0036 * @see Zend_Server_Abstract 0037 */ 0038 // require_once 'Zend/Server/Abstract.php'; 0039 /** 0040 * @see Zend_Uri 0041 */ 0042 // require_once 'Zend/Uri.php'; 0043 0044 /** 0045 * Zend_Soap_AutoDiscover 0046 * 0047 * @category Zend 0048 * @package Zend_Soap 0049 * @subpackage AutoDiscover 0050 */ 0051 class Zend_Soap_AutoDiscover implements Zend_Server_Interface 0052 { 0053 /** 0054 * @var Zend_Soap_Wsdl 0055 */ 0056 protected $_wsdl = null; 0057 0058 /** 0059 * @var Zend_Server_Reflection 0060 */ 0061 protected $_reflection = null; 0062 0063 /** 0064 * @var array 0065 */ 0066 protected $_functions = array(); 0067 0068 /** 0069 * @var boolean 0070 */ 0071 protected $_strategy; 0072 0073 /** 0074 * Url where the WSDL file will be available at. 0075 * 0076 * @var WSDL Uri 0077 */ 0078 protected $_uri; 0079 0080 /** 0081 * soap:body operation style options 0082 * 0083 * @var array 0084 */ 0085 protected $_operationBodyStyle = array('use' => 'encoded', 'encodingStyle' => "http://schemas.xmlsoap.org/soap/encoding/"); 0086 0087 /** 0088 * soap:operation style 0089 * 0090 * @var array 0091 */ 0092 protected $_bindingStyle = array('style' => 'rpc', 'transport' => 'http://schemas.xmlsoap.org/soap/http'); 0093 0094 /** 0095 * Name of the class to handle the WSDL creation. 0096 * 0097 * @var string 0098 */ 0099 protected $_wsdlClass = 'Zend_Soap_Wsdl'; 0100 0101 /** 0102 * Constructor 0103 * 0104 * @param boolean|string|Zend_Soap_Wsdl_Strategy_Interface $strategy 0105 * @param string|Zend_Uri $uri 0106 * @param string $wsdlClass 0107 */ 0108 public function __construct($strategy = true, $uri=null, $wsdlClass=null) 0109 { 0110 $this->_reflection = new Zend_Server_Reflection(); 0111 $this->setComplexTypeStrategy($strategy); 0112 0113 if($uri !== null) { 0114 $this->setUri($uri); 0115 } 0116 0117 if($wsdlClass !== null) { 0118 $this->setWsdlClass($wsdlClass); 0119 } 0120 } 0121 0122 /** 0123 * Set the location at which the WSDL file will be availabe. 0124 * 0125 * @see Zend_Soap_Exception 0126 * @param Zend_Uri|string $uri 0127 * @return Zend_Soap_AutoDiscover 0128 * @throws Zend_Soap_AutoDiscover_Exception 0129 */ 0130 public function setUri($uri) 0131 { 0132 if (!is_string($uri) && !($uri instanceof Zend_Uri)) { 0133 // require_once "Zend/Soap/AutoDiscover/Exception.php"; 0134 throw new Zend_Soap_AutoDiscover_Exception("No uri given to Zend_Soap_AutoDiscover::setUri as string or Zend_Uri instance."); 0135 } 0136 $this->_uri = $uri; 0137 0138 // change uri in WSDL file also if existant 0139 if ($this->_wsdl instanceof Zend_Soap_Wsdl) { 0140 $this->_wsdl->setUri($uri); 0141 } 0142 0143 return $this; 0144 } 0145 0146 /** 0147 * Return the current Uri that the SOAP WSDL Service will be located at. 0148 * 0149 * @return Zend_Uri 0150 */ 0151 public function getUri() 0152 { 0153 if($this->_uri !== null) { 0154 $uri = $this->_uri; 0155 } else { 0156 $schema = $this->getSchema(); 0157 $host = $this->getHostName(); 0158 $scriptName = $this->getRequestUriWithoutParameters(); 0159 $uri = Zend_Uri::factory($schema . '://' . $host . $scriptName); 0160 $this->setUri($uri); 0161 } 0162 return $uri; 0163 } 0164 0165 /** 0166 * Set the name of the WSDL handling class. 0167 * 0168 * @see Zend_Soap_Exception 0169 * @see Zend_Soap_Exception 0170 * @param string $wsdlClass 0171 * @return Zend_Soap_AutoDiscover 0172 * @throws Zend_Soap_AutoDiscover_Exception 0173 */ 0174 public function setWsdlClass($wsdlClass) 0175 { 0176 if (!is_string($wsdlClass) && !is_subclass_of($wsdlClass, 'Zend_Soap_Wsdl')) { 0177 // require_once "Zend/Soap/AutoDiscover/Exception.php"; 0178 throw new Zend_Soap_AutoDiscover_Exception("No Zend_Soap_Wsdl subclass given to Zend_Soap_AutoDiscover::setWsdlClass as string."); 0179 } 0180 $this->_wsdlClass = $wsdlClass; 0181 0182 return $this; 0183 } 0184 0185 /** 0186 * Return the name of the WSDL handling class. 0187 * 0188 * @return string 0189 */ 0190 public function getWsdlClass() 0191 { 0192 return $this->_wsdlClass; 0193 } 0194 0195 /** 0196 * Set options for all the binding operations soap:body elements. 0197 * 0198 * By default the options are set to 'use' => 'encoded' and 0199 * 'encodingStyle' => "http://schemas.xmlsoap.org/soap/encoding/". 0200 * 0201 * @see Zend_Soap_AutoDiscover_Exception 0202 * @param array $operationStyle 0203 * @return Zend_Soap_AutoDiscover 0204 * @throws Zend_Soap_AutoDiscover_Exception 0205 */ 0206 public function setOperationBodyStyle(array $operationStyle=array()) 0207 { 0208 if(!isset($operationStyle['use'])) { 0209 // require_once "Zend/Soap/AutoDiscover/Exception.php"; 0210 throw new Zend_Soap_AutoDiscover_Exception("Key 'use' is required in Operation soap:body style."); 0211 } 0212 $this->_operationBodyStyle = $operationStyle; 0213 return $this; 0214 } 0215 0216 /** 0217 * Set Binding soap:binding style. 0218 * 0219 * By default 'style' is 'rpc' and 'transport' is 'http://schemas.xmlsoap.org/soap/http'. 0220 * 0221 * @param array $bindingStyle 0222 * @return Zend_Soap_AutoDiscover 0223 */ 0224 public function setBindingStyle(array $bindingStyle=array()) 0225 { 0226 if(isset($bindingStyle['style'])) { 0227 $this->_bindingStyle['style'] = $bindingStyle['style']; 0228 } 0229 if(isset($bindingStyle['transport'])) { 0230 $this->_bindingStyle['transport'] = $bindingStyle['transport']; 0231 } 0232 return $this; 0233 } 0234 0235 /** 0236 * Detect and returns the current HTTP/HTTPS Schema 0237 * 0238 * @return string 0239 */ 0240 protected function getSchema() 0241 { 0242 $schema = "http"; 0243 if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') { 0244 $schema = 'https'; 0245 } 0246 return $schema; 0247 } 0248 0249 /** 0250 * Detect and return the current hostname 0251 * 0252 * @return string 0253 */ 0254 protected function getHostName() 0255 { 0256 if(isset($_SERVER['HTTP_HOST'])) { 0257 $host = $_SERVER['HTTP_HOST']; 0258 } else { 0259 $host = $_SERVER['SERVER_NAME']; 0260 } 0261 return $host; 0262 } 0263 0264 /** 0265 * Detect and return the current script name without parameters 0266 * 0267 * @return string 0268 */ 0269 protected function getRequestUriWithoutParameters() 0270 { 0271 if (isset($_SERVER['HTTP_X_ORIGINAL_URL'])) { // IIS with Microsoft Rewrite Module 0272 $requestUri = $_SERVER['HTTP_X_ORIGINAL_URL']; 0273 } elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // check this first so IIS will catch 0274 $requestUri = $_SERVER['HTTP_X_REWRITE_URL']; 0275 } elseif (isset($_SERVER['REQUEST_URI'])) { 0276 $requestUri = $_SERVER['REQUEST_URI']; 0277 } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI 0278 $requestUri = $_SERVER['ORIG_PATH_INFO']; 0279 } else { 0280 $requestUri = $_SERVER['SCRIPT_NAME']; 0281 } 0282 if( ($pos = strpos($requestUri, "?")) !== false) { 0283 $requestUri = substr($requestUri, 0, $pos); 0284 } 0285 0286 return $requestUri; 0287 } 0288 0289 /** 0290 * Set the strategy that handles functions and classes that are added AFTER this call. 0291 * 0292 * @param boolean|string|Zend_Soap_Wsdl_Strategy_Interface $strategy 0293 * @return Zend_Soap_AutoDiscover 0294 */ 0295 public function setComplexTypeStrategy($strategy) 0296 { 0297 $this->_strategy = $strategy; 0298 if($this->_wsdl instanceof Zend_Soap_Wsdl) { 0299 $this->_wsdl->setComplexTypeStrategy($strategy); 0300 } 0301 0302 return $this; 0303 } 0304 0305 /** 0306 * Set the Class the SOAP server will use 0307 * 0308 * @param string $class Class Name 0309 * @param string $namespace Class Namspace - Not Used 0310 * @param array $argv Arguments to instantiate the class - Not Used 0311 * @return Zend_Soap_AutoDiscover 0312 */ 0313 public function setClass($class, $namespace = '', $argv = null) 0314 { 0315 $uri = $this->getUri(); 0316 0317 $wsdl = new $this->_wsdlClass($class, $uri, $this->_strategy); 0318 0319 // The wsdl:types element must precede all other elements (WS-I Basic Profile 1.1 R2023) 0320 $wsdl->addSchemaTypeSection(); 0321 0322 $port = $wsdl->addPortType($class . 'Port'); 0323 $binding = $wsdl->addBinding($class . 'Binding', 'tns:' .$class. 'Port'); 0324 0325 $wsdl->addSoapBinding($binding, $this->_bindingStyle['style'], $this->_bindingStyle['transport']); 0326 $wsdl->addService($class . 'Service', $class . 'Port', 'tns:' . $class . 'Binding', $uri); 0327 foreach ($this->_reflection->reflectClass($class)->getMethods() as $method) { 0328 $this->_addFunctionToWsdl($method, $wsdl, $port, $binding); 0329 } 0330 $this->_wsdl = $wsdl; 0331 0332 return $this; 0333 } 0334 0335 /** 0336 * Add a Single or Multiple Functions to the WSDL 0337 * 0338 * @param string $function Function Name 0339 * @param string $namespace Function namespace - Not Used 0340 * @return Zend_Soap_AutoDiscover 0341 */ 0342 public function addFunction($function, $namespace = '') 0343 { 0344 static $port; 0345 static $operation; 0346 static $binding; 0347 0348 if (!is_array($function)) { 0349 $function = (array) $function; 0350 } 0351 0352 $uri = $this->getUri(); 0353 0354 if (!($this->_wsdl instanceof Zend_Soap_Wsdl)) { 0355 $parts = explode('.', basename($_SERVER['SCRIPT_NAME'])); 0356 $name = $parts[0]; 0357 $wsdl = new Zend_Soap_Wsdl($name, $uri, $this->_strategy); 0358 0359 // The wsdl:types element must precede all other elements (WS-I Basic Profile 1.1 R2023) 0360 $wsdl->addSchemaTypeSection(); 0361 0362 $port = $wsdl->addPortType($name . 'Port'); 0363 $binding = $wsdl->addBinding($name . 'Binding', 'tns:' .$name. 'Port'); 0364 0365 $wsdl->addSoapBinding($binding, $this->_bindingStyle['style'], $this->_bindingStyle['transport']); 0366 $wsdl->addService($name . 'Service', $name . 'Port', 'tns:' . $name . 'Binding', $uri); 0367 } else { 0368 $wsdl = $this->_wsdl; 0369 } 0370 0371 foreach ($function as $func) { 0372 $method = $this->_reflection->reflectFunction($func); 0373 $this->_addFunctionToWsdl($method, $wsdl, $port, $binding); 0374 } 0375 $this->_wsdl = $wsdl; 0376 0377 return $this; 0378 } 0379 0380 /** 0381 * Add a function to the WSDL document. 0382 * 0383 * @param Zend_Server_Reflection_Function_Abstract $function function to add 0384 * @param Zend_Soap_Wsdl $wsdl WSDL document 0385 * @param object $port wsdl:portType 0386 * @param object $binding wsdl:binding 0387 * @return void 0388 */ 0389 protected function _addFunctionToWsdl($function, $wsdl, $port, $binding) 0390 { 0391 $uri = $this->getUri(); 0392 0393 // We only support one prototype: the one with the maximum number of arguments 0394 $prototype = null; 0395 $maxNumArgumentsOfPrototype = -1; 0396 foreach ($function->getPrototypes() as $tmpPrototype) { 0397 $numParams = count($tmpPrototype->getParameters()); 0398 if ($numParams > $maxNumArgumentsOfPrototype) { 0399 $maxNumArgumentsOfPrototype = $numParams; 0400 $prototype = $tmpPrototype; 0401 } 0402 } 0403 if ($prototype === null) { 0404 // require_once "Zend/Soap/AutoDiscover/Exception.php"; 0405 throw new Zend_Soap_AutoDiscover_Exception("No prototypes could be found for the '" . $function->getName() . "' function"); 0406 } 0407 0408 // Add the input message (parameters) 0409 $args = array(); 0410 if ($this->_bindingStyle['style'] == 'document') { 0411 // Document style: wrap all parameters in a sequence element 0412 $sequence = array(); 0413 foreach ($prototype->getParameters() as $param) { 0414 $sequenceElement = array( 0415 'name' => $param->getName(), 0416 'type' => $wsdl->getType($param->getType()) 0417 ); 0418 if ($param->isOptional()) { 0419 $sequenceElement['nillable'] = 'true'; 0420 } 0421 $sequence[] = $sequenceElement; 0422 } 0423 $element = array( 0424 'name' => $function->getName(), 0425 'sequence' => $sequence 0426 ); 0427 // Add the wrapper element part, which must be named 'parameters' 0428 $args['parameters'] = array('element' => $wsdl->addElement($element)); 0429 } else { 0430 // RPC style: add each parameter as a typed part 0431 foreach ($prototype->getParameters() as $param) { 0432 $args[$param->getName()] = array('type' => $wsdl->getType($param->getType())); 0433 } 0434 } 0435 $wsdl->addMessage($function->getName() . 'In', $args); 0436 0437 $isOneWayMessage = false; 0438 if($prototype->getReturnType() == "void") { 0439 $isOneWayMessage = true; 0440 } 0441 0442 if($isOneWayMessage == false) { 0443 // Add the output message (return value) 0444 $args = array(); 0445 if ($this->_bindingStyle['style'] == 'document') { 0446 // Document style: wrap the return value in a sequence element 0447 $sequence = array(); 0448 if ($prototype->getReturnType() != "void") { 0449 $sequence[] = array( 0450 'name' => $function->getName() . 'Result', 0451 'type' => $wsdl->getType($prototype->getReturnType()) 0452 ); 0453 } 0454 $element = array( 0455 'name' => $function->getName() . 'Response', 0456 'sequence' => $sequence 0457 ); 0458 // Add the wrapper element part, which must be named 'parameters' 0459 $args['parameters'] = array('element' => $wsdl->addElement($element)); 0460 } else if ($prototype->getReturnType() != "void") { 0461 // RPC style: add the return value as a typed part 0462 $args['return'] = array('type' => $wsdl->getType($prototype->getReturnType())); 0463 } 0464 $wsdl->addMessage($function->getName() . 'Out', $args); 0465 } 0466 0467 // Add the portType operation 0468 if($isOneWayMessage == false) { 0469 $portOperation = $wsdl->addPortOperation($port, $function->getName(), 'tns:' . $function->getName() . 'In', 'tns:' . $function->getName() . 'Out'); 0470 } else { 0471 $portOperation = $wsdl->addPortOperation($port, $function->getName(), 'tns:' . $function->getName() . 'In', false); 0472 } 0473 $desc = $function->getDescription(); 0474 if (strlen($desc) > 0) { 0475 $wsdl->addDocumentation($portOperation, $desc); 0476 } 0477 0478 // When using the RPC style, make sure the operation style includes a 'namespace' attribute (WS-I Basic Profile 1.1 R2717) 0479 if ($this->_bindingStyle['style'] == 'rpc' && !isset($this->_operationBodyStyle['namespace'])) { 0480 $this->_operationBodyStyle['namespace'] = ''.$uri; 0481 } 0482 0483 // Add the binding operation 0484 if($isOneWayMessage == false) { 0485 $operation = $wsdl->addBindingOperation($binding, $function->getName(), $this->_operationBodyStyle, $this->_operationBodyStyle); 0486 } else { 0487 $operation = $wsdl->addBindingOperation($binding, $function->getName(), $this->_operationBodyStyle); 0488 } 0489 $wsdl->addSoapOperation($operation, $uri . '#' .$function->getName()); 0490 0491 // Add the function name to the list 0492 $this->_functions[] = $function->getName(); 0493 } 0494 0495 /** 0496 * Action to take when an error occurs 0497 * 0498 * @param string $fault 0499 * @param string|int $code 0500 * @throws Zend_Soap_AutoDiscover_Exception 0501 */ 0502 public function fault($fault = null, $code = null) 0503 { 0504 // require_once "Zend/Soap/AutoDiscover/Exception.php"; 0505 throw new Zend_Soap_AutoDiscover_Exception("Function has no use in AutoDiscover."); 0506 } 0507 0508 /** 0509 * Handle the Request 0510 * 0511 * @param string $request A non-standard request - Not Used 0512 */ 0513 public function handle($request = false) 0514 { 0515 if (!headers_sent()) { 0516 header('Content-Type: text/xml'); 0517 } 0518 $this->_wsdl->dump(); 0519 } 0520 0521 /** 0522 * Proxy to WSDL dump function 0523 * 0524 * @param string $filename 0525 * @return boolean 0526 * @throws Zend_Soap_AutoDiscover_Exception 0527 */ 0528 public function dump($filename) 0529 { 0530 if($this->_wsdl !== null) { 0531 return $this->_wsdl->dump($filename); 0532 } else { 0533 /** 0534 * @see Zend_Soap_AutoDiscover_Exception 0535 */ 0536 // require_once "Zend/Soap/AutoDiscover/Exception.php"; 0537 throw new Zend_Soap_AutoDiscover_Exception("Cannot dump autodiscovered contents, WSDL file has not been generated yet."); 0538 } 0539 } 0540 0541 /** 0542 * Proxy to WSDL toXml() function 0543 * 0544 * @return string 0545 * @throws Zend_Soap_AutoDiscover_Exception 0546 */ 0547 public function toXml() 0548 { 0549 if($this->_wsdl !== null) { 0550 return $this->_wsdl->toXml(); 0551 } else { 0552 /** 0553 * @see Zend_Soap_AutoDiscover_Exception 0554 */ 0555 // require_once "Zend/Soap/AutoDiscover/Exception.php"; 0556 throw new Zend_Soap_AutoDiscover_Exception("Cannot return autodiscovered contents, WSDL file has not been generated yet."); 0557 } 0558 } 0559 0560 /** 0561 * Return an array of functions in the WSDL 0562 * 0563 * @return array 0564 */ 0565 public function getFunctions() 0566 { 0567 return $this->_functions; 0568 } 0569 0570 /** 0571 * Load Functions 0572 * 0573 * @param unknown_type $definition 0574 * @throws Zend_Soap_AutoDiscover_Exception 0575 */ 0576 public function loadFunctions($definition) 0577 { 0578 // require_once "Zend/Soap/AutoDiscover/Exception.php"; 0579 throw new Zend_Soap_AutoDiscover_Exception("Function has no use in AutoDiscover."); 0580 } 0581 0582 /** 0583 * Set Persistance 0584 * 0585 * @param int $mode 0586 * @throws Zend_Soap_AutoDiscover_Exception 0587 */ 0588 public function setPersistence($mode) 0589 { 0590 // require_once "Zend/Soap/AutoDiscover/Exception.php"; 0591 throw new Zend_Soap_AutoDiscover_Exception("Function has no use in AutoDiscover."); 0592 } 0593 0594 /** 0595 * Returns an XSD Type for the given PHP type 0596 * 0597 * @param string $type PHP Type to get the XSD type for 0598 * @return string 0599 */ 0600 public function getType($type) 0601 { 0602 if (!($this->_wsdl instanceof Zend_Soap_Wsdl)) { 0603 /** @todo Exception throwing may be more correct */ 0604 0605 // WSDL is not defined yet, so we can't recognize type in context of current service 0606 return ''; 0607 } else { 0608 return $this->_wsdl->getType($type); 0609 } 0610 } 0611 }