From d60eb191ab8bf8e33fd61a48a237a758eebdbf2c Mon Sep 17 00:00:00 2001 From: Francis Besset Date: Tue, 15 Oct 2013 11:46:12 +0200 Subject: [PATCH] Rewrited Definition of WebService and WSDL dumper --- Definition/Definition.php | 148 +++++++++++++++++++++++++++++ Definition/Message.php | 61 ++++++++++++ Definition/Method.php | 98 +++++++++++++++++++ Definition/Part.php | 55 +++++++++++ Definition/Type/ArrayOfType.php | 30 ++++++ Definition/Type/ComplexType.php | 39 ++++++++ Definition/Type/Type.php | 38 ++++++++ Definition/Type/TypeInterface.php | 23 +++++ Definition/Type/TypeRepository.php | 135 ++++++++++++++++++++++++++ 9 files changed, 627 insertions(+) create mode 100644 Definition/Definition.php create mode 100644 Definition/Message.php create mode 100644 Definition/Method.php create mode 100644 Definition/Part.php create mode 100644 Definition/Type/ArrayOfType.php create mode 100644 Definition/Type/ComplexType.php create mode 100644 Definition/Type/Type.php create mode 100644 Definition/Type/TypeInterface.php create mode 100644 Definition/Type/TypeRepository.php diff --git a/Definition/Definition.php b/Definition/Definition.php new file mode 100644 index 0000000..7d9f742 --- /dev/null +++ b/Definition/Definition.php @@ -0,0 +1,148 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapCommon\Definition; + +use BeSimple\SoapCommon\Definition\Type\TypeRepository; + +/** + * @author Francis Besset + */ +class Definition +{ + protected $name; + protected $namespace; + + protected $typeRepository; + + protected $options; + protected $methods; + + public function __construct($name, $namespace, TypeRepository $typeRepository, array $options = array()) + { + $this->name = $name; + $this->namespace = $namespace; + $this->methods = array(); + + $this->typeRepository = $typeRepository; + + $this->setOptions($options); + } + + public function setOptions(array $options) + { + $this->options = array( + 'version' => \SOAP_1_1, + 'style' => \SOAP_RPC, + 'use' => \SOAP_LITERAL, + 'location' => null, + ); + + $invalid = array(); + foreach ($options as $key => $value) { + if (array_key_exists($key, $this->options)) { + $this->options[$key] = $value; + } else { + $invalid[] = $key; + } + } + + if ($invalid) { + throw new \InvalidArgumentException(sprintf('The Definition does not support the following options: "%s"', implode('", "', $invalid))); + } + + return $this; + } + + public function setOption($key, $value) + { + if (!array_key_exists($key, $this->options)) { + throw new \InvalidArgumentException(sprintf('The Definition does not support the "%s" option.', $key)); + } + + $this->options[$key] = $value; + + return $this; + } + + public function getOption($key) + { + if (!array_key_exists($key, $this->options)) { + throw new \InvalidArgumentException(sprintf('The Definition does not support the "%s" option.', $key)); + } + + return $this->options[$key]; + } + + public function getName() + { + return $this->name; + } + + public function getNamespace() + { + return $this->namespace; + } + + public function getType($phpType) + { + return $this->types[$phpType]; + } + + public function addType($phpType, $xmlType) + { + if (isset($$this->types[$phpType])) { + throw new \Exception(); + } + + $this->types[$phpType] = $xmlType; + } + + public function getMessages() + { + $messages = array(); + foreach ($this->methods as $method) { + $messages[] = $method->getHeaders(); + $messages[] = $method->getInput(); + $messages[] = $method->getOutput(); + } + + return $messages; + } + + public function getMethod($name, $default = null) + { + return isset($this->methods[$name]) ? $this->methods[$name] : $default; + } + + public function getMethods() + { + return $this->methods; + } + + public function addMethod(Method $method) + { + $name = $method->getName(); + if (isset($this->methods[$name])) { + throw new \Exception(sprintf('The method "%s" already exists', $name)); + } + + $this->methods[$name] = $method; + + return $method; + } + + public function getTypeRepository() + { + return $this->typeRepository; + } +} diff --git a/Definition/Message.php b/Definition/Message.php new file mode 100644 index 0000000..caa78fe --- /dev/null +++ b/Definition/Message.php @@ -0,0 +1,61 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapCommon\Definition; + +use BeSimple\SoapCommon\Definition\Type\TypeInterface; + +/** + * @author Francis Besset + */ +class Message +{ + protected $name; + protected $parts; + + public function __construct($name) + { + $this->name = $name; + $this->parts = array(); + } + + public function getName() + { + return $this->name; + } + + public function all() + { + return $this->parts; + } + + public function get($name, $default = null) + { + return isset($this->parts[$name]) ? $this->parts[$name] : $default; + } + + public function isEmpty() + { + return 0 === count($this->parts) ? true : false; + } + + public function add($name, $phpType, $nillable = false) + { + if ($phpType instanceof TypeInterface) { + $phpType = $phpType->getPhpType(); + } + + $this->parts[$name] = new Part($name, $phpType, $nillable); + + return $this; + } +} diff --git a/Definition/Method.php b/Definition/Method.php new file mode 100644 index 0000000..a592e6a --- /dev/null +++ b/Definition/Method.php @@ -0,0 +1,98 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapCommon\Definition; + +use BeSimple\SoapCommon\Definition\Type\TypeRepository; + +/** + * @author Francis Besset + */ +class Method +{ + private $name; + + private $headers; + private $input; + private $output; + private $fault; + + public function __construct($name, TypeRepository $typeRepository) + { + $this->name = $name; + + $this->headers = new Message($name.'Header', $typeRepository); + $this->input = new Message($name.'Request', $typeRepository); + $this->output = new Message($name.'Response', $typeRepository); + $this->fault = new Message($name.'Fault', $typeRepository); + } + + public function getName() + { + return $this->name; + } + + public function getDefinition() + { + return $this->definition; + } + + public function getVersions() + { + return array(\SOAP_1_1, \SOAP_1_2); + } + + public function getUse() + { + return \SOAP_LITERAL; + } + + public function addHeader($name, $type) + { + $this->headers->add($name, $type); + } + + public function addInput($name, $type) + { + $this->input->add($name, $type); + } + + public function setOutput($type) + { + $this->output->add('return', $type); + } + + public function getHeaders() + { + return $this->headers; + } + + public function getHeader($name, $default = null) + { + return $this->headers->get($name, $default); + } + + public function getInput() + { + return $this->input; + } + + public function getOutput() + { + return $this->output; + } + + public function getFault() + { + return $this->fault; + } +} diff --git a/Definition/Part.php b/Definition/Part.php new file mode 100644 index 0000000..317f046 --- /dev/null +++ b/Definition/Part.php @@ -0,0 +1,55 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapCommon\Definition; + +/** + * @author Francis Besset + */ +class Part +{ + protected $name; + protected $type; + protected $nillable; + + public function __construct($name, $type, $nillable = false) + { + $this->name = $name; + $this->type = $type; + $this->setNillable($nillable); + } + + public function getName() + { + return $this->name; + } + + public function getType() + { + return $this->type; + } + + public function setType($type) + { + $this->type = $type; + } + + public function isNillable() + { + return $this->nillable; + } + + public function setNillable($nillable) + { + $this->nillable = (boolean) $nillable; + } +} diff --git a/Definition/Type/ArrayOfType.php b/Definition/Type/ArrayOfType.php new file mode 100644 index 0000000..6f05215 --- /dev/null +++ b/Definition/Type/ArrayOfType.php @@ -0,0 +1,30 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapCommon\Definition\Type; + +/** + * @author Francis Besset + */ +class ArrayOfType extends ComplexType +{ + public function __construct($phpType, $arrayOf, $xmlTypeOf) + { + if ($arrayOf instanceof TypeInterface) { + $arrayOf = $arrayOf->getPhpType(); + } + + parent::__construct($phpType, 'ArrayOf'.ucfirst($xmlTypeOf ?: $arrayOf)); + + $this->add('item', $arrayOf); + } +} diff --git a/Definition/Type/ComplexType.php b/Definition/Type/ComplexType.php new file mode 100644 index 0000000..99d6d3e --- /dev/null +++ b/Definition/Type/ComplexType.php @@ -0,0 +1,39 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapCommon\Definition\Type; + +use BeSimple\SoapCommon\Definition\Message; + +/** + * @author Francis Besset + */ +class ComplexType extends Message implements TypeInterface +{ + public function __construct($phpType, $xmlType) + { + parent::__construct($xmlType); + + $this->phpType = $phpType; + $this->xmlType = $xmlType; + } + + public function getPhpType() + { + return $this->phpType; + } + + public function getXmlType() + { + return $this->xmlType; + } +} diff --git a/Definition/Type/Type.php b/Definition/Type/Type.php new file mode 100644 index 0000000..7911c5a --- /dev/null +++ b/Definition/Type/Type.php @@ -0,0 +1,38 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapCommon\Definition\Type; + +/** + * @author Francis Besset + */ +class Type implements TypeInterface +{ + protected $phpType; + protected $xmlType; + + public function __construct($phpType, $xmlType) + { + $this->phpType = $phpType; + $this->xmlType = $xmlType; + } + + public function getPhpType() + { + return $this->phpType; + } + + public function getXmlType() + { + return $this->xmlType; + } +} diff --git a/Definition/Type/TypeInterface.php b/Definition/Type/TypeInterface.php new file mode 100644 index 0000000..7263353 --- /dev/null +++ b/Definition/Type/TypeInterface.php @@ -0,0 +1,23 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapCommon\Definition\Type; + +/** + * @author Francis Besset + */ +interface TypeInterface +{ + public function getPhpType(); + + public function getXmlType(); +} diff --git a/Definition/Type/TypeRepository.php b/Definition/Type/TypeRepository.php new file mode 100644 index 0000000..38d0f30 --- /dev/null +++ b/Definition/Type/TypeRepository.php @@ -0,0 +1,135 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapCommon\Definition\Type; + +use BeSimple\SoapCommon\Classmap; + +/** + * @author Christian Kerl + * @author Francis Besset + */ +class TypeRepository +{ + const ARRAY_SUFFIX = '[]'; + + protected $xmlNamespaces = array(); + protected $types = array(); + + protected $classmap; + + public function __construct(Classmap $classmap = null) + { + $this->classmap = $classmap; + } + + public function getXmlNamespaces() + { + return $this->xmlNamespaces; + } + public function getXmlNamespace($prefix) + { + return $this->xmlNamespaces[$prefix]; + } + + public function addXmlNamespace($prefix, $url) + { + $this->xmlNamespaces[$prefix] = $url; + } + + public function getComplexTypes() + { + $types = array(); + foreach ($this->types as $type) { + if ($type instanceof ComplexType) { + $types[] = $type; + } + } + + return $types; + } + + public function getType($phpType) + { + if (!$this->hasType($phpType)) { + throw new \Exception(); + } + + return $this->types[$phpType]; + } + + public function addType($phpType, $xmlType) + { + return $this->types[$phpType] = $xmlType; + } + + public function addComplexType(ComplexType $type) + { + $phpType = $type->getPhpType(); + + $this->types[$phpType] = $type; + $this->addClassmap($type->getXmlType(), $phpType); + } + + public function hasType($type) + { + if ($type instanceof TypeInterface) { + $phpType = $type->getPhpType(); + + return !(!$this->hasType($phpType) || $type !== $this->getType($phpType)); + } + + if (isset($this->types[$type])) { + return true; + } + + if (false !== $arrayOf = $this->getArrayOf($type)) { + if ($this->hasType($arrayOf)) { + $xmlTypeOf = null; + $arrayOfType = $this->getType($arrayOf); + if ($arrayOfType instanceof ComplexType) { + $xmlTypeOf = $arrayOfType->getXmlType(); + } + + $arrayType = new ArrayOfType($type, $arrayOf, $xmlTypeOf); + $this->addType($type, $arrayType); + + return true; + } + } + + return false; + } + + public function getArrayOf($arrayType) + { + if (!preg_match('#(.*)'.preg_quote(static::ARRAY_SUFFIX, '#').'$#', $arrayType, $match)) { + return false; + } + + return $match[1]; + } + + public function getClassmap() + { + return $this->classmap; + } + + protected function addClassmap($xmlType, $phpType) + { + if (!$this->classmap) { + return; + } + + $this->classmap->add($xmlType, $phpType); + } +}