Backfill missing published/updated on inbox & outbox reads#3320
Open
pfefferle wants to merge 8 commits into
Open
Backfill missing published/updated on inbox & outbox reads#3320pfefferle wants to merge 8 commits into
pfefferle wants to merge 8 commits into
Conversation
Outbox::get_activity already had the row in hand but only set updated, and only for Update activities. Generalize: when published is empty, fill it from post_date_gmt; when updated is empty AND (type is Update OR the row was modified after creation), fill from post_modified_gmt. The existing line also read post_modified (local TZ); switch to post_modified_gmt so the value is correct on non-UTC sites. Tests cover both fill paths plus the "no synthesis when unmodified" case.
…970 dates Outbox::add inserts with post_status = 'pending', so WordPress leaves post_date_gmt as '0000-00-00 00:00:00'. The previous ! empty() guard treated that string as truthy and would have set published to '1970-01-01T00:00:00Z' on every still-pending row -- worse than leaving the field empty. Reject the sentinel explicitly for both post_date_gmt and post_modified_gmt. Tests now populate the date columns to real timestamps so they verify meaningful behavior instead of round-tripping epoch zero, and a new test pins the zero-sentinel case to "stay empty".
Mirrors Outbox::get_activity: decodes the stored JSON, returns an Activity object, and falls back to the inbox row's post_date_gmt / post_modified_gmt when the activity itself is missing published or updated. Rejects the '0000-00-00 00:00:00' sentinel for both columns so the fallback can't synthesize a 1970-01-01 date when a pending row's GMT timestamps haven't been populated yet.
The actors inbox controller's prepare_item_for_response used to return the raw json_decoded post_content, which meant the new published/updated fallback in Inbox::get_activity bypassed it. C2S clients reading the inbox endpoint now see the enriched dates instead of empty fields when the remote sender omitted them.
prepare_item_for_response now passes $item->ID to Inbox::get_activity, returns the WP_Error on failure (instead of swallowing it as array()), and the get_items loop skips WP_Error items the same way the outbox loop does. Also drops the per-item JSON-LD context and blind audience (bto/bcc) on the wire by calling to_array(false), matching the outbox controller's serialization. Inbox and Outbox collections themselves are unchanged.
There was a problem hiding this comment.
Pull request overview
Backfills missing published/updated timestamps on activities served from the inbox and outbox C2S endpoints by falling back to the underlying CPT row's GMT timestamps, while introducing a new Inbox::get_activity() helper that mirrors the outbox shape and incidentally stops leaking the persisted blind audience (bto/bcc) on the inbox listing.
Changes:
Outbox::get_activity()reworked to fall back topost_date_gmt/post_modified_gmt(rejecting the0000-00-00 00:00:00sentinel) and preserve theUpdatecarve-out.- New
Inbox::get_activity()helper hydratespost_contentinto anActivity, validates, and applies the same fallback;Actors_Inbox_Controller::prepare_item_for_responsenow routes through it and returnsWP_Erroron failure, withto_array( false )strippingbto/bcc. - Test coverage added for outbox/inbox fallback semantics, sentinel rejection, type/JSON validation, and the existing-
publishedpreservation case.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| includes/collection/class-outbox.php | Adds date fallback from row GMT timestamps with sentinel rejection. |
| includes/collection/class-inbox.php | New get_activity() mirroring outbox semantics with WP_Error handling. |
| includes/rest/class-actors-inbox-controller.php | Routes C2S inbox listing through Inbox::get_activity(), skipping errors and using to_array(false) to drop blind audience. |
| tests/phpunit/tests/includes/collection/class-test-outbox.php | New tests for published/updated fallbacks, sentinel handling, and modification-time logic. |
| tests/phpunit/tests/includes/collection/class-test-inbox.php | New tests for the inbox helper including error cases. |
| .github/changelog/fix-c2s-activity-date-fallback | Changelog entry. |
Switching post_modified to post_modified_gmt fixed the non-UTC timezone
bug but introduced a regression for Update activities at federation
time: the Dispatcher reads outbox rows while they are still pending,
and pending rows leave _gmt columns as the 0000-00-00 sentinel while
the local columns are populated via current_time('mysql'). The sentinel
rejection then short-circuited the Update carve-out, so Update
activities started federating without an updated field.
Fall back to get_gmt_from_date( $post->post_modified ) when the GMT
column is the sentinel but the local column is set. Apply the same
derivation to post_date_gmt so pending Create activities also gain a
published field. A regression test pins the pending-row state the
Dispatcher actually sees.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #
Proposed changes:
Outbox::get_activity()now backfills a missing top-levelpublishedfrom the outbox row'spost_date_gmt, and a missingupdatedfrompost_modified_gmtwhenever the row was modified after creation (the existingUpdate-type carve-out is preserved). Also rejects the0000-00-00 00:00:00sentinel that pending rows carry so the fallback can't synthesize a 1970-01-01 date.Inbox::get_activity()helper mirrors the outbox method: decodespost_content, validates the result, hydrates anActivity, applies the same date fallback. ReturnsWP_Erroron missing/wrong-type/corrupt rows.Actors_Inbox_Controller::prepare_item_for_response) now goes throughInbox::get_activity()and is shaped exactly like its outbox counterpart — passes$item->ID, returnsWP_Erroron failure, theget_items()loop skips errored items, and per-item serialization usesto_array( false )(drops the per-item@contextsince the collection carries it, and stripsbto/bcc).to_array( true, true )was leaking the stored blind audience (bto/bcc) on the C2S inbox endpoint; this change closes that as a side effect of unifying with the outbox style.Other information:
Testing instructions:
GET /wp-json/activitypub/1.0/actors/{id}/outboxwith auth (or browse a public outbox).orderedItemsshould now carry apublishedfield; items that were modified after they were queued should also carry anupdated.published, it now shows up — no DB migration needed, the value is computed at read time.publishedfield.publishedderived from the row'spost_date_gmt.btonorbccshould appear, even though they're persisted internally for addressing.npm run env-test(2565 tests, all passing locally).Changelog entry
A changelog file is already included in this branch at
.github/changelog/fix-c2s-activity-date-fallback. No automation needed.