Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ PHP NEWS
. Fixed bug GH-22257 (type confusion in Exception::getTraceAsString()).
(David Carlier)
. TSRM: make CG, EG, SCNG and AG compile-time offsets. (henderkes)
. Deprecate returning values from __construct() and __destruct(). (timwolla)

- BCMath:
. Added NUL-byte validation to BCMath functions. (jorgsowa)
Expand Down Expand Up @@ -88,6 +89,9 @@ PHP NEWS
- Intl:
. Fixed malformed ResourceBundle::get() error message when fallback is
disabled. (Weilin Du)
. Added Locale::getDisplayKeyword() and Locale::getDisplayKeywordValue(),
with the alias of locale_get_display_keyword() and
locale_get_display_keyword_value() respectively. (Weilin Du)
. Fix incorrect argument positions for invalid start/end arguments in
transliterator_transliterate(). (Weilin Du)
. Fixed IntlTimeZone::getDisplayName() to synchronize object error state
Expand Down
8 changes: 8 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ PHP 8.6 UPGRADE NOTES
. finfo_file() now works with remote streams.

- Intl:
. Added Locale::getDisplayKeyword() and Locale::getDisplayKeywordValue(),
with the alias of locale_get_display_keyword() and
locale_get_display_keyword_value() respectively.
RFC: https://wiki.php.net/rfc/getdisplaykeyword_and_getdisplaykeywordvalue
. Added IntlNumberRangeFormatter class to format an interval of two numbers
with a given skeleton, locale, IntlNumberRangeFormatter::COLLAPSE_AUTO,
IntlNumberRangeFormatter::COLLAPSE_NONE,
Expand Down Expand Up @@ -279,6 +283,10 @@ PHP 8.6 UPGRADE NOTES
- Core:
. Specifying a return type of array|null / ?array for __debugInfo() is now
deprecated. Specify array instead.
. Returning values from __construct() and __destruct() is now deprecated.
RFC: https://wiki.php.net/rfc/deprecate-return-value-from-construct
. Making __construct() and __destruct() a Generator is now deprecated.
RFC: https://wiki.php.net/rfc/deprecate-return-value-from-construct

- GMP
. The shift (<<, >>) and exponentiation (**) operators on GMP objects now
Expand Down
35 changes: 35 additions & 0 deletions Zend/tests/magic_methods/constructor_destructor_return.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--TEST--
Returning values from constructors and destructors is deprecated
--FILE--
<?php

class A {
public function __construct() { return ''; }
public function __destruct() { return ''; }
}

class B {
public function __construct() { return $this->voidMethod(); }
public function __destruct() { return $this->voidMethod(); }

public function voidMethod(): void { }
}

class Gen {
public function __construct() { yield ''; }
public function __destruct() { yield ''; }
}

?>
--EXPECTF--
Deprecated: Returning a value from a constructor is deprecated in %s on line %d

Deprecated: Returning a value from a destructor is deprecated in %s on line %d

Deprecated: Returning a value from a constructor is deprecated in %s on line %d

Deprecated: Returning a value from a destructor is deprecated in %s on line %d

Deprecated: Making a constructor a Generator is deprecated in %s on line %d

Deprecated: Making a destructor a Generator is deprecated in %s on line %d
1 change: 1 addition & 0 deletions Zend/tests/prop_const_expr/non_enums_catchable.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const A_prop = (new A)->{new Printer ? 'printer' : null};

?>
--EXPECTF--
Deprecated: Returning a value from a constructor is deprecated in %s on line %d
Printer

Fatal error: Uncaught Error: Fetching properties on non-enums in constant expressions is not allowed in %s:%d
Expand Down
4 changes: 4 additions & 0 deletions Zend/tests/traits/bug60536_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,9 @@ $a->__construct();
echo "DONE";
?>
--EXPECTF--
Deprecated: Returning a value from a constructor is deprecated in %s on line %d

Deprecated: Returning a value from a constructor is deprecated in %s on line %d

Warning: Undefined property: Z::$x in %s on line %d
DONE
30 changes: 24 additions & 6 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,12 @@ ZEND_API bool zend_is_compiling(void) /* {{{ */
}
/* }}} */

static bool zend_is_constructor(const zend_string *name) /* {{{ */
{
return zend_string_equals_literal_ci(name, ZEND_CONSTRUCTOR_FUNC_NAME);
}
/* }}} */

