Problem/Motivation
After update Drupal code to 9.3.13 and PHP 8.1 there are DateTime warnings.
Deprecated function: DateTime::__construct(): Passing null to parameter #1 ($datetime) of type string is deprecated in Drupal\Component\Datetime\DateTimePlus->__construct() (line 309 of /var/www/docroot/core/lib/Drupal/Component/Datetime/DateTimePlus.php)
#0 /var/www/docroot/core/includes/bootstrap.inc(346): _drupal_error_handler_real(8192, 'DateTime::__con...', '/var/www/docroo...', 309)
#1 [internal function]: _drupal_error_handler(8192, 'DateTime::__con...', '/var/www/docroo...', 309)
#2 /var/www/docroot/core/lib/Drupal/Component/Datetime/DateTimePlus.php(309): DateTime->__construct(NULL, Object(DateTimeZone))
#3 /var/www/docroot/core/lib/Drupal/Core/Datetime/DrupalDateTime.php(88): Drupal\Component\Datetime\DateTimePlus->__construct(NULL, NULL, Array)
#4 /var/www/docroot/core/lib/Drupal/Core/Datetime/DateHelper.php(477): Drupal\Core\Datetime\DrupalDateTime->__construct(NULL)
#5 /var/www/docroot/modules/contrib/openy_custom/openy_repeat_entity/src/Entity/Repeat.php(230): Drupal\Core\Datetime\DateHelper::daysInYear()
#6 /var/www/docroot/core/lib/Drupal/Core/Entity/EntityFieldManager.php(228): Drupal\openy_repeat_entity\Entity\Repeat::baseFieldDefinitions(Object(Drupal\Core\Entity\ContentEntityType))
#7 /var/www/docroot/core/lib/Drupal/Core/Entity/EntityFieldManager.php(193): Drupal\Core\Entity\EntityFieldManager->buildBaseFieldDefinitions('repeat')
#8 /var/www/docroot/core/lib/Drupal/Core/Entity/EntityFieldManager.php(448): Drupal\Core\Entity\EntityFieldManager->getBaseFieldDefinitions('repeat')
#9 /var/www/docroot/modules/contrib/address/address.tokens.inc(31): Drupal\Core\Entity\EntityFieldManager->getFieldStorageDefinitions('repeat')
#10 [internal function]: address_token_info()
Steps to reproduce
Drupal Core version - 9.3.13
PHP version - 8.1
See warning messages.
| Comment | File | Size | Author |
|---|---|---|---|
| #61 | interdiff-3281557-56-61.txt | 5.68 KB | acbramley |
| #61 | 3281557-61.patch | 7.87 KB | acbramley |
Issue fork drupal-3281557
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:
- 9.5.x
changes, plain diff MR !2300
- 3281557-datetimeconstruct-passing-null
changes, plain diff MR !2299
Comments
Comment #2
rollins commentedI will provide a patch to fix this
Comment #3
rollins commentedComment #4
cilefen commentedCan you confirm this is caused by module openy_custom passing a null?
Comment #6
sardis commentedThe problem comes from using the
DateHelper::daysInYear()method without specifying date. It can be reproduced by creating a simple controller with a call to the method daysInYear.Proposed solution is to not pass
NULLvalue to the DrupalDateTime constructor within daysInYear method:Comment #10
larowlanComment #12
podarokWe are using #2 in Open Y - Drupal core 9.4.1, PHP 8.1.4 - no more overwhelming log messages in Grafana
Comment #13
sardis commented@podarok, could you please have a look at the following https://git.drupalcode.org/project/drupal/-/merge_requests/2300/diffs to see if this alleviates the log messages problem? I think it's a better solution since the problem comes from the
#5 /var/www/docroot/modules/contrib/openy_custom/openy_repeat_entity/src/Entity/Repeat.php(230): Drupal\Core\Datetime\DateHelper::daysInYear()The actual method
daysInYear()performs inaccurate construction of the DrupalDateTime object.Comment #14
froboyI've tested the patch from https://git.drupalcode.org/project/drupal/-/merge_requests/2300/diffs and it works for me on Drupal 9.3.17 with PHP 8.1. It looks like the MR needs to be rebased now that it's on 9.5 and also I see @larowlan flagged that it needs tests. I'm not super familiar with core testing but if someone points me in the right direction I should be able to try.
Comment #15
smustgrave commentedCan knock out the tests today I think. Question though should we do the same for the other functions in DateHelper that use the same code?
Comment #16
smustgrave commentedSo the PR seemed the break the ability to pass in strings to the functions and would just result in NULL being returned.
Fixed those for all 4 functions and added test cases
Comment #17
smustgrave commentedWrong patch
Comment #18
smustgrave commentedThis is the same patch as #17 but adding a tests-only patch also
Comment #20
andypostLooks good
Comment #23
catchI think this should either be !isset($date) or \is_null($date), or we should add explicit test coverage for 0, '', FALSE etc.
Comment #24
ameymudras commentedAdding a patch which handles NULL & empty condition.
Comment #25
ameymudras commentedComment #27
smustgrave commentedNot sure if #24 was tested before being uploaded but it didn't wrap things correctly so ignoring and updating #18
Comment #28
catch#27 is what I was thinking of, thanks!
Last questions here:
I don't think we should do it in this issue, but I think it's worth a follow-up to consider deprecating passing NULL (and possibly any falsy value at all).
In this issue, I think it would be good to add test coverage for
FALSE,'',0,'0'with a @todo pointing to that issue, so that we pick up on any further type changes in PHP in the future.For example adding some extra assertions just after the NULL one.
Comment #29
smustgrave commentedUpdated the tests which required adding a !empty to the DateTimeHelper also. Opened up https://www.drupal.org/project/drupal/issues/3299788 too.
Comment #31
acbramley commentedisset() && !empty()is redundant - just use the latter. Also not seeing a todo with a link?Comment #32
smustgrave commentedReason I added both is that if '' or 0 is passed the empty check will catch it.
Comment #33
smustgrave commentedComment #34
acbramley commentedThese can all just be
!emptyhttps://stackoverflow.com/a/4559976/2259943
Comment #35
ravi.shankar commentedMade changes as per comment #34.
Comment #37
ravi.shankar commentedSetting status to needs review as patch #35 passes the tests.
Comment #38
acbramley commentedAll we're missing now is the @todo asked for in #28
Comment #39
smustgrave commentedNot sure I follow what the todo should go to?
Comment #40
igorbiki commentedShouldn't NULL/nothing be a valid $date param value, and return current month number of days like stated in param docstring?
Comment #41
benjifisherI have not reviewed the code changes myself, but here is a patch based on the one in #35 that adds the @todo comment requested in #28.
It is too late for 9.4.x. I am changing the target branch to 10.1.x.
@igorbiki, the current behavior matches the documented parameter string. The suggestion is that we change both. I do not have an opinion on that, but the right place to discuss it is the follow-up issue: #3299788: Follow up to 3281557 - Consider deprecating passing null to DateTime Helper.
Comment #43
smustgrave commentedSeems all the points have been addressed.
Comment #44
larowlanLet's simplify all of these with an early return
Instead of the extra nesting
Nit: I don't think it being a Saturday, a Monday, or a leap year make a difference to the tests for the number of days in a month or year? Let's keep those comments for the tests of the day of the week name/ID, but not for the days in year/days in month tests.
Comment #45
smustgrave commentedTagging for novice as this should be easy.
Comment #46
rishabh vishwakarma commentedAddressed Point-1 from Comment #44. Point-2 could have been a little more elaborate to act upon
Comment #47
acbramley commentedChanges in #46 are not correct.
All of this logic needs to remain, but instead of wrapping the entire block in the
if (!empty....You do
if (empty($date))and return NULL inside that. Then the remaining logic can be underneath that, un-nested.Comment #48
adeshsharma commentedSimplified return of NULL.
Comment #49
smustgrave commentedWhy are we removing the comments now?
Also not the solution has this removed the functionality.
Comment #50
ipo4ka704 commentedSimplified return of NULL.
Comment #51
ipo4ka704 commentedPlease review.
Comment #52
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #53
tanuj. commentedadding a reroll for drupal 10.1.x with simplified return of NULL
Comment #54
ipo4ka704 commentedRe-create patch, with simplified return
Comment #55
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #56
acbramley commentedFixed stan failure in #54 and also added missing null return types and docs. Hiding all old patches as they're stacking up.
Comment #57
smustgrave commentedThank you @acbramley
Comment #58
larowlanComment #59
larowlanI think this is a behaviour change here.
With HEAD, passing NULL would default to 'now' per the constructor of \DrupalDateTime
e.g.
So yes, there's a deprecation, but it still defaults to today and outputs 31 (Its March when I wrote this comment).
So I think we probably need a different fix here - one that involves falling back to the current date.
Comment #60
acbramley commented#59 is right - all of the doc blocks state that passing NULL to these functions will use the current date, e.g
Comment #61
acbramley commentedSo to keep parity with the current implementation - NULL, FALSE, and an empty string all default to now. 0 and '0' return NULL.
To avoid copying the implementation of each into the unit test (because we would need to construct a DateTime object at 'now' and format it, which then means for things like daysInYear we start to just copy the whole implementation since there would need to be the leap year check as well) I've opted with just making sure those 3 values are NOT null. Then checking for nulls in the other 2, then there is an actual implementation check (i.e a date string gives the correct output).
Comment #62
smustgrave commentedChange looks good.
There may be a few duplicates of this but I couldn't find them, but feel I saw one earlier.
Comment #64
benjifisherThis is unusual: the failing test is not one of the usual FunctionalJavascript (FJS) tests:
I do not see why it would fail, and it passes when I run the test locally. Neither the user test nor the trait that does most of the work has changed in almost two years.
I am setting the status back to RTBC.
Comment #66
acbramley commentedagain...
Comment #67
larowlanRe #64 #3091478: Improve StringItem::generateSampleValue() this was the cause of the random fail in the migrate test
Comment #68
larowlanQueued a 9.5 run
Comment #69
larowlanCrediting @igorbiki who pointed out the same thing as me in #40
Comment #70
larowlanAdding credits for @adeshsharma, @TanujJain-TJ and @Rishabh Vishwakarma - whilst their patches were not part of the final solution, they were trying to move the issue forward. Thanks folks, hopefully you picked up some new learning as part of contributing to this issue 💪
Comment #73
larowlanPushed to 10.1.x and backported to 10.0.x
Waiting for a test run on 9.5.x before backporting there, so leaving at RTBC
Comment #74
larowlanComment #76
larowlanBackported to 9.5.x - thanks all
Comment #78
eugene bocharov commentedCan someone explain why we return untranslated string, though the comment says that it should be translated?
Seems it was brought by these changes.