Skip to content

Commit 12af81e

Browse files
committed
Fix #44383: PHP DateTime not converted to xsd:datetime
1 parent 3ff3199 commit 12af81e

File tree

4 files changed

+136
-11
lines changed

4 files changed

+136
-11
lines changed

ext/date/php_date.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,11 @@ static zend_string *date_format(const char *format, size_t format_len, timelib_t
841841
return string.s;
842842
}
843843

844+
PHPAPI zend_string *php_format_date_ex(const char *format, size_t format_len, timelib_time *t, bool localtime)
845+
{
846+
return date_format(format, format_len, t, localtime);
847+
}
848+
844849
static void php_date(INTERNAL_FUNCTION_PARAMETERS, bool localtime)
845850
{
846851
zend_string *format;

ext/date/php_date.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ PHPAPI int php_idate(char format, time_t ts, bool localtime);
123123

124124
PHPAPI void php_strftime(INTERNAL_FUNCTION_PARAMETERS, bool gm);
125125
PHPAPI zend_string *php_format_date(const char *format, size_t format_len, time_t ts, bool localtime);
126+
PHPAPI zend_string *php_format_date_ex(const char *format, size_t format_len, timelib_time *t, bool localtime);
126127

127128
/* Mechanism to set new TZ database */
128129
PHPAPI void php_date_set_tzdb(timelib_tzdb *tzdb);

ext/soap/php_encoding.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "php_soap.h"
2222
#include "ext/libxml/php_libxml.h"
2323
#include "ext/standard/base64.h"
24+
#include "ext/date/php_date.h"
2425
#include <libxml/parserInternals.h>
2526
#include "zend_strtod.h"
2627
#include "zend_interfaces.h"
@@ -57,7 +58,7 @@ static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodeP
5758
static xmlNodePtr to_xml_list1(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent);
5859

5960
/* Datetime encode/decode */
60-
static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent);
61+
static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, const char *ext_date_format, size_t ext_date_format_len, int style, xmlNodePtr parent);
6162
static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
6263
static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
6364
static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
@@ -2833,7 +2834,7 @@ static zval *guess_zval_convert(zval *ret, encodeTypePtr type, xmlNodePtr data)
28332834
}
28342835

28352836
/* Time encode/decode */
2836-
static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent)
2837+
static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, const char *ext_date_format, size_t ext_date_format_len, int style, xmlNodePtr parent)
28372838
{
28382839
/* logic hacked from ext/standard/datetime.c */
28392840
struct tm *ta, tmbuf;
@@ -2891,6 +2892,17 @@ static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *forma
28912892
efree(buf);
28922893
} else if (Z_TYPE_P(data) == IS_STRING) {
28932894
xmlNodeSetContentLen(xmlParam, BAD_CAST(Z_STRVAL_P(data)), Z_STRLEN_P(data));
2895+
} else if (Z_TYPE_P(data) == IS_OBJECT) {
2896+
if (instanceof_function_slow(Z_OBJCE_P(data), php_date_get_interface_ce())) {
2897+
php_date_obj *dateobj = Z_PHPDATE_P(data);
2898+
if (dateobj->time) {
2899+
zend_string *formatted = php_format_date_ex(ext_date_format, ext_date_format_len, dateobj->time, dateobj->time->is_localtime);
2900+
xmlNodeSetContentLen(xmlParam, BAD_CAST(ZSTR_VAL(formatted)), ZSTR_LEN(formatted));
2901+
zend_string_release_ex(formatted, false);
2902+
} else {
2903+
soap_error0(E_ERROR, "Encoding: Invalid DateTimeInterface");
2904+
}
2905+
}
28942906
}
28952907

