$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 = '
固定摘要正文,用于 Zibll 与 AKSRT 的文章列表逐像素比较。
'; if (!empty($scenario['gallery'])) { $content .= implode('', array_map(static fn(string $url): string => '