static zend_always_inline uint32_t get_temporary_variable(void) /* {{{ */
{
return (uint32_t)CG(active_op_array)->T++;
Expand Down Expand Up @@ -5549,12 +5555,6 @@ static void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type
}
/* }}} */

static bool zend_is_constructor(const zend_string *name) /* {{{ */
{
return zend_string_equals_literal_ci(name, ZEND_CONSTRUCTOR_FUNC_NAME);
}
/* }}} */

static bool is_func_accessible(const zend_function *fbc)
{
if ((fbc->common.fn_flags & ZEND_ACC_PUBLIC) || fbc->common.scope == CG(active_class_entry)) {
Expand Down Expand Up @@ -5993,6 +5993,16 @@ static void zend_compile_return(const zend_ast *ast) /* {{{ */
zend_compile_expr(&expr_node, expr_ast);
}

if (expr_ast) {
if (CG(active_class_entry) != NULL) {
if (zend_is_constructor(CG(active_op_array)->function_name)) {
zend_error(E_DEPRECATED, "Returning a value from a constructor is deprecated");
} else if (zend_string_equals_literal_ci(CG(active_op_array)->function_name, ZEND_DESTRUCTOR_FUNC_NAME)) {
zend_error(E_DEPRECATED, "Returning a value from a destructor is deprecated");
}
}
}

if ((CG(active_op_array)->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)
&& (expr_node.op_type == IS_CV || (by_ref && expr_node.op_type == IS_VAR))
&& zend_has_finally()) {
Expand Down Expand Up @@ -8843,6 +8853,14 @@ static zend_op_array *zend_compile_func_decl_ex(
zend_compile_params(params_ast, return_type_ast,
is_method && zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_LCNAME) ? IS_STRING : 0);
if (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) {
if (CG(active_class_entry) != NULL) {
if (zend_is_constructor(CG(active_op_array)->function_name)) {
zend_error(E_DEPRECATED, "Making a constructor a Generator is deprecated");
} else if (zend_string_equals_literal_ci(CG(active_op_array)->function_name, ZEND_DESTRUCTOR_FUNC_NAME)) {
zend_error(E_DEPRECATED, "Making a destructor a Generator is deprecated");
}
}

zend_mark_function_as_generator();
zend_emit_op(NULL, ZEND_GENERATOR_CREATE, NULL, NULL);
}
Expand Down
10 changes: 10 additions & 0 deletions ext/intl/locale/locale.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@ public static function getDisplayLanguage(string $locale, ?string $displayLocale
*/
public static function getDisplayVariant(string $locale, ?string $displayLocale = null): string|false {}

/**
* @alias locale_get_display_keyword
*/
public static function getDisplayKeyword(string $keyword, ?string $displayLocale = null): string|false {}

/**
* @alias locale_get_display_keyword_value
*/
public static function getDisplayKeywordValue(string $locale, string $keyword, ?string $displayLocale = null): string|false {}

/**
* @tentative-return-type
* @alias locale_compose
Expand Down
17 changes: 16 additions & 1 deletion ext/intl/locale/locale_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

117 changes: 117 additions & 0 deletions ext/intl/locale/locale_methods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ ZEND_EXTERN_MODULE_GLOBALS( intl )
#define EXTLANG_PREFIX "a"
#define PRIVATE_PREFIX "x"
#define DISP_NAME "name"
#define DISP_KEYWORD "keyword"
#define DISP_KEYWORD_VALUE "keyword_value"

#define MAX_NO_VARIANT 15
#define MAX_NO_EXTLANG 3
Expand Down Expand Up @@ -671,6 +673,107 @@ static void get_icu_disp_value_src_php( const char* tag_name, INTERNAL_FUNCTION_
}
/* }}} */

/* {{{
* common code shared by display keyword functions to get the value from ICU
}}} */
static void get_icu_disp_keyword_value_src_php(const char* tag_name, INTERNAL_FUNCTION_PARAMETERS)
{
char* loc_name = NULL;
size_t loc_name_len = 0;
char* keyword_name = NULL;
size_t keyword_name_len = 0;
char* disp_loc_name = NULL;
size_t disp_loc_name_len = 0;
int free_loc_name = 0;

UChar* disp_name = NULL;
int32_t disp_name_len = 0;
int32_t buflen = 512;
UErrorCode status = U_ZERO_ERROR;

zend_string* u8str;
char* msg = NULL;

intl_error_reset( NULL );

if (strcmp(tag_name, DISP_KEYWORD) == 0) {
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_PATH(keyword_name, keyword_name_len)
Z_PARAM_OPTIONAL
Z_PARAM_PATH_OR_NULL(disp_loc_name, disp_loc_name_len)
ZEND_PARSE_PARAMETERS_END();
} else {
ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_PATH(loc_name, loc_name_len)
Z_PARAM_PATH(keyword_name, keyword_name_len)
Z_PARAM_OPTIONAL
Z_PARAM_PATH_OR_NULL(disp_loc_name, disp_loc_name_len)
ZEND_PARSE_PARAMETERS_END();

if (loc_name_len > ULOC_FULLNAME_CAPACITY) {
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "name too long");
RETURN_FALSE;
}

if (loc_name_len == 0) {
loc_name = (char *)intl_locale_get_default();
}
}

if (!disp_loc_name) {
disp_loc_name = estrdup(intl_locale_get_default());
free_loc_name = 1;
}

do {
disp_name = reinterpret_cast<UChar *>(erealloc(disp_name, buflen * sizeof(UChar)));
disp_name_len = buflen;

if (strcmp(tag_name, DISP_KEYWORD) == 0) {
buflen = uloc_getDisplayKeyword(keyword_name, disp_loc_name, disp_name, disp_name_len, &status);
} else {
buflen = uloc_getDisplayKeywordValue(loc_name, keyword_name, disp_loc_name, disp_name, disp_name_len, &status);
}

/* U_STRING_NOT_TERMINATED_WARNING is admissible here; don't look for it */
if (U_FAILURE(status)) {
if (status == U_BUFFER_OVERFLOW_ERROR) {
status = U_ZERO_ERROR;
continue;
}

spprintf(&msg, 0, "unable to get locale %s", tag_name);
intl_error_set( NULL, status, msg);
efree(msg);
if (disp_name) {
efree(disp_name);
}
if (free_loc_name) {
efree((void *)disp_loc_name);
disp_loc_name = NULL;
}
RETURN_FALSE;
}
} while (buflen > disp_name_len);

if (free_loc_name) {
efree((void *)disp_loc_name);
disp_loc_name = NULL;
}

u8str = intl_convert_utf16_to_utf8(disp_name, buflen, &status);
efree(disp_name);
if (!u8str) {
spprintf(&msg, 0, "error converting display name for %s to UTF-8", tag_name);
intl_error_set( NULL, status, msg);
efree(msg);
RETURN_FALSE;
}

RETVAL_NEW_STR(u8str);
}
/* }}} */

/* {{{ gets the name for the $locale in $in_locale or default_locale */
U_CFUNC PHP_FUNCTION(locale_get_display_name)
{
Expand Down Expand Up @@ -711,6 +814,20 @@ U_CFUNC PHP_FUNCTION(locale_get_display_variant)
{
get_icu_disp_value_src_php( LOC_VARIANT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
}
/* }}} */

/* {{{ gets the keyword display label in $in_locale or default_locale */
U_CFUNC PHP_FUNCTION(locale_get_display_keyword)
{
get_icu_disp_keyword_value_src_php(DISP_KEYWORD, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */

/* {{{ gets the keyword value display label in $in_locale or default_locale */
U_CFUNC PHP_FUNCTION(locale_get_display_keyword_value)
{
get_icu_disp_keyword_value_src_php(DISP_KEYWORD_VALUE, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */

/* {{{ return an associative array containing keyword-value
Expand Down
4 changes: 4 additions & 0 deletions ext/intl/php_intl.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,10 @@ function locale_get_display_language(string $locale, ?string $displayLocale = nu

function locale_get_display_variant(string $locale, ?string $displayLocale = null): string|false {}

function locale_get_display_keyword(string $keyword, ?string $displayLocale = null): string|false {}

function locale_get_display_keyword_value(string $locale, string $keyword, ?string $displayLocale = null): string|false {}

function locale_compose(array $subtags): string|false {}

function locale_parse(string $locale): ?array {}
Expand Down
Loading