Skip to content

Commit 7de2677

Browse files
committed
Implement phpGH-15711: Allow SoapClient to use the backing value during response serialization (string enums)
1 parent 47915dd commit 7de2677

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

ext/soap/php_encoding.c

+11
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,17 @@ static zval *to_zval_hexbin(zval *ret, encodeTypePtr type, xmlNodePtr data)
834834
static zend_string *get_serialization_string_from_zval(zval *data)
835835
{
836836
switch (Z_TYPE_P(data)) {
837+
case IS_OBJECT:
838+
if (Z_OBJCE_P(data)->ce_flags & ZEND_ACC_ENUM) {
839+
if (UNEXPECTED(Z_OBJCE_P(data)->enum_backing_type == IS_UNDEF)) {
840+
zend_value_error("Non-backed enums have no default serialization");
841+
return zend_empty_string;
842+
} else {
843+
zval *value = zend_enum_fetch_case_value(Z_OBJ_P(data));
844+
return zval_get_string_func(value);
845+
}
846+
}
847+
ZEND_FALLTHROUGH;
837848
default:
838849
return zval_get_string_func(data);
839850
}

ext/soap/tests/gh15711.phpt

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
--TEST--
2+
GH-15711 (SoapClient can't convert BackedEnum to scalar value)
3+
--EXTENSIONS--
4+
soap
5+
--INI--
6+
soap.wsdl_cache_enabled=0
7+
--FILE--
8+
<?php
9+
10+
enum TestBackedEnum: string
11+
{
12+
case First = 'BackingValue1';
13+
case Second = 'BackingValue2';
14+
case Third = 'BackingValue3';
15+
case Fourth = 'BackingValue4';
16+
case Fifth = 'BackingValue5';
17+
}
18+
19+
enum TestNonBackedEnum
20+
{
21+
case First;
22+
}
23+
24+
class TestSoapClient extends SoapClient {
25+
function __doRequest($request, $location, $action, $version, $one_way = 0): ?string {
26+
echo $request;
27+
}
28+
}
29+
30+
$client = new TestSoapClient('ext/soap/tests/gh15711.wsdl', ['classmap' => ['book' => 'book']]);
31+
32+
echo "--- Test with backed enum ---\n";
33+
34+
$book = new stdClass();
35+
$book->base64 = TestBackedEnum::First;
36+
$book->string = TestBackedEnum::Second;
37+
$book->any = TestBackedEnum::Third;
38+
$book->hexbin = TestBackedEnum::Fourth;
39+
$book->nmtokens = TestBackedEnum::Fifth;
40+
41+
try {
42+
$client->dotest($book);
43+
} catch (Throwable) {}
44+
45+
echo "--- Test with non-backed enum ---\n";
46+
47+
$book = new stdClass();
48+
$book->base64 = TestNonBackedEnum::First;
49+
$book->string = TestNonBackedEnum::First;
50+
$book->any = TestNonBackedEnum::First;
51+
$book->hexbin = TestNonBackedEnum::First;
52+
$book->nmtokens = TestNonBackedEnum::First;
53+
54+
try {
55+
$client->dotest($book);
56+
} catch (ValueError $e) {
57+
echo "ValueError: ", $e->getMessage(), "\n";
58+
}
59+
60+
?>
61+
--EXPECT--
62+
--- Test with backed enum ---
63+
<?xml version="1.0" encoding="UTF-8"?>
64+
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.nothing.com" 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/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:dotest><dotestReturn xsi:type="ns1:book"><base64 xsi:type="xsd:base64Binary">QmFja2luZ1ZhbHVlMQ==</base64><string xsi:type="xsd:string">BackingValue2</string><any xsi:type="xsd:any"><name xsi:type="xsd:string">Third</name><value xsi:type="xsd:string">BackingValue3</value></any><hexbin xsi:type="xsd:hexBinary">4261636B696E6756616C756534</hexbin><nmtokens>BackingValue5</nmtokens></dotestReturn></ns1:dotest></SOAP-ENV:Body></SOAP-ENV:Envelope>
65+
--- Test with non-backed enum ---
66+
ValueError: Non-backed enums have no default serialization

ext/soap/tests/gh15711.wsdl

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<wsdl:definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.nothing.com" targetNamespace="http://schemas.nothing.com">
2+
<wsdl:types>
3+
<xsd:schema targetNamespace="http://schemas.nothing.com">
4+
<xsd:complexType name="book">
5+
<xsd:all>
6+
<xsd:element name="base64" type="xsd:base64Binary"/>
7+
<xsd:element name="string" type="xsd:string"/>
8+
<xsd:element name="any" type="xsd:any"/>
9+
<xsd:element name="hexbin" type="xsd:hexBinary"/>
10+
<xsd:element name="nmtokens" type="xsd:NMTOKENS"/>
11+
</xsd:all>
12+
</xsd:complexType>
13+
</xsd:schema>
14+
</wsdl:types>
15+
<message name="dotestRequest">
16+
<part name="dotestReturn" type="tns:book"/>
17+
</message>
18+
<portType name="testPortType">
19+
<operation name="dotest">
20+
<input message="tns:dotestRequest"/>
21+
</operation>
22+
</portType>
23+
<binding name="testBinding" type="tns:testPortType">
24+
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
25+
<operation name="dotest">
26+
<soap:operation soapAction="http://localhost:81/test/interface.php?class=test/dotest" style="rpc"/>
27+
<input>
28+
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://schemas.nothing.com"/>
29+
</input>
30+
</operation>
31+
</binding>
32+
<service name="test">
33+
<port name="testPort" binding="tns:testBinding">
34+
<soap:address location="http://localhost:81/test/interface.php?class=test"/>
35+
</port>
36+
</service>
37+
</wsdl:definitions>

0 commit comments

Comments
 (0)