301 lines
9.7 KiB
PHP
301 lines
9.7 KiB
PHP
|
|
<?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();
|