Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

nicolas-grekas
Copy link
Contributor

@nicolas-grekas nicolas-grekas commented Jul 27, 2022

Before PHP 8.2 it was possible to create a child translator with a custom $id by using unserialize():

unserialize(sprintf('O:%d:"%s":1:{s:2:"id";s:%d:"%s";}', \strlen(self::class), self::class, \strlen($id), $id))

But since #7945, this doesn't work anymore, causing a BC break with no alternative.

Yet, there is a way to make this work in 8.2, which is to remove the custom code that makes $id read-only and replacing it with a native readonly declaration.

So here we are, see test case also.

@nicolas-grekas nicolas-grekas force-pushed the transliterator-readonly branch 2 times, most recently from 9f1e051 to c5a8c69 Compare July 27, 2022 13:28
Copy link
Member

@cmb69 cmb69 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transliterator should better have been final, but that ship has sailed, so this looks like a good idea to mitigate the BC break.

@kocsismate, thoughts?

@nicolas-grekas nicolas-grekas force-pushed the transliterator-readonly branch from c5a8c69 to 9796b2a Compare July 27, 2022 14:00
@nicolas-grekas
Copy link
Contributor Author

nicolas-grekas commented Jul 27, 2022

@cmb69 thanks for the review. Could you please help me on the failure?
make test TESTS=ext/intl/tests/transliterator_clone.phpt fails with Cannot modify readonly property Transliterator::$id.
I guess that's because Transliterator_clone_obj calls zend_objects_clone_members( &to_new->zo, &to_orig->zo ); but I'm not sure how the code should be instead...

@cmb69
Copy link
Member

cmb69 commented Jul 27, 2022

The problem:

zend_objects_clone_members( &to_new->zo, &to_orig->zo );
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 ) );

In the first line the properties are cloned (so id === "hex-any"), and in the last line the object is constructed, so that the id is set again. It would be sufficient to remove the zend_objects_clone_members() call, but since Transliterator supports dynamic properties 😢, we cannot for BC reasons.

I guess we can do something like:

 ext/intl/transliterator/transliterator_class.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/ext/intl/transliterator/transliterator_class.c b/ext/intl/transliterator/transliterator_class.c
index 2dbc940f37..3610b03d84 100644
--- a/ext/intl/transliterator/transliterator_class.c
+++ b/ext/intl/transliterator/transliterator_class.c
@@ -152,9 +152,7 @@ static zend_object *Transliterator_clone_obj( zend_object *object )
 		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 ) );
+		to_new->utrans = utrans;
 
 		if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to_orig ) ) )
 		{

(and do some cleanup regarding the error handling)

@nicolas-grekas nicolas-grekas force-pushed the transliterator-readonly branch from 9796b2a to 74e84af Compare July 27, 2022 17:29
@nicolas-grekas
Copy link
Contributor Author

nicolas-grekas commented Jul 27, 2022

+ to_new->utrans = utrans;

That worked thanks! (and that makes sense)

(and do some cleanup regarding the error handling)

not sure what you mean here :)

@nicolas-grekas nicolas-grekas force-pushed the transliterator-readonly branch from 74e84af to e520fb7 Compare July 27, 2022 17:33
@nicolas-grekas nicolas-grekas force-pushed the transliterator-readonly branch from e520fb7 to dcf0aed Compare July 27, 2022 21:31
@codecov-commenter
Copy link

Codecov Report

Merging #9167 (520bb2e) into master (520bb2e) will not change coverage.
The diff coverage is n/a.

❗ Current head 520bb2e differs from pull request most recent head dcf0aed. Consider uploading reports for the commit dcf0aed to get more accurate results

@@           Coverage Diff           @@
##           master    #9167   +/-   ##
=======================================
  Coverage   67.12%   67.12%           
=======================================
  Files         841      841           
  Lines      311272   311272           
=======================================
  Hits       208936   208936           
  Misses     102336   102336           

📣 Codecov can now indicate which changes are the most critical in Pull Requests. Learn more

nicolas-grekas added a commit to symfony/symfony that referenced this pull request Jul 28, 2022
This PR was merged into the 6.2 branch.

Discussion
----------

[Intl] Fix EmojiTransliterator on PHP 8.2

| Q             | A
| ------------- | ---
| Branch?       | 6.2
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | -
| License       | MIT
| Doc PR        | -

Requires php/php-src#9167

Commits
-------

c1df6da [Intl] Fix EmojiTransliterator on PHP 8.2
Copy link
Member

@cmb69 cmb69 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks right now. Thank you!

I'm leaving this open for a while, so that others can review.

Copy link
Member

@Girgias Girgias left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@nicolas-grekas nicolas-grekas force-pushed the transliterator-readonly branch from dcf0aed to ab64c94 Compare July 28, 2022 14:17
@nicolas-grekas nicolas-grekas force-pushed the transliterator-readonly branch from ab64c94 to b871bef Compare July 28, 2022 14:36
@cmb69 cmb69 closed this in dd9f477 Aug 1, 2022
@nicolas-grekas nicolas-grekas deleted the transliterator-readonly branch August 1, 2022 08:49
nicolas-grekas added a commit to symfony/symfony that referenced this pull request Aug 2, 2022
This PR was merged into the 6.2 branch.

Discussion
----------

[Intl] Remove unused code in tests

| Q             | A
| ------------- | ---
| Branch?       | 6.2
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Tickets       | -
| License       | MIT
| Doc PR        | -

Added in #47083 but not needed anymore since php/php-src#9167

Commits
-------

ca143fc [Intl] Remove dead code in tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants