Declare Transliterator::$id as readonly to unlock subclassing it

Closes GH-9167.
This commit is contained in:
Nicolas Grekas 2022-07-27 15:15:45 +02:00 committed by Christoph M. Becker
parent 962baf771d
commit dd9f47758e
No known key found for this signature in database
GPG key ID: D66C9593118BCCB6
5 changed files with 36 additions and 67 deletions

4
NEWS
View file

@ -23,6 +23,10 @@ PHP NEWS
. Fixed bug GH-9090 (Support assigning function pointers in FFI). (Adam
Saponara)
- Intl:
. Declared Transliterator::$id as readonly to unlock subclassing it. (Nicolas
Grekas)
- PCNTL:
. Fixed pcntl_(get|set)priority error handling for MacOS. (Juan Morales)

View file

@ -0,0 +1,26 @@
--TEST--
Subclass Transliterator
--EXTENSIONS--
intl
--FILE--
<?php
class ChildTransliterator extends Transliterator
{
public readonly string $id;
public static function new()
{
$tr = (new \ReflectionClass(ChildTransliterator::class))->newInstanceWithoutConstructor();
$tr->id = 'abc';
return $tr;
}
}
$tr = ChildTransliterator::new();
var_dump($tr->id);
?>
--EXPECT--
string(3) "abc"

View file

@ -5,7 +5,7 @@
/** @not-serializable */
class Transliterator
{
public string $id;
public readonly string $id;
final private function __construct() {}

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 8ef1f285c6138fbc58c1e4cef04d4ac09dfc3fef */
* Stub hash: 11e030b63f10d1362c41cc5c71aa0d4f014c1ffb */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Transliterator___construct, 0, 0, 0)
ZEND_END_ARG_INFO()
@ -66,7 +66,7 @@ static zend_class_entry *register_class_Transliterator(void)
zval property_id_default_value;
ZVAL_UNDEF(&property_id_default_value);
zend_string *property_id_name = zend_string_init("id", sizeof("id") - 1, 1);
zend_declare_typed_property(class_entry, property_id_name, &property_id_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING));
zend_declare_typed_property(class_entry, property_id_name, &property_id_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING));
zend_string_release(property_id_name);
return class_entry;

View file

@ -144,22 +144,11 @@ static zend_object *Transliterator_clone_obj( zend_object *object )
if( to_orig->utrans != NULL )
{
zval tempz; /* dummy zval to pass to transliterator_object_construct */
/* guaranteed to return NULL if it fails */
UTransliterator *utrans = utrans_clone( to_orig->utrans, TRANSLITERATOR_ERROR_CODE_P( to_orig ) );
if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to_orig ) ) )
goto err;
ZVAL_OBJ(&tempz, ret_val);
transliterator_object_construct( &tempz, utrans,
TRANSLITERATOR_ERROR_CODE_P( to_orig ) );
if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to_orig ) ) )
{
if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to_orig ) ) ) {
zend_string *err_msg;
err:
if( utrans != NULL )
transliterator_object_destroy( to_new );
@ -173,7 +162,8 @@ err:
err_msg = intl_error_get_message( TRANSLITERATOR_ERROR_P( to_orig ) );
zend_throw_error( NULL, "%s", ZSTR_VAL(err_msg) );
zend_string_free( err_msg ); /* if it's changed into a warning */
/* do not destroy tempz; we need to return something */
} else {
to_new->utrans = utrans;
}
}
else
@ -186,54 +176,6 @@ err:
}
/* }}} */
/* {{{ get_property_ptr_ptr handler */
static zval *Transliterator_get_property_ptr_ptr( zend_object *object, zend_string *name, int type, void **cache_slot )
{
if (zend_string_equals_literal(name, "id")) {
return NULL; /* fallback to read_property */
}
return zend_std_get_property_ptr_ptr( object, name, type, cache_slot );
}
/* }}} */
/* {{{ read_property handler */
static zval *Transliterator_read_property( zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv )
{
zval *retval;
if ((type != BP_VAR_R && type != BP_VAR_IS) && zend_string_equals_literal(name, "id")) {
zend_throw_error(NULL, "Transliterator::$id is read-only");
retval = &EG( uninitialized_zval );
} else {
retval = zend_std_read_property( object, name, type, cache_slot, rv );
}
return retval;
}
/* }}} */
/* {{{ write_property handler */
static zval *Transliterator_write_property( zend_object *object, zend_string *name, zval *value,
void **cache_slot )
{
zend_class_entry *scope;
if (EG(fake_scope)) {
scope = EG(fake_scope);
} else {
scope = zend_get_executed_scope();
}
if ((scope != Transliterator_ce_ptr) && zend_string_equals_literal(name, "id")) {
zend_throw_error(NULL, "Transliterator::$id is read-only");
} else {
value = zend_std_write_property( object, name, value, cache_slot );
}
return value;
}
/* }}} */
/* {{{ transliterator_register_Transliterator_class
* Initialize 'Transliterator' class
*/
@ -246,9 +188,6 @@ void transliterator_register_Transliterator_class( void )
Transliterator_handlers.offset = XtOffsetOf(Transliterator_object, zo);
Transliterator_handlers.free_obj = Transliterator_objects_free;
Transliterator_handlers.clone_obj = Transliterator_clone_obj;
Transliterator_handlers.get_property_ptr_ptr = Transliterator_get_property_ptr_ptr;
Transliterator_handlers.read_property = Transliterator_read_property;
Transliterator_handlers.write_property = Transliterator_write_property;
/* constants are declared in transliterator_register_constants, called from MINIT */