Skip to content

Commit

Permalink
added header handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
goetas committed Sep 8, 2016
1 parent 9aa5662 commit 61ed886
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 6 deletions.
41 changes: 40 additions & 1 deletion src/Arguments/ArgumentsReader.php
Expand Up @@ -3,6 +3,9 @@

use Doctrine\Common\Inflector\Inflector;
use Doctrine\Instantiator\Instantiator;
use GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\Handler\HeaderHandler;
use GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\Handler\HeaderPlaceholder;
use GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\Header;
use JMS\Serializer\Serializer;

class ArgumentsReader implements ArgumentsReaderInterface
Expand All @@ -11,10 +14,15 @@ class ArgumentsReader implements ArgumentsReaderInterface
* @var Serializer
*/
private $serializer;
/**
* @var HeaderHandler
*/
private $headerHandler;

public function __construct(Serializer $serializer)
public function __construct(Serializer $serializer, HeaderHandler $headerHandler)
{
$this->serializer = $serializer;
$this->headerHandler = $headerHandler;
}

/**
Expand All @@ -24,9 +32,40 @@ public function __construct(Serializer $serializer)
*/
public function readArguments(array $args, array $input)
{

$envelope = array_filter($args, function ($item) use ($input) {
return $item instanceof $input['message_fqcn'];
});
if ($envelope) {
return reset($envelope);
}

$instantiator = new Instantiator();
$envelope = $instantiator->instantiate($input['message_fqcn']);

$headers = array_filter($args, function ($item) use ($input) {
return $item instanceof $input['headers_fqcn'];
});
if ($headers) {
$envelope->setHeader(reset($headers));
} else {

$headers = array_filter($args, function ($item) {
return $item instanceof Header;
});
if (count($headers)) {
$headerPlaceholder = new HeaderPlaceholder();
foreach ($headers as $headerInfo) {
$this->headerHandler->addHeaderData($headerPlaceholder, $headerInfo);
}
$envelope->setHeader($headerPlaceholder);
}
}

$args = array_filter($args, function ($item) use ($input) {
return !($item instanceof Header) && !($item instanceof $input['headers_fqcn']);
});

if (!count($input['parts'])) {
return $envelope;
}
Expand Down
82 changes: 82 additions & 0 deletions src/Arguments/Headers/Handler/HeaderHandler.php
@@ -0,0 +1,82 @@
<?php
namespace GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\Handler;

use GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\Header;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\Metadata\StaticPropertyMetadata;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\XmlSerializationVisitor;

class HeaderHandler implements SubscribingHandlerInterface
{
protected $headerData = [];

public static function getSubscribingMethods()
{
return array(
array(
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'format' => 'xml',
'type' => HeaderPlaceholder::class,
'method' => 'serializeHeader'
),
);
}

public function addHeaderData(HeaderPlaceholder $reference, $data)
{
$this->headerData[spl_object_hash($reference)][] = $data;
}

public function serializeHeader(XmlSerializationVisitor $visitor, HeaderPlaceholder $data, array $type, SerializationContext $context)
{
if (!isset($this->headerData[spl_object_hash($data)])) {
return;
}
$factory = $context->getMetadataFactory();
/**
* @var $header Header
*/
foreach ($this->headerData[spl_object_hash($data)] as $header) {
/**
* @var $classMetadata \JMS\Serializer\Metadata\ClassMetadata
*/
$classMetadata = $factory->getMetadataForClass(get_class($header->getData()));

$metadata = new StaticPropertyMetadata($classMetadata->name, $classMetadata->xmlRootName, $header->getData());
$metadata->xmlNamespace = $classMetadata->xmlRootNamespace;
$metadata->serializedName = $classMetadata->xmlRootName;

$visitor->visitProperty($metadata, $header->getData(), $context);

$this->handleOptions($visitor, $header);
}
}

private function handleOptions(XmlSerializationVisitor $visitor, $header)
{
$options = $header->getOptions();
if (!count($options)) {
return;
}
$currentNode = $visitor->getCurrentNode();
foreach ($options as $option => $value) {
if ($option === 'mustUnderstand' || $option === 'required') {
$this->setAttributeOnNode($currentNode->lastChild, $option, "true", 'http://schemas.xmlsoap.org/soap/envelope/');
}
}
}

private function setAttributeOnNode(\DOMElement $node, $name, $value, $namespace)
{
if (!($prefix = $node->lookupPrefix($namespace)) && !($prefix = $node->ownerDocument->lookupPrefix($namespace))) {
$prefix = 'ns-' . substr(sha1($namespace), 0, 8);
}
$node->setAttributeNS($namespace, $prefix . ':' . $name, $value);
}

}



9 changes: 9 additions & 0 deletions src/Arguments/Headers/Handler/HeaderPlaceholder.php
@@ -0,0 +1,9 @@
<?php
namespace GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\Handler;


class HeaderPlaceholder
{
}


28 changes: 28 additions & 0 deletions src/Arguments/Headers/Header.php
@@ -0,0 +1,28 @@
<?php

namespace GoetasWebservices\SoapServices\SoapClient\Arguments\Headers;

class Header
{
private $data;
/**
* @var array
*/
private $options = [];

public function __construct($data, array $options = [])
{
$this->data = $data;
$this->options = $options;
}

public function getData()
{
return $this->data;
}

public function getOptions()
{
return $this->options;
}
}
11 changes: 11 additions & 0 deletions src/Arguments/Headers/MustUnderstandHeader.php
@@ -0,0 +1,11 @@
<?php

namespace GoetasWebservices\SoapServices\SoapClient\Arguments\Headers;

class MustUnderstandHeader extends Header
{
public function __construct($data, array $options = [])
{
parent::__construct($data, array_merge(['mustUnderstand' => true], $options));
}
}
5 changes: 3 additions & 2 deletions src/Client.php
Expand Up @@ -3,6 +3,7 @@

use GoetasWebservices\SoapServices\SoapClient\Arguments\ArgumentsReader;
use GoetasWebservices\SoapServices\SoapClient\Arguments\ArgumentsReaderInterface;
use GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\Handler\HeaderHandler;
use GoetasWebservices\SoapServices\SoapClient\Exception\ClientException;
use GoetasWebservices\SoapServices\SoapClient\Exception\FaultException;
use GoetasWebservices\SoapServices\SoapClient\Exception\ServerException;
Expand Down Expand Up @@ -48,14 +49,14 @@ class Client
private $argumentsReader;


public function __construct(array $serviceDefinition, Serializer $serializer, MessageFactory $messageFactory, HttpClient $client, $unwrap = false)
public function __construct(array $serviceDefinition, Serializer $serializer, MessageFactory $messageFactory, HttpClient $client, HeaderHandler $headerHandler, $unwrap = false)
{
$this->serviceDefinition = $serviceDefinition;
$this->serializer = $serializer;

$this->client = $client;
$this->messageFactory = $messageFactory;
$this->argumentsReader = new ArgumentsReader($this->serializer);
$this->argumentsReader = new ArgumentsReader($this->serializer, $headerHandler);
$this->resultCreator = new ResultCreator($this->serializer, $unwrap);
}

Expand Down
14 changes: 13 additions & 1 deletion src/ClientFactory.php
@@ -1,6 +1,7 @@
<?php
namespace GoetasWebservices\SoapServices\SoapClient;

use GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\Handler\HeaderHandler;
use GoetasWebservices\SoapServices\SoapCommon\Metadata\PhpMetadataGenerator;
use GoetasWebservices\SoapServices\SoapCommon\Metadata\PhpMetadataGeneratorInterface;
use GoetasWebservices\XML\WSDLReader\Exception\PortNotFoundException;
Expand Down Expand Up @@ -36,6 +37,11 @@ class ClientFactory

private $unwrap = false;

/**
* @var HeaderHandler
*/
private $headerHandler;

public function __construct(array $namespaces, SerializerInterface $serializer)
{
$this->setSerializer($serializer);
Expand All @@ -45,6 +51,11 @@ public function __construct(array $namespaces, SerializerInterface $serializer)
}
}

