Problem/Motivation
When using the timeago formatters on datatime fields, the setting summary does not display properly on the Manage Display page. This was likely a side effect of #2500525: Time ago/hence date/time formatting breaks caching; needs appropriate max age. The setting summary also does not with the timeago formatters on timestamps.
Proposed resolution
- Refactor DateTimeTimeAgoFormatter to extend TimestampAgoFormatter
- Fix settings bug with TimestampAgoFormatter
Remaining tasks
Finish it.
User interface changes
None.
API changes
None.
Data model changes
None.
Credits
#2867248: Timestamp Ago Formatter: Future and past format not selectable due to incorrect variable name... was closed as a dup of this. Please also credit @xSDx, @JaceRider for patches and @jhedstrom for a review from that issue.
| Comment | File | Size | Author |
|---|---|---|---|
| #67 | 2686409-67.patch | 17 KB | mpdonadio |
Comments
Comment #2
darrick commentedComment #3
mpdonadioRun TestBot, run!
Comment #4
Anonymous (not verified) commentedI was able to reproduce this issue, and #2 fixes the issue. However, I am wondering if there is a reason in particular to render the example with emphasis tags (%var instead of @var). It seems like the DateTimeFormatterBase doesn't do that for timezones either, so it seems inconsequent.
Comment #5
mpdonadio#4, core usage of this is consistent. That would be an out of scope change, though, of this issue.
This pains me to write, but we can't introduce usage of a global function in this patch. We need to inject the renderer service into DateTimeTimeAgoFormatter, and then use that instead of render() directly. I think a test for this is bug overkill, but we may get pushback on it.
Double checking that we just need to issue a CR for this in order to get into 8.1, but not may people in IRC right now.
I'll update the IS from the template, when I get time later, and we need a short beta eval.
Comment #6
Anonymous (not verified) commentedHere is a patch with the renderer injected. Also added a beta evaluation to the IS.
Comment #7
Anonymous (not verified) commentedComment #8
mpdonadioPretty sure this was caused by #2500525: Time ago/hence date/time formatting breaks caching; needs appropriate max age.
I think this is good to go. Once I update the IS and head from a framework manager on the proper steps to get this into 8.1 (b/c the container rebuild), I'll set RTBC.
Comment #9
dawehnerI'm wondering whether this means we have an actual API break in
\Drupal\Core\Datetime\DateFormatterInterface::formatitself ... Other code could have used it in a similar way.Comment #10
mpdonadio#9, yeah looking closer at #2500525: Time ago/hence date/time formatting breaks caching; needs appropriate max age, it looks like we should have written up a CR about it. I'll do that tomorrow (won't have time tonight).
Comment #11
mpdonadioOK, talked to @alexpott.
We need a short CR to announce the change to DateTimeTimeAgoFormatter, that we now inject the renderer service and that the patch requires a container rebuild as a result.
We need to add an empty hook_update_N w/ a comment mentioning the the change to DateTimeTimeAgoFormatter, that we now inject the renderer service, so the change requires a container rebuild (we should do a quick search through core/ for similar language). When the update process looks for hooks, it will find this, and at the end automagically do a drupal_flush_all_caches(), which contains a container invalidation.
Comment #12
Anonymous (not verified) commentedThis patch is loosely based on views_update_8004(). I couldn't find too much other examples, but it will do?
Comment #15
Anonymous (not verified) commentedI'm not sure why this fails. Anyway, added a forgotten docblock param and fixed the grammar in the update hook comment.
Comment #19
dawehner... with an update hook we don't need to add a change record.
Comment #20
mpdonadioLooks like #2728811: DateTimeTimeAgoFormatter::settingsSummary() produces htmlspecialchars() warning in field UI is a duplicate of this, but it begs the question why we don't have a test failure. A problem like that should have been caught?
Comment #22
mpdonadioWhat about this? Still needs a test to show the bug.
Comment #23
mpdonadioAnd curious if the test fail is as simple as this.
Comment #25
mpdonadioMoving back to Needs Review, the fail in #23 is a known random fail in the branch #2724871: Random failure in \Drupal\migrate_drupal_ui\Tests\d7\MigrateUpgrade7Test.
Going to ping @catch or @alexpott whether they want a test to demonstrate this bug. I said earlier that we didn't need one, but I am on the fence now.
Comment #26
catchI don't think this really requires a test - we should have tests for all the constituent parts, and the bug itself is minor.
Comment #27
mpdonadioComment #28
mpdonadioJust closed another issue as a duo of this. Which approach do we want to go with? #22 or #23? I think both are review-ready.
Comment #29
aspilicious commentedI think patch #23 is the way to go.
Comment #30
yoruvo commentedApplying patch #23 did nothing about the problem on my install.
Comment #31
mpdonadioI can't reproduce #30; tested with and without and the warning goes away.
This fixes up a notice that pops up with PHP 7.
Comment #32
mpdonadioJust reviewed this issue.
Given the two approaches, I think #21 is the best. This is a minor bug, and #21 is a simple fix that avoids injecting any new services and directly addresses what caused it.
Manually tested #21 again, and think it is still good to go.
Comment #33
ismail cherri commentedI came to this issue because I was seeing the same error with the "Checked" field from the core Aggregator module.
This is uses the TimestampAgoFormatter class. It is similar to the DateTimeTimeAgoFormatter but differs that it uses a timestamp.
Applying #21 on this class caused the following error:
PHP Fatal error: Call to a member function getTimestamp() on integer in /var/www/html/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampAgoFormatter.php on line 148, referer: http://v2.insideout.today/admin/config/services/aggregator/displayApplying #31 after changing the formatDate() function call to formatTimestamp() solved the issue with the field.
However applying the attached 2686409-33.patch on both classes fixes the issue.
Comment #34
mpdonadioYeah, fixing that formatter here is probably appropriate, too.
Not sure I really like the approach here. It's programming to the implementation, not the interface. The approach in #21 should work here, too. In this function, tough, the $future_date and $past_date are already timestamps, so you just don't need to call that method. Otherwise, it should work.
Comment #35
mpdonadioI think this would be the minimally invasive approach that fixes both formatters w/o needing to get the renderer involved and w/o poking around a render array for output.
Comment #38
bceyssensReapplied patch #35 to the 3.x branch
Comment #39
dawehnerFor a test we could just adapt
\Drupal\Tests\field\Kernel\Timestamp\TimestampFormatterTestand call out to this function.Comment #40
xsdx commentedHi guys I've also fixed this issue about summary for TimeAgoFormatter along with deprecated function replacement and some code refactoring changes and fixing wrong elements issue also here https://www.drupal.org/node/2867248 so check it out and review code and maybe we can close both issues then. Tnx
Comment #41
xsdx commentedI've checked the patch and it's not showing format entered for example 1 year ago like you set it in config form but just 1 year in either way so I added a patch for this and pushing it now for review.
Comment #42
mpdonadioNice catch.
Pondering
1. Whether we really should add #2867248: Timestamp Ago Formatter: Future and past format not selectable due to incorrect variable name... here, since the Timestamp settings are useless w/o that...
2. Whether we want to start a TimestampFieldTest. But, also see (1)
Few nits:
Needs to be alphabetical.
Should use short array syntax.
Needs to be alphabetical.
Leaning towards the merge, but not sure, so no need for new patch quite yet.
Comment #44
jhedstromNeeds work for #42.
Comment #45
claudiu.cristeaFixed #42 and moved #2867248: Timestamp Ago Formatter: Future and past format not selectable due to incorrect variable name... here. Added the test. Closing #2867248: Timestamp Ago Formatter: Future and past format not selectable due to incorrect variable name... as duplicate.
Comment #46
claudiu.cristea@mpdonadio, @jhedstrom shouldn't we extend
DateTimeTimeAgoFormatterfromTimestampAgoFormatter? Then we create a protected methodTimestampAgoFormatter::getValue()that is simply transforming the field stored value into a format that can be passed to unified::formatTimestamp()/::formatDate(). we would avoid a lot of code duplication. Or just use a trait?Comment #47
claudiu.cristeaHere's a rework that extends DateTimeTimeAgoFormatter from TimestampAgoFormatter.
TODO: Shouldn't be the "empty output" configurable? Now is hardcoded as t('never') for TimestampAgoFormatter and nothing for DateTimeTimeAgoFormatter.
Comment #48
claudiu.cristeaI needed the "time ago" formatter in our project but I found that is a bad choice. The problem is that a "time ago" interval string changes very often making it uncacheable. Then the whole page become uncacheable. What I did it was that I've created my own formatter by extending
TimestampFormatter. I used the timeago jquery plugin to replace the nice formatted date/time with a "timeago string". In this way non-JS browsers will show a formatted date (the default behaviour ofTimestampFormatter) and JS browsers (99%) will show the "time ago" interval. This is nice because:I think we should do the same in
TimestampFormatterand drop/deprecate this formatter. We can add the "time ago" as a formatter option. It's not necessary to use timeago jquery plugin which seems not very flexible, we can go with the industry standard, which is Moment.js.PS: Alternatively, we can keep the actual formatter and use a placeholder instead of rendering the the "time ago" but what is the gain?
Comment #49
jhedstromIIRC, this has been resolved for things like comment posted times, node posted times, etc. I had no idea it wasn't resolved for the datetime formatter. Let's add a follow-up issue to address that.
Comment #50
mpdonadioA pass at this was in #2500525: Time ago/hence date/time formatting breaks caching; needs appropriate max age.
Comment #51
claudiu.cristea@jhedstrom, @mpdonadio here's the followup where I proposed also the first patch #2921810: Allow TimestampFormatter to show as a fully cacheable time difference with JS. Unfortunately I don't have time to continue with that.
Comment #52
adamps commentedThanks @claudiu.cristea
#45 worked for me, RTBC from my perspective (but I didn't set that assuming the core experts should review it).
Given the idea in #51 that TimestampAgoFormatter could be deprecated, then maybe #47 "extend DateTimeTimeAgoFormatter from TimestampAgoFormatter" is counter-productive? On that basis I have tentatively hidden #47 and re-exposed #45. However please put it back if I did the wrong thing.
This bug generates a warning that is quite confusing to site-developers so I wonder if the priority is more like "Normal"? Anyway it would be great to have a fix.
Comment #53
adamps commentedPossibly a blocker for #2638250: The label "Member for" on user profiles is hardcoded markup that is different from other user fields, so I've increased the priority and set to RTBC based on my review/test. Still needs review from the experts.
Comment #54
mpdonadioI need to read this applied, and stare at the test some more to think about whether it will be glitchy and prone to sporadic fails.
Comment #55
mpdonadioNit, unneeded change.
This is a BC problem if anyone has extended this formatter.
Whis is this needed?
The bug is that they didn't appear on Manage Display, so I think we want to assert the text there and not that they were saved properly.
Like this, and think it will be glitch free.
Kinda seems like this is replicating logic from the format() method?
Comment #56
mpdonadioUpdate to #55-4, I think we need to add that coverage on Manage Display in addition to the save check. Do we also need coverage in DateTimeFieldTest?
Rescoping this a bit.
Updated IS w/ credits from dup (I can't update the list).
And, this is a bug so it is 8.4.x eligible, but the patches conflict b/c #2830094: Deprecate and remove usages of datetime_date_default_time(). and possibly #2826404: Create DateTimeItemInterface and deprecate global constants in datetime.module. So, I am moving this to 8.5.x per our workflow. One we wrap up that version, we can do a quick backport.
Comment #58
slefevre1 commentedWe were getting
Warning: htmlspecialchars() expects parameter 1 to be string, array given in Drupal\Component\Utility\Html::escape()after setting the "time ago" formatter on a display mode for a content type field. Patch #45 fixed the error popping up with no apparent ill effects. RTBCComment #59
adamps commentedHowever the review comments in #55, #56 have not yet been addressed so it can't be RTBC. If anyone is keen for RTBC it would be great if they can apply the comments.
Comment #61
tamasd commentedI updated the patch for Drupal 8.6.
Comment #62
joelpittetBumping this because it breaks the UI with a large warning about arrays to strings and is quite common. Moving it back to 8.6 in hopes it can get in a patch release.
Comment #63
mpdonadioBit of a do-over to match the IS. Will be adding tests shortly, but want to see if this causes any regressions.
Comment #64
joelpittetThank you for the quick patch update. That's a nice cleanup too, I hope it doesn't change too much.
Should we add another test back in? I'm trying to get my local tests working so I can help out here too
Comment #65
mpdonadioI have some tests in progress. I am working on a baseline TimestampAgoFormatterTest, which I will clone to DatetimeAgoFormatterTest. Doing this in bootstrap an effort to make DatetimeFieldTest manageable.
Comment #66
mpdonadioThis should cover all of the changes. Will clone to DatetimeAgoFormatterTest.
Comment #67
mpdonadioThis should be the minimal patch that addresses the bugs, covers the changed code, and tests for regressions.
Comment #68
joelpittetI've manually tested the patch and reviewed the iterations of the patches and it now has tests to. Thank you @mpdonadio!
Comment #69
claudiu.cristeaWonder why I was uncredited here
Comment #70
mpdonadio#69, I am not sure what you mean? You have patches on this issue, and are in the credit list. Pretty sure I just added the additional credits in the IS #56 when we closed the dup for people who weren't listed yet who contributed on the other issue. Your patches were before then, so you were already listed.
?
Comment #71
damienmckennaI'm not sure who made the change, but please leave the "credits" section for the maintainers to adjust, it's improper / impolite to remove people from this list if you aren't in a position to commit changes.
Comment #73
joelpittetAdding people to credit xSDx, JaceRider,jhedstrom
Comment #74
alexpottI've credited everyone who reviewed this issue and tried to move it along.
Comment #75
alexpottAs there were no test-only patches as far as I can see - ran them locally. And yep we can see that they are adding the missing coverage.
And
Comment #76
alexpottCommitted and pushed 21ba3dfc6f to 8.7.x and 855d0cf6d8 to 8.6.x. Thanks!
Backported to 8.6.x as this is a bug fix which does not make any API changes and make changes to anything covered by a BC promise and it fixes and error people are experiencing whilst using the UI.