feat(2meet-data-optimizer): backfill every registered user group with member-backfill --all

- member-backfill / member-audit take their groups from the registry (TMDO_Entity_Migration_Engine::backfillable_groups(), restored orphans excluded) instead of a hard-coded list that still named the never-registered `sso`; `--all` backfills every user group (R-2.1 had to use wp eval). TMDO_Post_Migration::backfillable_groups() now delegates to it.
- member-cutover checks the Mode_Manager result with is_wp_error(): a guarded or invalid transition used to crash with a fatal (WP_Error used as an array).
- Verify: CliMemberBackfillTest (--all and the orphan filter RED before; the --group case cannot fail under the non-throwing WP_CLI stub); dev36 `member-backfill --all --reset` 9 groups, 0 errors, checker user miss/diff/extra 0; `member-cutover --confirm` exits 1 with the Guard message, mode unchanged.
- PR: PR-068
This commit is contained in:
2026-09-26 23:30:28 +08:00
parent 7807eae957
commit 2022cf1d08
4 changed files with 132 additions and 34 deletions
+29 -27
View File
@@ -35,24 +35,6 @@ if ( ! class_exists( 'WP_CLI' ) ) {
*/
class TMDO_CLI_Member {
/**
* Valid group names managed by this CLI.
*
* V2.7.0: Extended with core_profile/social/commerce/hp_user to absorb
* the legacy WP/WC/HP wp_usermeta keys.
*/
private const VALID_GROUPS = array(
'membership',
'activity',
'profile',
'sso',
'core_profile',
'social',
'commerce',
'hp_user',
'admin_prefs',
);
// ── member-audit ─────────────────────────────────────────────────────────
/**
@@ -73,7 +55,7 @@ class TMDO_CLI_Member {
WP_CLI::log( '' );
$items = array();
foreach ( self::VALID_GROUPS as $group ) {
foreach ( TMDO_Entity_Registry::get_groups_for_type( 'user' ) as $group ) {
$table = $wpdb->prefix . 'wpdo_user_' . $group;
$exists = (bool) $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->prepare( 'SHOW TABLES LIKE %s', $table )
@@ -111,7 +93,7 @@ class TMDO_CLI_Member {
// ── member-backfill ───────────────────────────────────────────────────────
/**
* Backfill wp_usermeta rows into the specified user flat-table group.
* Backfill wp_usermeta rows into one user flat-table group, or all of them.
*
* Uses TMDO_Entity_Migration_Engine::migrate_group() — cursor-based,
* 500 rows/batch, checkpoint stored in wpdo_migration_status.
@@ -119,7 +101,10 @@ class TMDO_CLI_Member {
* ## OPTIONS
*
* [--group=<group>]
* : Which group to backfill: membership, activity, profile, sso. Default: membership.
* : Registered user group to backfill (e.g. membership, activity, core_profile). Default: membership.
*
* [--all]
* : Backfill every registered user group (restored orphan groups excluded).
*
* [--batch-size=<n>]
* : Rows per batch (default 500, max 2000).
@@ -134,21 +119,38 @@ class TMDO_CLI_Member {
*
* wp wpdo member-backfill --group=membership --dry-run
* wp wpdo member-backfill --group=membership
* wp wpdo member-backfill --group=sso --reset
* wp wpdo member-backfill --all
*
* @param array $args Positional arguments.
* @param array $assoc_args Named arguments.
*/
public function member_backfill( $args, $assoc_args ): void {
$group = (string) ( $assoc_args['group'] ?? 'membership' );
$batch_size = min( 2000, max( 1, (int) ( $assoc_args['batch-size'] ?? 500 ) ) );
$dry_run = isset( $assoc_args['dry-run'] );
$reset = isset( $assoc_args['reset'] );
$valid = TMDO_Entity_Migration_Engine::backfillable_groups( 'user' );
if ( ! in_array( $group, self::VALID_GROUPS, true ) ) {
WP_CLI::error( 'Invalid --group. Choose: ' . implode( ', ', self::VALID_GROUPS ) );
if ( isset( $assoc_args['all'] ) ) {
if ( isset( $assoc_args['group'] ) ) {
WP_CLI::error( 'Use either --group or --all, not both.' );
}
$groups = $valid;
} else {
$groups = array( (string) ( $assoc_args['group'] ?? 'membership' ) );
if ( ! in_array( $groups[0], $valid, true ) ) {
WP_CLI::error( 'Invalid --group. Choose: ' . implode( ', ', $valid ) );
}
}
foreach ( $groups as $group ) {
$this->backfill_group( $group, $batch_size, $dry_run, $reset );
}
}
/**
* Backfill one user group and report the result.
*/
private function backfill_group( string $group, int $batch_size, bool $dry_run, bool $reset ): void {
if ( $reset ) {
TMDO_Entity_Migration_Engine::reset_checkpoint( 'user', $group );
WP_CLI::log( "Checkpoint cleared for user/{$group}." );
@@ -298,8 +300,8 @@ class TMDO_CLI_Member {
$result = TMDO_Mode_Manager::set( 'user', 'aeav_only' );
if ( isset( $result['error'] ) ) {
WP_CLI::error( 'Cutover failed: ' . $result['error'] );
if ( is_wp_error( $result ) ) {
WP_CLI::error( 'Cutover failed: ' . $result->get_error_message() );
}
WP_CLI::success( 'User bridge mode set to aeav_only. All user meta reads/writes now go through flat tables.' );