Skip to content
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

Make date display consistently across manager components #16604

Open
wants to merge 15 commits into
base: 3.x
Choose a base branch
from

Conversation

smg6511
Copy link
Collaborator

@smg6511 smg6511 commented Aug 25, 2024

What does it do?

  1. Adds a new Formatter class and updated several processor classes (and a couple controllers) to use the new date formatting methods provided.
  2. Adds a timestamp validation static method on the main modX class.
  3. Includes missing language topic for the Resource data page (currently two column headings are missing because the manager_log topic needs to be included).

Why is it needed?

The manager UI is inconsistent in its formatting of dates and times. This PR consolidates the formatting logic in one place and applies it to every component that displays a date (unless I've overlooked something).

How to test

  1. As this PR includes two new system settings, a data rebuild is necessary (/_build/transport.core.php) then a reinstall (upgrade) via /setup.
  2. Set a manager_date_format and manager_time_format, as well as a manager_datetime_separator in the system settings.
  3. Take a run through the entire interface and verify that areas that display a date/time do so as expected and match your expected format everywhere. Note that there are two places where these changes are purposely no applied: The system info page (where the server and local times are shown) and the manager error log (where it's impractical to try to alter the entry format).

Related issue(s)/PR(s)

Resolves #14961.
Resolves #16512.

@smg6511 smg6511 added the pr/review-needed Pull request requires review and testing. label Aug 25, 2024
@theboxer
Copy link
Member

theboxer commented Sep 6, 2024

@smg6511 In general I like the proposed idea, but I didn't like the implementation much, it seemed a bit complicated.

Can you please check an updated version I pushed to my repo: theboxer@4133e16 and let me know your thoughts?

The key changes would be:

  • Renaming the formatter class to better reflect it's usage
  • Move the formatter under Formatter namespace, I can imagine we could have more formatters in the future
  • Removed the part where formatter was used as a parser in the edit profile and validate user (reverted to original)
  • Added the formatter into the DI container
  • Removed public $formatter from the generic processor, there's no need for it when it's not getting used on generic level
  • Simplified the formatter's functions, reduced number of arguments and converted them to separate functions, trying to keep SRP

@smg6511
Copy link
Collaborator Author

smg6511 commented Sep 6, 2024

@theboxer Thanks for going through it so thoroughly! I took an initial look and like what you did structure-wise. (I do sometimes try to do too much in some methods!) I do need to understand better how the use and implementation of services works. Anyway, let me pull this down and go over it more closely in the next few days or so.

The one thing I see that I will probably argue is your reversion to strtotime in some places. I chose to use the ...Immutable::createFromFormat because strtotime is incompatible with certain string formats (for example 2024-09-06 [yyyy-mm-dd], which I personally use a pretty often and I can't be the only one!) That said, I do need to closely check where you changed those to see whether it has the negative effect I think it might have.

Be back soon...

@theboxer
Copy link
Member

theboxer commented Sep 6, 2024

@smg6511

The one thing I see that I will probably argue is your reversion to strtotime in some places.

I'm fine with using the Immutable::createFromFormat, but I think it shouldn't be using anything from the formatter and probably shouldn't be part of this PR.

@rthrash rthrash added this to the v3.1.0 milestone Sep 12, 2024
@smg6511
Copy link
Collaborator Author

smg6511 commented Sep 20, 2024

@theboxer - Quick question: I've not pulled down a fork of a fork before; what's the best way of going about that? To this point I've used Github Desktop for all things modx git, but realize this may require some command line actions.

@opengeek
Copy link
Member

opengeek commented Sep 20, 2024

@theboxer - Quick question: I've not pulled down a fork of a fork before; what's the best way of going about that? To this point I've used Github Desktop for all things modx git, but realize this may require some command line actions.

@smg6511 — You should be able to add the fork as a new remote in your existing repository. I imagine GH Desktop has a feature for adding a remote?

@smg6511
Copy link
Collaborator Author

smg6511 commented Sep 20, 2024

Ok, so basically fork John's revo repo is what you're suggesting, right?

@opengeek
Copy link
Member

Ok, so basically fork John's revo repo is what you're suggesting, right?

No, you just add his fork as a remote to your local git repo.

@theboxer
Copy link
Member

@smg6511 for cli command, it'd be git remote add bxr https://github.com/theboxer/revolution.git where bxr is name of the remote, so you'll be able to do something like git pull bxr 3.x-issue-14961

@smg6511
Copy link
Collaborator Author

smg6511 commented Sep 23, 2024

I'm fine with using the Immutable::createFromFormat, but I think it shouldn't be using anything from the formatter and probably shouldn't be part of this PR.

Ok, I've pulled down your changes and am giving them a run-through. I'd referenced the incorrect format above when making the case for using Immutable::createFromFormat it wasn't Y-m-d [yyyy-mm-dd, that's ok], it's a format like m-d-Y that fails; you'll see this when changing/saving a User's birth date. For that reason, I think that usage should stay. Of course we don't have to pull the date format from the Formatter as I originally did and could just getOption('manager_date_format', [default format]); note that the logic behind that initial choice was that, as it stands, users can delete that setting and I don't believe there's a system-wide default persisted anywhere. But we could resolve that in another PR that's more centered around how modx-installed data and settings are persisted and/or protected.

Anyway, I'll be back with any other comments in the next day or so...

@smg6511
Copy link
Collaborator Author

smg6511 commented Sep 24, 2024

@theboxer @opengeek @rthrash - (re John's updated version) Another thing I noticed is the use of typed properties. I'd love to make use of this feature, but we'd need to bring up the required modx php version to 7.4. Currently we're stating 7.2.5. Is there movement toward upping the required php version for the next (or the 3.1) release?

@theboxer
Copy link
Member

@smg6511 Revo 3.x already requires 7.4 (https://github.com/modxcms/revolution/blob/3.x/composer.json#L52)

Ok, I've pulled down your changes and am giving them a run-through. I'd referenced the incorrect format above when making the case for using Immutable::createFromFormat it wasn't Y-m-d [yyyy-mm-dd, that's ok], it's a format like m-d-Y that fails; you'll see this when changing/saving a User's birth date. For that reason, I think that usage should stay. Of course we don't have to pull the date format from the Formatter as I originally did and could just getOption('manager_date_format', [default format]); note that the logic behind that initial choice was that, as it stands, users can delete that setting and I don't believe there's a system-wide default persisted anywhere. But we could resolve that in another PR that's more centered around how modx-installed data and settings are persisted and/or protected.

Like I said, I have no issues using the Immutable::createFromFormat in the user's save/update processors. I simply stated that it shouldn't use methods/properties from a class that's called formatter, because at that point you'd be misusing class intended for formatting (outputting data for user) for input validation. I simply reverted that part, to the original and if you'd want to go ahead with the immutable update, I'd put it as a standalone PR, because it solves different problem than the current PR.

@smg6511
Copy link
Collaborator Author

smg6511 commented Sep 24, 2024

@theboxer - Ok, no problem putting the use of Immutable::createFromFormat in another PR.

BTW, I think everything's looking great otherwise. I have a couple small additions/tweaks based on your updates which I have incorporated on a new branch:

On the php version, the modx.com/download page will need to be updated—it still claims 7.2.5 is the required version; the same goes for the Docs. Also, the phpcs.xml file needs updating as well (which I can do).

@theboxer
Copy link
Member

@smg6511 will you push all the stuff here?

smg6511 and others added 11 commits September 26, 2024 10:26
Adds a new centralized formatting class for datetime data, adjusting various classes to make use of the new formatters.
Applied formatter to system settings processor and made a few other corrections to previously-committed code.
Should have included this with the last commit
Include empty date display value in early return
Applies formatter to this object type
(Finding areas I'd missed updating in earlier commits)
Add/tweak method documentation; make nullable string more explicit in method signatures
Applies new modManagerDateFormatter to Context settings
Copy link

codecov bot commented Sep 26, 2024

Codecov Report

Attention: Patch coverage is 9.20097% with 375 lines in your changes missing coverage. Please review.

Project coverage is 21.53%. Comparing base (9a3f82c) to head (6150494).
Report is 8 commits behind head on 3.x.

Files with missing lines Patch % Lines
...c/Revolution/Formatter/modManagerDateFormatter.php 7.69% 60 Missing ⚠️
...Revolution/Processors/Security/User/Validation.php 0.00% 58 Missing ⚠️
core/src/Revolution/Processors/Resource/Data.php 0.00% 41 Missing ⚠️
.../Processors/Workspace/Packages/Version/GetList.php 0.00% 27 Missing ⚠️
.../Revolution/Processors/System/Settings/GetList.php 0.00% 26 Missing ⚠️
...volution/Processors/Workspace/Packages/GetList.php 0.00% 23 Missing ⚠️
.../Revolution/Processors/Context/Setting/GetList.php 0.00% 16 Missing ⚠️
core/src/Revolution/Processors/Processor.php 66.66% 14 Missing ⚠️
...c/Revolution/Processors/Workspace/Packages/Get.php 0.00% 12 Missing ⚠️
...lution/Processors/System/Dashboard/Widget/Feed.php 0.00% 11 Missing ⚠️
... and 13 more
Additional details and impacted files
@@             Coverage Diff              @@
##                3.x   #16604      +/-   ##
============================================
+ Coverage     21.47%   21.53%   +0.06%     
- Complexity    10652    10718      +66     
============================================
  Files           561      565       +4     
  Lines         32268    32521     +253     
============================================
+ Hits           6929     7005      +76     
- Misses        25339    25516     +177     
Flag Coverage Δ
21.53% <9.20%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@smg6511
Copy link
Collaborator Author

smg6511 commented Sep 26, 2024

@theboxer - Ok, I think this is all set to do a final run-through. In the end, we just need to be sure that this does not end up in a 3.0.x backport, as the php version requirement is still too low there for the use of typed props (used in the Formatter).

Copy link
Member

@theboxer theboxer left a comment

Choose a reason for hiding this comment

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

There's one more think I want to mention, I notice in same cases we're switching from JS doing the formatting to the PHP doing it, this will result in different value getting displayed to the user (if the user is in a different time zone than the server) and it also means that the JS has a different value for other functions that are getting called. I'm not sure if this is or isn't an issue, but wanted to mention it :)

core/src/Revolution/Formatter/modManagerDateFormatter.php Outdated Show resolved Hide resolved
core/src/Revolution/Formatter/modManagerDateFormatter.php Outdated Show resolved Hide resolved
core/src/Revolution/Formatter/modManagerDateFormatter.php Outdated Show resolved Hide resolved
Make requested changes and add a few more prop/method type declarations
Implement requested change missed in previous commit
@smg6511
Copy link
Collaborator Author

smg6511 commented Oct 2, 2024

There's one more think I want to mention, I notice in same cases we're switching from JS doing the formatting to the PHP doing it, this will result in different value getting displayed to the user

I don't think this should be a problem. All the core dates are stored as unix timestamps and users have control over the offset via the system setting. So long as we're consistently calculating and formatting dates on just one side of the equation (back end/php in our case), I think we should be fine.

If there's a worry here, I suppose the release notes could alert folks that, potentially, with this update datetimes displayed in the back end may be different than expected if a user's server_offset_time is not properly set.

Copy link
Member

@theboxer theboxer left a comment

Choose a reason for hiding this comment

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

Awesome, thank you!

@opengeek
Copy link
Member

opengeek commented Oct 2, 2024

If we have depended on the JS showing these in the proper timezone in the browser without needing server_offset_time to be managed before now, then this could be a problem.

@smg6511
Copy link
Collaborator Author

smg6511 commented Oct 3, 2024

@opengeek I did a quick run through of the changed js to be sure; I didn't see any issues when simulating different time zones. By and large the date formatting was being done in php before this PR—just in an inconsistent ways across the board—and we didn't change much in the js in that regard.

@theboxer
Copy link
Member

I'm fine with merging this one :)

@opengeek
Copy link
Member

This implementation still seems overly complicated to me. I don't understand the need for all these settings and a formatting class. PHP provides date formatting that should be sufficient to handle this.

@jaygilmore
Copy link
Member

@smg6511, can you elaborate on the necessity for the Formatter class? I.e. what does it do that can't be done natively with PHP? What else does it do? I'm not suggesting it's the wrong path. I'm just trying to understand it clearly and your intention.

@smg6511
Copy link
Collaborator Author

smg6511 commented Oct 31, 2024

@opengeek @jaygilmore - In a nutshell, the primary reasons for/advantages of the approach taken are:

  1. First and foremost, any time I end up writing the same two or more lines to do the same thing in multiple places I look to abstract out that functionality. (I think MODX suffers noticeably on the code duplication front and I'd like to avoid adding to it.) Soon after digging into solving the issue this PR addresses, it became clear that the functionality should be consolidated in some way.
  2. The date values taken in are not always the same type; sometimes they are a string value, other times (probably most times) a int timestamp. Add to that, strtotime can not handle certain formats (such as m-d-Y), which is why php's more capable DateTimeImmutable is used in the formatter class. Also, conditionals were needed in some places to account for various forms of an "empty" datetime value. This new service class provides a unified, one-liner way of formatting a date/time for string and int value types.
  3. The two settings I did add give the user more control over display of full datetimes (the separator) and empty ones. IMO it's better to not hard code these things anyway; what if you decide for some reason you'd rather use a different separator as the default one? Currently you'd have to change several files to do so. You could argue it's a bit nitpicky, but I personally like something other than a blank for places (primarily the grids) that show and updated on value (and the object has not been updated yet).
  4. And Jan's contribution of making this a service class (as well as simplifying my initial overly-heavy methods, breaking them up into smaller ones with more discrete purposes) might make this functionality more accessible for other uses.

All that's not to say it can't be improved further ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr/review-needed Pull request requires review and testing.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Recently edited resources crashes if createdon is 0 Display dates in manager in one format
5 participants