mirror of
https://github.com/php/php-src.git
synced 2024-11-27 03:44:07 +08:00
Implement backed enum coercion in http_build_query()
Fixes GH-15650 Closes GH-15704
This commit is contained in:
parent
7a8767fe62
commit
1b9568d354
3
NEWS
3
NEWS
@ -44,6 +44,9 @@ PHP NEWS
|
|||||||
. Fixed bug GH-15711 (SoapClient can't convert BackedEnum to scalar value).
|
. Fixed bug GH-15711 (SoapClient can't convert BackedEnum to scalar value).
|
||||||
(nielsdos)
|
(nielsdos)
|
||||||
|
|
||||||
|
- Standard:
|
||||||
|
. Add support for backed enums in http_build_query(). (ilutov)
|
||||||
|
|
||||||
12 Sep 2024, PHP 8.4.0beta5
|
12 Sep 2024, PHP 8.4.0beta5
|
||||||
|
|
||||||
- BCMath:
|
- BCMath:
|
||||||
|
@ -225,6 +225,7 @@ PHP 8.4 UPGRADE NOTES
|
|||||||
. php_uname() now throws ValueErrors on invalid inputs.
|
. php_uname() now throws ValueErrors on invalid inputs.
|
||||||
. The "allowed_classes" option for unserialize() now throws TypeErrors and
|
. The "allowed_classes" option for unserialize() now throws TypeErrors and
|
||||||
ValueErrors if it is not an array of class names.
|
ValueErrors if it is not an array of class names.
|
||||||
|
. http_build_query() now correctly handles backed enums.
|
||||||
|
|
||||||
- Tidy:
|
- Tidy:
|
||||||
. Failures in the constructor now throw exceptions rather than emitting
|
. Failures in the constructor now throw exceptions rather than emitting
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "SAPI.h"
|
#include "SAPI.h"
|
||||||
#include "zend_exceptions.h"
|
#include "zend_exceptions.h"
|
||||||
#include "basic_functions.h"
|
#include "basic_functions.h"
|
||||||
|
#include "zend_enum.h"
|
||||||
|
|
||||||
static void php_url_encode_scalar(zval *scalar, smart_str *form_str,
|
static void php_url_encode_scalar(zval *scalar, smart_str *form_str,
|
||||||
int encoding_type, zend_ulong index_int,
|
int encoding_type, zend_ulong index_int,
|
||||||
@ -56,6 +57,7 @@ static void php_url_encode_scalar(zval *scalar, smart_str *form_str,
|
|||||||
}
|
}
|
||||||
smart_str_appendc(form_str, '=');
|
smart_str_appendc(form_str, '=');
|
||||||
|
|
||||||
|
try_again:
|
||||||
switch (Z_TYPE_P(scalar)) {
|
switch (Z_TYPE_P(scalar)) {
|
||||||
case IS_STRING: {
|
case IS_STRING: {
|
||||||
zend_string *encoded_data;
|
zend_string *encoded_data;
|
||||||
@ -90,6 +92,14 @@ static void php_url_encode_scalar(zval *scalar, smart_str *form_str,
|
|||||||
case IS_TRUE:
|
case IS_TRUE:
|
||||||
smart_str_appendc(form_str, '1');
|
smart_str_appendc(form_str, '1');
|
||||||
break;
|
break;
|
||||||
|
case IS_OBJECT:
|
||||||
|
ZEND_ASSERT(Z_OBJCE_P(scalar)->ce_flags & ZEND_ACC_ENUM);
|
||||||
|
if (Z_OBJCE_P(scalar)->enum_backing_type == IS_UNDEF) {
|
||||||
|
zend_value_error("Unbacked enum %s cannot be converted to a string", ZSTR_VAL(Z_OBJCE_P(scalar)->name));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
scalar = zend_enum_fetch_case_value(Z_OBJ_P(scalar));
|
||||||
|
goto try_again;
|
||||||
/* All possible types are either handled here or previously */
|
/* All possible types are either handled here or previously */
|
||||||
EMPTY_SWITCH_DEFAULT_CASE();
|
EMPTY_SWITCH_DEFAULT_CASE();
|
||||||
}
|
}
|
||||||
@ -154,7 +164,9 @@ PHPAPI void php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ZVAL_DEREF(zdata);
|
ZVAL_DEREF(zdata);
|
||||||
if (Z_TYPE_P(zdata) == IS_ARRAY || Z_TYPE_P(zdata) == IS_OBJECT) {
|
if (Z_TYPE_P(zdata) == IS_ARRAY
|
||||||
|
|| (Z_TYPE_P(zdata) == IS_OBJECT
|
||||||
|
&& !(Z_OBJCE_P(zdata)->ce_flags & ZEND_ACC_ENUM))) {
|
||||||
zend_string *new_prefix;
|
zend_string *new_prefix;
|
||||||
if (key) {
|
if (key) {
|
||||||
zend_string *encoded_key;
|
zend_string *encoded_key;
|
||||||
@ -233,6 +245,11 @@ PHP_FUNCTION(http_build_query)
|
|||||||
Z_PARAM_LONG(enc_type)
|
Z_PARAM_LONG(enc_type)
|
||||||
ZEND_PARSE_PARAMETERS_END();
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
|
if (UNEXPECTED(Z_TYPE_P(formdata) == IS_OBJECT && (Z_OBJCE_P(formdata)->ce_flags & ZEND_ACC_ENUM))) {
|
||||||
|
zend_argument_type_error(1, "must be of type array, %s given", zend_zval_value_name(formdata));
|
||||||
|
RETURN_THROWS();
|
||||||
|
}
|
||||||
|
|
||||||
php_url_encode_hash_ex(HASH_OF(formdata), &formstr, prefix, prefix_len, /* key_prefix */ NULL, (Z_TYPE_P(formdata) == IS_OBJECT ? formdata : NULL), arg_sep, (int)enc_type);
|
php_url_encode_hash_ex(HASH_OF(formdata), &formstr, prefix, prefix_len, /* key_prefix */ NULL, (Z_TYPE_P(formdata) == IS_OBJECT ? formdata : NULL), arg_sep, (int)enc_type);
|
||||||
|
|
||||||
RETURN_STR(smart_str_extract(&formstr));
|
RETURN_STR(smart_str_extract(&formstr));
|
||||||
|
36
ext/standard/tests/http/gh15650.phpt
Normal file
36
ext/standard/tests/http/gh15650.phpt
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
--TEST--
|
||||||
|
GH-15650: http_build_query() with enum
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
enum E1: string {
|
||||||
|
case C = 'hello world!';
|
||||||
|
}
|
||||||
|
|
||||||
|
enum E2: int {
|
||||||
|
case C = 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum E3 {
|
||||||
|
case C;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo http_build_query(['e1' => E1::C, 'e2' => E2::C]), "\n";
|
||||||
|
|
||||||
|
try {
|
||||||
|
echo http_build_query(['e3' => E3::C]);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
echo http_build_query(E1::C);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo get_class($e), ': ', $e->getMessage(), "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
e1=hello+world%21&e2=42
|
||||||
|
ValueError: Unbacked enum E3 cannot be converted to a string
|
||||||
|
TypeError: http_build_query(): Argument #1 ($data) must be of type array, E1 given
|
Loading…
Reference in New Issue
Block a user