yith-brand-migrator/wp-cli-migrate-brands.php

301 lines
9.7 KiB
PHP
Raw Normal View History

2025-10-21 14:48:11 +08:00
<?php
/**
* WP-CLI 品牌迁移命令
*
* 使用方法:
* wp eval-file wp-cli-migrate-brands.php
*
* 或者添加参数:
* wp eval-file wp-cli-migrate-brands.php --dry-run=true # 预览模式
* wp eval-file wp-cli-migrate-brands.php --cleanup=true # 迁移后清理旧数据
*/
if (!defined('WP_CLI') || !WP_CLI) {
die('此脚本只能通过 WP-CLI 运行');
}
class WPCLIBrandsMigrator {
private $old_taxonomy = 'yith_product_brand';
private $new_taxonomy = 'product_brand';
private $dry_run = false;
private $cleanup = false;
public function __construct() {
global $argv;
$this->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();