refactor(2meet-data-optimizer): stop registering the wc_product post group

- WooCommerce reads product meta directly and writes stock by SQL, so a flat copy drifted (R-2.1 V1 T4); product meta now stays in native only (plan decision 2). TMDO_Post_Fields registers wp_core, attachment and nav_menu_item. Existing wp_wpdo_post_wc_product tables are left in place and still dropped on uninstall; the orphan restore registers nothing for them while native meta holds the keys; `wp tmdo bridge-restore-native post --group=wc_product --retire` archives them.
- Tests that route products register the former group themselves (tmdo_test_register_wc_product_group(), same name and table); live router Q06 runs on wp_core's _wp_page_template instead of _sku. The post stress tester already skips flat tables that do not exist.
- Verify: PostFieldsRegistrationTest (RED before); dev36: wc_product absent from the registry and not restored as an orphan, a CLI order took stock 452 → 450 in native with no DB error (reverted), drift post 10 groups 0.
- PR: PR-077
This commit is contained in:
2026-09-27 01:11:52 +08:00
parent f15473527c
commit f48df1a33f
12 changed files with 68 additions and 174 deletions
+1 -1
View File
@@ -55,7 +55,7 @@ final class TMDO_Post_Shadow_Verifier {
* is available.
*
* @param string $post_type WP post_type to sample.
* @param string $group_name Entity group name (e.g. 'wc_product').
* @param string $group_name Entity group name (e.g. 'hp_listing_core').
* @param string $flat_table Fully qualified flat table name.
* @param string[] $keys Meta keys to compare (each post checks all).
* @param int $sample_size Number of posts to sample (capped to DB count).
@@ -2,19 +2,18 @@
/**
* Post entity field registration for WP Data Optimizer (v2.9.1).
*
* Registers four post entity groups designed to absorb the bulk of
* Registers three post entity groups designed to absorb the bulk of
* wp_postmeta rows that previously bypassed any flat-table strategy.
* All groups use TMDO_Entity_Registry → flat tables instead of wp_postmeta EAV.
*
* Groups → flat tables (post_type targets):
* wp_core → wp_wpdo_post_wp_core (cross post_type)
* attachment → wp_wpdo_post_attachment (attachment)
* wc_product → wp_wpdo_post_wc_product (product)
* nav_menu_item → wp_wpdo_post_nav_menu_item (nav_menu_item)
*
* Pattern mirrors TMDO_Member_Fields::register(). Called from
* TMDO_Core::run() before the wpdo_register_entity_fields action fires;
* Schema_Manager materializes the four flat tables in init:1
* Schema_Manager materializes the three flat tables in init:1
* via process_pending_migrations() (idempotent via schema_hash compare).
*
* Keys not registered here (HivePress dynamic attrs, WPCS legacy keys,
@@ -39,7 +38,10 @@ if ( ! defined( 'ABSPATH' ) ) {
}
/**
* Registers four post entity groups.
* Registers three post entity groups. WooCommerce product meta is not one of
* them (1.2.0): WooCommerce reads it directly and writes stock by SQL, so
* native meta stays its only copy. Existing wp_wpdo_post_wc_product tables
* are left alone (see `wp tmdo bridge-restore-native post --group=wc_product --retire`).
*/
final class TMDO_Post_Fields {
@@ -49,7 +51,6 @@ final class TMDO_Post_Fields {
*/
private const GROUP_POST_TYPES = array(
'attachment' => 'attachment',
'wc_product' => 'product',
'nav_menu_item' => 'nav_menu_item',
);
@@ -104,7 +105,6 @@ final class TMDO_Post_Fields {
self::register_wp_core_group();
self::register_attachment_group();
self::register_wc_product_group();
self::register_nav_menu_item_group();
}
@@ -176,131 +176,6 @@ final class TMDO_Post_Fields {
);
}
/**
* WooCommerce product core meta keys (post_type=product).
* 19 keys — covers ~94% of wp_postmeta rows for products on dev10.
*
* @return void
*/
private static function register_wc_product_group(): void {
TMDO_Entity_Registry::register_group(
'post',
'wc_product',
array(
array(
'key' => '_price',
'type' => 'decimal',
'searchable' => true,
'label' => 'Effective price',
),
array(
'key' => '_regular_price',
'type' => 'decimal',
'searchable' => true,
'label' => 'Regular price',
),
array(
'key' => '_sale_price',
'type' => 'decimal',
'searchable' => true,
'label' => 'Sale price',
),
array(
'key' => '_stock',
'type' => 'integer',
'searchable' => true,
'label' => 'Stock quantity',
),
array(
'key' => '_stock_status',
'type' => 'enum',
'searchable' => true,
'options' => array( 'instock', 'outofstock', 'onbackorder' ),
'label' => 'Stock status',
),
array(
'key' => '_sku',
'type' => 'text',
'searchable' => true,
'label' => 'Product SKU',
),
array(
'key' => '_manage_stock',
'type' => 'enum',
'options' => array( 'yes', 'no' ),
'label' => 'Manage stock?',
),
array(
'key' => '_backorders',
'type' => 'enum',
'options' => array( 'yes', 'no', 'notify' ),
'label' => 'Allow backorders?',
),
array(
'key' => '_sold_individually',
'type' => 'enum',
'options' => array( 'yes', 'no' ),
'label' => 'Sold individually?',
),
array(
'key' => '_virtual',
'type' => 'enum',
'options' => array( 'yes', 'no' ),
'label' => 'Virtual product?',
),
array(
'key' => '_downloadable',
'type' => 'enum',
'options' => array( 'yes', 'no' ),
'label' => 'Downloadable?',
),
array(
'key' => '_tax_class',
'type' => 'text',
'label' => 'Tax class slug',
),
array(
'key' => '_tax_status',
'type' => 'enum',
'options' => array( 'taxable', 'shipping', 'none' ),
'label' => 'Tax status',
),
array(
'key' => '_download_limit',
'type' => 'integer',
'label' => 'Download limit',
),
array(
'key' => '_download_expiry',
'type' => 'integer',
'label' => 'Download expiry days',
),
array(
'key' => '_product_version',
'type' => 'text',
'label' => 'WC version product was created on',
),
array(
'key' => '_wc_average_rating',
'type' => 'decimal',
'searchable' => true,
'label' => 'Average rating',
),
array(
'key' => '_wc_review_count',
'type' => 'integer',
'label' => 'Review count',
),
array(
'key' => 'total_sales',
'type' => 'integer',
'searchable' => true,
'label' => 'Total sales count',
),
)
);
}
/**
* Nav menu item meta keys (post_type=nav_menu_item).
*
@@ -102,7 +102,7 @@ final class TMDO_Post_Migration {
* 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').
* @param string $group_name Entity group name (e.g. 'hp_listing_core').
* @return array{migrated:int,group:string,post_type:string|null}
* @throws InvalidArgumentException When group is not registered, or is a restored orphan group.
* @throws RuntimeException When the pivot SQL fails.