craftcms / cms

Build bespoke content experiences with Craft.
https://craftcms.com
Other
3.22k stars 627 forks source link

[3.9.3]: Entry postdate randomly changes to a different date on save #13731

Closed croxton closed 12 months ago

croxton commented 1 year ago

What happened?

Description

First, I'm not sure this really is a bug in Craft or has another cause, such as a plugin interfering with the entry save. But I wanted to put it out there in case someone can see how it might occur.

I had a report from a user that entry dates were sometimes changing when existing entries were edited, usually to a date in the future - putting the entry into a Pending status. This was a recent occurrence and may have followed the update to 3.9.3 (user is unsure if he had seen it before).

This user had never previously selected a preferred date formatting in his preferences, with the following value for his id in the userpreferences table:

{"language":null,"weekStartDay":null,"enableDebugToolbarForSite":false,"enableDebugToolbarForCp":false}

(Note: no 'locale' key. Not sure if that's relevant).

When we asked him to save his date formatting preferences the issue seemed to be resolved (jury's still out - it may recur).

I'm wondering if something like this could be the sequence that would lead the postdate of an entry to be changed to a future date:

<?php
$sourceDate = '2023-21-06'; // Y-d-m formatted postdate from entry save - Wednesday June 21 2023
$date = DateTime::createFromFormat('Y-m-d', $sourceDate); // the default format used by Craft doesn't match supplied date format
$tz = new DateTimeZone('Europe/London'); // server's timezone
$date->setTimezone($tz);
echo $date->format('l F j Y'); 
// yields Friday September 6 2024

Given a date that doesn't match the expected format, DateTime::createFromFormat does it's best to work out a valid date and seems to use the difference - 9 (21-12) for the input date month (=September), and +12 months to the year (=2024).

But.. how is it possible for the date format coming from an entry save to be different to that parsed by Craft (in DateTimeHelper::toDateTime)?

Craft CMS version

3.9.3

PHP version

7.4 Php Intl extension: 71.1

Operating system and version

No response

Database type and version

No response

Image driver and version

No response

Installed plugins and versions

"aelvan/inlin": "^2.0.0",
"craftcms/cms": "3.9.3",
"craftcms/google-cloud": "1.4.1",
"craftcms/mailgun": "2.0.1",
"craftcms/redactor": "2.10.12",
"hybridinteractive/craft-position-fieldtype": "^1.0.16",
"jabranr/postcodes-io": "^1.0",
"mikestecker/craft-videoembedder": "^1.0.9",
"nystudio107/craft-seomatic": "3.4.60",
"servd/craft-asset-storage": "2.9.8",
"superbig/craft3-imgix": "^2.0.5",
"superbig/craft3-templateselect": "^2.0.0",
"verbb/navigation": "^1.4",
"verbb/super-table": "2.7.5.1",
"vlucas/phpdotenv": "^4.1"
brandonkelly commented 12 months ago

If the user hadn’t ever saved their preferences, then the locale/formatting locale will be based on the preferred language stated by their browser. So maybe that changed for them while they were on the edit page (either directly or via their OS).

In any case, it’s an easy bug to reproduce by changing the formatting locale preference from another browser tab.

Just fixed this for the next Craft 4 release, by setting a hidden input that tracks the app’s current formatting locale ID, so we can be sure DateTimeHelper::toDateTime() will parse it with the same locale’s date/time formats on form submit.

(Realize you’re running Craft 3 still, but the fix was a little more involved than I wanted to make there and we’re supposed to only be fixing security issues there now.)

croxton commented 12 months ago

If the user hadn’t ever saved their preferences, then the locale/formatting locale will be based on the preferred language stated by their browser.

Ah ok, so it gets the language from the browser if not specified. Makes sense. So long as our Craft 3 users select their language preference they should be good. Many thanks!

brandonkelly commented 12 months ago

Craft 4.5.6 is out now with that change.