dry_run = in_array('--dry-run=true', $argv); $this->cleanup = in_array('--cleanup=true', $argv); if ($this->dry_run) { WP_CLI::line('🔍 预览模式:将显示迁移计划但不执行实际操作'); } $this->run(); } private function run() { WP_CLI::line('开始 YITH 品牌迁移...'); if (!$this->check_requirements()) { return; } $brands = $this->get_yith_brands(); if (empty($brands)) { WP_CLI::warning('未找到 YITH 品牌数据'); return; } WP_CLI::line(sprintf('找到 %d 个品牌需要迁移', count($brands))); if ($this->dry_run) { $this->preview_migration($brands); } else { $this->execute_migration($brands); } } private function check_requirements() { if (!class_exists('WooCommerce')) { WP_CLI::error('WooCommerce 插件未激活'); return false; } if (!taxonomy_exists($this->old_taxonomy)) { WP_CLI::error('YITH 品牌分类法不存在'); return false; } if (!taxonomy_exists($this->new_taxonomy)) { WP_CLI::line('注册 WooCommerce 原生品牌分类法...'); $this->register_product_brand_taxonomy(); } return true; } private function register_product_brand_taxonomy() { $labels = [ 'name' => '品牌', 'singular_name' => '品牌', 'menu_name' => '品牌', 'all_items' => '所有品牌', 'edit_item' => '编辑品牌', 'view_item' => '查看品牌', 'update_item' => '更新品牌', 'add_new_item' => '添加新品牌', 'new_item_name' => '新品牌名称', 'search_items' => '搜索品牌', 'popular_items' => '热门品牌', 'not_found' => '未找到品牌', ]; $args = [ 'labels' => $labels, 'public' => true, 'show_ui' => true, 'show_in_menu' => true, 'show_in_nav_menus' => true, 'show_tagcloud' => true, 'show_in_quick_edit' => true, 'show_admin_column' => true, 'hierarchical' => true, 'query_var' => true, 'rewrite' => ['slug' => 'product-brand', 'with_front' => false], 'show_in_rest' => true, ]; register_taxonomy($this->new_taxonomy, ['product'], $args); WP_CLI::success('品牌分类法注册成功'); } private function get_yith_brands() { return get_terms([ 'taxonomy' => $this->old_taxonomy, 'hide_empty' => false, 'number' => 0, ]); } private function preview_migration($brands) { WP_CLI::line(''); WP_CLI::line('📋 迁移预览:'); WP_CLI::line(''); $table_data = []; foreach ($brands as $brand) { $product_count = $this->get_brand_product_count($brand->term_id); $existing_brand = get_term_by('slug', $brand->slug, $this->new_taxonomy); $action = $existing_brand ? '更新' : '创建'; $table_data[] = [ 'ID' => $brand->term_id, '品牌名称' => $brand->name, '别名' => $brand->slug, '产品数量' => $product_count, '操作' => $action, ]; } WP_CLI\Utils\format_items('table', $table_data, ['ID', '品牌名称', '别名', '产品数量', '操作']); WP_CLI::line(''); WP_CLI::line('要执行实际迁移,请运行:'); WP_CLI::line('wp eval-file wp-cli-migrate-brands.php'); } private function execute_migration($brands) { $progress = WP_CLI\Utils\make_progress_bar('迁移品牌', count($brands)); $migrated_count = 0; $errors = []; foreach ($brands as $brand) { try { $this->migrate_single_brand($brand); $migrated_count++; } catch (Exception $e) { $errors[] = sprintf('品牌 "%s" 迁移失败:%s', $brand->name, $e->getMessage()); } $progress->tick(); } $progress->finish(); WP_CLI::line(''); WP_CLI::success(sprintf('成功迁移 %d 个品牌', $migrated_count)); if (!empty($errors)) { WP_CLI::warning('以下品牌迁移时出现错误:'); foreach ($errors as $error) { WP_CLI::line(' - ' . $error); } } if ($this->cleanup) { $this->cleanup_old_data(); } else { WP_CLI::line(''); WP_CLI::line('要清理旧数据,请运行:'); WP_CLI::line('wp eval-file wp-cli-migrate-brands.php --cleanup=true'); } wp_cache_flush(); } private function migrate_single_brand($old_term) { $existing_term = get_term_by('slug', $old_term->slug, $this->new_taxonomy); if ($existing_term) { $new_term_id = $existing_term->term_id; wp_update_term($new_term_id, $this->new_taxonomy, [ 'name' => $old_term->name, 'description' => $old_term->description, ]); } else { $result = wp_insert_term( $old_term->name, $this->new_taxonomy, [ 'slug' => $old_term->slug, 'description' => $old_term->description, ] ); if (is_wp_error($result)) { throw new Exception($result->get_error_message()); } $new_term_id = $result['term_id']; } $this->migrate_term_meta($old_term->term_id, $new_term_id); $this->migrate_product_relationships($old_term->term_id, $new_term_id); } private function migrate_term_meta($old_term_id, $new_term_id) { $meta_keys = [ 'thumbnail_id', 'brand_logo', 'brand_banner', 'brand_url', 'brand_email', 'brand_description', 'yith_wcbr_brand_logo', 'yith_wcbr_brand_banner', 'yith_wcbr_brand_url', 'yith_wcbr_brand_email', ]; foreach ($meta_keys as $meta_key) { $meta_value = get_term_meta($old_term_id, $meta_key, true); if (!empty($meta_value)) { update_term_meta($new_term_id, $meta_key, $meta_value); } } } private function migrate_product_relationships($old_term_id, $new_term_id) { global $wpdb; $products = $wpdb->get_col($wpdb->prepare(" SELECT object_id FROM {$wpdb->term_relationships} tr INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.term_id = %d AND tt.taxonomy = %s ", $old_term_id, $this->old_taxonomy)); foreach ($products as $product_id) { wp_set_object_terms($product_id, [$new_term_id], $this->new_taxonomy, false); } } private function get_brand_product_count($term_id) { global $wpdb; return $wpdb->get_var($wpdb->prepare(" SELECT COUNT(object_id) FROM {$wpdb->term_relationships} tr INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.term_id = %d AND tt.taxonomy = %s ", $term_id, $this->old_taxonomy)); } private function cleanup_old_data() { WP_CLI::line(''); WP_CLI::confirm('确定要删除 YITH 品牌的旧数据吗?此操作不可逆!'); global $wpdb; $term_taxonomy_ids = $wpdb->get_col($wpdb->prepare(" SELECT term_taxonomy_id FROM {$wpdb->term_taxonomy} WHERE taxonomy = %s ", $this->old_taxonomy)); if (!empty($term_taxonomy_ids)) { $placeholders = implode(',', array_fill(0, count($term_taxonomy_ids), '%d')); $relationships_deleted = $wpdb->query($wpdb->prepare(" DELETE FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ($placeholders) ", ...$term_taxonomy_ids)); $taxonomy_deleted = $wpdb->query($wpdb->prepare(" DELETE FROM {$wpdb->term_taxonomy} WHERE taxonomy = %s ", $this->old_taxonomy)); WP_CLI::success(sprintf('清理完成:删除了 %d 个关系记录和 %d 个分类法记录', $relationships_deleted, $taxonomy_deleted)); } wp_cache_flush(); } } new WPCLIBrandsMigrator();