diff --git a/includes/engine/class-tmdo-entity-migration-engine.php b/includes/engine/class-tmdo-entity-migration-engine.php index 72855f1..39cb1a9 100644 --- a/includes/engine/class-tmdo-entity-migration-engine.php +++ b/includes/engine/class-tmdo-entity-migration-engine.php @@ -278,6 +278,15 @@ final class TMDO_Entity_Migration_Engine { } } + // REPLACE drops columns it is not given: keep a post row's status/date + // copies, or one NULL row turns the copy route off for the group (2.4 PR-127). + if ( 'post' === $entity_type && class_exists( 'TMDO_Post_Status_Sync' ) ) { + foreach ( TMDO_Post_Status_Sync::insert_columns( $entity_id, $group_name ) as $col => $value ) { + $data[ $col ] = $value; + $formats[] = '%s'; + } + } + if ( $dry_run ) { return true; } diff --git a/tests/integration/PostStatusSyncTest.php b/tests/integration/PostStatusSyncTest.php index 21654bb..bd72132 100644 --- a/tests/integration/PostStatusSyncTest.php +++ b/tests/integration/PostStatusSyncTest.php @@ -25,6 +25,7 @@ class PostStatusSyncTest extends TestCase { 'includes/adapters/class-tmdo-adapter-post.php', 'includes/engine/class-tmdo-hook-bus.php', 'includes/engine/class-tmdo-post-status-sync.php', + 'includes/engine/class-tmdo-entity-migration-engine.php', ) as $file ) { require_once $base . $file; } @@ -173,6 +174,30 @@ class PostStatusSyncTest extends TestCase { $this->assertNotContains( 'post_status', $wpdb->get_col( 'SHOW COLUMNS FROM `' . self::A . '`' ) ); } + /** + * The migration engine (backfill, drift-check --fix) REPLACEs whole rows: + * without the copies, a rebuilt row had NULL post_status, which turns the + * status/date copy route off for the whole group (2.4 PR-127). + */ + public function test_a_row_rebuilt_from_native_keeps_its_copies(): void { + global $wpdb; + TMDO_Post_Status_Sync::run(); + $GLOBALS['_wp_posts'][2] = (object) array( 'ID' => 2, 'post_type' => 'hp_listing', 'post_status' => 'draft', 'post_date' => '2026-02-01 10:00:00' ); + $GLOBALS['_wp_posts'][3] = (object) array( 'ID' => 3, 'post_type' => 'hp_listing', 'post_status' => 'pending', 'post_date' => '2026-03-01 10:00:00' ); + $wpdb->query( "CREATE TABLE IF NOT EXISTS `{$wpdb->postmeta}` ( meta_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, post_id BIGINT UNSIGNED NOT NULL DEFAULT 0, meta_key VARCHAR(255) DEFAULT NULL, meta_value LONGTEXT, PRIMARY KEY (meta_id) ) ENGINE=InnoDB" ); + try { + $wpdb->query( "INSERT INTO `{$wpdb->postmeta}` (post_id, meta_key, meta_value) VALUES (2, 'k', 'a2-native'), (3, 'k', 'a3-native')" ); + + WPDO_Entity_Migration_Engine::migrate_entity( 'post', 'ps_a', 2 ); // Existing row. + WPDO_Entity_Migration_Engine::migrate_entity( 'post', 'ps_a', 3 ); // New row. + } finally { + $wpdb->query( "DROP TABLE IF EXISTS `{$wpdb->postmeta}`" ); + } + + $this->assertSame( array( 'draft', '2026-02-01 10:00:00' ), $this->copies( self::A )[2] ); + $this->assertSame( array( 'pending', '2026-03-01 10:00:00' ), $this->copies( self::A )[3] ); + } + public function test_flat_write_that_creates_a_row_fills_the_copies(): void { TMDO_Post_Status_Sync::run(); $mode = new ReflectionProperty( WPDO_Mode_Manager::class, 'cache' );