256 lines
9.2 KiB
PHP
256 lines
9.2 KiB
PHP
<?php
|
|
/**
|
|
* Reversible WP-CLI visual fixtures for AKSRT/Zibll comparison.
|
|
*
|
|
* Usage:
|
|
* wp eval-file wp-content/themes/AKSRT-theme/tools/wp-cli-visual-fixtures.php create
|
|
* wp eval-file wp-content/themes/AKSRT-theme/tools/wp-cli-visual-fixtures.php cleanup
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
if (!defined('WP_CLI') || !WP_CLI) {
|
|
return;
|
|
}
|
|
|
|
$fixture_action = sanitize_key((string) ($args[0] ?? ''));
|
|
$fixture_option = 'aksrt_visual_fixture_manifest_v1';
|
|
$fixture_prefix = 'aksrt_zibll_v1_';
|
|
$fixture_theme_dir = dirname(__DIR__);
|
|
$fixture_json = $fixture_theme_dir . '/tests/fixtures/widget-golden-v1.json';
|
|
|
|
if (!in_array($fixture_action, ['create', 'cleanup'], true)) {
|
|
WP_CLI::error('Expected create or cleanup.');
|
|
}
|
|
|
|
$cleanup = static function (array $manifest) use ($fixture_option): void {
|
|
$sidebars = wp_get_sidebars_widgets();
|
|
foreach ((array) ($manifest['widgets'] ?? []) as $widget) {
|
|
$id_base = sanitize_key((string) ($widget['id_base'] ?? ''));
|
|
$number = (int) ($widget['number'] ?? 0);
|
|
if ($id_base === '' || $number <= 0) {
|
|
continue;
|
|
}
|
|
$widget_id = $id_base . '-' . $number;
|
|
foreach ($sidebars as $area => $ids) {
|
|
if (!is_array($ids)) {
|
|
continue;
|
|
}
|
|
$sidebars[$area] = array_values(array_diff($ids, [$widget_id]));
|
|
}
|
|
$option_name = 'widget_' . $id_base;
|
|
$instances = get_option($option_name, []);
|
|
if (is_array($instances) && array_key_exists($number, $instances)) {
|
|
unset($instances[$number]);
|
|
update_option($option_name, $instances, false);
|
|
}
|
|
}
|
|
wp_set_sidebars_widgets($sidebars);
|
|
|
|
foreach (array_reverse((array) ($manifest['comments'] ?? [])) as $id) {
|
|
wp_delete_comment((int) $id, true);
|
|
}
|
|
foreach (array_reverse((array) ($manifest['posts'] ?? [])) as $id) {
|
|
wp_delete_post((int) $id, true);
|
|
}
|
|
foreach (array_reverse((array) ($manifest['attachments'] ?? [])) as $id) {
|
|
wp_delete_attachment((int) $id, true);
|
|
}
|
|
foreach (array_reverse((array) ($manifest['users'] ?? [])) as $id) {
|
|
if (function_exists('wp_delete_user')) {
|
|
wp_delete_user((int) $id);
|
|
}
|
|
}
|
|
foreach (array_reverse((array) ($manifest['terms'] ?? [])) as $term) {
|
|
wp_delete_term((int) ($term['id'] ?? 0), (string) ($term['taxonomy'] ?? 'category'));
|
|
}
|
|
delete_option($fixture_option);
|
|
};
|
|
|
|
$existing = get_option($fixture_option, []);
|
|
if ($fixture_action === 'cleanup') {
|
|
if (!is_array($existing) || empty($existing)) {
|
|
WP_CLI::success('No AKSRT visual fixtures found.');
|
|
return;
|
|
}
|
|
$cleanup($existing);
|
|
WP_CLI::success('AKSRT visual fixtures removed.');
|
|
return;
|
|
}
|
|
|
|
if (is_array($existing) && !empty($existing)) {
|
|
WP_CLI::error('Fixtures already exist. Run cleanup first.');
|
|
}
|
|
if (!is_file($fixture_json)) {
|
|
WP_CLI::error('Golden fixture JSON is missing.');
|
|
}
|
|
|
|
$golden = json_decode((string) file_get_contents($fixture_json), true);
|
|
if (!is_array($golden)) {
|
|
WP_CLI::error('Golden fixture JSON is invalid.');
|
|
}
|
|
|
|
$manifest = [
|
|
'prefix' => $fixture_prefix,
|
|
'created_at' => gmdate('c'),
|
|
'terms' => [],
|
|
'users' => [],
|
|
'attachments' => [],
|
|
'posts' => [],
|
|
'comments' => [],
|
|
'widgets' => [],
|
|
];
|
|
update_option($fixture_option, $manifest, false);
|
|
|
|
try {
|
|
$term_map = [];
|
|
foreach ((array) ($golden['dataset']['terms'] ?? []) as $source) {
|
|
$taxonomy = (string) ($source['taxonomy'] ?? 'category');
|
|
$result = wp_insert_term(
|
|
(string) ($source['name'] ?? 'Fixture'),
|
|
$taxonomy,
|
|
['slug' => $fixture_prefix . (int) ($source['id'] ?? 0)]
|
|
);
|
|
if (is_wp_error($result)) {
|
|
throw new RuntimeException($result->get_error_message());
|
|
}
|
|
$term_id = (int) $result['term_id'];
|
|
$term_map[(int) $source['id']] = $term_id;
|
|
$manifest['terms'][] = ['id' => $term_id, 'taxonomy' => $taxonomy];
|
|
}
|
|
|
|
$user_map = [];
|
|
foreach ((array) ($golden['dataset']['users'] ?? []) as $index => $source) {
|
|
$login = $fixture_prefix . 'user_' . ((int) $index + 1);
|
|
$user_id = wp_insert_user([
|
|
'user_login' => $login,
|
|
'user_pass' => 'AKSRT-Visual-2026!',
|
|
'user_email' => $login . '@example.test',
|
|
'display_name' => (string) ($source['name'] ?? $login),
|
|
'role' => 'subscriber',
|
|
]);
|
|
if (is_wp_error($user_id)) {
|
|
throw new RuntimeException($user_id->get_error_message());
|
|
}
|
|
$user_id = (int) $user_id;
|
|
$user_map[(int) ($source['id'] ?? 0)] = $user_id;
|
|
$manifest['users'][] = $user_id;
|
|
update_user_meta($user_id, 'aksrt_points', (int) ($source['points'] ?? 0));
|
|
if ($index === 0) {
|
|
update_user_meta($user_id, 'aksrt_vip_level', 2);
|
|
update_user_meta($user_id, 'aksrt_vip_expires', time() + YEAR_IN_SECONDS);
|
|
}
|
|
}
|
|
|
|
require_once ABSPATH . 'wp-admin/includes/image.php';
|
|
$media_sources = [
|
|
$fixture_theme_dir . '/assets/img/slider-bg.jpg',
|
|
$fixture_theme_dir . '/assets/img/user_t.jpg',
|
|
$fixture_theme_dir . '/assets/img/user-level-7.png',
|
|
];
|
|
foreach ($media_sources as $source_path) {
|
|
if (!is_file($source_path)) {
|
|
continue;
|
|
}
|
|
$upload = wp_upload_dir();
|
|
$filename = wp_unique_filename($upload['path'], $fixture_prefix . basename($source_path));
|
|
$target = trailingslashit($upload['path']) . $filename;
|
|
if (!copy($source_path, $target)) {
|
|
throw new RuntimeException('Unable to copy fixture media.');
|
|
}
|
|
$attachment_id = wp_insert_attachment([
|
|
'post_mime_type' => wp_check_filetype($target)['type'],
|
|
'post_title' => $fixture_prefix . pathinfo($filename, PATHINFO_FILENAME),
|
|
'post_status' => 'inherit',
|
|
], $target);
|
|
if (is_wp_error($attachment_id)) {
|
|
throw new RuntimeException($attachment_id->get_error_message());
|
|
}
|
|
$attachment_id = (int) $attachment_id;
|
|
wp_update_attachment_metadata($attachment_id, wp_generate_attachment_metadata($attachment_id, $target));
|
|
$manifest['attachments'][] = $attachment_id;
|
|
}
|
|
|
|
$post_map = [];
|
|
foreach ((array) ($golden['dataset']['posts'] ?? []) as $index => $source) {
|
|
$post_id = wp_insert_post([
|
|
'post_title' => $fixture_prefix . (string) ($source['title'] ?? 'Fixture post'),
|
|
'post_name' => $fixture_prefix . (int) ($source['id'] ?? $index),
|
|
'post_status' => 'publish',
|
|
'post_type' => 'post',
|
|
'post_author' => (int) ($user_map[(int) ($source['author'] ?? 0)] ?? 1),
|
|
'post_excerpt' => '用于 AKSRT 与 Zibll 同内容视觉比较的固定摘要。',
|
|
'post_content' => '<h2>视觉基线标题</h2><p>固定正文内容,用于检查排版、目录、付费状态和响应式布局。</p>',
|
|
], true);
|
|
if (is_wp_error($post_id)) {
|
|
throw new RuntimeException($post_id->get_error_message());
|
|
}
|
|
$post_id = (int) $post_id;
|
|
$post_map[(int) ($source['id'] ?? 0)] = $post_id;
|
|
$manifest['posts'][] = $post_id;
|
|
$category_id = (int) ($term_map[(int) ($source['category'] ?? 0)] ?? 0);
|
|
if ($category_id > 0) {
|
|
wp_set_post_terms($post_id, [$category_id], 'category');
|
|
}
|
|
if (!empty($manifest['attachments'])) {
|
|
set_post_thumbnail($post_id, (int) $manifest['attachments'][$index % count($manifest['attachments'])]);
|
|
}
|
|
$pay_type = sanitize_key((string) ($source['pay_type'] ?? 'no'));
|
|
$pay = class_exists('AKSRT\\Core\\DomainModel') ? \AKSRT\Core\DomainModel::default_pay_meta() : [];
|
|
$pay['pay_type'] = $pay_type;
|
|
$pay['price'] = $pay_type === 'no' ? 0 : 19.9 + $index;
|
|
$pay['pay_limit'] = $pay_type === 'vip' ? 1 : 0;
|
|
update_post_meta($post_id, '_aksrt_pay', $pay);
|
|
update_post_meta($post_id, '_aksrt_pay_type', $pay_type);
|
|
update_post_meta($post_id, '_aksrt_pay_price', $pay['price']);
|
|
update_post_meta($post_id, 'aksrt_post_views', 1200 + ($index * 137));
|
|
}
|
|
|
|
$no_image = wp_insert_post([
|
|
'post_title' => $fixture_prefix . '无图长标题文章用于检查纯文字模式和两行截断行为',
|
|
'post_name' => $fixture_prefix . 'no-image',
|
|
'post_status' => 'publish',
|
|
'post_type' => 'post',
|
|
'post_content' => '<p>无缩略图场景。</p>',
|
|
], true);
|
|
if (!is_wp_error($no_image)) {
|
|
$manifest['posts'][] = (int) $no_image;
|
|
}
|
|
if (!empty($manifest['posts'])) {
|
|
stick_post((int) $manifest['posts'][0]);
|
|
}
|
|
|
|
$components = (array) ($golden['components'] ?? []);
|
|
$sidebars = wp_get_sidebars_widgets();
|
|
$sidebars['home_top_content'] = is_array($sidebars['home_top_content'] ?? null) ? $sidebars['home_top_content'] : [];
|
|
$sidebars['home_sidebar'] = is_array($sidebars['home_sidebar'] ?? null) ? $sidebars['home_sidebar'] : [];
|
|
$number = 9100;
|
|
foreach ($components as $slug => $component) {
|
|
$id_base = sanitize_key((string) ($component['id_base'] ?? ''));
|
|
if ($id_base === '') {
|
|
continue;
|
|
}
|
|
$number++;
|
|
$settings = (array) ($component['settings'] ?? []);
|
|
$settings['title'] = $fixture_prefix . (string) ($settings['title'] ?? $slug);
|
|
$option_name = 'widget_' . $id_base;
|
|
$instances = get_option($option_name, []);
|
|
$instances = is_array($instances) ? $instances : [];
|
|
$instances[$number] = $settings;
|
|
$instances['_multiwidget'] = 1;
|
|
update_option($option_name, $instances, false);
|
|
$widget_id = $id_base . '-' . $number;
|
|
$area = (($component['size'] ?? '') === 'sidebar') ? 'home_sidebar' : 'home_top_content';
|
|
$sidebars[$area][] = $widget_id;
|
|
$manifest['widgets'][] = ['id_base' => $id_base, 'number' => $number, 'area' => $area];
|
|
}
|
|
wp_set_sidebars_widgets($sidebars);
|
|
update_option($fixture_option, $manifest, false);
|
|
WP_CLI::success('Created reversible AKSRT visual fixtures. Login password: AKSRT-Visual-2026!');
|
|
} catch (Throwable $error) {
|
|
$cleanup($manifest);
|
|
WP_CLI::error('Fixture creation rolled back: ' . $error->getMessage());
|
|
}
|