diff --git a/README.md b/README.md index 00be87e..f462d79 100644 --- a/README.md +++ b/README.md @@ -28,210 +28,236 @@ And why to use this library? ## Getting started -### 1. Creating an instance +### 1.Creating a Definition + +What is a definition class. It is a class that defined the name,namespace, functions and complex-types defined by the web service. + +In this example, we are defining a simple function : function hello($param); ```php -use eftec\cloudking\CloudKing; -include "../vendor/autoload.php"; - -$FILE = 'http://'.$_SERVER["SERVER_NAME"].$_SERVER["SCRIPT_NAME"]; -$NAMESPACE="examplenamespace"; -$NAME_WS='Example2WS'; -$ns=new CloudKing($FILE, $NAMESPACE, $NAME_WS); - -$ns->soap12=false; -$ns->verbose=2; -$ns->allowed_format["POST"]=true; -$ns->variable_type="array"; -// $service=new Example2WSService(); // we will work with this one later -// $ns->serviceInstance=$service; // we will work with this one later -$ns->description="Example Server"; +class ExampleDefinition { + public static $service; + + /** + * You must create this file manually. + * + * @param bool $gui if true then it shows the web gui + */ + public static function init($gui = true) { + $FILE = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['SCRIPT_NAME']; + $NAMESPACE + = 'http://www.examplenamespace.cl/'; // the namespace of the web service. It could be anything and not specifically an existing url + $NAME_WS = 'Example2WS'; // the name of the service + + self::$service = new CloudKing($FILE, $NAMESPACE, $NAME_WS); + self::$service->allowed_input['gui'] = $gui; // set to false to disable the web gui. + self::$service->serviceInstance = null; + self::$service->verbose = 2; // for debug purpose + self::$service->description = 'Example server SoapKing'; + + self::$service->addfunction('hello', + [ + self::$service->param('param', 'string', true, false), + ], + [ + self::$service->param('return', 'string') + ], + 'Example of function' + ); + } + + public static function run() { + $r = self::$service->run(); + echo $r; + } +} ``` -You should create an instance indicating the url, namespace, and the name of the webservice. +We will explain more about it later. -You could also indicates other factors and it depends on every case. In case of doubt, you could use the cases indicates in this example. +### 2. Running the first time. -This variable is important +Let's call the definition as follow ```php -$ns->soap12=false; +addfunction("ping" - , [CloudKing::argPrim('ping_param', 's:string')] - , [CloudKing::argPrim('return', 's:string')] - , "Descripcion :Prueba de conexion"); -``` +Open the SOAPUI (or the program that you want to use), and paste the url of the wsdl (obtained in the previous step) and runs it. -In this example, the input is an argument called **ping_param** (string) and the result (called return) is a string. +![docs/hellosoap.jpg](docs/hellosoap.jpg) -* s:**name** = means a primitive value -* tns:**Complex** = indicates a complex structure. +And it will show all the methods defined. In our case, there is a single function called "hello". Then, you can run it. -Example: getting a complex object +![docs/hellosoap2.jpg](docs/hellosoap2.jpg) -```php -$ns->addfunction("GetProducto" - , [CloudKing::argPrim('idProducto', 's:integer')] - , [CloudKing::argComplex('return', 'tns:Producto')] - , "Descripcion :obtiene los datos de una objeto"); -``` +If you run it, it will fail. Why? It is because we are yet to define the service class. -In this case, it uses an complex called tns:**Producto** in the argument return. The name "return" could not be required. +### 4. Service class -You must also specific the complex structure as follow: +In our website, there is a link called SOURCE GENERATION. Click on it and it will show the next screen. + +You can generate a c# code, and both php code (from server and client). We need to generate the server source. If you click on the View PHP Server Source, you can look at the code. However, you can also generate it directly. However, for that, you will need to set the folder + +![docs/helloservice2.jpg](docs/helloservice2.jpg) -```php -$ns->addtype("Producto", [ // because we use "tns:Producto" - CloudKing::argPrim('idProduct', 's:integer'), - CloudKing::argPrim('nombre', 's:string'), - CloudKing::argPrim('precio', 's:integer') -]); -``` -You could also create more complex types as follow + +Let's modify the file of the step 2 ```php -$ns->addtype("Cart", [ - CloudKing::argList('products', 'tns:Producto', 0, 'unbounded'), // a list of products - CloudKing::argPrim('total', 's:integer'), // a primitive - CloudKing::argComplex('category', 'tns:category') // a complex not created for this example -]); +folderServer=__DIR__; // or you could select any folder. +ExampleDefinition::run(); + ``` -Example of function (input value is a complex): +And if we refresh the website, it will show + +![docs/helloservice3.jpg](docs/helloservice3.jpg) + +So, you could generate 1 class and 1 interface automatically. Click on it, and it will generate both files + +![docs/helloservice4.jpg](docs/helloservice4.jpg) + +It will generate the folder service and 2 files + +📁 service + +___ 📃 ExampleHelloService.php (our service class) + +___ 📃 IExampleHelloService.php (the interface class) + +### 5. Editing the Service Class. + +This class is half-generated. We could edit our operations inside this class, so let's change our code. ```php -$ns->addfunction("InsertProducto" - , array(CloudKing::argComplex('Producto', 'tns:Producto')) - ,array(CloudKing::argPrim('return', 's:boolean')) - , "Descripcion :obtiene los datos de una objeto" -); +class ExampleHelloService implements IExampleHelloService { + + /** + * @inheritDoc + */ + public function hello(&$param) { + return $param." world!"; // <--- edit this. + } +} // end class ``` +### 6. Editing our service - -Example: returning a list of objects +Let's modify our service defined in the step 2 again and now, we must indicate our service class (created in the step 4) ```php -$ns->addfunction("GetProductos" - , [] - , [CloudKing::argList('return', 'tns:Producto', 0, 'unbounded')] - , "Descripcion :Obtiene una lista de productos"); +ExampleDefinition::init(); +ExampleDefinition::$service->folderServer=__DIR__; // or you could select any folder.run_initial.php +ExampleDefinition::$service->serviceInstance=new ExampleHelloService(); +ExampleDefinition::run(); ``` -In this case, the function doesn't requires an input value and it returns a list of objects. +And let's run it again using SOAPUI -### 3. Running +![docs/hellosoap3.jpg](docs/hellosoap3.jpg) -Finally, with the instance and the schema, you could run the interface +And now, we have the service up and running. -``` -$ns->run(); -``` +You could later disable the GUI -And open the website to show the interface. +# Definition -In the interface, you could see the WSDL, the methods and the generation of the code. +## Parameters -### 4. Generating the service class +Parameters are used to indicate the arguments of a function, the return value of a function or the fields of a complex structure. -![](docs/generation.jpg) +#### Defining a single parameter. -You could generate the client or server (our service class). Let's generate the PHP Server Source. +> param(name of the parameter, type , reference, required , description) -This generated class lacks of the implementation but everything else is ready. +* name of the parameter : it is the name of the parameter, for example "idCompany", "money" and such +* type: the type of the parameter. It could be a **primitive** value (string,integer,etc.) or it could be defined by a structure/class (called **complex**). If we want to use a **complex** type, we need to define it after we want to use it. +* reference: (optional)If true then the value is also returned. If false, then the value is not returned. +* required: (optional)If true then the value is required. +* description: (optional) An optional description of the parameter. ```php -class Example2WSService { - function ping($ping_param) { - try { - // todo: missing implementation - /* - $_ping_param=''; - */ - // End Input Values - $_pingResult=''; - return $_pingResult; - } catch (Exception $_exception) { - return(array("soap:Fault"=>'Caught exception: '. $_exception->getMessage())); - } - } - // .... -} +self::$service->param('counter', 'integer') // a parameter called "counter" of the type integer +self::$service->param('name', 'string', true, false, "description") // a string parameter called "name" +self::$service->param('prod', 'Product', true, false, "description") // a parameter called "prod" of the complex type Product (it must be defined) ``` -We should create a new PHP file, in our example **Example2WSService.php** +#### Defining an array of parameters -In the step 1, we create the instance of the CloudKing, with the service class up and running, we are ready to finish the implementation of the server. +It is also possible to define an array (list) of parameters. -Uncomment the next line of code (from the step 1) +> paramList(name of the parameter, type , reference, required , description ) ```php -include "Example2WSService.php"; -$service=new Example2WSService(); -$ns->serviceInstance=$service; +self::$service->paramList('names', 'string') // defining an array of string called "names" +self::$service->paramList('productList', 'Product',false,false,'List of products') // defining an array of complex type Product called "productList" ``` -And now, our web service is up and running and we could test into SOAPUI (or any other tools compatible with SOAP) +> Note: This function defines automatically a complex type called ArrayOf\ . If the complex type exists (complex with the same name), then it uses it instead of create a new one. -![](docs/soap1.jpg) +## Complex Types -> Remember that in the main website, you could obtain the description WSDL. It is required for some programs (see image). You could also obtain by calling the webserver with the argument ?wsdl Example: myws.php?wsdl +It is also possible to define a complex type. A complex type is used when we need to define a model or structure. -### 5. Creating the client +> addType( name of the type , [ parameters ] , description) -We could create the client in the same way (with the UI) and we could change the webport and the default namespace. +* name of the type: it is the name of the time. The case of the name matters. +* parameters: We could define one of more parameters for the type. We could even define list of parameters or even parameters that use complex types. +* description: (optional) The description of the type ```php -tempuri=$this->tempuri; - $_obj->soap='1.1' - $_param=''; - $_param.=$_obj->array2xml($ping_param,'ts:ping_param',false,false); - $resultado=$_obj->loadurl($this->url,$_param,'ping'); - return @$resultado['pingResult']; - } - // ... -} +self::$service->addtype('Product', + [ + self::$service->param('idProduct', 'int',false,true, 'comentary'), + self::$service->param('name', 'string'), + self::$service->param('price', 'int') + ]); ``` -And you could call this class like any other service class +Example: Defining a complex type of an invoice with the invoice detail. ```php -$x=new Example2WSClient(); -var_dump($x->ping(20)); +self::$service->addtype('InvoiceDetail', [ + self::$service->param('idInvoiceDetail', 'int'), + self::$service->param('idInvoice', 'int'), + self::$service->param('detail', 'string') +]); +self::$service->addtype('Invoice', [ + self::$service->param('idInvoice', 'int'), + self::$service->paramList('details','InvoiceDetail'), +]); ``` -## TODO - -There is some broken features but it works in basic examples. ## Versions +* 3.0 + * Rebuild the engine. Now SOAP and JSON works correctly. * 2.6 * Fixed the client when it returns an array of objects. * 2.5 diff --git a/composer.json b/composer.json index 691c148..48ed13e 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "type": "library", "description": "A SOAP webserver for PHP", "license": "MIT", - "version": "2.6", + "version": "3.0", "authors": [ { "name": "Jorge Castro", @@ -16,9 +16,17 @@ "ext-xml": "*", "ext-curl": "*" }, + "require-dev": { + "phpunit/phpunit": "^5.7" + }, "autoload": { "psr-4": { "eftec\\cloudking\\": "lib/" } + }, + "autoload-dev": { + "psr-4": { + "eftec\\tests\\": "tests/" + } } } diff --git a/docs/helloservice.jpg b/docs/helloservice.jpg new file mode 100644 index 0000000..50cea82 Binary files /dev/null and b/docs/helloservice.jpg differ diff --git a/docs/helloservice2.jpg b/docs/helloservice2.jpg new file mode 100644 index 0000000..3dd7547 Binary files /dev/null and b/docs/helloservice2.jpg differ diff --git a/docs/helloservice3.jpg b/docs/helloservice3.jpg new file mode 100644 index 0000000..85421fd Binary files /dev/null and b/docs/helloservice3.jpg differ diff --git a/docs/helloservice4.jpg b/docs/helloservice4.jpg new file mode 100644 index 0000000..1a24157 Binary files /dev/null and b/docs/helloservice4.jpg differ diff --git a/docs/hellosoap.jpg b/docs/hellosoap.jpg new file mode 100644 index 0000000..9569b53 Binary files /dev/null and b/docs/hellosoap.jpg differ diff --git a/docs/hellosoap2.jpg b/docs/hellosoap2.jpg new file mode 100644 index 0000000..40713be Binary files /dev/null and b/docs/hellosoap2.jpg differ diff --git a/docs/hellosoap3.jpg b/docs/hellosoap3.jpg new file mode 100644 index 0000000..80e4948 Binary files /dev/null and b/docs/hellosoap3.jpg differ diff --git a/examples/1.create/CreateWebService.php b/examples/1.create/CreateWebService.php deleted file mode 100644 index 24dcd2a..0000000 --- a/examples/1.create/CreateWebService.php +++ /dev/null @@ -1,7 +0,0 @@ -allowed_input['gui']=$gui; // set to false to disable the web gui. - self::$service->soap12 = false; - self::$service->verbose = 2; - self::$service->allowed_format['POST'] = true; - //self::$service->allowed_format["GET"]=false; - self::$service->variable_type = 'array'; - self::$service->serviceInstance = null; - self::$service->description = 'Example server SoapKing'; - - self::$service->addfunction('ping', - [ - CloudKing::argPrim('ping_param', 's:string'), - ], - [ - CloudKing::argPrim('return', 's:string') - ], - 'Descripcion :Prueba de conexion' - ); - self::$service->addfunction('GetProducto', - [ - CloudKing::argPrim('idProducto', 's:integer') - ], - [ - CloudKing::argComplex('return', 'tns:Producto') - ], - 'Descripcion :obtiene los datos de una objeto' - ); - self::$service->addfunction('InsertProducto' - , array(CloudKing::argComplex('Producto', 'tns:Producto')) - , array(CloudKing::argPrim('return', 's:boolean')) - , 'Descripcion :obtiene los datos de una objeto' - ); - self::$service->addfunction('GetProductos', - [ - - ], - [ - CloudKing::argList('return', 'tns:Producto', 0, 'unbounded') - ], - 'Descripcion :Obtiene una lista de productos' - ); - - // ***** type - self::$service->addtype('Producto', - [ - CloudKing::argPrim('idProduct', 's:integer'), - CloudKing::argPrim('nombre', 's:string'), - CloudKing::argPrim('precio', 's:integer') - ]); - self::$service->addtype('ProductoArray', - [ - CloudKing::argList('Producto', 'tns:Producto', '0', 'unbounded') - ]); - } - public static function run() { - $r = self::$service->run(); - echo $r; - } -} - - - diff --git a/examples/2.service/Example2WSService.php b/examples/2.service/Example2WSService.php deleted file mode 100644 index a53c82d..0000000 --- a/examples/2.service/Example2WSService.php +++ /dev/null @@ -1,85 +0,0 @@ -getDB(); - $values[]=$content; - $r=file_put_contents('data.txt',serialize($values)); - } - - - function ping($ping_param) { - try { - - - return $ping_param; - } catch (Exception $_exception) { - return(array("soap:Fault"=>'Caught exception: '. $_exception->getMessage())); - } - } - - function GetProducto($idProducto) { - try { - - $all=$this->getDB(); - $_Producto=null; - foreach($all as $item) { - if(@$item['idProducto']===$idProducto) { - $_Producto=$item; - break; - } - } - - - return $_Producto; - } catch (Exception $_exception) { - return(array("soap:Fault"=>'Caught exception: '. $_exception->getMessage())); - } - } - - function InsertProducto($Producto) { - - $all=$this->getDB(); - $all[]=$Producto; - $this->saveDB($all); - return count($all); - - } - - function GetProductos() { - - return $this->getDB(); - - } - - function factoryProducto($idProduct=0,$nombre='',$precio=0) { - $_Producto['idProduct']=$idProduct; - $_Producto['nombre']=$nombre; - $_Producto['precio']=$precio; - - } - - function factoryProductoArray($Producto=array()) { - $_ProductoArray['Producto']=$Producto; - - } -} // end class - -/************************************ Complex Types (Classes) ************************************/ - -class Producto { - var $idProduct; // s:integer - var $nombre; // s:string - var $precio; // s:integer -} - -class ProductoArray { - var $Producto; // tns:Producto -} \ No newline at end of file diff --git a/examples/3.join/WebService.php b/examples/3.join/WebService.php deleted file mode 100644 index 2e007aa..0000000 --- a/examples/3.join/WebService.php +++ /dev/null @@ -1,10 +0,0 @@ -serviceInstance=new Example2WSService(); // we tied the web service with our service class - -Definition::run(); \ No newline at end of file diff --git a/examples/3.join/data.txt b/examples/3.join/data.txt deleted file mode 100644 index 00eea1a..0000000 --- a/examples/3.join/data.txt +++ /dev/null @@ -1 +0,0 @@ -a:4:{i:0;a:3:{s:10:"idProducto";s:1:"2";s:6:"nombre";s:1:"3";s:6:"precio";s:1:"4";}i:1;a:3:{s:10:"idProducto";s:1:"2";s:6:"nombre";s:1:"3";s:6:"precio";s:1:"4";}i:2;a:3:{s:10:"idProducto";s:1:"6";s:6:"nombre";s:6:"fdfdfd";s:6:"precio";s:6:"dffdfd";}i:3;a:3:{s:9:"idProduct";s:1:"1";s:6:"nombre";s:9:"product 1";s:6:"precio";s:3:"555";}} \ No newline at end of file diff --git a/examples/4.client/Example2WSClient.php b/examples/4.client/Example2WSClient.php deleted file mode 100644 index 0e6319a..0000000 --- a/examples/4.client/Example2WSClient.php +++ /dev/null @@ -1,102 +0,0 @@ - - * Example server SoapKing
- * This code was generated automatically using CloudKing v2.5, Date:Sun, 18 Oct 2020 23:08:41 -0300
- * Using the web:http://localhost/currentproject/cloudking/examples/1.create/CreateWebService.php?source=phpclient - */ -class Example2WSClient { - /** @var string The full url where is the web service */ - protected $url='http://localhost/currentproject/cloudking/examples/3.join/WebService.php'; - /** @var string The namespace of the web service */ - protected $tempuri='examplenamespace'; - /** @var string The last error. It is cleaned per call */ - public $lastError=''; - /** @var float=[1.1,1.2][$i] The SOAP used by default */ - protected $soap=1.1; - /** @var CloudKingClient */ - public $service; - /** - * Example2WSClient constructor. - * - * @param string|null $url The full url (port) of the web service - * @param string|null $tempuri The namespace of the web service - * @param float|null $soap=[1.1,1.2][$i] The SOAP used by default - */ - public function __construct($url=null, $tempuri=null, $soap=null) { - $url!==null and $this->url = $url; - $tempuri!==null and $this->tempuri = $tempuri; - $soap!==null and $this->soap = $soap; - $this->service=new CloudKingClient($this->soap,$this->tempuri); - } - - - /** - * Descripcion :Prueba de conexion - * - * @param mixed $ping_param (s:string) - * @return mixed (s:string) - * @noinspection PhpUnused */ - public function ping($ping_param) { - $_param=''; - $_param.=$this->service->array2xml($ping_param,'ts:ping_param',false,false); - $resultado=$this->service->loadurl($this->url,$_param,'ping'); - $this->lastError=$this->service->lastError; - if(!is_array($resultado)) { - return false; // error - } - return @$resultado['pingResult']; - } - - /** - * Descripcion :obtiene los datos de una objeto - * - * @param mixed $idProducto (s:integer) - * @return mixed (tns:Producto) - * @noinspection PhpUnused */ - public function GetProducto($idProducto) { - $_param=''; - $_param.=$this->service->array2xml($idProducto,'ts:idProducto',false,false); - $resultado=$this->service->loadurl($this->url,$_param,'GetProducto'); - $this->lastError=$this->service->lastError; - if(!is_array($resultado)) { - return false; // error - } - return @$resultado['GetProductoResult']; - } - - /** - * Descripcion :obtiene los datos de una objeto - * - * @param mixed $Producto (tns:Producto) - * @return mixed (s:boolean) - * @noinspection PhpUnused */ - public function InsertProducto($Producto) { - $_param=''; - $_param.=$this->service->array2xml($Producto,'ts:Producto',false,false); - $resultado=$this->service->loadurl($this->url,$_param,'InsertProducto'); - $this->lastError=$this->service->lastError; - if(!is_array($resultado)) { - return false; // error - } - return @$resultado['InsertProductoResult']; - } - - /** - * Descripcion :Obtiene una lista de productos - * - * @return mixed (tns:Producto) - * @noinspection PhpUnused */ - public function GetProductos() { - $_param=''; - $resultado=$this->service->loadurl($this->url,$_param,'GetProductos'); - $this->lastError=$this->service->lastError; - if(!is_array($resultado)) { - return false; // error - } - return @$resultado['GetProductosResult']; - } -} // end Example2WSClient \ No newline at end of file diff --git a/examples/Definition.php b/examples/Definition.php new file mode 100644 index 0000000..c68bd36 --- /dev/null +++ b/examples/Definition.php @@ -0,0 +1,124 @@ +allowed_input['gui']=$gui; // set to false to disable the web gui. + self::$service->soap12 = false; // if we want to use soap 1.2 + self::$service->verbose = 2; // for debug purpose + + //self::$service->allowed_format["GET"]=false; + self::$service->serviceInstance = null; + self::$service->description = 'Example server SoapKing'; + // ***** complex types + self::$service->addtype('Producto', + [ + self::$service->param('idProduct', 'int',false,true, 'comentario'), + self::$service->param('nombre', 'string'), + self::$service->param('precio', 'int') + ]); + self::$service->addtype('InvoiceDetail', [ + self::$service->param('idInvoiceDetail', 'int',false,true), + self::$service->param('idInvoice', 'int'), + self::$service->param('detail', 'string') + ]); + self::$service->addtype('Invoice', [ + self::$service->param('idInvoice', 'int',false,true,'type invoice'), + self::$service->paramList('details','InvoiceDetail'), + ]); + + + self::$service->addfunction('GetInvoice' + , [self::$service->param('idInvoice','int',false,true,'the id of the invoice to get')] + , [self::$service->param('Invoice', 'Invoice')] + , 'Description :get invoices'); + + self::$service->addfunction('ping', + [ + self::$service->param('ping_param', 'string',true,false), + ], + [ + self::$service->param('return', 'string') + ], + 'Description :Prueba de conexion' + ); + self::$service->addfunction('pingshot', + [ + self::$service->param('ping_param', 'string'), + ],null, + 'Description :Prueba de conexion' + ); + self::$service->addfunction('doubleping', + [ + self::$service->param('ping_param1', 'string'), + self::$service->param('ping_param2', 'string'), + ], + [ + self::$service->param('return', 'string') + ], + 'Description :Prueba de conexion' + ); + + self::$service->addfunction('GetProducto', + [ + self::$service->param('idProducto', 'int',false,true,'id del producto') + ], + [ + self::$service->param('return', 'Producto',false) + ], + 'Description :obtiene los datos de una objeto' + ); + self::$service->addfunction('InsertProducto' + , array(self::$service->param('Producto', 'Producto')) + , array(self::$service->param('return', 'int')) + , 'Description :obtiene los datos de una objeto' + ); + self::$service->addfunction('UpdateProducto' + , array(self::$service->param('Producto', 'Producto')) + , array(self::$service->param('return', 'boolean')) + , 'Description :obtiene los datos de una objeto' + ); + self::$service->addfunction('DeleteProducto', + [ + self::$service->param('idProducto', 'int',false,true,'id del producto') + ], + [ + self::$service->param('return', 'boolean',false) + ], + 'Description :delete an product' + ); + self::$service->addfunction('GetProductos', + [], + [ + self::$service->paramList('return', 'Producto',false,false,'List of products') + ], + 'Description :Obtiene una lista de productos' + ); + + + } + public static function run() { + $r = self::$service->run(); + echo $r; + } +} + + + diff --git a/examples/Server.php b/examples/Server.php new file mode 100644 index 0000000..aefbe6c --- /dev/null +++ b/examples/Server.php @@ -0,0 +1,12 @@ +folderServer=__DIR__; +Definition::$service->serviceInstance=new Example2WSService(); +Definition::run(); diff --git a/examples/4.client/clientexample2.php b/examples/clienteexample.php similarity index 65% rename from examples/4.client/clientexample2.php rename to examples/clienteexample.php index dd079d8..4151646 100644 --- a/examples/4.client/clientexample2.php +++ b/examples/clienteexample.php @@ -1,14 +1,15 @@ "; var_dump($x->GetProductos()); +var_dump($x->doubleping('a1','a2')); echo "\nErrors:\n"; var_dump($x->lastError); echo ""; diff --git a/examples/service/Example2WSClient.php b/examples/service/Example2WSClient.php new file mode 100644 index 0000000..3394420 --- /dev/null +++ b/examples/service/Example2WSClient.php @@ -0,0 +1,194 @@ + + * Example server SoapKing
+ * This code was generated automatically using CloudKing v3.0, Date:Mon, 26 Oct 2020 18:13:02 -0300
+ * Using the web:http://localhost/currentproject/cloudking/examples/Server.php?source=phpclient + */ +class Example2WSClient { + /** @var string The full url where is the web service */ + protected $url='http://localhost/currentproject/cloudking/examples/Server.php'; + /** @var string The namespace of the web service */ + protected $tempuri='http://www.examplenamespace.cl/'; + /** @var string The last error. It is cleaned per call */ + public $lastError=''; + /** @var float=[1.1,1.2][$i] The SOAP used by default */ + protected $soap=1.1; + /** @var CloudKingClient */ + public $service; + /** + * Example2WSClient constructor. + * + * @param string|null $url The full url (port) of the web service + * @param string|null $tempuri The namespace of the web service + * @param float|null $soap=[1.1,1.2][$i] The SOAP used by default + */ + public function __construct($url=null, $tempuri=null, $soap=null) { + $url!==null and $this->url = $url; + $tempuri!==null and $this->tempuri = $tempuri; + $soap!==null and $this->soap = $soap; + $this->service=new CloudKingClient($this->soap,$this->tempuri); + } + + + /** + * Description :get invoices + * + * @param mixed $idInvoice the id of the invoice to get (s:int) + * @return mixed (tns:Invoice) + * @noinspection PhpUnused */ + public function GetInvoice($idInvoice) { + $_param=''; + $_param.=$this->service->array2xml($idInvoice,'ts:idInvoice',false,false); + $resultado=$this->service->loadurl($this->url,$_param,'GetInvoice'); + $this->lastError=$this->service->lastError; + if(!is_array($resultado)) { + return false; // error + } + return @$resultado['GetInvoiceResult']; + } + + /** + * Description :Prueba de conexion + * + * @param mixed $ping_param (s:string) + * @return mixed (s:string) + * @noinspection PhpUnused */ + public function ping(&$ping_param) { + $_param=''; + $_param.=$this->service->array2xml($ping_param,'ts:ping_param',false,false); + $resultado=$this->service->loadurl($this->url,$_param,'ping'); + $this->lastError=$this->service->lastError; + if(!is_array($resultado)) { + return false; // error + } + $ping_param=@$resultado['ping_param']; + return @$resultado['pingResult']; + } + + /** + * Description :Prueba de conexion + * + * @param mixed $ping_param (s:string) + * @return mixed (void) + * @noinspection PhpUnused */ + public function pingshot($ping_param) { + $_param=''; + $_param.=$this->service->array2xml($ping_param,'ts:ping_param',false,false); + $resultado=$this->service->loadurl($this->url,$_param,'pingshot'); + $this->lastError=$this->service->lastError; + if(!is_array($resultado)) { + return false; // error + } + return @$resultado['pingshotResult']; + } + + /** + * Description :Prueba de conexion + * + * @param mixed $ping_param1 (s:string) + * @param mixed $ping_param2 (s:string) + * @return mixed (s:string) + * @noinspection PhpUnused */ + public function doubleping($ping_param1, $ping_param2) { + $_param=''; + $_param.=$this->service->array2xml($ping_param1,'ts:ping_param1',false,false); + $_param.=$this->service->array2xml($ping_param2,'ts:ping_param2',false,false); + $resultado=$this->service->loadurl($this->url,$_param,'doubleping'); + $this->lastError=$this->service->lastError; + if(!is_array($resultado)) { + return false; // error + } + return @$resultado['doublepingResult']; + } + + /** + * Description :obtiene los datos de una objeto + * + * @param mixed $idProducto id del producto (s:int) + * @return mixed (tns:Producto) + * @noinspection PhpUnused */ + public function GetProducto($idProducto) { + $_param=''; + $_param.=$this->service->array2xml($idProducto,'ts:idProducto',false,false); + $resultado=$this->service->loadurl($this->url,$_param,'GetProducto'); + $this->lastError=$this->service->lastError; + if(!is_array($resultado)) { + return false; // error + } + return @$resultado['GetProductoResult']; + } + + /** + * Description :obtiene los datos de una objeto + * + * @param mixed $Producto (tns:Producto) + * @return mixed (s:int) + * @noinspection PhpUnused */ + public function InsertProducto($Producto) { + $_param=''; + $_param.=$this->service->array2xml($Producto,'ts:Producto',false,false); + $resultado=$this->service->loadurl($this->url,$_param,'InsertProducto'); + $this->lastError=$this->service->lastError; + if(!is_array($resultado)) { + return false; // error + } + return @$resultado['InsertProductoResult']; + } + + /** + * Description :obtiene los datos de una objeto + * + * @param mixed $Producto (tns:Producto) + * @return mixed (s:boolean) + * @noinspection PhpUnused */ + public function UpdateProducto($Producto) { + $_param=''; + $_param.=$this->service->array2xml($Producto,'ts:Producto',false,false); + $resultado=$this->service->loadurl($this->url,$_param,'UpdateProducto'); + $this->lastError=$this->service->lastError; + if(!is_array($resultado)) { + return false; // error + } + return @$resultado['UpdateProductoResult']; + } + + /** + * Description :delete an product + * + * @param mixed $idProducto id del producto (s:int) + * @return mixed (s:boolean) + * @noinspection PhpUnused */ + public function DeleteProducto($idProducto) { + $_param=''; + $_param.=$this->service->array2xml($idProducto,'ts:idProducto',false,false); + $resultado=$this->service->loadurl($this->url,$_param,'DeleteProducto'); + $this->lastError=$this->service->lastError; + if(!is_array($resultado)) { + return false; // error + } + return @$resultado['DeleteProductoResult']; + } + + /** + * Description :Obtiene una lista de productos + * + * @return mixed (tns:ArrayOfProducto) + * @noinspection PhpUnused */ + public function GetProductos() { + $_param=''; + $resultado=$this->service->loadurl($this->url,$_param,'GetProductos'); + $this->lastError=$this->service->lastError; + if(!is_array($resultado)) { + return false; // error + } + return @$resultado['GetProductosResult']; + } +} // end Example2WSClient diff --git a/examples/service/Example2WSService.php b/examples/service/Example2WSService.php new file mode 100644 index 0000000..6fe6bbe --- /dev/null +++ b/examples/service/Example2WSService.php @@ -0,0 +1,159 @@ +getDB(); + foreach($products as $k=>$product) { + if($idProducto==$product['idProduct']) { + return $product; + } + } + return null; + } + + + /** + * @inheritDoc + */ + public function InsertProducto($Producto) { + $products=$this->getDB(); + foreach($products as $k=>$product) { + if($Producto['idProduct']==$product['idProduct']) { + return 0; + } + } + $products[]=$Producto; + $this->saveDB($products); + return 1; + } + + + /** + * @inheritDoc + */ + public function GetProductos() { + return $this->getDB(); + } + + public function UpdateProducto($Producto) { + $products=$this->getDB(); + $found=0; + foreach($products as $k=>$product) { + if($Producto['idProduct']==$product['idProduct']) { + $products[$k]=$Producto; + $found=1; + break; + } + } + $this->saveDB($products); + return $found; + } + + public function DeleteProducto($idProducto) { + $products=$this->getDB(); + $found=0; + foreach($products as $k=>$product) { + if($idProducto==$product['idProduct']) { + array_splice($products,$k,1); + $found=1; + break; + } + } + $this->saveDB($products); + return $found; + } + + public static function factoryProducto($idProduct=null, $nombre=null, $precio=null) { + $_Producto['idProduct']=$idProduct; + $_Producto['nombre']=$nombre; + $_Producto['precio']=$precio; + return $_Producto; + } + + public static function factoryInvoiceDetail($idInvoiceDetail=null, $idInvoice=null, $detail=null) { + $_InvoiceDetail['idInvoiceDetail']=$idInvoiceDetail; + $_InvoiceDetail['idInvoice']=$idInvoice; + $_InvoiceDetail['detail']=$detail; + return $_InvoiceDetail; + } + + public static function factoryArrayOfInvoiceDetail($InvoiceDetail=null) { + $_ArrayOfInvoiceDetail['InvoiceDetail']=$InvoiceDetail; + return $_ArrayOfInvoiceDetail; + } + + public static function factoryInvoice($idInvoice=null, $details=null) { + $_Invoice['idInvoice']=$idInvoice; + $_Invoice['details']=$details; + return $_Invoice; + } + + public static function factoryArrayOfProducto($Producto=null) { + $_ArrayOfProducto['Producto']=$Producto; + return $_ArrayOfProducto; + } + + +} // end class + \ No newline at end of file diff --git a/examples/service/IExample2WSService.php b/examples/service/IExample2WSService.php new file mode 100644 index 0000000..690337f --- /dev/null +++ b/examples/service/IExample2WSService.php @@ -0,0 +1,97 @@ +allowed_input['gui'] = $gui; // set to false to disable the web gui. + self::$service->serviceInstance = null; + self::$service->verbose = 2; // for debug purpose + self::$service->description = 'Example server SoapKing'; + + self::$service->addfunction('hello', + [ + self::$service->param('param', 'string', true, false), + ], + [ + self::$service->param('return', 'string') + ], + 'Example of function' + ); + } + + public static function run() { + $r = self::$service->run(); + echo $r; + } +} \ No newline at end of file diff --git a/examples/startup_example/run_initial.php b/examples/startup_example/run_initial.php new file mode 100644 index 0000000..34d8fac --- /dev/null +++ b/examples/startup_example/run_initial.php @@ -0,0 +1,7 @@ +folderServer=__DIR__; // or you could select any folder.run_initial.php +ExampleDefinition::run(); \ No newline at end of file diff --git a/examples/startup_example/run_with_service.php b/examples/startup_example/run_with_service.php new file mode 100644 index 0000000..6c4e9eb --- /dev/null +++ b/examples/startup_example/run_with_service.php @@ -0,0 +1,12 @@ +folderServer=__DIR__; // or you could select any folder.run_initial.php +ExampleDefinition::$service->serviceInstance=new ExampleHelloService(); +ExampleDefinition::run(); \ No newline at end of file diff --git a/examples/startup_example/service/ExampleHelloService.php b/examples/startup_example/service/ExampleHelloService.php new file mode 100644 index 0000000..2b6c151 --- /dev/null +++ b/examples/startup_example/service/ExampleHelloService.php @@ -0,0 +1,17 @@ + true, 'rest' => true - , 'php' => true, 'xml' => true, 'none' => true,'gui'=>true - ,'phpclient'=>true,'unity'=>true]; + public $allowed_input + = [ + 'json' => true, + 'rest' => true, + 'php' => true, + 'xml' => true, + 'none' => true, + 'gui' => true, + 'phpclient' => true, + 'unity' => true + ]; /** * If the service is not set, then it will be unable to answer any call. + * * @var null|object */ - public $serviceInstance; + public $serviceInstance; public $oem = false; public $encoding = 'UTF-8'; public $custom_wsdl = ''; @@ -44,140 +56,293 @@ class CloudKing public $wsse_nonce = ''; public $wsse_created = ''; // ISO-8859-1 public $wsse_password_type = 'None'; - public $variable_type = 'array'; //Copyright (c)2009 - 2020, SouthProject www.southprojects.com"; + public $variable_type = 'array'; public $allowed = array('*'); public $disallowed = array(''); - protected $FILE; - protected $NAMESPACE; - protected $NAME_WS; + public $folderServer = ''; + public $lastError = ''; + /** @var string port URL */ + protected $portUrl; + /** @var string the namespace of the web service (with trailing dash) and the classes.
+ * Example: https://www.southprojects.com/ + */ + protected $nameSpace; + /** @var string The name of the web service, such as "myservice" */ + protected $nameWebService; /** @var array ['','None','PasswordDigest','PasswordText'][$i] */ protected $operation; //None, PasswordDigest, PasswordText ///** @var string=['array','object'][$i] it define if the implementation will use array (or primitives) or objects */ protected $complextype; - - protected $predef_types = [ - 'string', - 'long', - 'int', - 'integer', - 'boolean', - 'decimal', - 'float', - 'double', - 'duration', - 'dateTime', - 'time', - 'date', - 'gYearMonth', - 'gYear', - 'gMonthDay', - 'gDay', - 'gMonth', - 'hexBinary', - 'base64Binary', - 'anyURI', - 'QName', - 'NOTATION' - ]; - protected $predef_typesNS = [ - 'string', - 'long', - 'int', - 'integer', - 'boolean', - 'decimal', - 'float', - 'double', - 'duration', - 'dateTime', - 'time', - 'date', - 'gYearMonth', - 'gYear', - 'gMonthDay', - 'gDay', - 'gMonth', - 'hexBinary', - 'base64Binary', - 'anyURI', - 'QName', - 'NOTATION' - ]; - protected $predef_types_num = array( - 'long', - 'int', - 'integer', - 'boolean', - 'decimal', - 'float', - 'double', - 'duration' - ); - - public function __construct($FILE, $NAMESPACE = 'http://test-uri/', $NAME_WS = 'CKService1') { - $this->_CKLIB($FILE, $NAMESPACE, $NAME_WS); - } - private function _CKLIB($FILE, $NAMESPACE, $NAME_WS) { + protected $predef_types + = [ + 'string', + 'long', + 'int', + //'integer', + 'boolean', + 'decimal', + 'float', + 'double', + 'duration', + 'dateTime', + 'time', + 'date', + 'gYearMonth', + 'gYear', + 'gMonthDay', + 'gDay', + 'gMonth', + 'hexBinary', + 'base64Binary', + 'anyURI', + 'QName', + 'NOTATION' + ]; + protected $predef_typesNS + = [ + 'string', + 'long', + 'int', + //'integer', + 'boolean', + 'decimal', + 'float', + 'double', + 'duration', + 'dateTime', + 'time', + 'date', + 'gYearMonth', + 'gYear', + 'gMonthDay', + 'gDay', + 'gMonth', + 'hexBinary', + 'base64Binary', + 'anyURI', + 'QName', + 'NOTATION' + ]; + protected $predef_types_num + = array( + 'long', + 'int', + 'integer', + 'boolean', + 'decimal', + 'float', + 'double', + 'duration' + ); + /** + * CloudKing constructor. + * + * @param string $portUrl The port url where we will do the connection. + * @param string $nameSpace with trailing slash + * @param string $nameWebService + */ + public function __construct($portUrl='', $nameSpace = 'http://test-uri/', $nameWebService = 'CKService1') { + if($portUrl==='') { + if(!isset($_SERVER['SERVER_NAME'])) { + $portUrl = $_SERVER['SCRIPT_NAME']; + } else { + $portUrl = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['SCRIPT_NAME']; + } + + } + if (@$_SERVER['HTTPS']) { - $FILE = str_replace('http://', 'https://', $FILE); + $portUrl = str_replace('http://', 'https://', $portUrl); } - $this->FILE = $FILE; + $this->portUrl = $portUrl; - - $this->NAMESPACE = ($NAMESPACE != '') ? $NAMESPACE : $FILE . '/'; - $this->NAME_WS = ($NAME_WS != '') ? $NAME_WS : 'CKService1'; + $this->nameSpace = ($nameSpace != '') ? $nameSpace : $portUrl . '/'; + $this->nameWebService = ($nameWebService != '') ? $nameWebService : 'CKService1'; $this->operation = array(); $this->complextype = array(); - $this->custom_wsdl = $this->FILE . '?wsdl'; + $this->custom_wsdl = $this->portUrl . '?wsdl'; } /** * We add an argument that returns a list of complex. - * - * @param string $name Name of the argument - * @param string $type Type of the complex argument tns:NameComplex or NameComplex - * @param int $minOccurs - * @param string $maxOccurs + * + * @param string $name Name of the argument + * @param string $type Type of the complex argument tns:NameComplex or NameComplex + * @param int $minOccurs Minimum ocurrence,if 0 it means that the value is not required. + * @param string $maxOccurs Maximum ocurrences. If "unbounded" means unlimited. + * @param false $byref If the value will be returned. + * @param string $description (optional) the description of the web service. + * + * @return array + */ + public static function argList( + $name = 'return', + $type = 'tns:*', + $minOccurs = 0 + , + $maxOccurs = 'unbounded', + $byref = false, + $description = '' + ) { + $type = strpos($type, ':') === false ? 'tns:' . $type : $type; + return [ + 'name' => $name, + 'type' => $type, + 'minOccurs' => $minOccurs + , + 'maxOccurs' => $maxOccurs, + 'byref' => $byref, + 'description' => $description + ]; + } + + /** + * @param string $nameParam the name of the parameter. If it is return, then uses 'return' + * @param string $type =$this->predef_typesNS[$i] + * @param false $byref + * @param false $required + * @param string $description + * + * @return array + */ + public function paramList( + $nameParam = 'return', + $type = '', + $byref = false, + $required = false + , + $description = '' + ) { + + if (in_array($type, $this->predef_typesNS)) { + $primitive = true; + $prefix = 's:'; + } else { + $found = $this->findComplexByName($type); + if ($found === false) { + throw new RuntimeException("paramList: Type [$type] not defined"); + } + $primitive = false; + $prefix = 'tns:'; + } + if (!$primitive) { + $newType = 'ArrayOf' . $type; + $found = $this->findComplexByName($newType); + if (!$found) { + // we add a new complex type + $this->addtype($newType, array( + self::argList($type, $prefix . $type, '0', 'unbounded') + )); + } + } else { + $newType = 'ArrayOf' . $type; + } + return self::argList($nameParam, $newType, ($required ? 1 : 0), 1, $byref, $description); + } + + /** + * @param string $nameParam + * @param string $type =$this->predef_typesNS[$i] * @param false $byref + * @param false $required + * @param string $description * * @return array */ - public static function argList($name = 'return', $type = 'tns:*', $minOccurs = 0 - , $maxOccurs = 'unbounded', $byref = false) { - $type=strpos($type,':')===false ? 'tns:'.$type : $type; - return ['name' => $name, 'type' => $type, 'minOccurs' => $minOccurs - , 'maxOccurs' => $maxOccurs, 'byref' => $byref]; + public function param($nameParam, $type, $byref = false, $required = false, $description = '') { + if (in_array($type, $this->predef_typesNS)) { + $prefix = 's:'; + } else { + $found = $this->findComplexByName($type); + if ($found === false) { + throw new RuntimeException("paramList: Type [$type] not defined"); + } + $prefix = 'tns:'; + } + return self::argPrim($nameParam, $prefix . $type, $byref, $required, $description); + } + + /** + * It finds a complex type. If not found then it returns false. + * + * @param string $nameType without namespace + * + * @return false|mixed + */ + private function findComplexByName($nameType) { + if (isset($this->complextype[$nameType])) { + return $this->complextype[$nameType]; + } + return false; + } + + private function findOperationByName($nameOp) { + if (isset($this->operation[$nameOp])) { + return $this->operation[$nameOp]; + } + return false; } /** * We add a primary argument - * - * @param string $name Name of the argument - * @param string $type=$this->predef_typesNS[$i] It could be "s:int" or "int" - * @param bool $byref if true then it returns the value + * + * @param string $name Name of the argument + * @param string $type =$this->predef_typesNS[$i] It could be "s:int" or "int" + * @param bool $byref if true then it returns the value + * @param bool $required if true then the value is required + * @param string $description (optional) the description + * * @return array - * @see \eftec\cloudking\CloudKing::$predef_typesNS - * + * @see \eftec\cloudking\CloudKing::$predef_typesNS */ - public static function argPrim($name = 'return', $type = 's:*', $byref = false) { - $type=strpos($type,':')===false ? 's:'.$type : $type; - return ['name' => $name, 'type' => $type, 'byref' => $byref]; + public static function argPrim( + $name = 'return', + $type = 's:*', + $byref = false, + $required = false, + $description = '' + ) { + $type = strpos($type, ':') === false ? 's:' . $type : $type; + return [ + 'name' => $name, + 'type' => $type, + 'byref' => $byref + , + 'minOccurs' => ($required) ? '1' : '0', + 'description' => $description + ]; } /** * We add a complex argument (Comple arguments are added with the method addType) - * - * @param string $name Name of the argument - * @param string $type Type of the complex argument (SOAP specification) + * + * @param string $name Name of the argument + * @param string $type Type of the complex argument (SOAP specification) * @param false $byref if true then it returns the value + * @param bool $required + * @param string $description * * @return array */ - public static function argComplex($name = 'return', $type = 'tns:*', $byref = false) { - $type=strpos($type,':')===false ? 'tns:'.$type : $type; - return ['name' => $name, 'type' => $type, 'byref' => $byref]; + public static function argComplex( + $name = 'return', + $type = 'tns:*', + $byref = false + , + $required = false, + $description = '' + ) { + $type = strpos($type, ':') === false ? 'tns:' . $type : $type; + return [ + 'name' => $name, + 'type' => $type, + 'byref' => $byref + , + 'minOccurs' => ($required) ? '1' : '0', + 'description' => $description + ]; } public function set_copyright($copyright) { @@ -204,7 +369,7 @@ public function password_correct($password, $type = 'None') { } return true; } - + public function run() { $result = ''; if (!$this->security()) { @@ -212,122 +377,137 @@ public function run() { } global $_REQUEST; $param = @$_SERVER['QUERY_STRING'] . '&='; + $p = strpos($param, '&'); $p1 = strpos($param, '='); $paraminit = substr($param, 0, min($p, $p1)); // ?{value}&other=aaa - //$HTTP_RAW_POST_DATA=@$GLOBALS['HTTP_RAW_POST_DATA']; $HTTP_RAW_POST_DATA = file_get_contents('php://input'); + $isget = isset($_SERVER['REQUEST_METHOD']) + ? $_SERVER['REQUEST_METHOD'] === 'GET' + : true; + - $isget = false; - $methodcalled = ($paraminit == '') ? 'soap' : $paraminit; - $methoddefined = false; - if ($this->get && strlen($methodcalled) >= 3 && strpos($methodcalled, 'get') === 0) { - $methodcalled = str_replace('get', '', $methodcalled); - $methodcalled = ($methodcalled == '' ? 'none' : $methodcalled); - $isget = true; - $methoddefined = true; - } - if ($this->post && strlen($methodcalled) >= 4 && strpos($methodcalled, 'post') === 0) { - $methodcalled = str_replace('post', '', $methodcalled); - $methodcalled = ($methodcalled == '' ? 'none' : $methodcalled); - $isget = false; - $methoddefined = true; - } + //$info = explode('/', @$_SERVER['PATH_INFO']); + //$functionName = (count($info) >= 2) ? $info[1] : ''; + //$functionTypeOut = (count($info) >= 3) ? $info[2] : $methodcalled; - $info = explode('/', @$_SERVER['PATH_INFO']); - $function_name = (count($info) >= 2) ? $info[1] : 'unknown_unknown'; - $function_out = (count($info) >= 3) ? $info[2] : $methodcalled; + $functionName = isset($_GET['_op']) ? $_GET['_op'] : ''; + $functionTypeOut = isset($_GET['_out']) ? $_GET['_out'] : $paraminit; - if ($this->get && count($info) >= 4) { - // is passing more that the functionname && output type 0> is rest myphp?php/functionname/typeout/p1/p2.... - $isget = true; - $methodcalled = 'rest'; - $methoddefined = true; - } - if ($this->soap12) { - if (!$methoddefined && !$HTTP_RAW_POST_DATA && $function_name !== 'unknown_unknown' && $this->get) { + $methoddefined = false; + if ($this->soap12 || $this->soap11) { + /*if (!$paraminit && $functionName !== '' && $isget) { // mypage.php/functioname?param1=...... - $methodcalled = 'none'; - $function_out = 'xml'; + $paraminit = 'soap'; + //$functionTypeOut = 'xml'; $isget = true; $methoddefined = true; + }*/ + // url.php? (POST) + if ($paraminit === '' && $functionName === '' && !$isget) { + $paraminit = 'soap'; } - if (!$methoddefined && $function_name !== 'unknown_unknown' && $this->post) { + /*if (!$paraminit && $functionName !== '' && $this->post) { // mypage.php/functioname (it must be soap http post). - - $methodcalled = 'none'; - $function_out = 'xml'; + $paraminit = 'soap'; + $functionTypeOut = 'xml'; $HTTP_RAW_POST_DATA = ' '; // only for evaluation. $isget = false; $methoddefined = true; - } + }*/ } - if (!@$this->allowed_input[$methodcalled] && $methoddefined) { + if (!@$this->allowed_input[$paraminit] && $methoddefined) { - trigger_error("method $methodcalled not allowed. Did you use SOAP 1.1 or 1.2?", E_USER_ERROR); + trigger_error("method $paraminit not allowed. Did you use SOAP 1.1 or 1.2?", E_USER_ERROR); } - - if ($isget || $HTTP_RAW_POST_DATA != '') { - // is trying to evaluate a function. - - // ejemplo :http://www.micodigo.com/webservice.php/functionname/xml?getjson&value1={json..}&value2={json} - //info(0)=0 - //info(1)=functionname - //info(2)=serialize return type (optional, by default is the same name as passed) - - - $res = false; - switch ($methodcalled) { - case 'soap': - case 'wsdl': - $res = $this->requestSOAP($HTTP_RAW_POST_DATA); - break; - case 'json': - case 'rest': - case 'php': - case 'xml': - case 'none': - - $res = $this->requestNOSOAP($function_name, $function_out, $methodcalled, $isget, $info); - break; - } - if ($res) { + if ($this->folderServer) { + @$save = @$_GET['save']; + } else { + $save = null; + } + switch ($paraminit) { + case 'soap': + $res = $this->requestSOAP($HTTP_RAW_POST_DATA); $result .= $res; return $result; - } + case 'json': + case 'rest': + case 'php': + case 'xml': + case 'none': - return false; - } + $res = $this->requestNoSOAP($functionName, $functionTypeOut, $paraminit, $isget, $HTTP_RAW_POST_DATA); + $result .= $res; + return $result; - switch ($paraminit) { case 'wsdl': header('content-type:text/xml;charset=' . $this->encoding); $result .= $this->genwsdl(); return $result; case 'source': if ($this->verbose >= 2) { - $source=@$_GET['source']; - if(!$source) { + $source = @$_GET['source']; + if (!$source) { header('content-type:text/html'); $result .= $this->source(); break; } - if(!isset($this->allowed_input[$source])) { - $result.='Method not allowed'; + if (!isset($this->allowed_input[$source])) { + $result .= 'Method not allowed'; return $result; } - if($this->allowed_input[$source]===false) { - $result.='Method not allowed'; + if ($this->allowed_input[$source] === false) { + $result .= 'Method not allowed'; return $result; } switch ($source) { case 'php': header('content-type:text/plain;charset=' . $this->encoding); - $result .= $this->genphp(); + $result .= $this->generateServiceClass(true); + if ($save) { + echo "┌───────────────────────┐\n"; + echo "│ Saving │\n"; + echo "└───────────────────────┘\n"; + $folder = $this->folderServer . '\service'; + if (@!mkdir($folder) && !is_dir($folder)) { + $this->lastError = "Directory $folder was not created"; + return ''; + } + $file = "$folder\\I{$this->nameWebService}Service.php"; + $r = file_put_contents($file, "nameWebService}Service.php"; + if (!file_exists($file)) { + $r = file_put_contents($file, "generateServiceClass()); + if ($r) { + echo "Info: File $file saved\n"; + } else { + echo "Error: unable to save file $file\n"; + } + } else { + echo "Note: File $file already exist, skipped\n"; + } + $file = "$folder\\{$this->nameWebService}Client.php"; + $result = $this->genphpclient(); + $r = file_put_contents($file, $result); + if ($r) { + echo "Info: File $file saved\n"; + } else { + echo "Error: unable to save file $file\n"; + } + + echo "┌───────────────────────┐\n"; + echo "│ Done │\n"; + echo "└───────────────────────┘\n"; + } break; case 'phpclient': header('content-type:text/plain;charset=' . $this->encoding); @@ -350,11 +530,11 @@ public function run() { } break; } - if ($this->allowed_input['gui']===true) { + if ($this->allowed_input['gui'] === true) { $result .= $this->gen_description(); } else { $result .= $this->html_header(); - $result .= 'Name Web Service :' . $this->NAME_WS . '
'; + $result .= 'Name Web Service :' . $this->nameWebService . '
'; $result .= 'Method not allowed
'; $result .= $this->html_footer(); } @@ -362,8 +542,8 @@ public function run() { } private function security() { - $ip = $_SERVER['REMOTE_ADDR']; - $hostname = gethostbyaddr($_SERVER['REMOTE_ADDR']); + $ip =(isset($_SERVER['REMOTE_ADDR']))?$_SERVER['REMOTE_ADDR']:'0.0.0.0'; + $hostname = gethostbyaddr($ip); foreach ($this->disallowed as $value) { if ($value == $hostname || $value == $ip) { echo("host $ip $hostname not allowed (blacklist)\n"); @@ -381,13 +561,13 @@ private function security() { /** * It is called when we request a SOAP (a client called our web service as SOAP) - * + * * @param $HTTP_RAW_POST_DATA * * @return string|string[] */ private function requestSOAP($HTTP_RAW_POST_DATA) { - global $param, $r; + global $param, $resultService; $soapenv = ''; if ($this->soap11 && strpos($HTTP_RAW_POST_DATA, 'http://schemas.xmlsoap.org/soap/envelope/')) { header('content-type:text/xml;charset=' . $this->encoding); @@ -401,7 +581,7 @@ private function requestSOAP($HTTP_RAW_POST_DATA) { die('soap incorrect or not allowed'); } $arr = $this->xml2array($HTTP_RAW_POST_DATA); - + $this->wsse_username = @$arr['Envelope']['Header']['Security']['UsernameToken']['Username']; $this->wsse_password = @$arr['Envelope']['Header']['Security']['UsernameToken']['Password']; $this->wsse_nonce = @$arr['Envelope']['Header']['Security']['UsernameToken']['Nonce']; @@ -415,109 +595,100 @@ private function requestSOAP($HTTP_RAW_POST_DATA) { } else { $this->wsse_password_type = 'None'; } - $body=$arr['Envelope']['Body']; + $body = $arr['Envelope']['Body']; $funcion = array_keys($body); - $function_name0 = $funcion[0]; // as expressed in the xml - $function_name = $this->fixtag($function_name0); // "tem:getSix" (deberia ser solo una funcion?) + $functionNameXML = $funcion[0]; // as expressed in the xml + $functionName = $this->fixtag($functionNameXML); // "tem:getSix" (deberia ser solo una funcion?) // pasar los parametros $param = array(); - $paramt = []; $i = 0; - $indice_operation = -1; - foreach ($this->operation as $key => $value) { - if ($value['name'] == $function_name) { - $indice_operation = $key; - } - } - if ($indice_operation >= 0) { - $my_operation = $this->operation[$indice_operation]; - foreach ($my_operation['in'] as $value) { - $param[] = @$body[$function_name0][$value['name']]; - + $myOperation = $this->findOperationByName($functionName); + if ($myOperation !== false) { + + foreach ($myOperation['in'] as $key => $value) { + $param[] = @$body[$functionNameXML][$key]; + if (empty($param[$i])) { $param[$i] = ''; } - $paramt []= @$param[' . $i . ']; + $i++; } if ($this->variable_type === 'object') { // convert all parameters in classes. - foreach ($param as $key => $value) { - $classname = $my_operation['in'][$key]['type']; + foreach ($param as $nameOperation => $value) { + $classname = $myOperation['in'][$nameOperation]['type']; if (strpos($classname, 'tns:', 0) !== false) { - - $param[$key] = $this->array2class($value, $this->fixtag($classname)); + + $param[$nameOperation] = $this->array2class($value, $this->fixtag($classname)); } } } //$param_count = count($param); - $r = ''; + $resultService = ''; - $evalret=false; - - if ($this->serviceInstance === null ) { - $evalret = array('soap:Fault' => 'Caught exception: no service instance'); - } elseif(method_exists($this->serviceInstance,$function_name)) { - try { - $r = $this->serviceInstance->$function_name(...$paramt); - } catch(\Exception $ex) { - $evalret = array('soap:Fault' => 'Caught exception: '.$ex->getMessage()); - } - } else { - $evalret = array('soap:Fault' => 'Caught exception: method not defined'); - } - if ($this->variable_type === 'object') { - $classname = $my_operation['out'][0]['type']; - if (strpos($classname, 'tns:', 0) !== false) { - //$ttype = $this->fixtag($classname); - $r = $this->class2array($r, $this->fixtag($classname)); + $errorSOAP = false; + if ($this->serviceInstance === null) { + $errorSOAP = $this->returnErrorSOAP('Caught exception: no service instance' + , 'Caught exception: no service instance', 'Server'); + } elseif (method_exists($this->serviceInstance, $functionName)) { + try { + $resultService = $this->serviceInstance->$functionName(...$param); + } catch (RuntimeException $ex) { + $errorSOAP = $this->returnErrorSOAP('Caught exception: ' . $ex->getMessage(), + 'Caught exception: ' . $ex->getMessage(), 'Server'); } - //$r=@$r[$ttype]; + } else { + $errorSOAP = $this->returnErrorSOAP('Caught exception: method not defined ', + 'Caught exception: method not defined in service', 'Server'); } } else { - $evalret = array('soap:Fault' => 'Caught exception: function not defined'); - } - if (!isset($my_operation)) { - $evalret = array('soap:Fault' => 'Caught exception: no operation found'); - return $evalret; // no operation + $errorSOAP = $this->returnErrorSOAP('Caught exception: method not defined ', + 'Caught exception: method not defined in wsdl', 'Server'); } - if (is_array($r)) { + if (is_array($resultService)) { - $objectName = @$my_operation['out'][0]['name']; - if (!$objectName) { - $classname = $my_operation['out'][0]['type']; - $objectName = $this->separateNS($classname); - } + //var_dump($myOperation); + + $objectName = @$myOperation['out']['name']; + $classname = $objectName ? $myOperation['out']['type'] : ''; + //var_dump($objectName); + //var_dump($r); // the \n is for fixarray2xml - $serial = "\n" . $this->array2xml($r, 'array', false, false, $objectName) . "\n"; + + if (strpos($classname, 'tns:ArrayOf') === 0) { + $serial = "\n" . $this->array2xmlList($resultService, $classname) + . "\n"; // the last \n is important to cut the last value + } else { + $serial = "\n" . $this->array2xml($resultService, 'array', false, false, $classname) + . "\n"; // the last \n is important to cut the last value + } + + //var_dump($serial); $l = strlen($serial); if (($l > 2) && $serial[$l - 1] === "\n") { $serial = substr($serial, 0, $l - 1); } $serial = $this->fixarray2xml($serial); - if (@$r['soap:Fault'] != '') { - $evalret = false; - } } else { - $serial = $r; + $serial = $resultService; } // agregamos si tiene valor byref. $extrabyref = ''; $indice = 0; - $value = $this->operation[$indice_operation]; - foreach ($value['in'] as $key2 => $value2) { + foreach ($myOperation['in'] as $key2 => $value2) { if (@$value2['byref']) { $paramtmp = @$param[$indice]; if (is_array($paramtmp)) { @@ -526,50 +697,55 @@ private function requestSOAP($HTTP_RAW_POST_DATA) { } else { $tmp2 = $paramtmp; } - $extrabyref .= '<' . $value2['name'] . '>' . $tmp2 . ''; + $extrabyref .= '<' . $key2 . '>' . $tmp2 . ''; } $indice++; } - - if ($evalret === false) { + if ($errorSOAP === false) { + // no error $resultado = 'encoding . '"?>'; - $resultado .= '' . - "\n"; - $resultado .= "<{$function_name}Response xmlns=\"{$this->NAMESPACE}\">"; - $resultado .= "<{$function_name}Result>{$serial}"; + $resultado .= "'; + $resultado .= "\n<{$functionName}Response xmlns=\"{$this->nameSpace}\">"; + $resultado .= "<{$functionName}Result>{$serial}"; $resultado .= $extrabyref; - $resultado .= ""; + $resultado .= ""; $resultado .= ''; $resultado .= ''; } else { - $resultado = '' . - "\n"; - $resultado .= 'soap:Sender' . - $function_name . ' failed to evaluate .' . @$evalret['soap:Fault'] . ''; - $resultado .= ''; + // error + $resultado = 'encoding . '"?>'; + $resultado .= $errorSOAP; } - return $resultado; } - public function returnErrorSOAP($soapVersion,$reason,$message,$code) { - if($soapVersion>=1.2) { - $xml=<<soap12) { + $xml = << - env:Sender + env:$code $reason NAMESPACE}> + xmlns:e={$this->nameSpace}> $message $code @@ -579,17 +755,17 @@ public function returnErrorSOAP($soapVersion,$reason,$message,$code) { TAG; } else { - $xml=<< - soap:VersionMismatch + soap:Server $message - {$this->NAMESPACE} + {$this->nameSpace} @@ -597,10 +773,12 @@ public function returnErrorSOAP($soapVersion,$reason,$message,$code) { TAG; } + return $xml; } + public function xml2array($xml) { - $parentKey=[]; - $result=[]; + $parentKey = []; + $result = []; $parser = xml_parser_create(''); xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'utf-8'); xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); @@ -608,23 +786,22 @@ public function xml2array($xml) { @xml_parse_into_struct($parser, trim($xml), $xmls); xml_parser_free($parser); - - foreach($xmls as $x) { - $type=@$x['type']; - $level=@$x['level']; - $value=@$x['value']; - $tag=@$x['tag']; + foreach ($xmls as $x) { + $type = @$x['type']; + $level = @$x['level']; + $value = @$x['value']; + $tag = @$x['tag']; switch ($type) { case 'open': - $ns=$this->separateNS($tag); + $ns = $this->separateNS($tag); /*if(!isset($parentKey[$level])) { $parentKey[$level]=$ns; } else { $parentKey[$level]++; } */ - $parentKey[$level]=$ns; - $this->addElementArray($result,$parentKey,$level,$ns,[]); + $parentKey[$level] = $ns; + $this->addElementArray($result, $parentKey, $level, $ns, []); break; case 'close': //$parentKey[$level]++; @@ -644,62 +821,72 @@ public function xml2array($xml) { * $this->addElementArray($arr,['level1','level2'],3,'newlevel','hello']); * // $arr=['level1']['level2']['newlevel']=>'hello' * - * - * @param array $array The result array. - * @param array $keys the parent node - * @param int $level the level where we will add a new node - * @param string $tag the tag of the new node - * @param mixed $value the value of the new node + * + * @param array $array The result array. + * @param array $keys the parent node + * @param int $level the level where we will add a new node + * @param string $tag the tag of the new node + * @param mixed $value the value of the new node */ - private function addElementArray(&$array,$keys,$level,$tag,$value) { + private function addElementArray(&$array, $keys, $level, $tag, $value) { // we removed any namespace -> - foreach($keys as $k=>$v) { - if(strpos($v,':')!==false) { - $keys[$k]=explode(':',$v,2)[1]; + foreach ($keys as $k => $v) { + if (strpos($v, ':') !== false) { + $keys[$k] = explode(':', $v, 2)[1]; } } - if(strpos($tag,':')!==false) { - $tag=explode(':',$tag,2)[1]; + if (strpos($tag, ':') !== false) { + $tag = explode(':', $tag, 2)[1]; } // we store the value form the xml in our array. switch ($level) { case 1: - $array[$tag]=$value; + $array[$tag] = $value; break; case 2: - $array[$keys[1]][$tag]=$value; + $array[$keys[1]][$tag] = $value; break; case 3: - $array[$keys[1]][$keys[2]][$tag]=$value; + $array[$keys[1]][$keys[2]][$tag] = $value; break; case 4: - $array[$keys[1]][$keys[2]][$keys[3]][$tag]=$value; + $array[$keys[1]][$keys[2]][$keys[3]][$tag] = $value; break; case 5: - $array[$keys[1]][$keys[2]][$keys[3]][$keys[4]][$tag]=$value; + $array[$keys[1]][$keys[2]][$keys[3]][$keys[4]][$tag] = $value; break; case 6: - $array[$keys[1]][$keys[2]][$keys[3]][$keys[4]][$keys[5]][$tag]=$value; + $array[$keys[1]][$keys[2]][$keys[3]][$keys[4]][$keys[5]][$tag] = $value; break; case 7: $array[$keys[1]][$keys[2]][$keys[3]][$keys[4]][$keys[5]][$keys[6]] - [$tag]=$value; + [$tag] + = $value; break; case 8: $array[$keys[1]][$keys[2]][$keys[3]][$keys[4]][$keys[5]][$keys[6]] - [$keys[7]][$tag]=$value; + [$keys[7]][$tag] + = $value; break; case 9: $array[$keys[1]][$keys[2]][$keys[3]][$keys[4]][$keys[5]][$keys[6]] - [$keys[7]][$keys[8]][$tag]=$value; + [$keys[7]][$keys[8]][$tag] + = $value; break; case 10: $array[$keys[1]][$keys[2]][$keys[3]][$keys[4]][$keys[5]][$keys[6]] - [$keys[7]][$keys[8]][$keys[9]][$tag]=$value; + [$keys[7]][$keys[8]][$keys[9]][$tag] + = $value; break; case 11: $array[$keys[1]][$keys[2]][$keys[3]][$keys[4]][$keys[5]][$keys[6]] - [$keys[7]][$keys[8]][$keys[9]][$keys[10]][$tag]=$value; + [$keys[7]][$keys[8]][$keys[9]][$keys[10]][$tag] + = $value; + break; + case 12: + $array[$keys[1]][$keys[2]][$keys[3]][$keys[4]][$keys[5]][$keys[6]] + [$keys[7]][$keys[8]][$keys[9]][$keys[10]][$keys[11]][$tag] + = $value; break; } } @@ -718,13 +905,13 @@ private function array2class($arr, $newclass) { $serialized_parts[2] = '"' . $newclass . '"'; $result = unserialize(implode(':', $serialized_parts)); // aqui recorremos los miembros - $idx = $this->findIdxComplexType($newclass); - if ($idx == -1) { + $complex = $this->findComplexByName($newclass); + if ($complex === false) { trigger_error('Complex Type ' . $newclass . ' not found', E_USER_ERROR); } - foreach ($this->complextype[$idx]['elements'] as $value) { + foreach ($complex as $nameComplex => $value) { if (strpos($value['type'], 'tns:', 0) !== false) { - $result->$value['name'] = $this->array2class($result->$value['name'] + $result->$nameComplex = $this->array2class($result->$nameComplex , $this->fixtag($value['type'])); } } @@ -736,10 +923,10 @@ private function class2array($class, $classname) { if (is_object($class)) { $resultado = (array)$class; - $idx = $this->findIdxComplexType($classname); - foreach ($this->complextype[$idx]['elements'] as $value) { + $complex = $this->findComplexByName($classname); + foreach ($complex as $nameComplex => $value) { if (strpos($value['type'], 'tns:', 0) !== false) { - $this->class2array($resultado[$value['name']], $this->fixtag($value['type'])); + $this->class2array($resultado[$nameComplex], $this->fixtag($value['type'])); //$tmp=$this->class2array($resultado[$value['name']], $this->fixtag($value['type'])); //if ($tmp != "") { //$resultado[$value['name']]=$tmp; @@ -752,17 +939,6 @@ private function class2array($class, $classname) { return $resultado; } - private function findIdxComplexType($complexname) { - - foreach ($this->complextype as $key => $value) { - if ($value['name'] == $complexname) { - return $key; - } - } - return -1; - - } - protected function fixtag($tag) { $arr = explode(':', $tag); return ($arr[count($arr) - 1]); @@ -770,6 +946,7 @@ protected function fixtag($tag) { /** * @param $tnsName + * * @return mixed|string */ private function separateNS($tnsName) { @@ -780,27 +957,57 @@ private function separateNS($tnsName) { return $r[1]; } - public function array2xml($array, $name = 'root', $contenttype = true, $start = true, $keyx = '') { + /** + * It generates a xml form an array. + * + * @param string|array $array the input array + * @param string $name The name of the first node + * @param bool $contenttype if true then it shows the initial content type + * @param bool $start if true then it is the first and initial node. + * @param string $expected The expected node type with the namespace + * + * @return string + */ + public function array2xml($array, $name = 'root', $contenttype = true, $start = true, $expected = '') { // \n is important, you should not remove it. if (!is_array($array)) { return $array; } + //var_dump($expected); + //var_dump($name); + //var_dump($start); + if (strpos($expected, 'tns:') !== false) { + //echo "expected:"; + //var_dump($expected); + $complex = $this->findComplexByName(str_replace('tns:', '', $expected)); + //echo "complex:"; + //var_dump($complex); + } else { + //echo "nexpected:"; + //var_dump($expected); + $complex = null; + } $xmlstr = ''; if ($start) { if ($contenttype) { - @header('content-type:text/xml;charset=' . $this->encoding); + @header("content-type:text/xml;charset={$this->encoding}"); } - $xmlstr .= 'encoding . "\"?>\n"; - $xmlstr .= '<' . $name . ">\n"; + $xmlstr .= "encoding}\"?>\n"; + $xmlstr .= "<{$name}>\n"; } foreach ($array as $key => $child) { if (is_array($child)) { - $xmlstr .= (is_string($key)) ? '<' . $key . ">\n" : '<' . $keyx . ">\n"; - $child = $this->array2xml($child, '', '', false, $key); + $xmlstr .= "<{$key}>\n"; + if (strpos($complex[$key]['type'], 'tns:ArrayOf') === 0) { + $child = $this->array2xmlList($child, $complex[$key]['type']); + } else { + $child = $this->array2xml($child, '', '', false, $complex[$key]['type']); + } + $xmlstr .= $child; - $xmlstr .= (is_string($key)) ? '\n" : '\n"; + $xmlstr .= "\n"; } else { $type = $this->array2xmltype($child); if ($this->variable_type === 'object' && is_object($child)) { @@ -818,6 +1025,32 @@ public function array2xml($array, $name = 'root', $contenttype = true, $start = return $xmlstr; } + /** @noinspection LoopWhichDoesNotLoopInspection */ + private function array_key_first($arr) { + foreach ($arr as $key => $unused) { + return $key; + } + return null; + } + + public function array2xmlList($array, $expected = '') { + // \n is important, you should not remove it. + if (!is_array($array)) { + return $array; + } + $xmlstr = ''; + $keyName = str_replace('tns:', '', $expected); + $complex = $this->findComplexByName($keyName); + $firstKey = $this->array_key_first($complex); + //var_dump('list'); + //var_dump($complex); + foreach ($array as $idx => $value) { + $xmlstr .= "<$firstKey>" . $this->array2xml($value, '', '', false, $complex[$firstKey]['type']) + . "\n"; + } + return $xmlstr; + } + public function array2xmltype($value) { if (is_float($value)) { return 'float'; @@ -849,10 +1082,18 @@ private function fixarray2xml($string) { return $resultado; } - private function requestNOSOAP($function_name, $function_out, $methodcalled, $isget, $info = array()) { - global $param, $r; - - + /** + * Process a non-soap request into an array. + * + * @param string $functionName the name of the function + * @param string $functionTypeOut =['json','xml','php','none'][$i] + * @param string $methodcalled =['soap','wsdl','json','rest','php','xml','none'][$i] + * @param string $isget + * @param array $body + * + * @return false|string + */ + private function requestNoSOAP($functionName, $functionTypeOut, $methodcalled, $isget, $body = array()) { $this->wsse_username = @$_POST['Username']; $this->wsse_password = @$_POST['Password']; $this->wsse_nonce = @$_POST['Nonce']; @@ -866,96 +1107,59 @@ private function requestNOSOAP($function_name, $function_out, $methodcalled, $is } else { $this->wsse_password_type = 'None'; } - // pasar los parametros - $param = array(); - $paramt = ''; - - $indice_operation = -1; - foreach ($this->operation as $key => $value) { - if ($value['name'] == $function_name) { - $indice_operation = $key; - } - } - $operation = array('in' => array()); - if ($indice_operation >= 0) { - $i = 0; - $operation = $this->operation[$indice_operation]; - foreach ($operation['in'] as $key => $value) { - $tmpvalue = ($isget) ? @$_GET[$value['name']] : @$_POST[$value['name']]; - if ($methodcalled === 'rest') { - $param[] = @$info[$i + 3]; + $operationN = $this->findOperationByName($functionName); + if ($operationN != false) { + $operation = $operationN; + if ($isget) { + $param = $_GET; + } else { + $param = $this->decodeNOSOAP($methodcalled, $body); + } + // order and filter the arguments. + $arguments = []; + $argumentCounter = 0; + $paramxArgument = []; + foreach ($operation['in'] as $nameArg => $value) { + if (isset($param[$nameArg])) { + $arguments[$argumentCounter] = $param[$nameArg]; + + $paramxArgument[$nameArg] = $argumentCounter; + $argumentCounter++; } else { - $param[] = $this->decodeNOSOAP($methodcalled, $tmpvalue); - } - $paramt .= '@$param[' . $i . '],'; - $i++; - } - if ($this->variable_type === 'object') { - // convert all parameters in classes. - foreach ($param as $key => $value) { - $classname = $operation['in'][$key]['type']; - if (strpos($classname, 'tns:', 0) !== false) { - $param[$key] = $this->array2class($value, $this->fixtag($classname)); - } + $arguments[$argumentCounter] = null; + $paramxArgument[$nameArg] = $argumentCounter; + $argumentCounter++; } } - // $param_count = count($param); - $paramt = substr($paramt, 0, -1); - $r = ''; - if (!$this->serviceInstance) { - $evalstr = "\$r=$function_name($paramt);"; - } else { - //@eval("global \$" . $this->serviceInstance . ";"); - $evalstr = "\$r=\$this->serviceInstance->$function_name($paramt);"; - + try { + $er = $this->serviceInstance->$functionName(...$arguments); + } catch (RuntimeException $ex) { + return $this->returnErrorNoSOAP($functionTypeOut, 'Caught exception: ' . $ex->getMessage(), + 'Caught exception: ' . $ex->getMessage(), 'Server'); } - - $evalret = eval($evalstr); - - if ($this->variable_type === 'object') { - - - $r = $this->class2array($r, $this->fixtag($operation['out'][0]['type'])); - + $evalret = null; + if (count($operation['out'])) { + $returnArgName = $operation['out']['name']; + $evalret[$returnArgName] = $er; } - } else { - $evalret = array('soap:Fault' => 'Caught exception: function not defined'); - } - - $max_result = array(); - - - $max_result[$function_name . 'Result'] = $r; - - // agregamos si tiene valor byref. - //$extrabyref = ""; - $indice = 0; - - foreach ($operation['in'] as $key2 => $value2) { - if (@$value2['byref']) { - $paramtmp = @$param[$indice]; - $max_result[$value2['name']] = $paramtmp; - // $extrabyref .= $value2['name'] . "=" . $paramtmp . "\n"; + foreach ($operation['in'] as $nameArg => $value) { + if (isset($paramxArgument[$nameArg]) && $value['byref']) { + $evalret[$nameArg] = $arguments[$paramxArgument[$nameArg]]; + } else { + $evalret[$nameArg] = null; + } } - $indice++; - } - - if (count($max_result) === 1) { - - $max_result = $r; // if not byref then we returned as a single value - } - - if ($evalret !== false) { - - $resultado = $max_result; } else { - $resultado = $r; + return $this->returnErrorNoSOAP($functionTypeOut, 'Caught exception: function not defined' + , 'Caught exception: function not defined', 'Server'); } + return $this->encodeNOSOAP($functionTypeOut, $evalret, $functionName . 'Result'); + } - - $resultado = $this->encodeNOSOAP($function_out, $resultado, $function_name . 'Result'); - return $resultado; + private function returnErrorNoSOAP($methodcalled, $reason, $message, $code) { + return $this->decodeNOSOAP($methodcalled, + ['origin' => 'Cloudking Error', 'reason' => $reason, 'message' => $message, 'code' => $code]); } private function decodeNOSOAP($methodcalled, $tmpvalue) { @@ -963,7 +1167,7 @@ private function decodeNOSOAP($methodcalled, $tmpvalue) { $tmp = ''; switch ($methodcalled) { case 'json': - $tmp = json_decode($tmpvalue,false); + $tmp = json_decode($tmpvalue, true); break; case 'xml': $this->xml2array($tmpvalue); @@ -981,16 +1185,17 @@ private function decodeNOSOAP($methodcalled, $tmpvalue) { return $tmp; } - private function encodeNOSOAP($methodcalled, $tmpvalue, $tmpname) { + private function encodeNOSOAP($functionTypeOut, $tmpvalue, $tmpname) { $tmp = ''; - switch ($methodcalled) { + switch ($functionTypeOut) { case 'json': + @header('Content-type: application/json'); $tmp = json_encode($tmpvalue); break; case 'xml': if (!is_array($tmpvalue)) { @header('content-type:text/xml;charset=' . $this->encoding); - $tmp = '<' . '?' . 'xml version="1.0" encoding="' . $this->encoding . '"' . '?' . '>' . "\n"; + $tmp = "encoding}\"?>\n"; $tmp .= "<$tmpname>$tmpvalue"; } else { $tmp = $this->array2xml($tmpvalue, 'array', true, true); @@ -1016,79 +1221,138 @@ private function encodeNOSOAP($methodcalled, $tmpvalue, $tmpname) { return $tmp; } - protected function genphp() { - - $r=<<nameSpace); + $namespacephp = rtrim($namespacephp, '\\'); + if ($interface) { + $r = <<nameWebService}Service + */ +interface I{$this->nameWebService}Service { +cin; + } else { + $r = <<nameWebService}Service.php /** * @generated The structure of this class is generated by CloudKing - * Class {$this->NAME_WS}Service + * Class {$this->nameWebService}Service */ -class {$this->NAME_WS}Service { +class {$this->nameWebService}Service implements I{$this->nameWebService}Service { cin; + } - - foreach ($this->operation as $key => $value) { + foreach ($this->operation as $complexName => $args) { $param = ''; - foreach ($value['in'] as $key2 => $value2) { + foreach ($args['in'] as $key2 => $value2) { $param .= ($value2['byref']) ? '&' : ''; - $param .= '$' . $value2['name'] . ', '; - + $param .= '$' . $key2 . ', '; } if ($param != '') { $param = $this->right($param, 2); } - $r .= "\n"; - $r .= "\tpublic function " . $value['name'] . "($param) {\n"; - $r .= "\t\ttry {\n"; + $phpdoc = "\t/**\n\t * {$args['description']}\n\t *\n"; + foreach ($args['in'] as $key2 => $value2) { + $phpdoc .= "\t * @param mixed \${$key2}\n"; + } + if (is_array($args['out']) && count($args['out']) > 0) { + $phpdoc .= "\t *\n\t * @return mixed\n"; + } + $phpdoc .= "\t */"; + if ($interface) { + $r .= "\n$phpdoc\n"; + $r .= "\tpublic function {$complexName}($param);\n"; + } else { + $r .= "\n"; + $r .= "\n\t/**\n\t * @inheritDoc\n\t */\n"; + $r .= "\tpublic function {$complexName}($param) {\n"; + $r .= "\t\t// todo:custom implementation goes here\n"; + $r .= "\t}\n"; + } - $r .= "\t\t\t// todo: missing implementation \n"; - $r .= "\t\t\t/*\n"; - $param = ''; - foreach ($value['in'] as $key2 => $value2) { - $param .= "\t\t\t\$_" . $value2['name'] . '=' . - $this->Param2PHPValue($value2['type'], $value2['maxOccurs']) . ";\n"; + } + foreach ($this->complextype as $complexName => $args) { + $params = ''; + foreach ($args as $key2 => $value2) { + $params .= '$' . $key2 . '=null, '; } + if ($params != '') { + $params = $this->right($params, 2); + } + if ($interface) { + $r .= "\n\tpublic static function factory" . $complexName . '(' . $params . ");\n"; + } else { + $r .= "\n\tpublic static function factory" . $complexName . '(' . $params . ') {'; + $r .= "\n"; + $r .= $this->Param2PHP('tns:' . $complexName, @$args['maxOccurs']) . "\n"; + $r .= "\t\treturn \$_$complexName;\n"; + $r .= "\t}\n"; + } + } + $r .= "} // end class \n "; - $r .= $param; - $r .= "\t\t\t*/\n"; - $r .= "\t\t\t// End Input Values \n"; - foreach ($value['out'] as $key2 => $value2) { - $r .= "\t\t\t\$_" . $value['name'] . 'Result=' . - $this->Param2PHPValue($value2['type'], $value2['maxOccurs']) . ";\n"; + /*$r .= "\n" . $this->genphpast('Complex Types (Classes)'); + foreach ($this->complextype as $complexName => $args) { + $r .= "\nclass " . $complexName . " {\n"; + foreach ($args as $key2 => $value2) { + $r .= "\tvar $" . $key2 . '; // ' . $value2['type'] . "\n"; } - foreach ($value['out'] as $key2 => $value2) { + $r .= "}\n"; + } + */ + return $r; + } - $param .= $this->Param2PHPvalue($value2['type'], $value2['maxOccurs']); + private function createArgument($argArray) { + $param = ''; + foreach ($argArray as $key2 => $value2) { + $param .= ($value2['byref']) ? '&' : ''; + $param .= '$' . $key2 . ', '; + } + if ($param != '') { + $param = $this->right($param, 2); + } + return $param; + } - } - //$r.="\t\t \$result=\$_".$value['name']."Result ".$param."; \n"; - $r .= "\t\t\t return \$_" . $value['name'] . "Result; \n"; - $r .= "\t\t} catch (Exception \$_exception) {\n"; - $r .= "\t\t\treturn(array(\"soap:Fault\"=>'Caught exception: '. \$_exception->getMessage()));\n"; - $r .= "\t\t}\n"; - $r .= "\t}\n"; + protected function generateServiceInterface() { + + $r = <<nameWebService}Service + */ +interface I{$this->nameWebService}Service { +cin; + + foreach ($this->operation as $complexName => $args) { + $param = $this->createArgument($args['in']); + $r .= "\n"; + $r .= "\tpublic function " . $complexName . "($param);\n"; } - foreach ($this->complextype as $key => $value) { - - - $r.="\n\tpublic function factory".$value['name']. '(' - .$this->Param2PHPArg('tns:' . $value['name'], @$value['maxOccurs'],','). ') {'; + foreach ($this->complextype as $complexName => $args) { + $params = count($args) > 0 ? '$' . implode(',$', array_keys($args)) : ''; + + $r .= "\n\tpublic static function factory" . $complexName . '(' . $params . ') {'; $r .= "\n"; - $r .= $this->Param2PHP('tns:' . $value['name'], @$value['maxOccurs']) . "\n"; - $r.="\n\t }\n"; + $r .= $this->Param2PHP('tns:' . $complexName, @$args['maxOccurs']) . "\n"; + $r .= "\t\treturn \$_$complexName;\n"; + $r .= "\t}\n"; } $r .= "} // end class \n "; $r .= "\n" . $this->genphpast('Complex Types (Classes)'); - foreach ($this->complextype as $key => $value) { - $r .= "\nclass " . $value['name'] . " {\n"; - foreach ($value['elements'] as $key2 => $value2) { - $r .= "\tvar $" . $value2['name'] . '; // ' . $value2['type'] . "\n"; + foreach ($this->complextype as $complexName => $args) { + $r .= "\nclass " . $complexName . " {\n"; + foreach ($args as $key2 => $value2) { + $r .= "\tvar $" . $key2 . '; // ' . $value2['type'] . "\n"; } $r .= "}\n"; } - - + return $r; } @@ -1107,11 +1371,11 @@ protected function right($string, $num_cut = 1) { } protected function Param2PHPvalue($type, $max) { - $x1 = explode(':', $type,2); + $x1 = explode(':', $type, 2); if (count($x1) != 2) { return "// type $type not defined "; } - list($space,$name)=$x1; + list($space, $name) = $x1; $p = ''; if ($space === 's') { if (!in_array($name, $this->predef_types)) { @@ -1125,8 +1389,8 @@ protected function Param2PHPvalue($type, $max) { } } if ($space === 'tns') { - foreach ($this->complextype as $key => $value) { - if ($name == $value['name']) { + foreach ($this->complextype as $complexName => $args) { + if ($name === $complexName) { $p = '$_' . $name; } } @@ -1152,12 +1416,12 @@ protected function Param2PHPvalue($type, $max) { return "\\ complex type $type not defined"; } - protected function Param2PHP($type, $max, $separator=";\n",$pre="\t\t") { - $x1 = explode(':', $type,2); + protected function Param2PHP($type, $max, $separator = ";\n", $pre = "\t\t") { + $x1 = explode(':', $type, 2); if (count($x1) != 2) { return "// type $type not defined "; } - list($space,$name)=$x1; + list($space, $name) = $x1; if ($space === 's') { if (!in_array($name, $this->predef_types)) { return "// type $type not found"; @@ -1178,12 +1442,12 @@ protected function Param2PHP($type, $max, $separator=";\n",$pre="\t\t") { } $resultado = ''; if ($space === 'tns') { - foreach ($this->complextype as $key => $value) { - if ($name == $value['name']) { + foreach ($this->complextype as $complexName => $args) { + if ($name == $complexName) { - foreach ($value['elements'] as $key2 => $value2) { - $resultado .= $pre. '$_' . $name . "['" . $value2['name'] . "']=$" . - $value2['name'] . $separator; + foreach ($args as $key2 => $value2) { + $resultado .= $pre . '$_' . $name . "['" . $key2 . "']=$" . + $key2 . $separator; //$resultado.="'".$value2['name']."'=>".$this->Param2PHP($value2['type'],$value2['maxOccurs']).","; } $resultado = $this->right($resultado); @@ -1194,12 +1458,13 @@ protected function Param2PHP($type, $max, $separator=";\n",$pre="\t\t") { } return ''; } - protected function Param2PHPArg($type, $max, $separator=";\n") { - $x1 = explode(':', $type,2); + + protected function Param2PHPArg($type, $max) { + $x1 = explode(':', $type, 2); if (count($x1) != 2) { return "// type $type not defined "; } - list($space,$name)=$x1; + list($space, $name) = $x1; if ($space === 's') { if (!in_array($name, $this->predef_types)) { return "// type $type not found"; @@ -1220,12 +1485,12 @@ protected function Param2PHPArg($type, $max, $separator=";\n") { } $resultado = ''; if ($space === 'tns') { - foreach ($this->complextype as $key => $value) { - if ($name == $value['name']) { + foreach ($this->complextype as $complexName => $args) { + if ($name === $complexName) { - foreach ($value['elements'] as $key2 => $value2) { - $resultado .= '$' . $value2['name'] . '=' . - $this->Param2PHPValue($value2['type'], $value2['maxOccurs']) . $separator; + foreach ($args as $key2 => $value2) { + $resultado .= '$' . $key2; // . '=' . + // $this->Param2PHPValue($value2['type'], $value2['maxOccurs']) . $separator; //$resultado.="'".$value2['name']."'=>".$this->Param2PHP($value2['type'],$value2['maxOccurs']).","; } $resultado = $this->right($resultado); @@ -1238,28 +1503,32 @@ protected function Param2PHPArg($type, $max, $separator=";\n") { } /** - * @param float $soap The default SOAP. * * @return string */ - protected function genphpclient($soap=1.1) { - $namespacephp=str_replace(['http://','https://','.'],['','','\\'],$this->NAMESPACE); + protected function genphpclient() { + $namespacephp = str_replace(['http://', 'https://', '.','/'], ['', '', '\\','\\'], $this->nameSpace); + $namespacephp=trim($namespacephp,'\\'); $r = "NAME_WS}Client
\n"; + $r .= " * Class {$this->nameWebService}Client
\n"; if ($this->description) { $r .= " * {$this->description}
\n"; } - $r .= " * This code was generated automatically using CloudKing v{$this->version}, Date:".date('r')."
\n"; - $r .= ' * Using the web:' .$this->FILE."?source=phpclient\n"; + $r .= " * This code was generated automatically using CloudKing v{$this->version}, Date:" . date('r') + . "
\n"; + $r .= ' * Using the web:' . $this->portUrl . "?source=phpclient\n"; $r .= " */\n"; - $r .= "class {$this->NAME_WS}Client {\n"; + $r .= "class {$this->nameWebService}Client {\n"; $r .= "\t/** @var string The full url where is the web service */\n"; - $r .= "\tprotected \$url='" . $this->FILE . "';\n"; + $r .= "\tprotected \$url='" . $this->portUrl . "';\n"; $r .= "\t/** @var string The namespace of the web service */\n"; - $r .= "\tprotected \$tempuri='" . $this->NAMESPACE . "';\n"; + $r .= "\tprotected \$tempuri='" . $this->nameSpace . "';\n"; $r .= "\t/** @var string The last error. It is cleaned per call */\n"; $r .= "\tpublic \$lastError='';\n"; $r .= "\t/** @var float=[1.1,1.2][\$i] The SOAP used by default */\n"; @@ -1280,37 +1549,36 @@ protected function genphpclient($soap=1.1) { $r .= "\t\t\$soap!==null and \$this->soap = \$soap;\n"; $r .= "\t\t\$this->service=new CloudKingClient(\$this->soap,\$this->tempuri);\n"; $r .= "\t}\n\n"; - - + foreach ($this->operation as $key => $value) { - $functionname = $value['name']; - if (isset($value['out'])) { - $outType=$value['out'][0]['type']; + $functionname = $key; + if (isset($value['out']) && count($value['out']) > 0) { + $outType = $value['out']['type']; } else { - $outType='void'; + $outType = 'void'; } $param = ''; foreach ($value['in'] as $key2 => $value2) { $param .= ($value2['byref']) ? '&' : ''; - $param .= '$' . $value2['name'] . ', '; + $param .= '$' . $key2 . ', '; } if ($param != '') { $param = $this->right($param, 2); } - $r.="\n\t/**\n"; - $r.="\t * ".@$value['description']."\n"; - $r.="\t *\n"; + $r .= "\n\t/**\n"; + $r .= "\t * " . @$value['description'] . "\n"; + $r .= "\t *\n"; foreach ($value['in'] as $key2 => $value2) { - $varname = $value2['name']; - $r .= "\t * @param mixed \$$varname " . @$value2['description'] . ' ('.@$value2['type'].") \n"; + $varname = $key2; + $r .= "\t * @param mixed \$$varname " . @$value2['description'] . ' (' . @$value2['type'] . ") \n"; } - $r .= "\t * @return mixed ($outType)\n"; - $r .= "\t * @noinspection PhpUnused */\n"; + $r .= "\t * @return mixed ($outType)\n"; + $r .= "\t * @noinspection PhpUnused */\n"; $r .= "\tpublic function $functionname($param) {\n"; $r .= "\t\t\$_param='';\n"; foreach ($value['in'] as $key2 => $value2) { - $varname = $value2['name']; + $varname = $key2; $r .= "\t\t\$_param.=\$this->service->array2xml(\$$varname,'ts:$varname',false,false);\n"; } $r .= "\t\t\$resultado=\$this->service->loadurl(\$this->url,\$_param,'$functionname');\n"; @@ -1320,14 +1588,14 @@ protected function genphpclient($soap=1.1) { $r .= "\t\t}\n"; foreach ($value['in'] as $key2 => $value2) { if ($value2['byref']) { - $r .= "\t\t\$" . $value2['name'] . "=@\$resultado['" . $value2['name'] . "'];\n"; + $r .= "\t\t\$" . $key2 . "=@\$resultado['" . $key2 . "'];\n"; } } $r .= "\t\treturn @\$resultado['" . $functionname . "Result'];\n"; $r .= "\t}\n"; } - $r .= "} // end {$this->NAME_WS}Client\n"; + $r .= "} // end {$this->nameWebService}Client\n"; return $r; } @@ -1343,25 +1611,26 @@ protected function genunitycsharp() { using System.Collections; using System.Collections.Generic; -public class ' . $this->NAME_WS . ' : MonoBehaviour +public class ' . $this->nameWebService . ' : MonoBehaviour { // Use this for initialization private string charset = "UTF-8"; - private string url = "' . $this->FILE . '"; - private string tempuri = "' . $this->NAMESPACE . '"; + private string url = "' . $this->portUrl . '"; + private string tempuri = "' . $this->nameSpace . '"; private string prefixns = "ts"; public string cookie=""; '; - foreach ($this->operation as $key => $value) { - $tmpname = $value['name']; - if (count($value['out']) >= 1) { - $outtype = $this->fixtag($value['out'][0]['type']); - $outtypereal = $this->type2csharp($outtype); - } else { - $outtypereal = ''; - } - $r .= ' + foreach ($this->operation as $complexName => $args) { + foreach ($args as $argname => $v) { + $tmpname = $argname; + if (isset($value['out']) && count($v['out']) >= 1) { + $outtype = $this->fixtag($v['out']['type']); + $outtypereal = $this->type2csharp($outtype); + } else { + $outtypereal = ''; + } + $r .= ' // ' . $tmpname . ' public Boolean is' . $tmpname . 'Running = false; private WWW webservice' . $tmpname . '; @@ -1370,44 +1639,45 @@ protected function genunitycsharp() { public ' . $outtypereal . ' ' . $tmpname . 'Result; // End ' . $tmpname . ' '; + } } $r .= ' private void Start() { return; }'; - foreach ($this->operation as $key => $value) { - $tmpname = $value['name']; - $param = ''; - foreach ($value['in'] as $key2 => $value2) { - $param .= $this->fixtag($value2['type']) . ' ' . $value2['name'] . ','; - } - $param = $this->right($param, 1); - $r .= ' + foreach ($this->operation as $complexName => $args) { + foreach ($args as $argname => $v) { + $tmpname = $argname; + $param = ''; + foreach ($v['in'] as $key2 => $value2) { + $param .= $this->fixtag($value2['type']) . ' ' . $key2 . ','; + } + $param = $this->right($param, 1); + $r .= ' private void ' . $tmpname . 'Async(' . $param . ') { string namefunction = "' . $tmpname . '"; Single soapVersion=1.1f; string ss2 = SoapHeader(namefunction,soapVersion);'; - foreach ($value['in'] as $key2 => $value2) { - $name = $value2['name']; - $r .= ' + foreach ($v['in'] as $key2 => $value2) { + $name = $key2; + $r .= ' ss2 += "<" + prefixns + ":' . $name . '>" + Obj2XML(' . $name . ',true) + ""; '; - } - - if (count($value['out']) >= 1) { - $outtype = $this->fixtag($value['out'][0]['type']); - $outtypereal = $this->type2csharp($outtype); - $outinit = $this->csharp_init($outtype); - } else { - $outtype = ''; - $outtypereal = ''; - $outinit = ''; - } + } + if (isset($value['out']) && count($v['out']) >= 1) { + $outtype = $this->fixtag($v['out']['type']); + $outtypereal = $this->type2csharp($outtype); + $outinit = $this->csharp_init($outtype); + } else { + $outtype = ''; + $outtypereal = ''; + $outinit = ''; + } - $r .= 'ss2 += SoapFooter(namefunction,soapVersion); + $r .= 'ss2 += SoapFooter(namefunction,soapVersion); is' . $tmpname . 'Running = true; StartCoroutine(' . $tmpname . 'Async2(ss2)); } @@ -1426,25 +1696,27 @@ protected function genunitycsharp() { is' . $tmpname . 'Running = false; string other = cleanSOAPAnswer(webservice' . $tmpname . '.text, "' . $tmpname . '",ref ' . $tmpname . 'Error); '; - if ($outtype != '') { - $r .= $tmpname . 'Result=' . $outinit . ";\n"; - $r .= ' ' . $tmpname . 'Result=(' . $outtypereal . ')XML2Obj(other,"' . $outtype . '",' . - $tmpname . 'Result.GetType()); + if ($outtype != '') { + $r .= $tmpname . 'Result=' . $outinit . ";\n"; + $r .= ' ' . $tmpname . 'Result=(' . $outtypereal . ')XML2Obj(other,"' . $outtype + . '",' . + $tmpname . 'Result.GetType()); '; - } - $r .= 'webservice' . $tmpname . '.responseHeaders.TryGetValue("SET-COOKIE",out cookie); + } + $r .= 'webservice' . $tmpname . '.responseHeaders.TryGetValue("SET-COOKIE",out cookie); '; - $r .= $tmpname . 'AsyncDone(); + $r .= $tmpname . 'AsyncDone(); } public void ' . $tmpname . 'AsyncDone() { // we do something...'; - if ($outtype != '') { - $r .= ' + if ($outtype != '') { + $r .= ' // ' . $outtypereal . ' dnx=' . $tmpname . 'Result;'; - } - $r .= ' + } + $r .= ' } '; + } } $r .= ' @@ -1598,29 +1870,26 @@ protected function genunitycsharp() { '; $r .= "\n" . $this->genphpast('Complex Types (Classes)'); - foreach ($this->complextype as $key => $value) { - $type = $this->fixtag(@$value['type']); - + foreach ($this->complextype as $complexName => $args) { + $type = $this->fixtag(@$args['type']); - if (strlen($value['name']) <= 7 || strpos($value['name'], 'ArrayOf') === 0) { - $r .= "\npublic class " . $value['name'] . " {\n"; - foreach ($value['elements'] as $key2 => $value2) { - $r .= "\tprivate " . $type . ' _' . $value2['name'] . "; \n"; + if (strlen($complexName) <= 7 || strpos($complexName, 'ArrayOf') === 0) { + $r .= "\npublic class " . $complexName . " {\n"; + foreach ($args as $key2 => $value2) { + $r .= "\tprivate " . $type . ' _' . $key2 . "; \n"; } $r .= "\n"; - foreach ($value['elements'] as $key2 => $value2) { - $r .= "\tpublic " . $type . ' ' . $value2['name'] . "\n"; + foreach ($args as $key2 => $value2) { + $r .= "\tpublic {$type} {$key2}\n"; $r .= "\t{\n"; - $r .= "\t\tget { return _" . $value2['name'] . "; }\n"; - $r .= "\t\tset { _" . $value2['name'] . " = value; }\n"; + $r .= "\t\tget { return _{$key2}; }\n"; + $r .= "\t\tset { _{$key2} = value; }\n"; $r .= "\t}\n"; } - $r .= "}\n"; } } - return ($r); } @@ -1656,9 +1925,13 @@ protected function csharp_init($type) { protected function source() { $result = $this->html_header(); $result .= '

List of Operations

'; $result .= $this->html_footer(); @@ -1667,7 +1940,7 @@ protected function source() { protected function html_header() { $r = '
'; - $r .= '' . $this->NAME_WS . "\n"; + $r .= '' . $this->nameWebService . "\n"; $r .= "