public function setHeaderHandler(HeaderHandler $headerHandler)
{
$this->headerHandler = $headerHandler;
}

public function setUnwrapResponses($unwrap)
{
$this->unwrap = !!$unwrap;
Expand Down Expand Up @@ -105,9 +116,10 @@ public function getClient($wsdl, $portName = null, $serviceName = null, $unwrap

$this->httpClient = $this->httpClient ?: HttpClientDiscovery::find();
$this->messageFactory = $this->messageFactory ?: MessageFactoryDiscovery::find();
$headerHandler = $this->headerHandler ?: new HeaderHandler();
$unwrap = is_null($unwrap) ? $this->unwrap : $unwrap;

return new Client($service, $this->serializer, $this->messageFactory, $this->httpClient, $unwrap);
return new Client($service, $this->serializer, $this->messageFactory, $this->httpClient, $headerHandler, $unwrap);
}

/**
Expand Down
64 changes: 62 additions & 2 deletions tests/Client/ClientRequestResponsesTest.php
Expand Up @@ -2,8 +2,11 @@

namespace GoetasWebservices\SoapServices\Tests;

use GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\Handler\HeaderHandler;
use GoetasWebservices\SoapServices\SoapClient\ClientFactory;
use GoetasWebservices\SoapServices\SoapClient\Exception\FaultException;
use GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\Header;
use GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\MustUnderstandHeader;
use GoetasWebservices\SoapServices\SoapCommon\Metadata\PhpMetadataGenerator;
use GoetasWebservices\SoapServices\SoapCommon\SoapEnvelope\Parts\Fault;
use GoetasWebservices\WsdlToPhp\Tests\Generator;
Expand All @@ -13,6 +16,7 @@
use GuzzleHttp\Middleware;
use GuzzleHttp\Psr7\Response;
use Http\Adapter\Guzzle6\Client as GuzzleAdapter;
use JMS\Serializer\Handler\HandlerRegistryInterface;
use Psr\Http\Message\ResponseInterface;

class ClientRequestResponsesTest extends \PHPUnit_Framework_TestCase
Expand All @@ -39,7 +43,7 @@ public static function setUpBeforeClass()
'http://www.example.org/test/' => "Ex"
];

self::$generator = new Generator($namespaces);
self::$generator = new Generator($namespaces);//, [], '/home/goetas/projects/soap-client/tmp');
self::$generator->generate([__DIR__ . '/../Fixtures/Soap/test.wsdl']);
self::$generator->registerAutoloader();
}
Expand All @@ -57,7 +61,10 @@ public function setUp()
];
$generator = new Generator($namespaces);
$ref = new \ReflectionClass(Fault::class);
$serializer = $generator->buildSerializer(null, [
$headerHandler = new HeaderHandler();
$serializer = $generator->buildSerializer(function (HandlerRegistryInterface $h) use ($headerHandler) {
$h->registerSubscribingHandler($headerHandler);
}, [
'GoetasWebservices\SoapServices\SoapCommon\SoapEnvelope' => dirname($ref->getFileName()) . '/../../Resources/metadata/jms'
]);

Expand All @@ -71,6 +78,7 @@ public function setUp()

$this->factory = new ClientFactory($namespaces, $serializer);
$this->factory->setHttpClient(new GuzzleAdapter($guzzle));
$this->factory->setHeaderHandler($headerHandler);

$metadataGenerator = new PhpMetadataGenerator($namespaces);
$this->factory->setMetadataGenerator($metadataGenerator);
Expand Down Expand Up @@ -104,6 +112,58 @@ public function testGetSimple()
$this->assertEquals("A", $response->getOut());
}

public function testHeaders()
{
$httpResponse = new Response(200, ['Content-Type' => 'text/xml'], '
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Body xmlns:ns-b3c6b39d="http://www.example.org/test/">
<ns-b3c6b39d:getSimpleResponse xmlns:ns-b3c6b39d="http://www.example.org/test/">
<out><![CDATA[A]]></out>
</ns-b3c6b39d:getSimpleResponse>
</SOAP:Body>
</SOAP:Envelope>');

$this->responseMock->append($httpResponse);
$this->responseMock->append($httpResponse);

$client = $this->factory->getClient(__DIR__ . '/../Fixtures/Soap/test.wsdl', null, null, true);

$mp = new \Ex\GetReturnMultiParam();
$mp->setIn("foo");

$client->getSimple("foo", new Header($mp));
$client->getSimple("foo", new MustUnderstandHeader($mp));
$this->assertXmlStringEqualsXmlString(
'<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Body xmlns:ns-b3c6b39d="http://www.example.org/test/">
<ns-b3c6b39d:getSimple xmlns:ns-b3c6b39d="http://www.example.org/test/">
<in><![CDATA[foo]]></in>
</ns-b3c6b39d:getSimple>
</SOAP:Body>
<SOAP:Header xmlns:ns-b3c6b39d="http://www.example.org/test/">
<ns-b3c6b39d:getReturnMultiParam xmlns:ns-b3c6b39d="http://www.example.org/test/">
<in><![CDATA[foo]]></in>
</ns-b3c6b39d:getReturnMultiParam>
</SOAP:Header>
</SOAP:Envelope>',
(string)$this->requestResponseStack[0]['request']->getBody());

$this->assertXmlStringEqualsXmlString(
'<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Body xmlns:ns-b3c6b39d="http://www.example.org/test/">
<ns-b3c6b39d:getSimple xmlns:ns-b3c6b39d="http://www.example.org/test/">
<in><![CDATA[foo]]></in>
</ns-b3c6b39d:getSimple>
</SOAP:Body>
<SOAP:Header xmlns:ns-b3c6b39d="http://www.example.org/test/">
<ns-b3c6b39d:getReturnMultiParam xmlns:ns-b3c6b39d="http://www.example.org/test/" xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" SOAP:mustUnderstand="true">
<in><![CDATA[foo]]></in>
</ns-b3c6b39d:getReturnMultiParam>
</SOAP:Header>
</SOAP:Envelope>',
(string)$this->requestResponseStack[1]['request']->getBody());
}

public function testNoOutput()
{
$this->responseMock->append(
Expand Down

0 comments on commit 61ed886

Please sign in to comment.