Skip to content

Commit e93d20a

Browse files
committed
Add ZPP macros for class name or object parameters
Closes GH-5647
1 parent c2b23d8 commit e93d20a

File tree

7 files changed

+150
-91
lines changed

7 files changed

+150
-91
lines changed

Zend/tests/010.phpt

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,37 @@ var_dump(get_parent_class("bar"));
3232
var_dump(get_parent_class("foo"));
3333
var_dump(get_parent_class("i"));
3434

35-
var_dump(get_parent_class(""));
36-
var_dump(get_parent_class("[[[["));
37-
var_dump(get_parent_class(" "));
35+
try {
36+
get_parent_class("");
37+
} catch (TypeError $exception) {
38+
echo $exception->getMessage() . "\n";
39+
}
40+
41+
try {
42+
get_parent_class("[[[[");
43+
} catch (TypeError $exception) {
44+
echo $exception->getMessage() . "\n";
45+
}
46+
47+
try {
48+
get_parent_class(" ");
49+
} catch (TypeError $exception) {
50+
echo $exception->getMessage() . "\n";
51+
}
52+
3853
var_dump(get_parent_class(new stdclass));
39-
var_dump(get_parent_class(array()));
40-
var_dump(get_parent_class(1));
54+
55+
try {
56+
get_parent_class(array());
57+
} catch (TypeError $exception) {
58+
echo $exception->getMessage() . "\n";
59+
}
60+
61+
try {
62+
get_parent_class(1);
63+
} catch (TypeError $exception) {
64+
echo $exception->getMessage() . "\n";
65+
}
4166

4267
echo "Done\n";
4368
?>
@@ -50,10 +75,10 @@ bool(false)
5075
string(3) "foo"
5176
bool(false)
5277
bool(false)
78+
get_parent_class(): Argument #1 ($object) must be a valid class name or object, string given
79+
get_parent_class(): Argument #1 ($object) must be a valid class name or object, string given
80+
get_parent_class(): Argument #1 ($object) must be a valid class name or object, string given
5381
bool(false)
54-
bool(false)
55-
bool(false)
56-
bool(false)
57-
bool(false)
58-
bool(false)
82+
get_parent_class(): Argument #1 ($object) must be a valid class name or object, array given
83+
get_parent_class(): Argument #1 ($object) must be a valid class name or object, int given
5984
Done

Zend/zend_API.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,8 @@ static zend_always_inline zval *zend_try_array_init(zval *zv)
12171217
_(Z_EXPECTED_STRING_OR_ARRAY_OR_NULL, "of type string|array|null") \
12181218
_(Z_EXPECTED_STRING_OR_LONG, "of type string|int") \
12191219
_(Z_EXPECTED_STRING_OR_LONG_OR_NULL, "of type string|int|null") \
1220+
_(Z_EXPECTED_CLASS_NAME_OR_OBJECT, "a valid class name or object") \
1221+
_(Z_EXPECTED_CLASS_NAME_OR_OBJECT_OR_NULL, "a valid class name, object, or null") \
12201222

12211223
#define Z_EXPECTED_TYPE
12221224

@@ -1395,6 +1397,20 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num
13951397
#define Z_PARAM_CLASS(dest) \
13961398
Z_PARAM_CLASS_EX(dest, 0, 0)
13971399

1400+
#define Z_PARAM_CLASS_NAME_OR_OBJ_EX(dest, allow_null) \
1401+
Z_PARAM_PROLOGUE(0, 0); \
1402+
if (UNEXPECTED(!zend_parse_arg_class_name_or_obj(_arg, &dest, _i, allow_null))) { \
1403+
_expected_type = allow_null ? Z_EXPECTED_CLASS_NAME_OR_OBJECT_OR_NULL : Z_EXPECTED_CLASS_NAME_OR_OBJECT; \
1404+
_error_code = ZPP_ERROR_WRONG_ARG; \
1405+
break; \
1406+
}
1407+
1408+
#define Z_PARAM_CLASS_NAME_OR_OBJ(dest) \
1409+
Z_PARAM_CLASS_NAME_OR_OBJ_EX(dest, 0);
1410+
1411+
#define Z_PARAM_CLASS_NAME_OR_OBJ_OR_NULL(dest) \
1412+
Z_PARAM_CLASS_NAME_OR_OBJ_EX(dest, 1);
1413+
13981414
/* old "d" */
13991415
#define Z_PARAM_DOUBLE_EX2(dest, is_null, check_null, deref, separate) \
14001416
Z_PARAM_PROLOGUE(deref, separate); \
@@ -1513,6 +1529,9 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num
15131529
#define Z_PARAM_OBJECT(dest) \
15141530
Z_PARAM_OBJECT_EX(dest, 0, 0)
15151531

1532+
#define Z_PARAM_OBJECT_OR_NULL(dest) \
1533+
Z_PARAM_OBJECT_EX(dest, 1, 0)
1534+
15161535
/* old "O" */
15171536
#define Z_PARAM_OBJECT_OF_CLASS_EX2(dest, _ce, check_null, deref, separate) \
15181537
Z_PARAM_PROLOGUE(deref, separate); \
@@ -1534,6 +1553,9 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num
15341553
#define Z_PARAM_OBJECT_OF_CLASS(dest, _ce) \
15351554
Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, 0, 0)
15361555

1556+
#define Z_PARAM_OBJECT_OF_CLASS_OR_NULL(dest, _ce) \
1557+
Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, 1, 0)
1558+
15371559
/* old "p" */
15381560
#define Z_PARAM_PATH_EX2(dest, dest_len, check_null, deref, separate) \
15391561
Z_PARAM_PROLOGUE(deref, separate); \
@@ -1673,6 +1695,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num
16731695

16741696
#define Z_PARAM_STR_OR_LONG_OR_NULL(dest_str, dest_long, is_null) \
16751697
Z_PARAM_STR_OR_LONG_EX(dest_str, dest_long, is_null, 1);
1698+
16761699
/* End of new parameter parsing API */
16771700

16781701
/* Inlined implementations shared by new and old parameter parsing APIs */
@@ -1931,6 +1954,24 @@ static zend_always_inline int zend_parse_arg_str_or_long(zval *arg, zend_string
19311954
return 1;
19321955
}
19331956

1957+
static zend_always_inline int zend_parse_arg_class_name_or_obj(
1958+
zval *arg, zend_class_entry **destination, int num, int allow_null
1959+
) {
1960+
if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
1961+
*destination = zend_lookup_class(Z_STR_P(arg));
1962+
1963+
return *destination != NULL;
1964+
} else if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
1965+
*destination = Z_OBJ_P(arg)->ce;
1966+
} else if (allow_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
1967+
*destination = NULL;
1968+
} else {
1969+
return 0;
1970+
}
1971+
1972+
return 1;
1973+
}
1974+
19341975
END_EXTERN_C()
19351976

19361977
#endif /* ZEND_API_H */

Zend/zend_builtin_functions.c

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -637,26 +637,15 @@ ZEND_FUNCTION(get_called_class)
637637
Retrieves the parent class name for object or class or current scope or false if not in a scope. */
638638
ZEND_FUNCTION(get_parent_class)
639639
{
640-
zval *arg;
641640
zend_class_entry *ce = NULL;
642641

643-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|z", &arg) == FAILURE) {
644-
RETURN_THROWS();
645-
}
642+
ZEND_PARSE_PARAMETERS_START(0, 1)
643+
Z_PARAM_OPTIONAL
644+
Z_PARAM_CLASS_NAME_OR_OBJ(ce)
645+
ZEND_PARSE_PARAMETERS_END();
646646

647-
if (!ZEND_NUM_ARGS()) {
647+
if (!ce) {
648648
ce = zend_get_executed_scope();
649-
if (ce && ce->parent) {
650-
RETURN_STR_COPY(ce->parent->name);
651-
} else {
652-
RETURN_FALSE;
653-
}
654-
}
655-
656-
if (Z_TYPE_P(arg) == IS_OBJECT) {
657-
ce = Z_OBJ_P(arg)->ce;
658-
} else if (Z_TYPE_P(arg) == IS_STRING) {
659-
ce = zend_lookup_class(Z_STR_P(arg));
660649
}
661650

662651
if (ce && ce->parent) {

Zend/zend_builtin_functions.stub.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function get_class(object $object = UNKNOWN): string {}
3030

3131
function get_called_class(): string {}
3232

33-
function get_parent_class($object = UNKNOWN): string|false {}
33+
function get_parent_class(string|object $object = UNKNOWN): string|false {}
3434

3535
function is_subclass_of($object, string $class_name, bool $allow_string = true): bool {}
3636

Zend/zend_builtin_functions_arginfo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ ZEND_END_ARG_INFO()
5454
#define arginfo_get_called_class arginfo_zend_version
5555

5656
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_get_parent_class, 0, 0, MAY_BE_STRING|MAY_BE_FALSE)
57-
ZEND_ARG_INFO(0, object)
57+
ZEND_ARG_TYPE_MASK(0, object, MAY_BE_STRING|MAY_BE_OBJECT, NULL)
5858
ZEND_END_ARG_INFO()
5959

6060
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_is_subclass_of, 0, 2, _IS_BOOL, 0)

