295 lines
12 KiB
PHP
295 lines
12 KiB
PHP
<?php
|
|
/**
|
|
* Theme-neutral article fixtures shared by the Zibll and AKSRT visual sites.
|
|
*
|
|
* Usage: wp eval-file /visual-fixtures/article-fixtures.php create|cleanup
|
|
*/
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
if (!defined('WP_CLI') || !WP_CLI) {
|
|
return;
|
|
}
|
|
|
|
$action = sanitize_key((string) ($args[0] ?? ''));
|
|
$manifest_key = 'zibll_article_visual_fixture_v1';
|
|
$prefix = 'zibll_article_v1_';
|
|
|
|
if (!in_array($action, ['create', 'cleanup'], true)) {
|
|
WP_CLI::error('Expected create or cleanup.');
|
|
}
|
|
|
|
$cleanup = static function (array $manifest) use ($manifest_key): void {
|
|
require_once ABSPATH . 'wp-admin/includes/user.php';
|
|
foreach (array_reverse((array) ($manifest['posts'] ?? [])) as $post_id) {
|
|
unstick_post((int) $post_id);
|
|
wp_delete_post((int) $post_id, true);
|
|
}
|
|
foreach (array_reverse((array) ($manifest['attachments'] ?? [])) as $attachment_id) {
|
|
wp_delete_attachment((int) $attachment_id, true);
|
|
}
|
|
$upload = wp_upload_dir();
|
|
$upload_root = wp_normalize_path((string) ($upload['basedir'] ?? ''));
|
|
foreach (array_reverse((array) ($manifest['files'] ?? [])) as $file) {
|
|
$file = wp_normalize_path((string) $file);
|
|
if ($upload_root !== '' && str_starts_with($file, trailingslashit($upload_root)) && is_file($file)) {
|
|
unlink($file);
|
|
}
|
|
}
|
|
foreach (array_reverse((array) ($manifest['terms'] ?? [])) as $term) {
|
|
wp_delete_term((int) $term['id'], (string) $term['taxonomy']);
|
|
}
|
|
foreach (array_reverse((array) ($manifest['users'] ?? [])) as $user_id) {
|
|
wp_delete_user((int) $user_id);
|
|
}
|
|
foreach ((array) ($manifest['options'] ?? []) as $name => $state) {
|
|
if (!empty($state['exists'])) {
|
|
update_option((string) $name, $state['value'], false);
|
|
} else {
|
|
delete_option((string) $name);
|
|
}
|
|
}
|
|
delete_option($manifest_key);
|
|
};
|
|
|
|
$existing = get_option($manifest_key, []);
|
|
if ($action === 'cleanup') {
|
|
if (!is_array($existing) || !$existing) {
|
|
WP_CLI::success('No article visual fixtures found.');
|
|
return;
|
|
}
|
|
$cleanup($existing);
|
|
WP_CLI::success('Article visual fixtures removed.');
|
|
return;
|
|
}
|
|
|
|
if (is_array($existing) && $existing) {
|
|
WP_CLI::error('Fixtures already exist. Run cleanup first.');
|
|
}
|
|
|
|
$manifest = [
|
|
'created_at' => gmdate('c'),
|
|
'users' => [],
|
|
'terms' => [],
|
|
'attachments' => [],
|
|
'posts' => [],
|
|
'files' => [],
|
|
'options' => [],
|
|
];
|
|
foreach (['aksrt_settings', 'zibll_options'] as $option_name) {
|
|
$manifest['options'][$option_name] = [
|
|
'exists' => get_option($option_name, null) !== null,
|
|
'value' => get_option($option_name),
|
|
];
|
|
}
|
|
update_option($manifest_key, $manifest, false);
|
|
|
|
try {
|
|
$visual_options = [
|
|
'list_type' => 'thumb',
|
|
'list_show_type' => 'separate',
|
|
'list_list_option' => ['style' => 'null', 'img_position' => 'left', 'scale' => 70],
|
|
'list_card_option' => ['style' => 'null', 'scale' => 70],
|
|
'post_list_author' => true,
|
|
'post_list_time' => true,
|
|
'post_time_source' => 'modified',
|
|
'list_meta_show' => 'like',
|
|
'list_badge_show' => ['pay', 'cat', 'tag'],
|
|
'list_thumb_slides_s' => true,
|
|
'list_thumb_video_s' => true,
|
|
'list_thumb_video_mute_s' => true,
|
|
'thumb_postfirstimg_s' => true,
|
|
'thumb_catimg_s' => true,
|
|
'list_thumb_fit' => '',
|
|
'paging_ajax_s' => '1',
|
|
'paging_ajax_ias_s' => true,
|
|
'ias_max' => 3,
|
|
'post_related_s' => true,
|
|
'post_related_type' => 'img',
|
|
'post_related_n' => 6,
|
|
'post_related_orderby' => 'views',
|
|
'related_title' => '相关推荐',
|
|
];
|
|
foreach (['aksrt_settings', 'zibll_options'] as $option_name) {
|
|
$current = get_option($option_name, []);
|
|
update_option($option_name, array_merge(is_array($current) ? $current : [], $visual_options), false);
|
|
}
|
|
|
|
$authors = [
|
|
['login' => $prefix . 'author_a', 'name' => '视觉作者甲'],
|
|
['login' => $prefix . 'author_b', 'name' => '视觉作者乙'],
|
|
];
|
|
$author_ids = [];
|
|
foreach ($authors as $author) {
|
|
$user_id = wp_insert_user([
|
|
'user_login' => $author['login'],
|
|
'user_pass' => 'AKSRT-Visual-2026!',
|
|
'user_email' => $author['login'] . '@example.test',
|
|
'display_name' => $author['name'],
|
|
'description' => '固定作者简介,用于文章卡片视觉对比。',
|
|
'role' => 'author',
|
|
]);
|
|
if (is_wp_error($user_id)) {
|
|
throw new RuntimeException($user_id->get_error_message());
|
|
}
|
|
$author_ids[] = (int) $user_id;
|
|
$manifest['users'][] = (int) $user_id;
|
|
}
|
|
|
|
$category = wp_insert_term('视觉文章', 'category', ['slug' => 'zibll-article-fixture']);
|
|
$tag = wp_insert_term('视觉标签', 'post_tag', ['slug' => 'zibll-visual-tag']);
|
|
if (is_wp_error($category) || is_wp_error($tag)) {
|
|
throw new RuntimeException('Unable to create article fixture terms.');
|
|
}
|
|
$category_id = (int) $category['term_id'];
|
|
$tag_id = (int) $tag['term_id'];
|
|
$manifest['terms'][] = ['id' => $category_id, 'taxonomy' => 'category'];
|
|
$manifest['terms'][] = ['id' => $tag_id, 'taxonomy' => 'post_tag'];
|
|
|
|
require_once ABSPATH . 'wp-admin/includes/image.php';
|
|
$upload = wp_upload_dir();
|
|
if (!empty($upload['error'])) {
|
|
throw new RuntimeException((string) $upload['error']);
|
|
}
|
|
$attachment_ids = [];
|
|
$colors = [
|
|
[240, 68, 148],
|
|
[58, 134, 255],
|
|
[92, 191, 147],
|
|
[255, 175, 56],
|
|
[126, 87, 194],
|
|
];
|
|
foreach ($colors as $index => $rgb) {
|
|
$filename = $prefix . 'image-' . ($index + 1) . '.jpg';
|
|
$filepath = trailingslashit($upload['path']) . $filename;
|
|
if (function_exists('imagecreatetruecolor')) {
|
|
$image = imagecreatetruecolor(1200, 800);
|
|
$background = imagecolorallocate($image, $rgb[0], $rgb[1], $rgb[2]);
|
|
$foreground = imagecolorallocate($image, 255, 255, 255);
|
|
imagefill($image, 0, 0, $background);
|
|
imagestring($image, 5, 48, 48, 'Zibll 9.0 Article Fixture ' . ($index + 1), $foreground);
|
|
imagejpeg($image, $filepath, 92);
|
|
imagedestroy($image);
|
|
} else {
|
|
$pixel = base64_decode('/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAP//////////////////////////////////////////////////////////////////////////////////////2wBDAf//////////////////////////////////////////////////////////////////////////////////////wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAX/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAEf/8QAFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQABBQJ//8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAwEBPwF//8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAgEBPwF//8QAFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQAGPwJ//8QAFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQABPyF//9oADAMBAAIAAwAAABAf/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAwEBPxB//8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAgEBPxB//8QAFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQABPxB//9k=', true);
|
|
file_put_contents($filepath, $pixel);
|
|
}
|
|
$attachment_id = wp_insert_attachment([
|
|
'post_mime_type' => 'image/jpeg',
|
|
'post_title' => '视觉图片 ' . ($index + 1),
|
|
'post_status' => 'inherit',
|
|
], $filepath);
|
|
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, $filepath));
|
|
$attachment_ids[] = $attachment_id;
|
|
$manifest['attachments'][] = $attachment_id;
|
|
}
|
|
|
|
$image_urls = array_map(static fn(int $id): string => (string) wp_get_attachment_image_url($id, 'full'), $attachment_ids);
|
|
$video_path = trailingslashit($upload['path']) . $prefix . 'fixture-video.mp4';
|
|
file_put_contents($video_path, '');
|
|
$manifest['files'][] = $video_path;
|
|
$video_url = trailingslashit($upload['url']) . basename($video_path);
|
|
$term_other = (array) get_term_meta($category_id, 'zib_other_data', true);
|
|
$term_other['cover_image'] = $image_urls[4];
|
|
update_term_meta($category_id, 'zib_other_data', $term_other);
|
|
update_term_meta($category_id, 'cover_image', $image_urls[4]);
|
|
update_term_meta($category_id, 'aksrt_category_cover_id', $attachment_ids[4]);
|
|
|
|
$scenarios = [
|
|
['slug' => 'featured', 'title' => '特色图文章:标准列表与卡片基线', 'featured' => 0],
|
|
['slug' => 'no-image', 'title' => '无图长标题文章用于检查纯文字模式与两行截断', 'no_image' => true],
|
|
['slug' => 'multi', 'title' => '多图文章:四张真实内容图片', 'featured' => 1, 'gallery' => true],
|
|
['slug' => 'external', 'title' => '自定义外链封面文章', 'external' => 2],
|
|
['slug' => 'slides', 'title' => '幻灯片封面文章', 'featured' => 3, 'slides' => true],
|
|
['slug' => 'video', 'title' => '视频悬停封面文章', 'featured' => 4, 'video' => true],
|
|
['slug' => 'paid', 'title' => '付费阅读文章价格徽章', 'featured' => 0, 'pay' => 'reading'],
|
|
['slug' => 'vip', 'title' => '会员专属文章 VIP 徽章', 'featured' => 1, 'pay' => 'vip'],
|
|
['slug' => 'first-image', 'title' => '文章首图作为缩略图', 'first_image' => 3],
|
|
];
|
|
foreach ($scenarios as $index => $scenario) {
|
|
$content = '<p>固定摘要正文,用于 Zibll 与 AKSRT 的文章列表逐像素比较。</p>';
|
|
if (!empty($scenario['gallery'])) {
|
|
$content .= implode('', array_map(static fn(string $url): string => '<img src="' . esc_url($url) . '" alt="">', array_slice($image_urls, 0, 4)));
|
|
} elseif (isset($scenario['first_image'])) {
|
|
$content .= '<img src="' . esc_url($image_urls[(int) $scenario['first_image']]) . '" alt="">';
|
|
}
|
|
$post_id = wp_insert_post([
|
|
'post_type' => 'post',
|
|
'post_status' => 'publish',
|
|
'post_author' => $author_ids[$index % 2],
|
|
'post_title' => $scenario['title'],
|
|
'post_name' => $prefix . $scenario['slug'],
|
|
'post_excerpt' => '固定文章摘要用于检查字号、行高、留白和截断。',
|
|
'post_content' => $content,
|
|
'post_date' => gmdate('Y-m-d H:i:s', strtotime('2026-07-01 08:00:00') + ($index * DAY_IN_SECONDS)),
|
|
'post_date_gmt' => gmdate('Y-m-d H:i:s', strtotime('2026-07-01 00:00:00') + ($index * DAY_IN_SECONDS)),
|
|
], true);
|
|
if (is_wp_error($post_id)) {
|
|
throw new RuntimeException($post_id->get_error_message());
|
|
}
|
|
$post_id = (int) $post_id;
|
|
$manifest['posts'][] = $post_id;
|
|
wp_set_post_terms($post_id, [$category_id], 'category');
|
|
wp_set_post_terms($post_id, [$tag_id], 'post_tag');
|
|
if (isset($scenario['featured'])) {
|
|
set_post_thumbnail($post_id, $attachment_ids[(int) $scenario['featured']]);
|
|
}
|
|
if (!empty($scenario['gallery'])) {
|
|
set_post_format($post_id, 'gallery');
|
|
}
|
|
|
|
$post_meta = [
|
|
'subtitle' => ' · 固定副标题',
|
|
];
|
|
$zib_meta = (array) get_post_meta($post_id, 'zib_other_data', true);
|
|
$zib_meta['subtitle'] = $post_meta['subtitle'];
|
|
if (isset($scenario['external'])) {
|
|
$post_meta['thumbnail_url'] = $image_urls[(int) $scenario['external']];
|
|
$zib_meta['thumbnail_url'] = $post_meta['thumbnail_url'];
|
|
}
|
|
if (!empty($scenario['slides'])) {
|
|
$post_meta['featured_slide'] = implode(',', array_slice($attachment_ids, 0, 4));
|
|
$zib_meta['featured_slide'] = $post_meta['featured_slide'];
|
|
}
|
|
if (!empty($scenario['video'])) {
|
|
$post_meta['featured_video'] = $video_url;
|
|
$zib_meta['featured_video'] = $video_url;
|
|
}
|
|
$zib_meta['views'] = 1200 + ($index * 137);
|
|
$zib_meta['like'] = 30 + ($index * 7);
|
|
update_post_meta($post_id, 'zib_other_data', $zib_meta);
|
|
update_post_meta($post_id, 'aksrt_post_meta', $post_meta);
|
|
update_post_meta($post_id, 'aksrt_post_views', $zib_meta['views']);
|
|
update_post_meta($post_id, '_aksrt_like_count', $zib_meta['like']);
|
|
update_post_meta($post_id, '_aksrt_favorite_count', 10 + $index);
|
|
|
|
$pay_type = (string) ($scenario['pay'] ?? 'no');
|
|
$pay_limit = $pay_type === 'vip' ? 2 : 0;
|
|
$pay_price = $pay_type === 'reading' ? 19.9 : 0;
|
|
update_post_meta($post_id, '_aksrt_pay', [
|
|
'pay_type' => $pay_type,
|
|
'pay_modo' => '0',
|
|
'price' => $pay_price,
|
|
'pay_limit' => $pay_limit,
|
|
]);
|
|
update_post_meta($post_id, 'posts_zibpay', [
|
|
'pay_type' => $pay_type,
|
|
'pay_modo' => '0',
|
|
'pay_price' => $pay_price,
|
|
'pay_limit' => $pay_limit,
|
|
]);
|
|
}
|
|
if ($manifest['posts']) {
|
|
stick_post((int) $manifest['posts'][0]);
|
|
}
|
|
update_option($manifest_key, $manifest, false);
|
|
WP_CLI::success('Created identical Zibll/AKSRT article fixtures.');
|
|
} catch (Throwable $error) {
|
|
$cleanup($manifest);
|
|
WP_CLI::error('Fixture creation rolled back: ' . $error->getMessage());
|
|
}
|