Permalink
Browse files

Return varray / darray from ext_soap

Summary: `ext_soap` is a nest of PHP arrays and zend values: let's try to return `varray` and `darray` where we can.

Reviewed By: jjgriego

Differential Revision: D10446808

fbshipit-source-id: 09f5af8e7bc06b1d7b5273cdd1b5d7b9d6f28bc5
  • Loading branch information...
huntergoldstein authored and hhvm-bot committed Nov 17, 2018
1 parent 1b01e01 commit 253b620b7e49580463a76934b5d815721fa51c28
@@ -27,6 +27,7 @@
#include "hphp/runtime/base/comparisons.h"
#include "hphp/runtime/base/http-client.h"
#include "hphp/runtime/base/php-globals.h"
#include "hphp/runtime/base/type-variant.h"
#include "hphp/runtime/server/http-protocol.h"
#include "hphp/runtime/ext/soap/soap.h"
#include "hphp/runtime/ext/soap/packet.h"
@@ -2098,15 +2099,19 @@ Variant HHVM_METHOD(SoapServer, getfunctions) {
} else if (data->m_type == SOAP_CLASS) {
class_name = data->m_soap_class.name;
} else if (data->m_soap_functions.functions_all) {
return Unit::getSystemFunctions() + Unit::getUserFunctions();
return (Unit::getSystemFunctions() + Unit::getUserFunctions()).toVArray();
} else if (!data->m_soap_functions.ft.empty()) {
return array_keys_helper(data->m_soap_functions.ftOriginal);
auto ret = array_keys_helper(data->m_soap_functions.ftOriginal);
if (ret.isArray()) {
return ret.toVArray();
}
return ret;
}
Class* cls = Unit::lookupClass(class_name.get());
auto ret = Array::attach(PackedArray::MakeReserve(cls->numMethods()));
Class::getMethodNames(cls, nullptr, ret);
return Variant::attach(HHVM_FN(array_values)(ret));
return ret.toVArray();
}
static bool valid_function(SoapServer *server, Object &soap_obj,
@@ -2543,12 +2548,13 @@ void HHVM_METHOD(SoapClient, __construct,
}
}
Variant HHVM_METHOD(SoapClient, __soapcall,
Variant HHVM_METHOD(SoapClient, soapcallImpl,
const String& name,
const Array& args,
const Array& options = null_array,
const Variant& input_headers = uninit_variant,
VRefParam output_headers_ref = init_null()) {
SuppressHACRefBindNotices shacn;
auto* data = Native::data<SoapClient>(this_);
SoapClientScope ss(this_);
@@ -2706,13 +2712,6 @@ Variant HHVM_METHOD(SoapClient, __soapcall,
return return_value;
}
Variant HHVM_METHOD(SoapClient, __call,
const Variant& name,
const Variant& args) {
return HHVM_MN(SoapClient, __soapcall)(this_, name.toString(),
args.toArray());
}
Variant HHVM_METHOD(SoapClient, __getlastrequest) {
auto* data = Native::data<SoapClient>(this_);
return data->m_last_request;
@@ -2738,13 +2737,13 @@ Variant HHVM_METHOD(SoapClient, __getfunctions) {
SoapClientScope ss(this_);
if (data->m_sdl) {
Array ret = Array::Create();
for (auto& func: data->m_sdl->functionsOrder) {
VArrayInit ret(data->m_sdl->functionsOrder.size());
for (const auto& func: data->m_sdl->functionsOrder) {
StringBuffer sb;
function_to_string(data->m_sdl->functions[func], sb);
ret.append(sb.detach());
}
return ret;
return ret.toArray();
}
return init_null();
}
@@ -2754,13 +2753,13 @@ Variant HHVM_METHOD(SoapClient, __gettypes) {
SoapClientScope ss(this_);
if (data->m_sdl) {
Array ret = Array::Create();
for (unsigned int i = 0; i < data->m_sdl->types.size(); i++) {
VArrayInit ret(data->m_sdl->types.size());
for (const auto& type: data->m_sdl->types) {
StringBuffer sb;
type_to_string(data->m_sdl->types[i].get(), sb, 0);
type_to_string(type.get(), sb, 0);
ret.append(sb.detach());
}
return ret;
return ret.toArray();
}
return init_null();
}
@@ -3108,8 +3107,7 @@ static struct SoapExtension final : Extension {
Native::NDIFlags::NO_SWEEP);
HHVM_ME(SoapClient, __construct);
HHVM_ME(SoapClient, __call);
HHVM_ME(SoapClient, __soapcall);
HHVM_ME(SoapClient, soapcallImpl);
HHVM_ME(SoapClient, __getlastrequest);
HHVM_ME(SoapClient, __getlastresponse);
HHVM_ME(SoapClient, __getlastrequestheaders);
@@ -4,7 +4,10 @@
class SoapServer {
<<__Native>>
function __construct(mixed $wsdl, array $options = []): void;
function __construct(
mixed $wsdl,
darray<string, mixed> $options = darray[],
): void;
/**
* Exports all methods from specified class. The object can be made
@@ -115,18 +118,75 @@ function addsoapheader(mixed $fault): void;
<<__NativeData("SoapClient")>>
class SoapClient {
<<__Native>>
function __construct(mixed $wsdl, array $options = []): void;
// Clean out different kinds of arrays, recursively, from an input. For
// __soapcall, we want to pass in PHP arrays but receive Hack arrays, so we
// invoke cleanArrays twice: once with a PHP array as the base, once with
// a Hack array as the base.
private static function cleanArrays(
mixed $input,
mixed $base,
mixed $seen = null,
): mixed {
if ($seen === null) {
$seen = new stdClass();
$seen->set = keyset[];
}
if (HH\is_any_array($input)) {
$ret = $base;
foreach ($input as $k => $v) {
$ret[$k] = self::cleanArrays($v, $base, $seen);
}
return $ret;
} else if (is_object($input)) {
$hash = spl_object_hash($input);
if (array_key_exists($hash, $seen->set)) {
return $input;
}
$seen->set[] = $hash;
foreach ($input as $k => $v) {
$input->$k = self::cleanArrays($v, $base, $seen);
}
return $input;
}
return $input;
}
<<__Native>>
function __call(mixed $name, mixed $args): mixed;
function __construct(
mixed $wsdl,
darray<string, mixed> $options = darray[],
): void;
<<__Native>>
function __soapcall(string $name,
array $args,
array $options = [],
mixed $input_headers = null,
mixed &$output_headers = null): mixed;
private function soapcallImpl(
string $name,
varray<mixed> $args,
darray $options = darray[],
mixed $input_headers = null,
mixed &$output_headers = null
): mixed;
function __call(mixed $name, mixed $args): mixed {
return $this->__soapcall($name, $args);
}
function __soapcall(
string $name,
varray<mixed> $args,
darray $options = darray[],
mixed $input_headers = null,
mixed &$output_headers = null,
): mixed {
$args = self::cleanArrays($args, array());
$ret = $this->soapcallImpl(
$name,
varray($args),
$options,
$input_headers,
&$output_headers,
);
return self::cleanArrays($ret, darray[]);
}
<<__Native>>
function __getlastrequest(): mixed;
@@ -0,0 +1,55 @@
<?xml version="1.0" ?>
<definitions
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd"
xmlns:tns="http://linuxsrv.home/~dmitry/soap/test.wsdl"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://linuxsrv.home/~dmitry/soap/test.wsdl">
<types>
<xsd:schema targetNamespace="http://linuxsrv.home/~dmitry/soap/test.wsdl">
<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
</xsd:schema>
</types>
<message name="AddRequest">
<part name="x" type="xsd:double" />
<part name="y" type="xsd:double" />
</message>
<message name="AddResponse">
<part name="result" type="xsd:double" />
</message>
<portType name="TestServicePortType">
<operation name="Add">
<input message="tns:AddRequest" />
<output message="tns:AddResponse" />
</operation>
</portType>
<binding name="TestServiceBinding" type="tns:TestServicePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="Add">
<soap:operation soapAction="Add" style="rpc" />
<input>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</input>
<output>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
</output>
</operation>
</binding>
<service name="TestService">
<port name="TestServicePort" binding="tns:TestServiceBinding">
<soap:address location="http://linuxsrv.home/~dmitry/soap/soap_server.php" />
</port>
</service>
</definitions>
@@ -0,0 +1,33 @@
<?hh
function Test($param) {
global $g1, $g2;
$g1 = $param->boolA;
$g2 = $param->boolB;
return 1;
}
class TestSoapClient extends SoapClient {
function __construct($wsdl) {
parent::__construct($wsdl);
$this->server = new SoapServer($wsdl);
$this->server->addFunction('Test');
}
function __doRequest($request, $location, $action, $version, $one_way = 0) {
ob_start();
$this->server->handle($request);
$response = ob_get_contents();
ob_end_clean();
return $response;
}
}
$client = new TestSoapClient(dirname(__FILE__).'/bug38055.wsdl');
var_dump($client->__getfunctions());
var_dump($client->__gettypes());
$boolA = 1;
$boolB = '1';
$res = $client->Test(darray['boolA'=>$boolA, 'boolB'=>$boolB]);
var_dump($g1);
var_dump($g2);
@@ -0,0 +1,13 @@
array(1) {
[0]=>
string(26) "int Test(Test $parameters)"
}
array(1) {
[0]=>
string(47) "struct Test {
boolean boolA;
boolean boolB;
}"
}
bool(true)
bool(true)
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:s0="http://test.pl"
targetNamespace="http://test.pl"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<s:schema elementFormDefault="qualified" targetNamespace="http://test.pl">
<s:complexType name="Test">
<s:attribute use="required" name="boolA" type="s:boolean"/>
<s:attribute use="required" name="boolB" type="s:boolean"/>
</s:complexType>
<s:element type="s0:Test" name="Test"/>
<s:element type="s:int" name="Ret"/>
</s:schema>
</types>
<message name="TestSoapIn">
<part name="parameters" element="s0:Test"/>
</message>
<message name="TestSoapOut">
<part name="parameters" element="s0:Ret"/>
</message>
<portType name="TestSoap">
<operation name="Test">
<input message="s0:TestSoapIn"/>
<output message="s0:TestSoapOut"/>
</operation>
</portType>
<binding name="TestSoap" type="s0:TestSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="Test">
<soap:operation soapAction="http:/Test/Test" style="document"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="Test">
<port name="TestSoapPort" binding="s0:TestSoap">
<soap:address location="http://localhost/server.php"/>
</port>
</service>
</definitions>
@@ -0,0 +1,28 @@
hhvm.env_variables[HPHP_INTERPRETER] = 1
hhvm.error_handling.notice_frequency = 1
hhvm.error_handling.warning_frequency = 1
hhvm.allow_hhas = true
hhvm.jit_a_size = 10485760
hhvm.jit_a_cold_size = 4194304
hhvm.jit_a_frozen_size = 6291456
hhvm.jit_a_prof_size = 6291456
hhvm.jit_global_data_size = 2097152
hhvm.thread_tc_main_buffer_size = 1048576
hhvm.thread_tc_cold_buffer_size = 1048576
hhvm.thread_tc_frozen_buffer_size = 1048576
hhvm.hack.lang.auto_typecheck = false
hhvm.hack.lang.ints_overflow_to_ints = true
hhvm.hack.lang.look_for_typechecker = false
hhvm.http.slow_query_threshold = 0
hhvm.mysql.read_timeout = 5000
hhvm.mysql.slow_query_threshold = 0
hhvm.resource_limit.serialization_size_limit = 134217728
hhvm.server_variables[ALPHA_CONSOLE] = 1
hhvm.server_variables[TFBENV] = 16777216
hhvm.hack.lang.autoprime_generators = true
hhvm.raise_missing_this = false
hhvm.php7.all = false
hhvm.force_hh = true
hhvm.hack_arr_compat_type_hint_notices = 1
hhvm.hack_arr_compat_check_ref_bind = 1
Oops, something went wrong.

0 comments on commit 253b620

Please sign in to comment.