Repository navigation
Model: Handle dates in UTC in Serde and the message factory - #627
jonathanbossenger merged 5 commits into
Conversation
Serde read MySQL datetime strings in the PHP default timezone and accepted out of range dates, which PHP silently rolls over. It now reads and writes dates in UTC and rejects invalid dates. `Message::$meta_keys` listed `expires_at`, `severity` and `channel_title`, so `encode_meta()` wrote them into the `meta` JSON. They are removed from `$meta_keys` and kept in `jsonSerialize()`. `Factory\Message` now deserializes `created_at` and `expires_at` with Serde, like the Notification and Subscription factories, so a message loaded from the database no longer throws a `TypeError`. Also removes the unused `Message::validate_message()`. Fixes WordPress#614.
|
Hi @huzaifaalmesbah, #637 and this PR both change In the review on #637 this split was suggested:
Is this OK for you? Whichever PR merges second, please check that |
|
Thanks @faisalahammad, that split works for me. I'll remove the |
Restore includes/model/class-message.php and its tests to develop, so this PR only keeps the Serde UTC fixes and the Factory\Message date deserialization. The $meta_keys, channel_title and message length changes are handled in WordPress#637.
|
@jonathanbossenger @faisalahammad I pushed 5601aba. It restores Tests: 79 tests, 0 failures on single site and multisite. PHPCS is clean. Since the scope changed after the approval, could you take another look, @jonathanbossenger? |
What?
Part of #614. Part of #302.
Makes
Helper\Serderead and write dates in UTC, and makesFactory\Messagedeserialize its dates the same way the other factories do.The
Message::$meta_keys,channel_titleand message length changes from #614 are handled in #637, because they follow from the new v2 columns (see #627 (comment)).Why?
maybe_deserialize_mysql_date()calledDateTime::createFromFormat()without a timezone. WordPress sets the default to UTC, but anything that changes it shifts every date read from the database. It also accepted dates like2024-02-30, which PHP silently rolls over to March.Factory\Messagecould not load a message from the database. It passedcreated_at/expires_atstraight to the model, whose properties are typed?DateTime, so a MySQL date string threwTypeError: Cannot assign string to property … of type ?DateTime. Implement querying the database for notifications #307 would hit this first.How?
includes/helper/class-serde.phpmaybe_deserialize_mysql_date()parses with!Y-m-d H:i:sin UTC (!also resets microseconds).2024-02-30, month13, the MySQL zero date) and non-string values now returnnull.DateTimepassed in is converted to UTC without modifying the original.maybe_serialize_json_date()always outputs UTC (+00:00).includes/factory/class-message.phpcreated_atandexpires_atgo throughSerde::maybe_deserialize_mysql_date(), matching the Notification and Subscription factories.Tests
tests/phpunit/tests/test-serde.php. It sets the PHP default timezone toAmerica/New_Yorkto prove Serde doesn't depend on it, and covers the round trip,DateTimeconversion, no mutation of the input, and invalid input (including the MySQL zero date).test-factory-message.php: added a test that makes a message from MySQL date strings.Testing Instructions
npx wp-env startnpx wp-env run tests-cli --env-cwd=wp-content/plugins/wp-feature-notifications vendor/bin/phpunitnpx wp-env run tests-cli --env-cwd=wp-content/plugins/wp-feature-notifications env WP_MULTISITE=1 vendor/bin/phpunitnpx wp-env run tests-cli --env-cwd=wp-content/plugins/wp-feature-notifications vendor/bin/phpunit --filter "Test_Serde|Test_Factory_Message"Local results: 79 tests, 0 failures on single site and multisite (the 24 skipped are the existing REST controller placeholder tests). PHPCS is clean.
Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5
Used for: Drafting the fix and unit tests. I chose the approach from the issue, agreed the split with #637, reviewed every change, and verified it locally with PHPUnit (single site and multisite) and PHPCS.