added wsdl:include to WsdlDownloader (and also the wsdl:import,

xs:import)
This commit is contained in:
Andreas Schamberger 2011-11-20 18:13:42 +01:00
parent 7b1e2eef93
commit 7b4b832d61
6 changed files with 121 additions and 23 deletions

View File

@ -241,19 +241,17 @@ class SoapClient extends \SoapClient
*/
private function loadWsdl($wsdl, array $options)
{
// option to resolve xsd includes
$resolveXsdIncludes = true;
if (isset($options['resolve_xsd_includes']))
{
$resolveXsdIncludes = $options['resolve_xsd_includes'];
// option to resolve wsdl/xsd includes
$resolveRemoteIncludes = true;
if (isset($options['resolve_wsdl_remote_includes'])) {
$resolveRemoteIncludes = $options['resolve_wsdl_remote_includes'];
}
// option to enable cache
$wsdlCache = WSDL_CACHE_DISK;
if (isset($options['cache_wsdl']))
{
if (isset($options['cache_wsdl'])) {
$wsdlCache = $options['cache_wsdl'];
}
$wsdlDownloader = new WsdlDownloader($this->curl, $resolveXsdIncludes, $wsdlCache);
$wsdlDownloader = new WsdlDownloader($this->curl, $resolveRemoteIncludes, $wsdlCache);
try {
$cacheFileName = $wsdlDownloader->download($wsdl);
} catch (\RuntimeException $e) {

View File

@ -54,23 +54,23 @@ class WsdlDownloader
private $curl;
/**
* Resolve XSD includes.
* Resolve WSDl/XSD includes.
*
* @var boolean
*/
protected $resolveXsdIncludes = true;
protected $resolveRemoteIncludes = true;
/**
* Constructor.
*
* @param \BeSimple\SoapClient\Curl $curl Curl instance
* @param boolean $resolveXsdIncludes XSD include enabled?
* @param boolean $cacheWsdl Cache constant
* @param \BeSimple\SoapClient\Curl $curl Curl instance
* @param boolean $resolveRemoteIncludes WSDL/XSD include enabled?
* @param boolean $cacheWsdl Cache constant
*/
public function __construct(Curl $curl, $resolveXsdIncludes = true, $cacheWsdl = WSDL_CACHE_DISK)
public function __construct(Curl $curl, $resolveRemoteIncludes = true, $cacheWsdl = WSDL_CACHE_DISK)
{
$this->curl = $curl;
$this->resolveXsdIncludes = $resolveXsdIncludes;
$this->resolveRemoteIncludes = $resolveRemoteIncludes;
// get current WSDL caching config
$this->cacheEnabled = (bool)ini_get('soap.wsdl_cache_enabled');
if ($this->cacheEnabled === true
@ -96,7 +96,7 @@ class WsdlDownloader
// download and cache remote WSDL files or local ones where we want to
// resolve remote XSD includes
$isRemoteFile = $this->isRemoteFile($wsdl);
if ($isRemoteFile === true || $this->resolveXsdIncludes === true) {
if ($isRemoteFile === true || $this->resolveRemoteIncludes === true) {
$cacheFile = $this->cacheDir . DIRECTORY_SEPARATOR . 'wsdl_' . md5($wsdl) . '.cache';
if ($this->cacheEnabled === false
|| !file_exists($cacheFile)
@ -107,8 +107,8 @@ class WsdlDownloader
// get content
if ($responseSuccessfull === true) {
$response = $this->curl->getResponseBody();
if ($this->resolveXsdIncludes === true) {
$this->resolveXsdIncludes($response, $cacheFile, $wsdl);
if ($this->resolveRemoteIncludes === true) {
$this->resolveRemoteIncludes($response, $cacheFile, $wsdl);
} else {
file_put_contents($cacheFile, $response);
}
@ -117,7 +117,7 @@ class WsdlDownloader
}
} elseif (file_exists($wsdl)) {
$response = file_get_contents($wsdl);
$this->resolveXsdIncludes($response, $cacheFile);
$this->resolveRemoteIncludes($response, $cacheFile);
} else {
throw new \ErrorException("SOAP-ERROR: Parsing WSDL: Couldn't load from '" . $wsdl ."'");
}
@ -149,20 +149,38 @@ class WsdlDownloader
}
/**
* Resolves remote XSD includes within the WSDL files.
* Resolves remote WSDL/XSD includes within the WSDL files.
*
* @param string $xml
* @param string $cacheFile
* @param unknown_type $parentIsRemote
* @return string
*/
private function resolveXsdIncludes($xml, $cacheFile, $parentFile = null)
private function resolveRemoteIncludes($xml, $cacheFile, $parentFile = null)
{
$doc = new \DOMDocument();
$doc->loadXML($xml);
$xpath = new \DOMXPath($doc);
$xpath->registerNamespace(Helper::PFX_XML_SCHEMA, Helper::NS_XML_SCHEMA);
$query = './/' . Helper::PFX_XML_SCHEMA . ':include';
$xpath->registerNamespace('wsdl', 'http://schemas.xmlsoap.org/wsdl/'); // TODO add to Helper
// WSDL include/import
$query = './/wsdl:include | .//wsdl:import';
$nodes = $xpath->query($query);
if ($nodes->length > 0) {
foreach ($nodes as $node) {
$location = $node->getAttribute('location');
if ($this->isRemoteFile($location)) {
$location = $this->download($location);
$node->setAttribute('location', $location);
} elseif (!is_null($parentFile)) {
$location = $this->resolveRelativePathInUrl($parentFile, $location);
$location = $this->download($location);
$node->setAttribute('location', $location);
}
}
}
// XML schema include/import
$query = './/' . Helper::PFX_XML_SCHEMA . ':include | .//' . Helper::PFX_XML_SCHEMA . ':import';
$nodes = $xpath->query($query);
if ($nodes->length > 0) {
foreach ($nodes as $node) {

View File

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<wsdl:types xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://test.sample">
<xs:element name="note">
<xs:complexType>
<xs:sequence>
<xs:element name="to" type="xs:string"/>
<xs:element name="from" type="xs:string"/>
<xs:element name="heading" type="xs:string"/>
<xs:element name="body" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<wsdl:documentation>wsdlincludetest</wsdl:documentation>
<wsdl:include location="http://localhost:8000/wsdl_include.wsdl"/>
</wsdl:definitions>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<wsdl:documentation>wsdlincludetest</wsdl:documentation>
<wsdl:include location="../wsdl_include.wsdl"/>
</wsdl:definitions>

View File

@ -115,6 +115,63 @@ class WsdlDownloaderTest extends \PHPUnit_Framework_TestCase
$this->assertFalse($method->invoke($wd, '../dir/test.html'));
}
public function testResolveWsdlIncludes()
{
$this->startPhpWebserver();
$curl = new Curl();
$wd = new WsdlDownloader($curl);
$class = new \ReflectionClass($wd);
$method = $class->getMethod('resolveRemoteIncludes');
$method->setAccessible(true);
$cacheDir = ini_get('soap.wsdl_cache_dir');
if (!is_dir($cacheDir)) {
$cacheDir = sys_get_temp_dir();
$cacheDirForRegExp = preg_quote( $cacheDir );
}
$remoteUrlAbsolute = 'http://localhost:8000/wsdlinclude/wsdlinctest_absolute.xml';
$remoteUrlRelative = 'http://localhost:8000/wsdlinclude/wsdlinctest_relative.xml';
$tests = array(
'localWithAbsolutePath' => array(
'source' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/wsdlinclude/wsdlinctest_absolute.xml',
'cacheFile' => $cacheDir.'/cache_local_absolute.xml',
'remoteParentUrl' => null,
'assertRegExp' => '~.*'.$cacheDirForRegExp.'\\\wsdl_.*\.cache.*~',
),
'localWithRelativePath' => array(
'source' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/wsdlinclude/wsdlinctest_relative.xml',
'cacheFile' => $cacheDir.'/cache_local_relative.xml',
'remoteParentUrl' => null,
'assertRegExp' => '~.*\.\./wsdl_include\.wsdl.*~',
),
'remoteWithAbsolutePath' => array(
'source' => $remoteUrlAbsolute,
'cacheFile' => $cacheDir.'/cache_remote_absolute.xml',
'remoteParentUrl' => $remoteUrlAbsolute,
'assertRegExp' => '~.*'.$cacheDirForRegExp.'\\\wsdl_.*\.cache.*~',
),
'remoteWithAbsolutePath' => array(
'source' => $remoteUrlRelative,
'cacheFile' => $cacheDir.'/cache_remote_relative.xml',
'remoteParentUrl' => $remoteUrlRelative,
'assertRegExp' => '~.*'.$cacheDirForRegExp.'\\\wsdl_.*\.cache.*~',
),
);
foreach ($tests as $name => $values) {
$wsdl = file_get_contents( $values['source'] );
$method->invoke($wd, $wsdl, $values['cacheFile'],$values['remoteParentUrl']);
$result = file_get_contents($values['cacheFile']);
$this->assertRegExp($values['assertRegExp'],$result,$name);
unlink($values['cacheFile']);
}
$this->stopPhpWebserver();
}
public function testResolveXsdIncludes()
{
$this->startPhpWebserver();
@ -123,7 +180,7 @@ class WsdlDownloaderTest extends \PHPUnit_Framework_TestCase
$wd = new WsdlDownloader($curl);
$class = new \ReflectionClass($wd);
$method = $class->getMethod('resolveXsdIncludes');
$method = $class->getMethod('resolveRemoteIncludes');
$method->setAccessible(true);
$cacheDir = ini_get('soap.wsdl_cache_dir');