refactor(2meet-data-optimizer): list post groups for backfill from the registry

- Admin "backfill all" and `wp tmdo post-migrate-group` take any registered post group via TMDO_Post_Migration::backfillable_groups() instead of a hard-coded list of 7 (dev36 registers 11; the 4 HP add-on groups were never backfilled). Restored orphan groups are excluded and rejected — their values live only in the flat table.
- Groups with json fields (attachment, nav_menu_item) go row by row through the migration engine instead of leaving the json columns NULL in the bulk pivot.
- Verify: PostBackfillJsonTest (3 RED on hardening/2.2); dev36 post-migrate-group attachment / nav_menu_item / hp_draft_flags: json columns semantically equal native (24/24, 21/21), checker unchanged.
- PR: PR-067
This commit is contained in:
2026-09-26 22:54:27 +08:00
parent 13ea341ef8
commit 7807eae957
4 changed files with 82 additions and 25 deletions
@@ -99,11 +99,12 @@ final class TMDO_Post_Migration {
/**
* Bulk SQL pivot for one group: select managed keys from wp_postmeta,
* filter by post_type, pivot via MAX(CASE) GROUP BY post_id, UPSERT
* into the group's flat table.
* into the group's flat table. Groups with json fields go row by row
* through backfill_group_json() instead.
*
* @param string $group_name Entity group name (e.g. 'wc_product').
* @return array{migrated:int,group:string,post_type:string|null}
* @throws InvalidArgumentException When group is not registered.
* @throws InvalidArgumentException When group is not registered, or is a restored orphan group.
* @throws RuntimeException When the pivot SQL fails.
*/
public static function backfill_group( string $group_name ): array {
@@ -115,8 +116,30 @@ final class TMDO_Post_Migration {
'Unknown post entity group: ' . esc_html( $group_name )
);
}
if ( ! in_array( $group_name, self::backfillable_groups(), true ) ) {
throw new InvalidArgumentException(
'Orphan post group, its values live only in the flat table: ' . esc_html( $group_name )
);
}
$post_type = self::group_post_type( $group_name );
// json values need PHP-level unserialize → json encode, which the bulk
// pivot below cannot do: backfill such groups row by row instead.
if ( in_array( 'json', array_column( $fields, 'type' ), true ) ) {
$result = self::backfill_group_json( $group_name, array( 'resume' => false ) );
if ( ! empty( $result['error'] ) || ! empty( $result['errors'] ) ) {
throw new RuntimeException(
'backfill_group failed for ' . esc_html( $group_name ) . ': ' . esc_html( (string) ( $result['error'] ?? $result['errors'] . ' row error(s)' ) )
);
}
return array(
'migrated' => (int) $result['migrated'],
'group' => $group_name,
'post_type' => $post_type,
);
}
$post_type = self::group_post_type( $group_name );
$flat_table = TMDO_Schema_Manager::get_table_name( self::ENTITY_TYPE, $group_name );
// Introspect target table columns so we only pivot fields that actually
@@ -131,16 +154,10 @@ final class TMDO_Post_Migration {
}
// Build column list and CASE expressions.
// Skip json/textarea types from the bulk pivot — those need row-by-row
// unserialize handling (deferred to v2.9.4 backfill_unserialize phase).
$columns = array();
$cases = array();
$update_parts = array();
foreach ( $fields as $field ) {
$type = $field['type'] ?? 'text';
if ( 'json' === $type ) {
continue;
}
$col = TMDO_Schema_Manager::sanitize_column_name( $field['key'] );
if ( ! isset( $existing_cols[ $col ] ) ) {
continue; // Column not present in this table — skip silently.
@@ -536,6 +553,23 @@ final class TMDO_Post_Migration {
// Helpers
// ─────────────────────────────────────────────────────────────────────────
/**
* Registered post groups that can be backfilled from wp_postmeta. Orphan
* groups restored from wpdo_registry_meta are left out: their values live
* only in the flat table.
*
* @return string[]
*/
public static function backfillable_groups(): array {
$orphans = array();
foreach ( TMDO_Entity_Registry::get_restored_groups() as $restored ) {
if ( self::ENTITY_TYPE === $restored['entity_type'] ) {
$orphans[] = $restored['group'];
}
}
return array_values( array_diff( TMDO_Entity_Registry::get_groups_for_type( self::ENTITY_TYPE ), $orphans ) );
}
/**
* All meta_keys registered for any post entity group.
*