Problem/Motivation
Follow-up to #2454439: [META] Support PHP 7
The \Drupal\Component\Datetime\DateTimePlus
class currently extends \DateTime
. But as of PHP 5.5 there is a new method on the DateTime object with the same name as a previously existing method in the DateTimePlus class (createFromFormat()).
DateTimePlus::createFromFormat()
was not intended to override this DateTime
method. With the different class definitions, this will currently make tests fail and break date-related functionality in PHP7.
Proposed resolution
Wrap DateTime class instead of extending it.
Remaining tasks
Review patch.
User interface changes
N/A
API changes
N/A
Comment | File | Size | Author |
---|---|---|---|
#56 | interdiff.txt | 829 bytes | stefan.r |
#56 | 2457405-datetimeplus-56.patch | 6.77 KB | stefan.r |
#54 | interdiff.txt | 928 bytes | stefan.r |
#54 | 2457405-datetimeplus-54.patch | 6.62 KB | stefan.r |
#50 | interdiff.txt | 511 bytes | stefan.r |
Comments
Comment #1
josephdpurcell CreditAttribution: josephdpurcell commentedAdded task instructions.
Comment #2
andypostThis method is from http://php.net/manual/en/datetimeimmutable.createfromformat.php that we need for php 5.5 as well
Comment #3
andypostAnyway we need to extend DataTime http://php.net/manual/en/datetime.createfromformat.php
EDIT The issue added this is #1844956: Optimize date formatting performance
So maybe better to rename the method because
$timezone
should beDateTimeZone
typeComment #4
andypostLet's see if we still need the settings to pass, otoh we can loose ability to pass language
Comment #8
stefan.r CreditAttribution: stefan.r commentedWould we have to conditionally define this method based on PHP version as per this?
Comment #9
stefan.r CreditAttribution: stefan.r commentedI think over in the issue linked in #8 they are suggesting we do this... Though maybe we can push to have that commit reverted from PHP7 so we don't have to resort to patches like this? :)
Comment #10
BerdirI don't think that makes sense, then we'd provide a different API depending on the version. We can't do that.
It's not just the type hint, $timezone is a string in our implementation.
I see two options:
a) Rename the method. We didn't design it as an override, it might work differently than the parent.
b) Keep it, adjust the type hints and arguments, and check what the parent is doing exactly in 5.5, so that it is consistent to the native behavior, if possible.
Either way, we need to change the API.
Comment #11
BerdirWhich makes this a release blocker, so changing to critical.
Comment #12
stefan.r CreditAttribution: stefan.r commented@Berdir yes more work would be needed than just that patch, I wasn't suggesting a different API for both versions! I asked about this because not having the type hint will give a strict warning on PHP7, and having it will give a strict warning on PHP5.5 (see the red tests in #4 and http://3v4l.org/DCOJB).
In any case, renaming the method seems like the better solution. Moreso as this was not intended to be an override, @andypost already suggested simply renaming in #3 as well.
Comment #13
stefan.r CreditAttribution: stefan.r commentedComment #14
dawehnerShould we maybe encode the difference to createFromFormat in its name? What about choosing createFromFormatWithSettings ?
Comment #15
stefan.r CreditAttribution: stefan.r commentedComment #16
stefan.r CreditAttribution: stefan.r commentedComment #17
dawehnerTo be clear, I was just trying to make a suggestion, do you like it?
Comment #18
stefan.r CreditAttribution: stefan.r commentedYes, essentially it just calls DateTime::createFromFormat() using a settings array so I do think that's a clearer title :)
Comment #19
dawehnerAs the lower part of the patch shows, we have test coverage for that method, ... so I think this is RTBC.
Maybe someone will come, who disagrees with the name, but well, this solution is pragmatic.
Comment #20
alexpotti think we shouldn't we extending the class here - it makes us very vulnerable to changes in PHP's DateTime object. We should wrap it instead and provide a __call(). That way we can do this change with no API change.
Comment #21
BerdirNot sure how much refactoring we should be doing here, but lets see if we can find a way that makes sense.
@xjm: This is critical because this is otherwise giving strict warnings everywhere, and changing this somehow is needed to get rid of it. See #2454439-15: [META] Support PHP 7
Comment #22
stefan.r CreditAttribution: stefan.r commentedComment #23
stefan.r CreditAttribution: stefan.r commentedComment #25
dawehnerI think you should store the wrapper object, otherwise it doesn't inheri the time / timezone
Comment #26
stefan.r CreditAttribution: stefan.r commentedComment #28
stefan.r CreditAttribution: stefan.r commentedComment #30
stefan.r CreditAttribution: stefan.r commentedComment #32
stefan.r CreditAttribution: stefan.r commentedComment #34
stefan.r CreditAttribution: stefan.r commentedComment #35
stefan.r CreditAttribution: stefan.r commentedUpdated issue summary now that tests are green
Comment #36
stefan.r CreditAttribution: stefan.r commentedComment #37
alexpottMissing typehint
This needs to check if a dateTimeObject is set
I don't understand this change. I think this shows we need to implement a DateTimePlus::__construct that populates the dateTimeObject property.
Comment #38
stefan.r CreditAttribution: stefan.r commented@alexpott I don't understand your suggestion in #3, can you explain further? What do you mean by "populating", isn't $this->dateTimeObject already being set and populated with the time and the timezone in the constructor in the current patch? I.e. now that we do this:
As to the change in #3, I'm probably explaining the obvious and missing the point, but: the problem there is that
DateTimePlus::createFromDateTime()
requires aDateTime
as its first argument per its type hint. Previously, as aDateTimePlus
object,$input
was aDateTime
as well. This is not the case anymore now that we wrap theDateTimePlus
class.Comment #39
dawehnerWell, ideally this would be an assertion ... the constructor sets it, doesn't it?
So what you can do is that
DateTimePlus::createFromDateTime()
converts the Datetime object passed in, into a DatteTimePlus object and then carry on.Comment #40
stefan.r CreditAttribution: stefan.r commentedWell the constructor sets the object already, but if there's an error intializing the object (ie. when doing
DateTimePlus('invalid')
), the exception thatDateTime
throws will be caught and the object will not be set.It already does that :)
Comment #41
dawehnerA got it, thanks for the explanation!
Nitpick: I guess we can use
{@inheritdoc}
here.Comment #42
stefan.r CreditAttribution: stefan.r commentedComment #43
stefan.r CreditAttribution: stefan.r commentedComment #45
stefan.r CreditAttribution: stefan.r commentedComment #46
stefan.r CreditAttribution: stefan.r commentedDoes this make sense?
Comment #48
stefan.r CreditAttribution: stefan.r commentedOK patch is green again. The red "patch" was supposed to be a .txt file :)
Comment #49
dawehnerCan we add a todo for pointing to #2451793: [META] Assert Statement Use in Drupal as those calls should be using an assertion in the future.
Comment #50
stefan.r CreditAttribution: stefan.r commentedthis adds a @todo as per #49
Comment #51
dawehnerThank you!
Comment #52
alexpottActually there's no docs to inherit here. So we need to provide them.
Comment #53
dawehnerOh, you are right, its storm which is showing them.
Comment #54
stefan.r CreditAttribution: stefan.r commentedComment #55
dawehnerNote: We use the following bits in other parts of the code:
Comment #56
stefan.r CreditAttribution: stefan.r commentedWe don't do it for __call and __callStatic elsewhere but since you listed those may as well do it here.
Comment #57
dawehnerSorry for the nitpicks!
Comment #58
webchickBack to Alex, but looks good to me.
Comment #60
alexpottThis issue addresses a critical bug and is allowed per https://www.drupal.org/core/beta-changes. Committed 0d0ed66 and pushed to 8.0.x. Thanks!