added WsdlHandler

This commit is contained in:
Andreas Schamberger 2011-11-01 10:45:02 +01:00
parent da344ad03f
commit 247f9ae5da
5 changed files with 446 additions and 0 deletions

View File

@ -0,0 +1,206 @@
<?php
/*
* This file is part of BeSimpleSoapCommon.
*
* (c) Christian Kerl <christian-kerl@web.de>
* (c) Francis Besset <francis.besset@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace BeSimple\SoapCommon;
/**
* This class loads the given WSDL file and allows to check MIME binding
* information.
*
* @author Andreas Schamberger <mail@andreass.net>
*/
class WsdlHandler
{
/**
* Binding type 'input' .
*/
const BINDING_OPERATION_INPUT = 'input';
/**
* Binding type 'output' .
*/
const BINDING_OPERATION_OUTPUT = 'output';
/**
* WSDL 1.1 namespace.
*/
const NS_WSDL = 'http://schemas.xmlsoap.org/wsdl/';
/**
* WSDL MIME namespace.
*/
const NS_WSDL_MIME = 'http://schemas.xmlsoap.org/wsdl/mime/';
/**
* WSDL SOAP 1.1 namespace.
*/
const NS_WSDL_SOAP_1_1 = 'http://schemas.xmlsoap.org/wsdl/soap/';
/**
* WSDL SOAP 1.2 namespace.
*/
const NS_WSDL_SOAP_1_2 = 'http://schemas.xmlsoap.org/wsdl/soap12/';
/**
* WSDL file name.
*
* @var string
*/
private $wsdlFile;
/**
* DOMDocument WSDL file.
*
* @var \DOMDocument
*/
private $domDocument;
/**
* DOMXPath WSDL file.
*
* @var DOMXPath
*/
private $domXpath;
/**
* Array of mime type information.
*
* @var array(string=>array(string=>array(string=>array(string))))
*/
private $mimeTypes = array();
/**
* WSDL namespace of current WSDL file.
*
* @var string
*/
private $wsdlSoapNamespace;
/**
* Constructor.
*
* @param string $wsdlFile WSDL file name
* @param string $soapVersion SOAP version constant
*/
public function __construct($wsdlFile, $soapVersion)
{
$this->wsdlFile = $wsdlFile;
if ($soapVersion == SOAP_1_1) {
$this->wsdlSoapNamespace = self::NS_WSDL_SOAP_1_1;
} else {
$this->wsdlSoapNamespace = self::NS_WSDL_SOAP_1_2;
}
$this->domDocument = new \DOMDocument('1.0', 'utf-8');
$this->domDocument->load($this->wsdlFile);
$this->domXpath = new \DOMXPath($this->domDocument);
$this->domXpath->registerNamespace('wsdl', self::NS_WSDL);
$this->domXpath->registerNamespace('mime', self::NS_WSDL_MIME);
$this->domXpath->registerNamespace('soap', $this->wsdlSoapNamespace);
}
/**
* Gets the mime type information from the WSDL file.
*
* @param string $soapAction Soap action to analyse
* @return array(string=>array(string=>array(string)))
*/
private function getMimeTypesForSoapAction($soapAction)
{
$query = '/wsdl:definitions/wsdl:binding/wsdl:operation/soap:operation[@soapAction="'.$soapAction.'"]/..';
$nodes = $this->domXpath->query($query);
$mimeTypes = array();
if (($wsdlOperation = $nodes->item(0)) !== null) {
//$wsdlOperationName = $wsdlOperation->getAttribute('name');
foreach ($wsdlOperation->childNodes as $soapOperationChild) {
// wsdl:input or wsdl:output
if ($soapOperationChild->localName == 'input' || $soapOperationChild->localName == 'output') {
$operationType = $soapOperationChild->localName;
// mime:multipartRelated/mime:part
$mimeParts = $soapOperationChild->getElementsByTagNameNS(self::NS_WSDL_MIME, 'part');
if ($mimeParts->length > 0) {
foreach ($mimeParts as $mimePart) {
foreach ($mimePart->childNodes as $child) {
switch ($child->localName) {
case 'body':
$parts = $child->getAttribute('parts');
$parts = ($parts == '') ? '[body]' : $parts;
$mimeTypes[$operationType][$parts] = array('text/xml');
break;
case 'content':
$part = $child->getAttribute('part');
$part = ($part == '') ? null : $part;
$type = $child->getAttribute('type');
$type = ($type == '') ? '*/*' : $type;
if (!isset($mimeTypes[$operationType][$part])) {
$mimeTypes[$operationType][$part] = array();
}
$mimeTypes[$operationType][$part][] = $type;
break;
case 'mimeXml':
// this does not conform to the spec
$part = $child->getAttribute('part');
$part = ($part == '') ? null : $part;
$mimeTypes[$operationType][$part] = array('text/xml');
break;
}
}
}
} else {
$child = $soapOperationChild->getElementsByTagNameNS($this->wsdlSoapNamespace, 'body')->item(0);
if (!is_null($child)) {
$parts = $child->getAttribute('parts');
$parts = ($parts == '') ? '[body]' : $parts;
$mimeTypes[$operationType][$parts] = array('text/xml');
}
}
}
}
}
return $mimeTypes;
}
/**
* Checks the mime type of the part for the given operation.
*
* @param string $soapAction Soap action
* @param string $operationType Operation type
* @param string $part Part name
* @param string $currentMimeType Current mime type
* @return boolean
*/
public function isValidMimeTypeType($soapAction, $operationType, $part, $currentMimeType)
{
// load data from WSDL
if (!isset($this->mimeTypes[$soapAction])) {
$this->mimeTypes[$soapAction] = $this->getMimeTypesForSoapAction($soapAction);
}
// part is valid as we do not have an explicit entry for current part
if (!isset($this->mimeTypes[$soapAction][$operationType][$part])) {
return true;
}
$mimeTypes = $this->mimeTypes[$soapAction][$operationType][$part];
// wildcard or exact match
if (in_array('*/*', $mimeTypes) || in_array($currentMimeType, $mimeTypes)) {
return true;
// type/* match
} else {
list($ctype, $csubtype) = explode('/', $currentMimeType);
foreach ($mimeTypes as $mimeType) {
list($type, $subtype) = explode('/', $mimeType);
if ($subtype == '*' && $type == $ctype) {
return true;
}
}
}
return false;
}
}

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8" ?>
<wsdl:definitions xmlns:types="http://example.com/mimetypes"
xmlns:ref="http://ws-i.org/profiles/basic/1.1/xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapbind="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
targetNamespace="http://example.com/mimewsdl"
xmlns:tns="http://example.com/mimewsdl">
<wsdl:types>
<xsd:schema targetNamespace="http://example.com/mimetypes"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="ClaimDetail" type="types:ClaimDetailType"/>
<xsd:complexType name="ClaimDetailType">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<!-- lots of other claim detail stuff -->
</xsd:sequence>
</xsd:complexType>
<xsd:element name="ClaimRefNo" type="xsd:string"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="ClaimIn">
<wsdl:part name="body" element="types:ClaimDetail"/>
<wsdl:part name="ClaimPhoto" type="xsd:base64Binary"/>
</wsdl:message>
<wsdl:message name="ClaimOut">
<wsdl:part name="out" element="types:ClaimRefNo"/>
</wsdl:message>
<wsdl:portType name="ClaimPortType">
<wsdl:operation name="SendClaim">
<wsdl:input message="tns:ClaimIn"/>
<wsdl:output message="tns:ClaimOut"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ClaimBinding" type="tns:ClaimPortType">
<soapbind:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="SendClaim">
<soapbind:operation soapAction="http://example.com/soapaction"/>
<wsdl:input>
<mime:multipartRelated>
<mime:part>
<soapbind:body parts="body" use="literal"/>
</mime:part>
<mime:part>
<mime:content part="ClaimPhoto" type="image/jpeg"/>
</mime:part>
</mime:multipartRelated>
</wsdl:input>
<wsdl:output>
<soapbind:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
</wsdl:definitions>

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8" ?>
<wsdl:definitions xmlns:types="http://example.com/mimetypes"
xmlns:ref="http://ws-i.org/profiles/basic/1.1/xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapbind="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
targetNamespace="http://example.com/mimewsdl"
xmlns:tns="http://example.com/mimewsdl">
<wsdl:types>
<xsd:schema targetNamespace="http://example.com/mimetypes"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="ClaimDetail" type="types:ClaimDetailType"/>
<xsd:complexType name="ClaimDetailType">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<!-- lots of other claim detail stuff -->
</xsd:sequence>
</xsd:complexType>
<xsd:element name="ClaimRefNo" type="xsd:string"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="ClaimIn">
<wsdl:part name="body" element="types:ClaimDetail"/>
<wsdl:part name="ClaimPhoto" type="xsd:base64Binary"/>
</wsdl:message>
<wsdl:message name="ClaimOut">
<wsdl:part name="out" element="types:ClaimRefNo"/>
</wsdl:message>
<wsdl:portType name="ClaimPortType">
<wsdl:operation name="SendClaim">
<wsdl:input message="tns:ClaimIn"/>
<wsdl:output message="tns:ClaimOut"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ClaimBinding" type="tns:ClaimPortType">
<soapbind:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="SendClaim">
<soapbind:operation soapAction="http://example.com/soapaction"/>
<wsdl:input>
<mime:multipartRelated>
<mime:part>
<soapbind:body parts="body" use="literal"/>
</mime:part>
<mime:part>
<mime:content part="ClaimPhoto" type="image/*"/>
</mime:part>
</mime:multipartRelated>
</wsdl:input>
<wsdl:output>
<soapbind:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
</wsdl:definitions>

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8" ?>
<wsdl:definitions xmlns:types="http://example.com/mimetypes"
xmlns:ref="http://ws-i.org/profiles/basic/1.1/xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapbind="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
targetNamespace="http://example.com/mimewsdl"
xmlns:tns="http://example.com/mimewsdl">
<wsdl:types>
<xsd:schema targetNamespace="http://example.com/mimetypes"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="ClaimDetail" type="types:ClaimDetailType"/>
<xsd:complexType name="ClaimDetailType">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<!-- lots of other claim detail stuff -->
</xsd:sequence>
</xsd:complexType>
<xsd:element name="ClaimRefNo" type="xsd:string"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="ClaimIn">
<wsdl:part name="body" element="types:ClaimDetail"/>
<wsdl:part name="ClaimPhoto" type="xsd:base64Binary"/>
</wsdl:message>
<wsdl:message name="ClaimOut">
<wsdl:part name="out" element="types:ClaimRefNo"/>
</wsdl:message>
<wsdl:portType name="ClaimPortType">
<wsdl:operation name="SendClaim">
<wsdl:input message="tns:ClaimIn"/>
<wsdl:output message="tns:ClaimOut"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ClaimBinding" type="tns:ClaimPortType">
<soapbind:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="SendClaim">
<soapbind:operation soapAction="http://example.com/soapaction"/>
<wsdl:input>
<mime:multipartRelated>
<mime:part>
<soapbind:body parts="body" use="literal"/>
</mime:part>
<mime:part>
<mime:content part="ClaimPhoto" type="*/*"/>
</mime:part>
</mime:multipartRelated>
</wsdl:input>
<wsdl:output>
<soapbind:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
</wsdl:definitions>

