added initial support for service definition
This commit is contained in:
parent
783ced3b7b
commit
31d40380a6
|
@ -28,10 +28,26 @@ class WebServiceExtension extends Extension
|
||||||
$loader = new XmlFileLoader($configuration, __DIR__ . '/../Resources/config');
|
$loader = new XmlFileLoader($configuration, __DIR__ . '/../Resources/config');
|
||||||
$loader->load('services.xml');
|
$loader->load('services.xml');
|
||||||
|
|
||||||
$configuration->setAlias('http_kernel', 'webservice_http_kernel');
|
$configuration->setAlias('http_kernel', 'webservice.kernel');
|
||||||
}
|
}
|
||||||
|
|
||||||
$configuration->setParameter('webservice.config.wsdl', $config['wsdl']);
|
if(!isset($config['definition']))
|
||||||
|
{
|
||||||
|
throw new \InvalidArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->registerServiceDefinitionConfig($config['definition'], $configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerServiceDefinitionConfig(array $config, ContainerBuilder $configuration)
|
||||||
|
{
|
||||||
|
if(!isset($config['name']))
|
||||||
|
{
|
||||||
|
throw new \InvalidArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$configuration->setParameter('webservice.definition.name', $config['name']);
|
||||||
|
$configuration->setParameter('webservice.definition.resource', isset($config['resource']) ? $config['resource'] : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getXsdValidationBasePath()
|
public function getXsdValidationBasePath()
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
|
|
||||||
<parameters>
|
<parameters>
|
||||||
<parameter key="request.class">Bundle\WebServiceBundle\Soap\SoapRequest</parameter>
|
<parameter key="request.class">Bundle\WebServiceBundle\Soap\SoapRequest</parameter>
|
||||||
|
|
||||||
|
<parameter key="webservice.definition.class">Bundle\WebServiceBundle\ServiceDefinition\ServiceDefinition</parameter>
|
||||||
|
<parameter key="webservice.definition.loader.class">Bundle\WebServiceBundle\ServiceDefinition\Loader\XmlFileLoader</parameter>
|
||||||
|
<parameter key="webservice.definition.dumper.class">Bundle\WebServiceBundle\ServiceDefinition\Dumper\Wsdl11DocumentLiteralFileDumper</parameter>
|
||||||
</parameters>
|
</parameters>
|
||||||
|
|
||||||
<services>
|
<services>
|
||||||
|
@ -14,12 +18,21 @@
|
||||||
<argument type="service" id="controller_resolver" />
|
<argument type="service" id="controller_resolver" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="webservice_soap_server" class="SoapServer">
|
<service id="webservice.kernel" class="Bundle\WebServiceBundle\SoapKernel">
|
||||||
<argument type="string">%webservice.config.wsdl%</argument>
|
<argument type="service" id="webservice.definition" />
|
||||||
</service>
|
<argument type="service" id="webservice.definition.loader" />
|
||||||
<service id="webservice_http_kernel" class="Bundle\WebServiceBundle\SoapKernel">
|
<argument type="service" id="webservice.definition.dumper" />
|
||||||
<argument type="service" id="webservice_soap_server" />
|
|
||||||
<argument type="service" id="symfony_http_kernel" />
|
<argument type="service" id="symfony_http_kernel" />
|
||||||
</service>
|
</service>
|
||||||
|
<service id="webservice.definition" class="%webservice.definition.class%" shared="true">
|
||||||
|
<argument type="string">%webservice.definition.name%</argument>
|
||||||
|
</service>
|
||||||
|
<service id="webservice.definition.loader" class="%webservice.definition.loader.class%">
|
||||||
|
<argument type="string">%webservice.definition.resource%</argument>
|
||||||
|
</service>
|
||||||
|
<service id="webservice.definition.dumper" class="%webservice.definition.dumper.class%">
|
||||||
|
<argument type="string"></argument>
|
||||||
|
</service>
|
||||||
</services>
|
</services>
|
||||||
</container>
|
</container>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bundle\WebServiceBundle\ServiceDefinition\Dumper;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\ServiceDefinition\ServiceDefinition;
|
||||||
|
|
||||||
|
interface DumperInterface
|
||||||
|
{
|
||||||
|
function dumpServiceDefinition(ServiceDefinition $definition);
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bundle\WebServiceBundle\ServiceDefinition\Loader;
|
||||||
|
|
||||||
|
abstract class FileLoader implements LoaderInterface
|
||||||
|
{
|
||||||
|
protected $file;
|
||||||
|
|
||||||
|
public function __construct($file)
|
||||||
|
{
|
||||||
|
if (!file_exists($file)) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('The service definition file %s does not exist', $file));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_readable($file)) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('The service definition file %s is not readable', $file));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->file = $file;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bundle\WebServiceBundle\ServiceDefinition\Loader;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\ServiceDefinition\ServiceDefinition;
|
||||||
|
|
||||||
|
interface LoaderInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Loads the contents of the given ServiceDefinition.
|
||||||
|
*
|
||||||
|
* @param ServiceDefinition $definition
|
||||||
|
*/
|
||||||
|
function loadServiceDefinition(ServiceDefinition $definition);
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bundle\WebServiceBundle\ServiceDefinition\Loader;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\ServiceDefinition\ServiceType;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\ServiceDefinition\ServiceDefinition;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\ServiceDefinition\ServiceMethod;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\ServiceDefinition\ServiceHeader;
|
||||||
|
|
||||||
|
class XmlFileLoader extends FileLoader
|
||||||
|
{
|
||||||
|
public function loadServiceDefinition(ServiceDefinition $definition)
|
||||||
|
{
|
||||||
|
$xml = $this->parseFile($this->file);
|
||||||
|
|
||||||
|
if($definition->getName() != $xml['name'])
|
||||||
|
{
|
||||||
|
throw new \InvalidArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($xml->header as $header)
|
||||||
|
{
|
||||||
|
$definition->getHeaders()->add($this->parseHeader($header));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($xml->method as $method)
|
||||||
|
{
|
||||||
|
$definition->getMethods()->add($this->parseMethod($method));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \SimpleXMLElement $node
|
||||||
|
*
|
||||||
|
* @return \Bundle\WebServiceBundle\ServiceDefinition\ServiceHeader
|
||||||
|
*/
|
||||||
|
protected function parseHeader(\SimpleXMLElement $node)
|
||||||
|
{
|
||||||
|
$header = new ServiceHeader((string)$node['name'], $this->parseType($node->type));
|
||||||
|
|
||||||
|
return $header;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \SimpleXMLElement $node
|
||||||
|
*
|
||||||
|
* @return \Bundle\WebServiceBundle\ServiceDefinition\ServiceMethod
|
||||||
|
*/
|
||||||
|
protected function parseMethod(\SimpleXMLElement $node)
|
||||||
|
{
|
||||||
|
$method = new ServiceMethod((string)$node['name'], (string)$node['controller']);
|
||||||
|
|
||||||
|
return $method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \SimpleXMLElement $node
|
||||||
|
*
|
||||||
|
* @return \Bundle\WebServiceBundle\ServiceDefinition\ServiceType
|
||||||
|
*/
|
||||||
|
protected function parseType(\SimpleXMLElement $node)
|
||||||
|
{
|
||||||
|
$namespaces = $node->getDocNamespaces(true);
|
||||||
|
$qname = explode(':', $node['xml-type'], 2);
|
||||||
|
$xmlType = sprintf('{%s}%s', $namespaces[$qname[0]], $qname[1]);
|
||||||
|
|
||||||
|
$type = new ServiceType((string)$node['php-type'], $xmlType, (string)$node['converter']);
|
||||||
|
|
||||||
|
return $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $file
|
||||||
|
*
|
||||||
|
* @return \SimpleXMLElement
|
||||||
|
*/
|
||||||
|
protected function parseFile($file)
|
||||||
|
{
|
||||||
|
$dom = new \DOMDocument();
|
||||||
|
libxml_use_internal_errors(true);
|
||||||
|
if (!$dom->load($file, LIBXML_COMPACT)) {
|
||||||
|
throw new \InvalidArgumentException(implode("\n", $this->getXmlErrors()));
|
||||||
|
}
|
||||||
|
if (!$dom->schemaValidate(__DIR__.'/schema/servicedefinition-1.0.xsd')) {
|
||||||
|
throw new \InvalidArgumentException(implode("\n", $this->getXmlErrors()));
|
||||||
|
}
|
||||||
|
$dom->validateOnParse = true;
|
||||||
|
$dom->normalizeDocument();
|
||||||
|
libxml_use_internal_errors(false);
|
||||||
|
|
||||||
|
return simplexml_import_dom($dom);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getXmlErrors()
|
||||||
|
{
|
||||||
|
$errors = array();
|
||||||
|
foreach (libxml_get_errors() as $error) {
|
||||||
|
$errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
|
||||||
|
LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
|
||||||
|
$error->code,
|
||||||
|
trim($error->message),
|
||||||
|
$error->file ? $error->file : 'n/a',
|
||||||
|
$error->line,
|
||||||
|
$error->column
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
libxml_clear_errors();
|
||||||
|
libxml_use_internal_errors(false);
|
||||||
|
|
||||||
|
return $errors;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://christiankerl.github.com/WebServiceBundle/servicedefinition/1.0/" xmlns:tns="http://christiankerl.github.com/WebServiceBundle/servicedefinition/1.0/" elementFormDefault="qualified">
|
||||||
|
<element name="webservice" type="tns:WebserviceType" />
|
||||||
|
<complexType name="WebserviceType">
|
||||||
|
<sequence>
|
||||||
|
<element name="header" type="tns:HeaderType" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
<element name="method" type="tns:MethodType" maxOccurs="unbounded" />
|
||||||
|
</sequence>
|
||||||
|
<attribute name="name" type="string" use="required" />
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
<complexType name="HeaderType">
|
||||||
|
<complexContent>
|
||||||
|
<extension base="tns:TransferObjectType">
|
||||||
|
<sequence>
|
||||||
|
<element name="exception" type="tns:ExceptionType" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
</sequence>
|
||||||
|
<attribute name="name" type="ID" use="required" />
|
||||||
|
</extension>
|
||||||
|
</complexContent>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
<complexType name="HeaderRefType">
|
||||||
|
<attribute name="name" type="IDREF" />
|
||||||
|
<attribute name="direction">
|
||||||
|
<simpleType>
|
||||||
|
<restriction base="string">
|
||||||
|
<enumeration value="in" />
|
||||||
|
<enumeration value="out" />
|
||||||
|
<enumeration value="inout" />
|
||||||
|
</restriction>
|
||||||
|
</simpleType>
|
||||||
|
</attribute>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
<complexType name="MethodType">
|
||||||
|
<sequence>
|
||||||
|
<element name="exception" type="tns:ExceptionType" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
<element name="header" type="tns:HeaderRefType" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
|
||||||
|
<element name="argument" type="tns:ArgumentType" minOccurs="0" maxOccurs="unbounded" />
|
||||||
|
<element name="return" type="tns:ReturnType" minOccurs="0" maxOccurs="1" />
|
||||||
|
</sequence>
|
||||||
|
<attribute name="name" type="string" use="required" />
|
||||||
|
<attribute name="controller" type="string" use="required" />
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
<complexType name="TransferObjectType" abstract="true">
|
||||||
|
<sequence>
|
||||||
|
<element name="type" type="tns:TypeConversionType" />
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
<complexType name="ExceptionType">
|
||||||
|
<complexContent>
|
||||||
|
<extension base="tns:TransferObjectType">
|
||||||
|
<attribute name="name" type="string" use="required" />
|
||||||
|
</extension>
|
||||||
|
</complexContent>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
<complexType name="ArgumentType">
|
||||||
|
<complexContent>
|
||||||
|
<extension base="tns:TransferObjectType">
|
||||||
|
<attribute name="name" type="string" use="required" />
|
||||||
|
</extension>
|
||||||
|
</complexContent>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
<complexType name="ReturnType">
|
||||||
|
<complexContent>
|
||||||
|
<extension base="tns:TransferObjectType" />
|
||||||
|
</complexContent>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
<complexType name="TypeConversionType">
|
||||||
|
<attribute name="php-type" type="string" use="required" />
|
||||||
|
<attribute name="xml-type" type="QName" use="required" />
|
||||||
|
<attribute name="converter" type="string" use="optional" />
|
||||||
|
</complexType>
|
||||||
|
</schema>
|
|
@ -0,0 +1,80 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bundle\WebServiceBundle\ServiceDefinition;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\Util\Collection;
|
||||||
|
|
||||||
|
class ServiceDefinition
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Bundle\WebServiceBundle\Util\Collection
|
||||||
|
*/
|
||||||
|
private $methods;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Bundle\WebServiceBundle\Util\Collection
|
||||||
|
*/
|
||||||
|
private $headers;
|
||||||
|
|
||||||
|
public function __construct($name = null, array $methods = array(), array $headers = array())
|
||||||
|
{
|
||||||
|
$this->setName($name);
|
||||||
|
$this->setMethods($methods);
|
||||||
|
$this->setHeaders($headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
*/
|
||||||
|
public function setName($name)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Bundle\WebServiceBundle\Util\Collection
|
||||||
|
*/
|
||||||
|
public function getMethods()
|
||||||
|
{
|
||||||
|
return $this->methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $methods
|
||||||
|
*/
|
||||||
|
public function setMethods($methods)
|
||||||
|
{
|
||||||
|
$this->methods = new Collection('getName');
|
||||||
|
$this->methods->addAll($methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Bundle\WebServiceBundle\Util\Collection
|
||||||
|
*/
|
||||||
|
public function getHeaders()
|
||||||
|
{
|
||||||
|
return $this->headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $headers
|
||||||
|
*/
|
||||||
|
public function setHeaders($headers)
|
||||||
|
{
|
||||||
|
$this->headers = new Collection('getName');
|
||||||
|
$this->headers->addAll($headers);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bundle\WebServiceBundle\ServiceDefinition;
|
||||||
|
|
||||||
|
class ServiceHeader
|
||||||
|
{
|
||||||
|
private $name;
|
||||||
|
private $type;
|
||||||
|
|
||||||
|
public function __construct($name = null, ServiceType $type = null)
|
||||||
|
{
|
||||||
|
$this->setName($name);
|
||||||
|
$this->setType($type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName($name)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getType()
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setType($type)
|
||||||
|
{
|
||||||
|
$this->type = $type;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bundle\WebServiceBundle\ServiceDefinition;
|
||||||
|
|
||||||
|
class ServiceMethod
|
||||||
|
{
|
||||||
|
private $name;
|
||||||
|
private $controller;
|
||||||
|
|
||||||
|
public function __construct($name = null, $controller = null)
|
||||||
|
{
|
||||||
|
$this->setName($name);
|
||||||
|
$this->setController($controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName($name)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getController()
|
||||||
|
{
|
||||||
|
return $this->controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setController($controller)
|
||||||
|
{
|
||||||
|
$this->controller = $controller;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bundle\WebServiceBundle\ServiceDefinition;
|
||||||
|
|
||||||
|
class ServiceType
|
||||||
|
{
|
||||||
|
private $phpType;
|
||||||
|
private $xmlType;
|
||||||
|
private $converter;
|
||||||
|
|
||||||
|
public function __construct($phpType = null, $xmlType = null, $converter = null)
|
||||||
|
{
|
||||||
|
$this->setPhpType($phpType);
|
||||||
|
$this->setXmlType($xmlType);
|
||||||
|
$this->setConverter($converter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPhpType()
|
||||||
|
{
|
||||||
|
return $this->phpType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPhpType($value)
|
||||||
|
{
|
||||||
|
$this->phpType = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getXmlType()
|
||||||
|
{
|
||||||
|
return $this->xmlType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setXmlType($value)
|
||||||
|
{
|
||||||
|
$this->xmlType = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConverter()
|
||||||
|
{
|
||||||
|
return $this->converter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setConverter($value)
|
||||||
|
{
|
||||||
|
$this->converter = $value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bundle\WebServiceBundle\Soap;
|
||||||
|
|
||||||
|
class SoapHeader
|
||||||
|
{
|
||||||
|
private $namespace;
|
||||||
|
private $name;
|
||||||
|
private $data;
|
||||||
|
|
||||||
|
public function __construct($namespace, $name, $data)
|
||||||
|
{
|
||||||
|
$this->namespace = $namespace;
|
||||||
|
$this->name = $name;
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNamespace()
|
||||||
|
{
|
||||||
|
return $this->namespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getData()
|
||||||
|
{
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toNativeSoapHeader()
|
||||||
|
{
|
||||||
|
return new \SoapHeader($this->namespace, $this->name, $this->data);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
namespace Bundle\WebServiceBundle\Soap;
|
namespace Bundle\WebServiceBundle\Soap;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\Util\Collection;
|
||||||
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,9 +32,9 @@ class SoapRequest extends Request
|
||||||
protected $soapAction;
|
protected $soapAction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var unknown
|
* @var \Bundle\WebServiceBundle\Util\Collection
|
||||||
*/
|
*/
|
||||||
protected $soapHeader;
|
protected $soapHeaders;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var unknown
|
* @var unknown
|
||||||
|
@ -44,6 +46,8 @@ class SoapRequest extends Request
|
||||||
parent::__construct($query, null, $attributes, $cookies, null, $server);
|
parent::__construct($query, null, $attributes, $cookies, null, $server);
|
||||||
|
|
||||||
$this->rawContent = $rawContent != null ? $rawContent : $this->loadRawContent();
|
$this->rawContent = $rawContent != null ? $rawContent : $this->loadRawContent();
|
||||||
|
|
||||||
|
$this->soapHeaders = new Collection('getName');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,6 +60,11 @@ class SoapRequest extends Request
|
||||||
return $this->rawContent;
|
return $this->rawContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSoapHeaders()
|
||||||
|
{
|
||||||
|
return $this->soapHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the plain HTTP POST data.
|
* Loads the plain HTTP POST data.
|
||||||
*
|
*
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
namespace Bundle\WebServiceBundle\Soap;
|
namespace Bundle\WebServiceBundle\Soap;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\Util\Collection;
|
||||||
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,21 +21,19 @@ use Symfony\Component\HttpFoundation\Response;
|
||||||
*/
|
*/
|
||||||
class SoapResponse extends Response
|
class SoapResponse extends Response
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var \Bundle\WebServiceBundle\Util\Collection
|
||||||
|
*/
|
||||||
protected $soapHeaders;
|
protected $soapHeaders;
|
||||||
|
|
||||||
protected $soapReturnValue;
|
protected $soapReturnValue;
|
||||||
|
|
||||||
public function __construct($returnValue)
|
public function __construct($returnValue = null)
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
$this->soapHeaders = array();
|
$this->soapHeaders = new Collection('getName');
|
||||||
$this->soapReturnValue = $returnValue;
|
$this->setReturnValue($returnValue);
|
||||||
}
|
|
||||||
|
|
||||||
public function addSoapHeader(\SoapHeader $header)
|
|
||||||
{
|
|
||||||
$this->soapHeaders[] = $header;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSoapHeaders()
|
public function getSoapHeaders()
|
||||||
|
@ -41,6 +41,11 @@ class SoapResponse extends Response
|
||||||
return $this->soapHeaders;
|
return $this->soapHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setReturnValue($value)
|
||||||
|
{
|
||||||
|
$this->soapReturnValue = $value;
|
||||||
|
}
|
||||||
|
|
||||||
public function getReturnValue()
|
public function getReturnValue()
|
||||||
{
|
{
|
||||||
return $this->soapReturnValue;
|
return $this->soapReturnValue;
|
||||||
|
|
|
@ -10,6 +10,12 @@
|
||||||
|
|
||||||
namespace Bundle\WebServiceBundle;
|
namespace Bundle\WebServiceBundle;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\Soap\SoapHeader;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\ServiceDefinition\ServiceHeader;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\ServiceDefinition\Dumper\DumperInterface;
|
||||||
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
@ -18,6 +24,9 @@ use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||||
use Bundle\WebServiceBundle\Soap\SoapRequest;
|
use Bundle\WebServiceBundle\Soap\SoapRequest;
|
||||||
use Bundle\WebServiceBundle\Soap\SoapResponse;
|
use Bundle\WebServiceBundle\Soap\SoapResponse;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\ServiceDefinition\ServiceDefinition;
|
||||||
|
use Bundle\WebServiceBundle\ServiceDefinition\Loader\LoaderInterface;
|
||||||
|
|
||||||
use Bundle\WebServiceBundle\Util\String;
|
use Bundle\WebServiceBundle\Util\String;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,14 +54,25 @@ class SoapKernel implements HttpKernelInterface
|
||||||
*/
|
*/
|
||||||
protected $soapResponse;
|
protected $soapResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Bundle\WebServiceBundle\ServiceDefinition\ServiceDefinition
|
||||||
|
*/
|
||||||
|
protected $serviceDefinition;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Symfony\Component\HttpKernel\HttpKernelInterface
|
* @var \Symfony\Component\HttpKernel\HttpKernelInterface
|
||||||
*/
|
*/
|
||||||
protected $kernel;
|
protected $kernel;
|
||||||
|
|
||||||
public function __construct(\SoapServer $server, HttpKernelInterface $kernel)
|
public function __construct(ServiceDefinition $definition, LoaderInterface $loader, DumperInterface $dumper, HttpKernelInterface $kernel)
|
||||||
{
|
{
|
||||||
$this->soapServer = $server;
|
$this->serviceDefinition = $definition;
|
||||||
|
$loader->loadServiceDefinition($this->serviceDefinition);
|
||||||
|
|
||||||
|
// assume $dumper creates WSDL 1.1 file
|
||||||
|
$wsdl = $dumper->dumpServiceDefinition($this->serviceDefinition);
|
||||||
|
|
||||||
|
$this->soapServer = new \SoapServer($wsdl);
|
||||||
$this->soapServer->setObject($this);
|
$this->soapServer->setObject($this);
|
||||||
|
|
||||||
$this->kernel = $kernel;
|
$this->kernel = $kernel;
|
||||||
|
@ -76,26 +96,43 @@ class SoapKernel implements HttpKernelInterface
|
||||||
return $this->soapResponse;
|
return $this->soapResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method gets called once for every SOAP header the \SoapServer received
|
||||||
|
* and afterwards once for the called SOAP operation.
|
||||||
|
*
|
||||||
|
* @param string $method The SOAP header or SOAP operation name
|
||||||
|
* @param array $arguments
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function __call($method, $arguments)
|
public function __call($method, $arguments)
|
||||||
{
|
{
|
||||||
if($this->isSoapHeaderCallback($method))
|
if($this->serviceDefinition->getHeaders()->has($method))
|
||||||
{
|
{
|
||||||
// $this->soapRequest->addSoapHeader(null);
|
// collect request soap headers
|
||||||
}
|
$headerDefinition = $this->serviceDefinition->getHeaders()->get($method);
|
||||||
else
|
$this->soapRequest->getSoapHeaders()->add($this->createSoapHeader($headerDefinition, $arguments[0]));
|
||||||
{
|
|
||||||
// TODO: set _controller attribute of request
|
|
||||||
$this->soapRequest->attributes->set('_controller', $method);
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->serviceDefinition->getMethods()->has($method))
|
||||||
|
{
|
||||||
|
$methodDefinition = $this->serviceDefinition->getMethods()->get($method);
|
||||||
|
$this->soapRequest->attributes->set('_controller', $methodDefinition->getController());
|
||||||
|
|
||||||
|
// delegate to standard http kernel
|
||||||
$response = $this->kernel->handle($this->soapRequest, self::MASTER_REQUEST, true);
|
$response = $this->kernel->handle($this->soapRequest, self::MASTER_REQUEST, true);
|
||||||
|
|
||||||
$this->soapResponse = $this->checkResponse($response);
|
$this->soapResponse = $this->checkResponse($response);
|
||||||
|
|
||||||
|
// add response soap headers to soap server
|
||||||
foreach($this->soapResponse->getSoapHeaders() as $header)
|
foreach($this->soapResponse->getSoapHeaders() as $header)
|
||||||
{
|
{
|
||||||
$this->soapServer->addSoapHeader($header);
|
$this->soapServer->addSoapHeader($header->toNativeSoapHeader());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return operation return value to soap server
|
||||||
return $this->soapResponse->getReturnValue();
|
return $this->soapResponse->getReturnValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,8 +181,13 @@ class SoapKernel implements HttpKernelInterface
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function isSoapHeaderCallback($method)
|
protected function createSoapHeader(ServiceHeader $headerDefinition, $data)
|
||||||
{
|
{
|
||||||
return false; //String::endsWith($method, 'Header');
|
if(!preg_match('/^\{(.+)\}(.+)$/', $headerDefinition->getType()->getXmlType(), $matches))
|
||||||
|
{
|
||||||
|
throw new \InvalidArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SoapHeader($matches[1], $matches[2], $data);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,6 +11,10 @@
|
||||||
namespace Bundle\WebServiceBundle\Tests;
|
namespace Bundle\WebServiceBundle\Tests;
|
||||||
|
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\ServiceDefinition\ServiceMethod;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\ServiceDefinition\ServiceDefinition;
|
||||||
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
|
||||||
use Bundle\WebServiceBundle\SoapKernel;
|
use Bundle\WebServiceBundle\SoapKernel;
|
||||||
|
@ -31,13 +35,18 @@ class SoapKernelTest extends \PHPUnit_Framework_TestCase
|
||||||
|
|
||||||
public function setUp()
|
public function setUp()
|
||||||
{
|
{
|
||||||
$soapServer = new \SoapServer(__DIR__ . '/fixtures/api.wsdl');
|
$serviceDefinition = new ServiceDefinition('api');
|
||||||
|
$serviceDefinition->getMethods()->add(new ServiceMethod('math_multiply', 'MathController::multiply'));
|
||||||
|
|
||||||
|
$serviceDefinitionLoader = null;
|
||||||
|
$serviceDefinitionDumper = new StaticFileDumper(__DIR__ . '/fixtures/api.wsdl');
|
||||||
|
|
||||||
$httpKernel = $this->getMock('Symfony\\Component\\HttpKernel\\HttpKernelInterface');
|
$httpKernel = $this->getMock('Symfony\\Component\\HttpKernel\\HttpKernelInterface');
|
||||||
$httpKernel->expects($this->any())
|
$httpKernel->expects($this->any())
|
||||||
->method('handle')
|
->method('handle')
|
||||||
->will($this->returnValue(new SoapResponse(200)));
|
->will($this->returnValue(new SoapResponse(200)));
|
||||||
|
|
||||||
$this->soapKernel = new SoapKernel($soapServer, $httpKernel);
|
$this->soapKernel = new SoapKernel($serviceDefinition, $serviceDefinitionLoader, $serviceDefinitionDumper, $httpKernel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testHandle()
|
public function testHandle()
|
||||||
|
@ -48,11 +57,10 @@ class SoapKernelTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertXmlStringEqualsXmlString(self::$soapResponseContent, $response->getContent());
|
$this->assertXmlStringEqualsXmlString(self::$soapResponseContent, $response->getContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException InvalidArgumentException
|
|
||||||
*/
|
|
||||||
public function testHandleWithInvalidRequest()
|
public function testHandleWithInvalidRequest()
|
||||||
{
|
{
|
||||||
|
$this->setExpectedException('InvalidArgumentException');
|
||||||
|
|
||||||
$this->soapKernel->handle(new Request());
|
$this->soapKernel->handle(new Request());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bundle\WebServiceBundle\Tests;
|
||||||
|
|
||||||
|
use Bundle\WebServiceBundle\ServiceDefinition\ServiceDefinition;
|
||||||
|
use Bundle\WebServiceBundle\ServiceDefinition\Dumper\DumperInterface;
|
||||||
|
|
||||||
|
class StaticFileDumper implements DumperInterface
|
||||||
|
{
|
||||||
|
private $file;
|
||||||
|
|
||||||
|
public function __construct($file)
|
||||||
|
{
|
||||||
|
$this->file = $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dumpServiceDefinition(ServiceDefinition $definition)
|
||||||
|
{
|
||||||
|
return $this->file;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Bundle\WebServiceBundle\Util;
|
||||||
|
|
||||||
|
class Collection implements \IteratorAggregate, \Countable
|
||||||
|
{
|
||||||
|
private $elements = array();
|
||||||
|
private $keyPropertyGetter;
|
||||||
|
|
||||||
|
public function __construct($keyPropertyGetter)
|
||||||
|
{
|
||||||
|
$this->keyPropertyGetter = $keyPropertyGetter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function add($element)
|
||||||
|
{
|
||||||
|
$this->elements[call_user_func(array($element, $this->keyPropertyGetter))] = $element;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addAll($elements)
|
||||||
|
{
|
||||||
|
foreach ($elements as $element)
|
||||||
|
{
|
||||||
|
$this->add($element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function has($key)
|
||||||
|
{
|
||||||
|
return isset($this->elements[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get($key)
|
||||||
|
{
|
||||||
|
return $this->has($key) ? $this->elements[$key] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clear()
|
||||||
|
{
|
||||||
|
$this->elements = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function count()
|
||||||
|
{
|
||||||
|
return count($this->elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIterator ()
|
||||||
|
{
|
||||||
|
return new \ArrayIterator($this->elements);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue