From 9c346ebbb7ed3080d1d6834156c79d22eebe3146 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 2 Feb 2020 21:43:42 +0000 Subject: [PATCH 1/8] Added get_debug_type as new function --- ext/standard/basic_functions.c | 1 + ext/standard/basic_functions.stub.php | 3 ++ ext/standard/basic_functions_arginfo.h | 2 ++ ext/standard/php_type.h | 1 + .../get_debug_type_basic.phpt | 34 +++++++++++++++++++ ext/standard/type.c | 25 ++++++++++++++ 6 files changed, 66 insertions(+) create mode 100644 ext/standard/tests/general_functions/get_debug_type_basic.phpt diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index f6d513f53d224..f600d0570116c 100755 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -487,6 +487,7 @@ static const zend_function_entry basic_functions[] = { /* {{{ */ PHP_FE(strval, arginfo_strval) PHP_FE(boolval, arginfo_boolval) PHP_FE(gettype, arginfo_gettype) + PHP_FE(get_debug_type, arginfo_get_debug_type) PHP_FE(settype, arginfo_settype) PHP_FE(is_null, arginfo_is_null) PHP_FE(is_resource, arginfo_is_resource) diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 2a427b8ab8444..5fbbb72c1c96f 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -1317,6 +1317,9 @@ function stream_set_timeout($socket, int $seconds, int $microseconds = 0): bool /** @param mixed $var */ function gettype($var): string {} +/** @param mixed $var */ +function get_debug_type($var): string {} + function settype(&$var, string $type): bool {} /** @param mixed $value */ diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 93e2a5bda69f5..52501252656d1 100755 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -2010,6 +2010,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gettype, 0, 1, IS_STRING, 0) ZEND_ARG_INFO(0, var) ZEND_END_ARG_INFO() +#define arginfo_get_debug_type arginfo_gettype + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_settype, 0, 2, _IS_BOOL, 0) ZEND_ARG_INFO(1, var) ZEND_ARG_TYPE_INFO(0, type, IS_STRING, 0) diff --git a/ext/standard/php_type.h b/ext/standard/php_type.h index be056201dbfb9..b0d543ed9723e 100644 --- a/ext/standard/php_type.h +++ b/ext/standard/php_type.h @@ -22,6 +22,7 @@ PHP_FUNCTION(floatval); PHP_FUNCTION(strval); PHP_FUNCTION(boolval); PHP_FUNCTION(gettype); +PHP_FUNCTION(get_debug_type); PHP_FUNCTION(settype); PHP_FUNCTION(is_null); PHP_FUNCTION(is_resource); diff --git a/ext/standard/tests/general_functions/get_debug_type_basic.phpt b/ext/standard/tests/general_functions/get_debug_type_basic.phpt new file mode 100644 index 0000000000000..e541c36f884c3 --- /dev/null +++ b/ext/standard/tests/general_functions/get_debug_type_basic.phpt @@ -0,0 +1,34 @@ +--TEST-- +Test get_debug_type() class reading +--FILE-- +ce->name); + } + + type = zend_zval_get_type(arg); + if (EXPECTED(type)) { + RETURN_INTERNED_STR(type); + } else { + RETURN_STRING("unknown type"); + } +} +/* }}} */ + + /* {{{ proto bool settype(mixed &var, string type) Set the type of the variable */ PHP_FUNCTION(settype) From 5756a6d9e165e84776fbca10cfa5fa7fa477a898 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 2 Feb 2020 22:03:50 +0000 Subject: [PATCH 2/8] Resolve type names to in-code version --- .../get_debug_type_basic.phpt | 17 +++++++--- ext/standard/type.c | 32 ++++++++++++------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/ext/standard/tests/general_functions/get_debug_type_basic.phpt b/ext/standard/tests/general_functions/get_debug_type_basic.phpt index e541c36f884c3..481463e4c659a 100644 --- a/ext/standard/tests/general_functions/get_debug_type_basic.phpt +++ b/ext/standard/tests/general_functions/get_debug_type_basic.phpt @@ -19,16 +19,23 @@ namespace { echo get_debug_type(new Demo\ClassInNamespace()) . "\n"; /* scalars */ + echo get_debug_type("foo") . "\n"; + echo get_debug_type(false) . "\n"; + echo get_debug_type(true) . "\n"; echo get_debug_type(1) . "\n"; echo get_debug_type(1.1) . "\n"; - echo get_debug_type("foo") . "\n"; - echo get_debug_type(Test::class) . "\n"; + echo get_debug_type([]) . "\n"; + echo get_debug_type(null) . "\n"; + } --EXPECT-- ClassInGlobal Demo\ClassInNamespace -integer -double -string string +bool +bool +int +float +array +null diff --git a/ext/standard/type.c b/ext/standard/type.c index 23fc8e277712d..3aef0787f5f7e 100644 --- a/ext/standard/type.c +++ b/ext/standard/type.c @@ -42,22 +42,32 @@ PHP_FUNCTION(gettype) PHP_FUNCTION(get_debug_type) { zval *arg; - zend_string *type; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ZVAL(arg) ZEND_PARSE_PARAMETERS_END(); - if (Z_TYPE_P(arg) == IS_OBJECT) { - RETURN_STR_COPY(Z_OBJ_P(arg)->ce->name); - } - - type = zend_zval_get_type(arg); - if (EXPECTED(type)) { - RETURN_INTERNED_STR(type); - } else { - RETURN_STRING("unknown type"); - } + switch (Z_TYPE_P(arg)) { + case IS_NULL: + RETURN_STRING("null"); + case IS_FALSE: + case IS_TRUE: + RETURN_STRING("bool"); + case IS_LONG: + RETURN_STRING("int"); + case IS_DOUBLE: + RETURN_STRING("float"); + case IS_STRING: + RETURN_STRING("string"); + case IS_ARRAY: + RETURN_STRING("array"); + case IS_OBJECT: + RETURN_STR_COPY(Z_OBJ_P(arg)->ce->name); + case IS_RESOURCE: + RETURN_STRING("resource"); + default: + RETURN_STRING("unknown"); + } } /* }}} */ From bd32f07eaf3fa2a297caec1962f79c94ef76b3ef Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 2 Feb 2020 22:06:57 +0000 Subject: [PATCH 3/8] Team tabs supremacy --- ext/standard/type.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/ext/standard/type.c b/ext/standard/type.c index 3aef0787f5f7e..1b4ab65a71a04 100644 --- a/ext/standard/type.c +++ b/ext/standard/type.c @@ -47,27 +47,27 @@ PHP_FUNCTION(get_debug_type) Z_PARAM_ZVAL(arg) ZEND_PARSE_PARAMETERS_END(); - switch (Z_TYPE_P(arg)) { - case IS_NULL: - RETURN_STRING("null"); - case IS_FALSE: - case IS_TRUE: - RETURN_STRING("bool"); - case IS_LONG: - RETURN_STRING("int"); - case IS_DOUBLE: - RETURN_STRING("float"); - case IS_STRING: - RETURN_STRING("string"); - case IS_ARRAY: - RETURN_STRING("array"); - case IS_OBJECT: - RETURN_STR_COPY(Z_OBJ_P(arg)->ce->name); - case IS_RESOURCE: - RETURN_STRING("resource"); - default: - RETURN_STRING("unknown"); - } + switch (Z_TYPE_P(arg)) { + case IS_NULL: + RETURN_STRING("null"); + case IS_FALSE: + case IS_TRUE: + RETURN_STRING("bool"); + case IS_LONG: + RETURN_STRING("int"); + case IS_DOUBLE: + RETURN_STRING("float"); + case IS_STRING: + RETURN_STRING("string"); + case IS_ARRAY: + RETURN_STRING("array"); + case IS_OBJECT: + RETURN_STR_COPY(Z_OBJ_P(arg)->ce->name); + case IS_RESOURCE: + RETURN_STRING("resource"); + default: + RETURN_STRING("unknown"); + } } /* }}} */ From 9d5d333dc30103ee67ff01b2902dc891f81a9797 Mon Sep 17 00:00:00 2001 From: Mark Randall Date: Mon, 3 Feb 2020 21:49:24 +0000 Subject: [PATCH 4/8] Return known interned strings --- .../general_functions/get_debug_type_basic.phpt | 2 ++ ext/standard/type.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ext/standard/tests/general_functions/get_debug_type_basic.phpt b/ext/standard/tests/general_functions/get_debug_type_basic.phpt index 481463e4c659a..3061c4f7f1216 100644 --- a/ext/standard/tests/general_functions/get_debug_type_basic.phpt +++ b/ext/standard/tests/general_functions/get_debug_type_basic.phpt @@ -26,6 +26,7 @@ namespace { echo get_debug_type(1.1) . "\n"; echo get_debug_type([]) . "\n"; echo get_debug_type(null) . "\n"; + echo get_debug_type(fopen(__FILE__, 'r')) . "\n"; } @@ -39,3 +40,4 @@ int float array null +resource diff --git a/ext/standard/type.c b/ext/standard/type.c index 1b4ab65a71a04..aecaa5181e552 100644 --- a/ext/standard/type.c +++ b/ext/standard/type.c @@ -49,24 +49,24 @@ PHP_FUNCTION(get_debug_type) switch (Z_TYPE_P(arg)) { case IS_NULL: - RETURN_STRING("null"); + RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_NULL_LOWERCASE)); case IS_FALSE: case IS_TRUE: - RETURN_STRING("bool"); + RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_BOOL)); case IS_LONG: - RETURN_STRING("int"); + RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_INT)); case IS_DOUBLE: - RETURN_STRING("float"); + RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_FLOAT)); case IS_STRING: - RETURN_STRING("string"); + RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_STRING)); case IS_ARRAY: - RETURN_STRING("array"); + RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_ARRAY)); case IS_OBJECT: RETURN_STR_COPY(Z_OBJ_P(arg)->ce->name); case IS_RESOURCE: - RETURN_STRING("resource"); + RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_RESOURCE)); default: - RETURN_STRING("unknown"); + RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_UNKNOWN)); } } /* }}} */ From b2d43dd183955f6d3706c8e961f2e1263bfb2cdf Mon Sep 17 00:00:00 2001 From: Mark Randall Date: Sat, 15 Feb 2020 16:48:28 +0000 Subject: [PATCH 5/8] Cutting off anonymous class names, resolving resource names --- .../get_debug_type_basic.phpt | 13 ++++++++++++- ext/standard/type.c | 18 ++++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/ext/standard/tests/general_functions/get_debug_type_basic.phpt b/ext/standard/tests/general_functions/get_debug_type_basic.phpt index 3061c4f7f1216..25895f6eed0f2 100644 --- a/ext/standard/tests/general_functions/get_debug_type_basic.phpt +++ b/ext/standard/tests/general_functions/get_debug_type_basic.phpt @@ -14,9 +14,19 @@ namespace { } + $anon = new class { + + }; + + $fp = fopen(__FILE__, 'r'); + + $fp_closed = fopen(__FILE__, 'r'); + fclose($fp_closed); + /* tests against an object type */ echo get_debug_type(new ClassInGlobal()) . "\n"; echo get_debug_type(new Demo\ClassInNamespace()) . "\n"; + echo get_debug_type($anon) . "\n"; /* scalars */ echo get_debug_type("foo") . "\n"; @@ -26,7 +36,8 @@ namespace { echo get_debug_type(1.1) . "\n"; echo get_debug_type([]) . "\n"; echo get_debug_type(null) . "\n"; - echo get_debug_type(fopen(__FILE__, 'r')) . "\n"; + echo get_debug_type($fp) . "\n"; + echo get_debug_type($fp_closed) . "\n"; } diff --git a/ext/standard/type.c b/ext/standard/type.c index aecaa5181e552..788731004b249 100644 --- a/ext/standard/type.c +++ b/ext/standard/type.c @@ -42,6 +42,8 @@ PHP_FUNCTION(gettype) PHP_FUNCTION(get_debug_type) { zval *arg; + zend_string *name; + const char* res_name; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ZVAL(arg) @@ -62,12 +64,24 @@ PHP_FUNCTION(get_debug_type) case IS_ARRAY: RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_ARRAY)); case IS_OBJECT: - RETURN_STR_COPY(Z_OBJ_P(arg)->ce->name); + goto resolve_class; case IS_RESOURCE: - RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_RESOURCE)); + goto resolve_resource; default: RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_UNKNOWN)); } + +resolve_class: + name = Z_OBJ_P(arg)->ce->name; + RETURN_NEW_STR(zend_string_init(ZSTR_VAL(name), strlen(ZSTR_VAL(name)), 0)); + +resolve_resource: + res_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg)); + if (res_name) { + RETURN_NEW_STR(zend_strpprintf(0, "resource (%s)", res_name)); + } else { + RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE)); + } } /* }}} */ From ee672b1e8ff9bb7f586b2adbba1c342b3fa8e784 Mon Sep 17 00:00:00 2001 From: Mark Randall Date: Sat, 15 Feb 2020 16:55:17 +0000 Subject: [PATCH 6/8] Blessed tests --- .../tests/general_functions/get_debug_type_basic.phpt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/standard/tests/general_functions/get_debug_type_basic.phpt b/ext/standard/tests/general_functions/get_debug_type_basic.phpt index 25895f6eed0f2..2c4f6a48cc78c 100644 --- a/ext/standard/tests/general_functions/get_debug_type_basic.phpt +++ b/ext/standard/tests/general_functions/get_debug_type_basic.phpt @@ -44,6 +44,7 @@ namespace { --EXPECT-- ClassInGlobal Demo\ClassInNamespace +class@anonymous string bool bool @@ -51,4 +52,5 @@ int float array null -resource +resource (stream) +resource (closed) From d05ac577920e3e1950ca5774537129be40d05beb Mon Sep 17 00:00:00 2001 From: Mark Randall Date: Sat, 15 Feb 2020 17:09:22 +0000 Subject: [PATCH 7/8] Inlined logic, return existing string if not anon class --- ext/standard/type.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/ext/standard/type.c b/ext/standard/type.c index 788731004b249..78589a549b093 100644 --- a/ext/standard/type.c +++ b/ext/standard/type.c @@ -42,8 +42,7 @@ PHP_FUNCTION(gettype) PHP_FUNCTION(get_debug_type) { zval *arg; - zend_string *name; - const char* res_name; + const char *name; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ZVAL(arg) @@ -64,24 +63,22 @@ PHP_FUNCTION(get_debug_type) case IS_ARRAY: RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_ARRAY)); case IS_OBJECT: - goto resolve_class; + if (Z_OBJ_P(arg)->ce->ce_flags & ZEND_ACC_ANON_CLASS) { + name = ZSTR_VAL(Z_OBJ_P(arg)->ce->name); + RETURN_NEW_STR(zend_string_init(name, strlen(name), 0)); + } else { + RETURN_STR_COPY(Z_OBJ_P(arg)->ce->name); + } case IS_RESOURCE: - goto resolve_resource; + name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg)); + if (name) { + RETURN_NEW_STR(zend_strpprintf(0, "resource (%s)", name)); + } else { + RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE)); + } default: RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_UNKNOWN)); } - -resolve_class: - name = Z_OBJ_P(arg)->ce->name; - RETURN_NEW_STR(zend_string_init(ZSTR_VAL(name), strlen(ZSTR_VAL(name)), 0)); - -resolve_resource: - res_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg)); - if (res_name) { - RETURN_NEW_STR(zend_strpprintf(0, "resource (%s)", res_name)); - } else { - RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE)); - } } /* }}} */ From 0fe134428433e947b4917fb5297788e0ae1df06d Mon Sep 17 00:00:00 2001 From: Mark Randall Date: Sun, 22 Mar 2020 13:04:16 +0000 Subject: [PATCH 8/8] Added tests for extending and implementing --- .../general_functions/get_debug_type_basic.phpt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ext/standard/tests/general_functions/get_debug_type_basic.phpt b/ext/standard/tests/general_functions/get_debug_type_basic.phpt index 2c4f6a48cc78c..35fc8085175c8 100644 --- a/ext/standard/tests/general_functions/get_debug_type_basic.phpt +++ b/ext/standard/tests/general_functions/get_debug_type_basic.phpt @@ -10,13 +10,10 @@ namespace Demo { } namespace { - class ClassInGlobal { + class ClassInGlobal { } - } - - $anon = new class { - - }; + class ToBeExtended { } + interface ToBeImplemented { } $fp = fopen(__FILE__, 'r'); @@ -26,7 +23,9 @@ namespace { /* tests against an object type */ echo get_debug_type(new ClassInGlobal()) . "\n"; echo get_debug_type(new Demo\ClassInNamespace()) . "\n"; - echo get_debug_type($anon) . "\n"; + echo get_debug_type(new class {}) . "\n"; + echo get_debug_type(new class extends ToBeExtended {}) . "\n"; + echo get_debug_type(new class implements ToBeImplemented {}) . "\n"; /* scalars */ echo get_debug_type("foo") . "\n"; @@ -45,6 +44,8 @@ namespace { ClassInGlobal Demo\ClassInNamespace class@anonymous +ToBeExtended@anonymous +ToBeImplemented@anonymous string bool bool