View File

@ -0,0 +1,48 @@
<?php
/*
* This file is part of the BeSimpleSoapBundle.
*
* (c) Christian Kerl <christian-kerl@web.de>
* (c) Francis Besset <francis.besset@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace BeSimple\Tests\SoapCommon\Soap;
use BeSimple\SoapCommon\WsdlHandler;
class WsdlHandlerTest extends \PHPUnit_Framework_TestCase
{
public function testIsValidMimeTypeType()
{
$filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/WsdlMimeContent.wsdl';
$wh = new WsdlHandler($filename, SOAP_1_1);
$this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'body', 'text/xml'));
$this->assertFalse($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'body', 'image/gif'));
$this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'image/jpeg'));
$this->assertFalse($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'image/gif'));
$this->assertFalse($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'text/xml'));
$filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/WsdlMimeContent2.wsdl';
$wh = new WsdlHandler($filename, SOAP_1_1);
$this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'body', 'text/xml'));
$this->assertFalse($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'body', 'image/gif'));
$this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'image/jpeg'));
$this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'image/gif'));
$this->assertFalse($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'text/xml'));
$filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/WsdlMimeContent3.wsdl';
$wh = new WsdlHandler($filename, SOAP_1_1);
$this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'body', 'text/xml'));
$this->assertFalse($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'body', 'image/gif'));
$this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'image/jpeg'));
$this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'image/gif'));
$this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'text/xml'));
}
}