28962908
if (style == SOAP_ENCODED) {
@@ -2905,45 +2917,47 @@ static xmlNodePtr to_xml_duration(encodeTypePtr type, zval *data, int style, xml
29052917
return to_xml_string(type, data, style, parent);
29062918
}
29072919

2920+
#define TO_XML_DATETIME_EX_HELPER(type, date, format, ext_date_format, style, parent) \
2921+
to_xml_datetime_ex(type, data, format, ext_date_format, strlen(ext_date_format), style, parent)
2922+
29082923
static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
29092924
{
2910-
return to_xml_datetime_ex(type, data, "%Y-%m-%dT%H:%M:%S", style, parent);
2925+
return TO_XML_DATETIME_EX_HELPER(type, data, "%Y-%m-%dT%H:%M:%S", "Y-m-d\\TH:i:s.up", style, parent);
29112926
}
29122927

29132928
static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
29142929
{
2915-
/* TODO: microsecconds */
2916-
return to_xml_datetime_ex(type, data, "%H:%M:%S", style, parent);
2930+
return TO_XML_DATETIME_EX_HELPER(type, data, "%H:%M:%S", "H:i:s.up", style, parent);
29172931
}
29182932

29192933
static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
29202934
{
2921-
return to_xml_datetime_ex(type, data, "%Y-%m-%d", style, parent);
2935+
return TO_XML_DATETIME_EX_HELPER(type, data, "%Y-%m-%d", "Y-m-dp", style, parent);
29222936
}
29232937

29242938
static xmlNodePtr to_xml_gyearmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
29252939
{
2926-
return to_xml_datetime_ex(type, data, "%Y-%m", style, parent);
2940+
return TO_XML_DATETIME_EX_HELPER(type, data, "%Y-%m", "Y-mp", style, parent);
29272941
}
29282942

29292943
static xmlNodePtr to_xml_gyear(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
29302944
{
2931-
return to_xml_datetime_ex(type, data, "%Y", style, parent);
2945+
return TO_XML_DATETIME_EX_HELPER(type, data, "%Y", "Yp", style, parent);
29322946
}
29332947

29342948
static xmlNodePtr to_xml_gmonthday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
29352949
{
2936-
return to_xml_datetime_ex(type, data, "--%m-%d", style, parent);
2950+
return TO_XML_DATETIME_EX_HELPER(type, data, "--%m-%d", "--m-dp", style, parent);
29372951
}
29382952

29392953
static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
29402954
{
2941-
return to_xml_datetime_ex(type, data, "---%d", style, parent);
2955+
return TO_XML_DATETIME_EX_HELPER(type, data, "---%d", "---dp", style, parent);
29422956
}
29432957

29442958
static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
29452959
{
2946-
return to_xml_datetime_ex(type, data, "--%m--", style, parent);
2960+
return TO_XML_DATETIME_EX_HELPER(type, data, "--%m--", "--m--p", style, parent);
29472961
}
29482962

29492963
static zval* to_zval_list(zval *ret, encodeTypePtr enc, xmlNodePtr data) {

ext/soap/tests/schema/schema086.phpt

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
--TEST--
2+
SOAP XML Schema 86: DateTimeInterface date/time types
3+
--EXTENSIONS--
4+
soap
5+
xml
6+
--FILE--
7+
<?php
8+
include "test_schema.inc";
9+
$schema = <<<EOF
10+
<complexType name="testType">
11+
<sequence>
12+
<element name="dateTime" type="dateTime"/>
13+
<element name="time" type="time"/>
14+
<element name="date" type="date"/>
15+
<element name="gYearMonth" type="gYearMonth"/>
16+
<element name="gYear" type="gYear"/>
17+
<element name="gMonthDay" type="gMonthDay"/>
18+
<element name="gDay" type="gDay"/>
19+
<element name="gMonth" type="gMonth"/>
20+
</sequence>
21+
</complexType>
22+
EOF;
23+
24+
$test_dates = [
25+
new DateTime("2023-10-14 13:37:42.1234+02:00"),
26+
new DateTimeImmutable("2023-10-14 13:37:42.1234+02:00"),
27+
new DateTime("2023-10-14 13:37:42.1234Z"),
28+
];
29+
30+
foreach ($test_dates as $date) {
31+
test_schema($schema,'type="tns:testType"',array(
32+
'dateTime' => $date,
33+
'time' => $date,
34+
'date' => $date,
35+
'gYearMonth' => $date,
36+
'gYear' => $date,
37+
'gMonthDay' => $date,
38+
'gDay' => $date,
39+
'gMonth' => $date
40+
));
41+
}
42+
echo "ok";
43+
?>
44+
--EXPECTF--
45+
<?xml version="1.0" encoding="UTF-8"?>
46+
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="ns1:testType"><dateTime xsi:type="xsd:dateTime">2023-10-14T13:37:42.123400+02:00</dateTime><time xsi:type="xsd:time">13:37:42.123400+02:00</time><date xsi:type="xsd:date">2023-10-14+02:00</date><gYearMonth xsi:type="xsd:gYearMonth">2023-10+02:00</gYearMonth><gYear xsi:type="xsd:gYear">2023+02:00</gYear><gMonthDay xsi:type="xsd:gMonthDay">--10-14+02:00</gMonthDay><gDay xsi:type="xsd:gDay">---14+02:00</gDay><gMonth xsi:type="xsd:gMonth">--10--+02:00</gMonth></testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope>
47+
object(stdClass)#%d (8) {
48+
["dateTime"]=>
49+
string(32) "2023-10-14T13:37:42.123400+02:00"
50+
["time"]=>
51+
string(21) "13:37:42.123400+02:00"
52+
["date"]=>
53+
string(16) "2023-10-14+02:00"
54+
["gYearMonth"]=>
55+
string(13) "2023-10+02:00"
56+
["gYear"]=>
57+
string(10) "2023+02:00"
58+
["gMonthDay"]=>
59+
string(13) "--10-14+02:00"
60+
["gDay"]=>
61+
string(11) "---14+02:00"
62+
["gMonth"]=>
63+
string(12) "--10--+02:00"
64+
}
65+
<?xml version="1.0" encoding="UTF-8"?>
66+
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="ns1:testType"><dateTime xsi:type="xsd:dateTime">2023-10-14T13:37:42.123400+02:00</dateTime><time xsi:type="xsd:time">13:37:42.123400+02:00</time><date xsi:type="xsd:date">2023-10-14+02:00</date><gYearMonth xsi:type="xsd:gYearMonth">2023-10+02:00</gYearMonth><gYear xsi:type="xsd:gYear">2023+02:00</gYear><gMonthDay xsi:type="xsd:gMonthDay">--10-14+02:00</gMonthDay><gDay xsi:type="xsd:gDay">---14+02:00</gDay><gMonth xsi:type="xsd:gMonth">--10--+02:00</gMonth></testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope>
67+
object(stdClass)#9 (8) {
68+
["dateTime"]=>
69+
string(32) "2023-10-14T13:37:42.123400+02:00"
70+
["time"]=>
71+
string(21) "13:37:42.123400+02:00"
72+
["date"]=>
73+
string(16) "2023-10-14+02:00"
74+
["gYearMonth"]=>
75+
string(13) "2023-10+02:00"
76+
["gYear"]=>
77+
string(10) "2023+02:00"
78+
["gMonthDay"]=>
79+
string(13) "--10-14+02:00"
80+
["gDay"]=>
81+
string(11) "---14+02:00"
82+
["gMonth"]=>
83+
string(12) "--10--+02:00"
84+
}
85+
<?xml version="1.0" encoding="UTF-8"?>
86+
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="ns1:testType"><dateTime xsi:type="xsd:dateTime">2023-10-14T13:37:42.123400Z</dateTime><time xsi:type="xsd:time">13:37:42.123400Z</time><date xsi:type="xsd:date">2023-10-14Z</date><gYearMonth xsi:type="xsd:gYearMonth">2023-10Z</gYearMonth><gYear xsi:type="xsd:gYear">2023Z</gYear><gMonthDay xsi:type="xsd:gMonthDay">--10-14Z</gMonthDay><gDay xsi:type="xsd:gDay">---14Z</gDay><gMonth xsi:type="xsd:gMonth">--10--Z</gMonth></testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope>
87+
object(stdClass)#8 (8) {
88+
["dateTime"]=>
89+
string(27) "2023-10-14T13:37:42.123400Z"
90+
["time"]=>
91+
string(16) "13:37:42.123400Z"
92+
["date"]=>
93+
string(11) "2023-10-14Z"
94+
["gYearMonth"]=>
95+
string(8) "2023-10Z"
96+
["gYear"]=>
97+
string(5) "2023Z"
98+
["gMonthDay"]=>
99+
string(8) "--10-14Z"
100+
["gDay"]=>
101+
string(6) "---14Z"
102+
["gMonth"]=>
103+
string(7) "--10--Z"
104+
}
105+
ok

0 commit comments

Comments
 (0)