ext/date/php_date.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2295,7 +2295,7 @@ PHP_FUNCTION(date_create)
22952295
ZEND_PARSE_PARAMETERS_START(0, 2)
22962296
Z_PARAM_OPTIONAL
22972297
Z_PARAM_STRING(time_str, time_str_len)
2298-
Z_PARAM_OBJECT_OF_CLASS_EX(timezone_object, date_ce_timezone, 1, 0)
2298+
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
22992299
ZEND_PARSE_PARAMETERS_END();
23002300

23012301
php_date_instantiate(date_ce_date, return_value);
@@ -2318,7 +2318,7 @@ PHP_FUNCTION(date_create_immutable)
23182318
ZEND_PARSE_PARAMETERS_START(0, 2)
23192319
Z_PARAM_OPTIONAL
23202320
Z_PARAM_STRING(time_str, time_str_len)
2321-
Z_PARAM_OBJECT_OF_CLASS_EX(timezone_object, date_ce_timezone, 1, 0)
2321+
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
23222322
ZEND_PARSE_PARAMETERS_END();
23232323

23242324
php_date_instantiate(date_ce_immutable, return_value);
@@ -2342,7 +2342,7 @@ PHP_FUNCTION(date_create_from_format)
23422342
Z_PARAM_STRING(format_str, format_str_len)
23432343
Z_PARAM_STRING(time_str, time_str_len)
23442344
Z_PARAM_OPTIONAL
2345-
Z_PARAM_OBJECT_OF_CLASS_EX(timezone_object, date_ce_timezone, 1, 0)
2345+
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
23462346
ZEND_PARSE_PARAMETERS_END();
23472347

23482348
php_date_instantiate(date_ce_date, return_value);
@@ -2366,7 +2366,7 @@ PHP_FUNCTION(date_create_immutable_from_format)
23662366
Z_PARAM_STRING(format_str, format_str_len)
23672367
Z_PARAM_STRING(time_str, time_str_len)
23682368
Z_PARAM_OPTIONAL
2369-
Z_PARAM_OBJECT_OF_CLASS_EX(timezone_object, date_ce_timezone, 1, 0)
2369+
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
23702370
ZEND_PARSE_PARAMETERS_END();
23712371

23722372
php_date_instantiate(date_ce_immutable, return_value);
@@ -2390,7 +2390,7 @@ PHP_METHOD(DateTime, __construct)
23902390
ZEND_PARSE_PARAMETERS_START(0, 2)
23912391
Z_PARAM_OPTIONAL
23922392
Z_PARAM_STRING(time_str, time_str_len)
2393-
Z_PARAM_OBJECT_OF_CLASS_EX(timezone_object, date_ce_timezone, 1, 0)
2393+
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
23942394
ZEND_PARSE_PARAMETERS_END();
23952395

23962396
zend_replace_error_handling(EH_THROW, NULL, &error_handling);
@@ -2412,7 +2412,7 @@ PHP_METHOD(DateTimeImmutable, __construct)
24122412
ZEND_PARSE_PARAMETERS_START(0, 2)
24132413
Z_PARAM_OPTIONAL
24142414
Z_PARAM_STRING(time_str, time_str_len)
2415-
Z_PARAM_OBJECT_OF_CLASS_EX(timezone_object, date_ce_timezone, 1, 0)
2415+
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(timezone_object, date_ce_timezone)
24162416
ZEND_PARSE_PARAMETERS_END();
24172417

24182418
zend_replace_error_handling(EH_THROW, NULL, &error_handling);

0 commit comments

Comments
 (0)