Rewrited Definition of WebService and WSDL dumper
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
@ -14,6 +14,8 @@ namespace BeSimple\SoapBundle\ServiceDefinition\Loader;
|
||||
|
||||
use BeSimple\SoapBundle\ServiceDefinition as Definition;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Annotation;
|
||||
use BeSimple\SoapCommon\Definition\Type\ComplexType;
|
||||
use BeSimple\SoapCommon\Definition\Type\TypeRepository;
|
||||
|
||||
use Doctrine\Common\Annotations\Reader;
|
||||
|
||||
@ -26,19 +28,23 @@ use Symfony\Component\Config\Loader\LoaderResolverInterface;
|
||||
* Based on \Symfony\Component\Routing\Loader\AnnotationClassLoader
|
||||
*
|
||||
* @author Christian Kerl <christian-kerl@web.de>
|
||||
* @author Francis Besset <francis.besset@gmail.com>
|
||||
*/
|
||||
class AnnotationClassLoader extends Loader
|
||||
{
|
||||
protected $reader;
|
||||
|
||||
protected $typeRepository;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \Doctrine\Common\Annotations\Reader $reader
|
||||
*/
|
||||
public function __construct(Reader $reader)
|
||||
public function __construct(Reader $reader, TypeRepository $typeRepository)
|
||||
{
|
||||
$this->reader = $reader;
|
||||
$this->typeRepository = $typeRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -58,39 +64,26 @@ class AnnotationClassLoader extends Loader
|
||||
}
|
||||
|
||||
$class = new \ReflectionClass($class);
|
||||
$definition = new Definition\ServiceDefinition();
|
||||
$definition = new Definition\Definition($this->typeRepository);
|
||||
|
||||
$serviceMethodHeaders = array();
|
||||
$sharedHeaders = array();
|
||||
foreach ($this->reader->getClassAnnotations($class) as $annotation) {
|
||||
if ($annotation instanceof Annotation\Header) {
|
||||
$serviceMethodHeaders[$annotation->getValue()] = $annotation;
|
||||
$sharedHeaders[$annotation->getValue()] = $this->loadType($annotation->getPhpType());
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($class->getMethods() as $method) {
|
||||
$serviceArguments =
|
||||
$serviceHeaders = array();
|
||||
$serviceHeaders = $sharedHeaders;
|
||||
$serviceArguments = array();
|
||||
$serviceMethod =
|
||||
$serviceReturn = null;
|
||||
|
||||
foreach ($serviceMethodHeaders as $annotation) {
|
||||
$serviceHeaders[$annotation->getValue()] = new Definition\Header(
|
||||
$annotation->getValue(),
|
||||
$this->getArgumentType($method, $annotation)
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($this->reader->getMethodAnnotations($method) as $annotation) {
|
||||
if ($annotation instanceof Annotation\Header) {
|
||||
$serviceHeaders[$annotation->getValue()] = new Definition\Header(
|
||||
$annotation->getValue(),
|
||||
$this->getArgumentType($method, $annotation)
|
||||
);
|
||||
$serviceHeaders[$annotation->getValue()] = $this->loadType($annotation->getPhpType());
|
||||
} elseif ($annotation instanceof Annotation\Param) {
|
||||
$serviceArguments[] = new Definition\Argument(
|
||||
$annotation->getValue(),
|
||||
$this->getArgumentType($method, $annotation)
|
||||
);
|
||||
$serviceArguments[$annotation->getValue()] = $this->loadType($annotation->getPhpType());
|
||||
} elseif ($annotation instanceof Annotation\Method) {
|
||||
if ($serviceMethod) {
|
||||
throw new \LogicException(sprintf('@Soap\Method defined twice for "%s".', $method->getName()));
|
||||
@ -98,6 +91,7 @@ class AnnotationClassLoader extends Loader
|
||||
|
||||
$serviceMethod = new Definition\Method(
|
||||
$annotation->getValue(),
|
||||
$this->typeRepository,
|
||||
$this->getController($class, $method, $annotation)
|
||||
);
|
||||
} elseif ($annotation instanceof Annotation\Result) {
|
||||
@ -105,7 +99,7 @@ class AnnotationClassLoader extends Loader
|
||||
throw new \LogicException(sprintf('@Soap\Result defined twice for "%s".', $method->getName()));
|
||||
}
|
||||
|
||||
$serviceReturn = new Definition\Type($annotation->getPhpType(), $annotation->getXmlType());
|
||||
$serviceReturn = $annotation->getPhpType();
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,16 +108,21 @@ class AnnotationClassLoader extends Loader
|
||||
}
|
||||
|
||||
if ($serviceMethod) {
|
||||
$serviceMethod->setArguments($serviceArguments);
|
||||
$serviceMethod->setHeaders($serviceHeaders);
|
||||
foreach ($serviceHeaders as $name => $type) {
|
||||
$serviceMethod->addHeader($name, $type);
|
||||
}
|
||||
|
||||
foreach ($serviceArguments as $name => $type) {
|
||||
$serviceMethod->addInput($name, $type);
|
||||
}
|
||||
|
||||
if (!$serviceReturn) {
|
||||
throw new \LogicException(sprintf('@Soap\Result non-existent for "%s".', $method->getName()));
|
||||
}
|
||||
|
||||
$serviceMethod->setReturn($serviceReturn);
|
||||
$serviceMethod->setOutput($this->loadType($serviceReturn));
|
||||
|
||||
$definition->getMethods()->add($serviceMethod);
|
||||
$definition->addMethod($serviceMethod);
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,6 +168,30 @@ class AnnotationClassLoader extends Loader
|
||||
return new Definition\Type($phpType, $xmlType);
|
||||
}
|
||||
|
||||
private function loadType($phpType)
|
||||
{
|
||||
if (false !== $arrayOf = $this->typeRepository->getArrayOf($phpType)) {
|
||||
$this->loadType($arrayOf);
|
||||
}
|
||||
|
||||
if (!$this->typeRepository->hasType($phpType)) {
|
||||
$complexTypeResolver = $this->resolve($phpType, 'annotation_complextype');
|
||||
if (!$complexTypeResolver) {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
$loaded = $complexTypeResolver->load($phpType);
|
||||
$complexType = new ComplexType($phpType, $loaded['alias']);
|
||||
foreach ($loaded['properties'] as $name => $property) {
|
||||
$complexType->add($name, $this->loadType($property->getValue()), $property->isNillable());
|
||||
}
|
||||
|
||||
$this->typeRepository->addComplexType($complexType);
|
||||
}
|
||||
|
||||
return $phpType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this class supports the given resource.
|
||||
*
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
@ -65,4 +65,17 @@ class AnnotationComplexTypeLoader extends AnnotationClassLoader
|
||||
|
||||
return $annotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this class supports the given resource.
|
||||
*
|
||||
* @param mixed $resource A resource
|
||||
* @param string $type The resource type
|
||||
*
|
||||
* @return Boolean True if this class supports the given resource, false otherwise
|
||||
*/
|
||||
public function supports($resource, $type = null)
|
||||
{
|
||||
return is_string($resource) && class_exists($resource) && 'annotation_complextype' === $type;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the BeSimpleSoapBundle.
|
||||
* This file is part of the BeSimpleSoap.
|
||||
*
|
||||
* (c) Christian Kerl <christian-kerl@web.de>
|
||||
* (c) Francis Besset <francis.besset@gmail.com>
|
||||
|
@ -1,145 +0,0 @@
|
||||
<?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\SoapBundle\ServiceDefinition\Loader;
|
||||
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Argument;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Header;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Method;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\Type;
|
||||
use BeSimple\SoapBundle\ServiceDefinition\ServiceDefinition;
|
||||
|
||||
use Symfony\Component\Config\Loader\FileLoader;
|
||||
|
||||
class XmlFileLoader extends FileLoader
|
||||
{
|
||||
public function supports($resource, $type = null)
|
||||
{
|
||||
return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION);
|
||||
}
|
||||
|
||||
public function load($file, $type = null)
|
||||
{
|
||||
$path = $this->locator->locate($file);
|
||||
$xml = $this->parseFile($path);
|
||||
|
||||
$definition = new ServiceDefinition();
|
||||
$definition->setName((string) $xml['name']);
|
||||
$definition->setNamespace((string) $xml['namespace']);
|
||||
|
||||
foreach($xml->header as $header) {
|
||||
$definition->getHeaders()->add($this->parseHeader($header));
|
||||
}
|
||||
|
||||
foreach($xml->method as $method) {
|
||||
$definition->getMethods()->add($this->parseMethod($method));
|
||||
}
|
||||
|
||||
return $definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \SimpleXMLElement $node
|
||||
*
|
||||
* @return \BeSimple\SoapBundle\ServiceDefinition\Header
|
||||
*/
|
||||
protected function parseHeader(\SimpleXMLElement $node)
|
||||
{
|
||||
return new Header((string)$node['name'], $this->parseType($node->type));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \SimpleXMLElement $node
|
||||
*
|
||||
* @return \BeSimple\SoapBundle\ServiceDefinition\Method
|
||||
*/
|
||||
protected function parseMethod(\SimpleXMLElement $node)
|
||||
{
|
||||
$method = new Method((string)$node['name'], (string)$node['controller']);
|
||||
|
||||
foreach($node->argument as $argument) {
|
||||
$method->getArguments()->add($this->parseArgument($argument));
|
||||
}
|
||||
|
||||
$method->setReturn($this->parseType($node->return->type));
|
||||
|
||||
return $method;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \SimpleXMLElement $node
|
||||
*
|
||||
* @return \BeSimple\SoapBundle\ServiceDefinition\Argument
|
||||
*/
|
||||
protected function parseArgument(\SimpleXMLElement $node)
|
||||
{
|
||||
$argument = new Argument((string)$node['name'], $this->parseType($node->type));
|
||||
|
||||
return $argument;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \SimpleXMLElement $node
|
||||
*
|
||||
* @return \BeSimple\SoapBundle\ServiceDefinition\Type
|
||||
*/
|
||||
protected function parseType(\SimpleXMLElement $node)
|
||||
{
|
||||
$namespaces = $node->getDocNamespaces(true);
|
||||
$qname = explode(':', $node['xml-type'], 2);
|
||||
$xmlType = sprintf('{%s}%s', $namespaces[$qname[0]], $qname[1]);
|
||||
|
||||
return new Type((string)$node['php-type'], $xmlType, (string)$node['converter']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user