@@ -524,6 +524,92 @@ public function test_pending_distribution() {
524524 $ this ->assertSame ( 'publish ' , get_post_status ( $ post_id ) );
525525 }
526526
527+ /**
528+ * Test that a scheduled (future) hub post does not auto-publish on the node
529+ * when status_on_publish is set to a non-publish status.
530+ *
531+ * Regression test for: hub distributes a draft, then schedules it shortly
532+ * after. The scheduling sync sends post_status='future' to the node. If the
533+ * node applies that status directly, WordPress cron will find a future-status
534+ * post and auto-publish it via wp_publish_post(), bypassing the
535+ * status_on_publish setting entirely.
536+ *
537+ * The node should keep the post in the status_on_publish state, such as draft,
538+ * so that WP cron never has a chance to publish it.
539+ */
540+ public function test_future_status_with_non_publish_status_on_publish () {
541+ $ payload = $ this ->get_sample_payload ();
542+
543+ // Simulate Event 1: hub distributes the post as a draft.
544+ // status_on_publish='draft' means the node should never auto-publish.
545+ $ payload ['post_data ' ]['post_status ' ] = 'draft ' ;
546+ $ payload ['status_on_publish ' ] = 'draft ' ;
547+
548+ $ post_id = $ this ->incoming_post ->insert ( $ payload );
549+ $ this ->assertSame ( 'draft ' , get_post_status ( $ post_id ) );
550+
551+ // Simulate Event 2: hub schedules the post, syncing post_status='future'.
552+ // The node must not apply 'future', as a future-status post with a past date
553+ // is auto-published by WP cron, bypassing status_on_publish entirely.
554+ $ payload ['post_data ' ]['post_status ' ] = 'future ' ;
555+ $ this ->incoming_post ->insert ( $ payload );
556+
557+ $ this ->assertSame ( 'draft ' , get_post_status ( $ post_id ) );
558+ }
559+
560+ /**
561+ * Test that a scheduled (future) hub post mirrors the future status on the
562+ * node when status_on_publish is 'publish'.
563+ *
564+ * When a publisher wants the node to publish in sync with the hub, the node
565+ * should mirror the 'future' status so that WP cron fires on both sites at
566+ * the same scheduled time.
567+ */
568+ public function test_future_status_with_publish_status_on_publish () {
569+ $ payload = $ this ->get_sample_payload ();
570+
571+ $ payload ['post_data ' ]['post_status ' ] = 'draft ' ;
572+ $ payload ['status_on_publish ' ] = 'publish ' ;
573+
574+ $ post_id = $ this ->incoming_post ->insert ( $ payload );
575+
576+ // Hub schedules the post. date_gmt must be in the future or WordPress
577+ // will immediately publish the post rather than storing it as 'future'.
578+ $ payload ['post_data ' ]['post_status ' ] = 'future ' ;
579+ $ payload ['post_data ' ]['date_gmt ' ] = gmdate ( 'Y-m-d H:i:s ' , strtotime ( '+1 week ' ) );
580+ $ this ->incoming_post ->insert ( $ payload );
581+
582+ // Node should mirror the hub's scheduled status so both publish together.
583+ $ this ->assertSame ( 'future ' , get_post_status ( $ post_id ) );
584+ }
585+
586+ /**
587+ * Test that a scheduled (future) hub post mirrors the future status on the
588+ * node when status_on_publish is absent from the payload.
589+ *
590+ * The sample payload includes status_on_publish by default, so it is
591+ * explicitly unset here to simulate a payload that omits the key.
592+ * The node should fall back to mirroring the hub's future status.
593+ */
594+ public function test_future_status_with_unset_status_on_publish () {
595+ $ payload = $ this ->get_sample_payload ();
596+
597+ // Remove status_on_publish to simulate a payload that omits the key.
598+ unset( $ payload ['status_on_publish ' ] );
599+
600+ $ payload ['post_data ' ]['post_status ' ] = 'draft ' ;
601+ $ post_id = $ this ->incoming_post ->insert ( $ payload );
602+
603+ // Hub schedules the post. date_gmt must be in the future or WordPress
604+ // will immediately publish the post rather than storing it as 'future'.
605+ $ payload ['post_data ' ]['post_status ' ] = 'future ' ;
606+ $ payload ['post_data ' ]['date_gmt ' ] = gmdate ( 'Y-m-d H:i:s ' , strtotime ( '+1 week ' ) );
607+ $ this ->incoming_post ->insert ( $ payload );
608+
609+ // With no status_on_publish set, the node should mirror the hub's schedule.
610+ $ this ->assertSame ( 'future ' , get_post_status ( $ post_id ) );
611+ }
612+
527613 /**
528614 * Test that "status on publish" only applies once.
529615 */
0 commit comments