Problem/Motivation
Per https://wiki.php.net/rfc/implicit-float-int-deprecate, as of PHP8.1, type coercion of a float-like variable to integer will result in a PHP E_DEPRECATED
and become TypeError
in PHP9.
As of 2023-05, The Drupal\Component\Datetime::createFromTimestamp
does not declare a type for its $timestamp
parameter and relies on using an is_numeric
check, however this does not prevent the float-to-int deprecation case from happening.
Steps to reproduce
This has been documented in contrib projects:
ultimate_cron
Deprecated function: Implicit conversion from float-string to int loses precision in Drupal\Component\Datetime\DateTimePlus->__call()
Drupal\Component\Datetime\DateTimePlus->__call('setTimestamp', Array) (Line: 204)
Drupal\Component\Datetime\DateTimePlus::createFromTimestamp(, Object, Array) (Line: 122)
Drupal\Core\Datetime\DateFormatter->format(, 'short') (Line: 52)
Drupal\ultimate_cron\CronJobListBuilder->buildRow(Object) (Line: 126)
Drupal\Core\Config\Entity\DraggableListBuilder->buildForm(Array, Object)
https://www.drupal.org/project/drupal/issues/3264979#comment-14531035
migrate_tools
https://www.drupal.org/project/drupal/issues/3264979#comment-14642373
Proposed resolution
Current state of MR + patches is to cast the $timestamp
variable to an integer but not change the method parameter type.
Comment #28 suggests declaring int $timestamp
and rely on typechecking.
Remaining tasks
Decide on more strict type declaration for the ::createFromTimestamp
method param.
User interface changes
API changes
TBD
Data model changes
Release notes snippet
Comment | File | Size | Author |
---|---|---|---|
#36 | Screenshot 2023-11-08 at 09.41.26.png | 54.61 KB | lathan |
#16 | 3264979-16.patch | 627 bytes | anacona16 |
#10 | interdiff-3-10.txt | 722 bytes | DantonMariano |
#10 | 3264979-10.patch | 844 bytes | DantonMariano |
#3 | reroll_diff3264979_1-3.txt | 1010 bytes | ankithashetty |
Issue fork drupal-3264979
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
jhedstromFix looks good to me, but the patch fails to apply.
Comment #3
ankithashettyFixed the patch in #1. Issue was with the file path, changed it from
a/lib/Drupal/Component/Datetime/DateTimePlus.php
toa/core/lib/Drupal/Component/Datetime/DateTimePlus.php
.Thanks!
Comment #4
daffie CreditAttribution: daffie commentedI think that it is better change the first line of the method and throw the exception when the $timestamp is not an integer instead of not numeric. We also need a test.
Comment #5
3liJust to add that I believe this issue comes from ultimate_cron module.
Created an issue for it:
#3281350: Deprecated function: Implicit conversion from float-string "<float>" to int loses precision
Though i do think that @daffie is correct this should be changed to throw and error with invalid int though I'm sure that will need more testing and possible cause issues in other places.
Comment #6
3liComment #8
steinmb CreditAttribution: steinmb as a volunteer commentedPHP 8.1 and Drupal 9.4.5
How to reproduce
Go to
/admin/structure/migrate/manage/migrate_drupal_7/migrations
Seems to be coming from `migrate_tools`.
Installed 3-part migrate_tools
Dependencies prevent me from testing migrate_tools
6.x
that have improved PHP 8.1 support. The wider question is perhaps how core should handle these type of situations?Comment #9
trickfun CreditAttribution: trickfun commentedIt works with drupal 9.5-beta.2
Thank you
Comment #10
DantonMariano CreditAttribution: DantonMariano at Zoocha commentedHi @daffie, I have changed is_numeric to is_int to verify whether the number is an integer, perhaps we could remove the typecast below as logically it would never reach that point if it were not an integer. Testing still needs work.
Comment #11
solideogloria CreditAttribution: solideogloria commentedI agree that the type cast to int can be removed.
Comment #12
smustgrave CreditAttribution: smustgrave at Mobomo commentedAppears there are errors in #10
Also was tagged for tests so moving back to NW for both.
Comment #14
anacona16 CreditAttribution: anacona16 at Agileana commentedSeems like #10 does not work for other scenarios like:
The timestamp is valid, but it's a string. So we can check if it's numeric a if it's cast the value to (int)
Comment #15
anacona16 CreditAttribution: anacona16 at Agileana commentedComment #16
anacona16 CreditAttribution: anacona16 at Agileana commentedSame as #14, fixed to work with a new Drupal installation.
Comment #17
Bhanu951 CreditAttribution: Bhanu951 as a volunteer commentedComment #19
Bhanu951 CreditAttribution: Bhanu951 as a volunteer commentedRerolled to 10.x and queued for retest.
Still needs tests.
Comment #20
smulvih2#16 works for me on 9.4.9
Comment #21
quadrexdevWe also used a patch from #10 on our project and it caused a fatal error:
InvalidArgumentException: The timestamp must be numeric. in Drupal\Component\Datetime\DateTimePlus::createFromTimestamp() (line 201 of core/lib/Drupal/Component/Datetime/DateTimePlus.php).
Applying a patch from #16 fixed this issue. Thanks, @anacona16
Comment #22
anacona16 CreditAttribution: anacona16 at Agileana commentedBased on the merge in #18 the merge passed the tests.
Comment #23
smustgrave CreditAttribution: smustgrave at Mobomo commentedStill needs tests though
Comment #26
volegerAdded test case with different datatypes of the timestamp passed to the static method.
Comment #27
smustgrave CreditAttribution: smustgrave at Mobomo commentedTest does cover the scenario.
Ran locally without the fix and got
Comment #28
alexpottGiven this is a public static method it is super tempting to add a typehint to the method and remove the is_numeric check... like
Going to ping release managers and ask for a thought. Also FWIW the calling code could cast to an integer from a float. It shouldn't be passing floats in here. Why is a float being passed in here?
Comment #29
alexpottWe could tidy up this code in migrate plus to not pass in a float.
Because PHP is not going to do the right thing... see https://3v4l.org/HDF4t
Comment #30
smustgrave CreditAttribution: smustgrave at Mobomo commentedProbably would make the code cleaner to use typehints vs (int) check.
Tests should still cover that.
Comment #32
dpiMinor formatting.
Can we improve the issue summary a little? such as with standard template
Comment #33
angrytoast CreditAttribution: angrytoast at Tableau commentedPer #32, update issue summary with default template and relevant details
Comment #34
angrytoast CreditAttribution: angrytoast at Tableau commentedI see that the newly added tests are in Functional tests
Drupal\Tests\system\Functional\Datetime\DrupalDateTimeTest
, however there are already existing unit tests inDrupal\Tests\Component\Datetime\DateTimePlusTest::testTimestamp
. This looks more appropriate to add to the unit test class as they would be better grouped and much faster?Comment #36
lathanthere are a few more references to setTimestamp that have been missed here in this patch
Comment #37
angrytoast CreditAttribution: angrytoast as a volunteer commentedRegarding comments #28-30 that suggest using type hinting, wouldn't this cause issues for code out in the wild that call the method and currently does not cast the first
$timestamp
parameter? If we go down this route, should it have a BC layer to warn and eventually enforce the parameter strict typing?IMO the current approach in https://git.drupalcode.org/project/drupal/-/merge_requests/3254 is more accommodating and would cause less issues for existing implementations.
Thoughts?
Comment #38
solideogloria CreditAttribution: solideogloria commentedWhen it's the return type, you can use the
ReturnTypeWillChange
attribute. I don't think there's something similar for parameters.Also, this seems relevant: #1158720: Improve text for parameter type hinting in function declaration