hardening 2.4: 2meet-data-optimizer 1.4.0 (index-ordered routed sorts, date copy route, count invalidation) #8

Merged
wpdev merged 8 commits from hardening/2.4 into main 2026-09-27 23:40:31 +08:00
2 changed files with 60 additions and 1 deletions
Showing only changes of commit 692b23aed9 - Show all commits
@@ -176,6 +176,9 @@ final class TMDO_Entity_Migration_Engine {
// 標記完成
if ( ! $options['dry_run'] ) {
self::mark_migration_completed( $entity_type, $group_name );
if ( $stats['migrated'] > 0 ) {
self::counts_changed( $entity_type );
}
}
$stats['elapsed_sec'] = round( microtime( true ) - $start_time, 2 );
@@ -183,6 +186,19 @@ final class TMDO_Entity_Migration_Engine {
return $stats;
}
/**
* Rows rebuilt outside the Hook Bus (backfill, drift-check --fix): routed
* post counts cached for the old rows are stale (2.4 PR-129).
*
* @param string $entity_type Entity type.
* @return void
*/
private static function counts_changed( string $entity_type ): void {
if ( 'post' === $entity_type && class_exists( 'TMDO_Post_Query_Router' ) ) {
TMDO_Post_Query_Router::bump_count_version();
}
}
/**
* Rebuild one entity's row of a group from native meta.
*
@@ -194,7 +210,7 @@ final class TMDO_Entity_Migration_Engine {
if ( ! $adapter || empty( $group_fields ) ) {
return false;
}
return self::migrate_single_entity(
$migrated = self::migrate_single_entity(
$entity_type,
$group_name,
$entity_id,
@@ -203,6 +219,10 @@ final class TMDO_Entity_Migration_Engine {
$adapter,
false
);
if ( $migrated ) {
self::counts_changed( $entity_type );
}
return $migrated;
}
/**
@@ -409,6 +429,9 @@ final class TMDO_Entity_Migration_Engine {
$total = $prev_total + $batch_migrated;
$done = count( $entity_ids ) < $batch_size;
if ( $batch_migrated > 0 ) {
self::counts_changed( $entity_type );
}
if ( $done ) {
self::mark_migration_completed( $entity_type, $group_name );
+36
View File
@@ -26,6 +26,8 @@ class PostStatusSyncTest extends TestCase {
'includes/engine/class-tmdo-hook-bus.php',
'includes/engine/class-tmdo-post-status-sync.php',
'includes/engine/class-tmdo-entity-migration-engine.php',
'includes/integrations/class-tmdo-post-fields.php',
'includes/query/class-tmdo-post-query-router.php',
) as $file ) {
require_once $base . $file;
}
@@ -223,6 +225,40 @@ class PostStatusSyncTest extends TestCase {
$this->assertSame( array( 'pending', '2026-03-01 10:00:00' ), $this->copies( self::A )[3] );
}
/**
* Backfills and drift-check --fix rebuild rows outside the Hook Bus: the
* routed counts cached for the old rows must go (2.4 PR-129; dev36: a
* vendor search kept counting 21515 of 21522 matches after a fix).
*/
public function test_rebuilding_post_rows_invalidates_cached_routed_counts(): void {
global $wpdb;
$status = $wpdb->prefix . TMDO_TABLE_PREFIX . 'migration_status';
$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" );
$wpdb->query( "CREATE TABLE IF NOT EXISTS `{$status}` ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, entity_type VARCHAR(50) NOT NULL, group_name VARCHAR(50) NOT NULL, last_id BIGINT UNSIGNED NOT NULL DEFAULT 0, total_migrated BIGINT UNSIGNED NOT NULL DEFAULT 0, status VARCHAR(20) NOT NULL DEFAULT 'pending', started_at DATETIME DEFAULT NULL, completed_at DATETIME DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY entity_group (entity_type, group_name) ) ENGINE=InnoDB" );
$version = static fn() => $GLOBALS['_wp_last_changed'][ TMDO_Post_Query_Router::COUNT_VERSION_GROUP ] ?? null;
try {
$wpdb->query( "INSERT INTO `{$wpdb->postmeta}` (post_id, meta_key, meta_value) VALUES (2, 'k', 'a2-native')" );
$GLOBALS['_wp_last_changed'][ TMDO_Post_Query_Router::COUNT_VERSION_GROUP ] = 'before';
TMDO_Entity_Migration_Engine::migrate_group( 'post', 'ps_a', array( 'resume' => false, 'sleep_ms' => 0, 'dry_run' => true ) );
$this->assertSame( 'before', $version(), 'a dry run writes nothing' );
foreach ( array(
'migrate_entity' => static fn() => TMDO_Entity_Migration_Engine::migrate_entity( 'post', 'ps_a', 2 ),
'migrate_group' => static fn() => TMDO_Entity_Migration_Engine::migrate_group( 'post', 'ps_a', array( 'resume' => false, 'sleep_ms' => 0 ) ),
'migrate_group_batch' => static fn() => TMDO_Entity_Migration_Engine::migrate_group_batch( 'post', 'ps_a' ),
) as $path => $run ) {
TMDO_Entity_Migration_Engine::reset_checkpoint( 'post', 'ps_a' );
$GLOBALS['_wp_last_changed'][ TMDO_Post_Query_Router::COUNT_VERSION_GROUP ] = 'before';
$run();
$this->assertNotSame( 'before', $version(), $path );
}
} finally {
$wpdb->query( "DROP TABLE IF EXISTS `{$wpdb->postmeta}`" );
$wpdb->query( "DROP TABLE IF EXISTS `{$status}`" );
}
}
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' );