true, 'remove_emoji' => true, 'remove_open_sans' => true, 'remove_more_wp_head' => true, 'remove_dashboard_widgets' => true, 'display_wp_update' => true, 'split_upload_s' => true, 'split_minimum_size' => 20, 'newfilename' => false, 'newfilename_type' => 'time', 'disabled_large_thumbnail' => true, 'admin_user_del_fields' => true, 'admin_frontend_set' => true, 'close_gutenberg' => false, 'disabled_autoembed' => true, 'mce_float_toolbar' => ['pc_s', 'm_s'], 'time_ago_s' => true, 'time_format' => 'n月j日 H:i', ]; foreach ($expected as $key => $value) { system_tools_check(array_key_exists($key, $defaults), "system tools setting missing: {$key}"); system_tools_check($defaults[$key] === $value, "system tools default wrong for {$key}"); } // 2) Stored values sanitize: rename type whitelist, switch coercion, passthrough format. $GLOBALS['aksrt_system_settings'] = [ 'newfilename_type' => 'bogus', 'newfilename' => 1, 'time_ago_s' => 0, 'time_format' => 'Y/m/d H:i', 'close_gutenberg' => 'yes', 'split_minimum_size' => 500, 'mce_float_toolbar' => ['m_s', 'bogus', 'm_s'], ]; $clean = ExtensionRuntime::get_system_tools_settings(); system_tools_check($clean['newfilename_type'] === 'time', 'bogus rename type should fall back to time'); system_tools_check($clean['newfilename'] === true, 'truthy rename switch should coerce to true'); system_tools_check($clean['time_ago_s'] === false, 'falsy time_ago_s should coerce to false'); system_tools_check($clean['time_format'] === 'Y/m/d H:i', 'time format should pass through'); system_tools_check($clean['close_gutenberg'] === true, 'truthy gutenberg switch should coerce to true'); system_tools_check($clean['split_minimum_size'] === 100, 'split minimum size should clamp to the 4..100 range'); system_tools_check($clean['mce_float_toolbar'] === ['m_s'], 'float toolbar scenes should whitelist and dedupe'); // 2b) Unsaved float toolbar key keeps the both-scenes default; explicit empty stays empty. $GLOBALS['aksrt_system_settings'] = ['hide_admin_bar' => 0]; $clean = ExtensionRuntime::get_system_tools_settings(); system_tools_check($clean['mce_float_toolbar'] === ['pc_s', 'm_s'], 'float toolbar should default to pc+mobile'); system_tools_check($clean['hide_admin_bar'] === false, 'stored falsy value should not fall back to default'); $GLOBALS['aksrt_system_settings'] = ['mce_float_toolbar' => []]; $clean = ExtensionRuntime::get_system_tools_settings(); system_tools_check($clean['mce_float_toolbar'] === [], 'explicitly empty float toolbar should stay empty'); // 3) Hook wiring with every switch enabled. $GLOBALS['aksrt_system_settings'] = array_fill_keys(array_keys($expected), true); $GLOBALS['aksrt_system_settings']['time_format'] = 'n月j日 H:i'; $GLOBALS['aksrt_system_is_super_admin'] = false; system_tools_reset(); SystemTools::get_instance()->init(); system_tools_check(system_tools_added('filter', 'show_admin_bar'), 'hide_admin_bar should gate show_admin_bar'); system_tools_check(system_tools_added('action', 'init'), 'remove_open_sans should hook init'); system_tools_check(system_tools_added('action', 'after_setup_theme'), 'head cleanup and thumbnail pruning should hook after_setup_theme'); system_tools_check(system_tools_added('action', 'do_meta_boxes'), 'dashboard widget removal should hook do_meta_boxes'); system_tools_check(system_tools_added('filter', 'site_status_tests'), 'site status tests should be filtered'); system_tools_check(system_tools_added('filter', 'pre_http_request'), 'site health http requests should be blocked'); system_tools_check(system_tools_added('action', 'admin_menu'), 'update notices should hook admin_menu'); system_tools_check(system_tools_added('filter', 'automatic_updater_disabled'), 'automatic updates should be disabled'); system_tools_check(system_tools_added('filter', 'use_block_editor_for_post'), 'close_gutenberg should gate the block editor'); system_tools_check(system_tools_added('action', 'show_user_profile'), 'user profile cleanup should hook show_user_profile'); system_tools_check(system_tools_added('action', 'edit_user_profile'), 'user profile cleanup should hook edit_user_profile'); system_tools_check(system_tools_removed('action', 'admin_print_scripts', 'print_emoji_detection_script'), 'emoji scripts should be removed'); system_tools_check(system_tools_removed('filter', 'the_content', 'autoembed'), 'auto embed should be removed from the_content'); system_tools_check(system_tools_removed('action', 'admin_init', '_maybe_update_core'), 'core update checks should be removed'); system_tools_check(system_tools_removed('action', 'init', 'wp_schedule_update_checks'), 'update cron schedule should be removed'); // 4) hide_admin_bar off keeps the admin bar for super admins. $GLOBALS['aksrt_system_settings']['hide_admin_bar'] = false; $GLOBALS['aksrt_system_is_super_admin'] = true; system_tools_reset(); SystemTools::get_instance()->init(); system_tools_check(!system_tools_added('filter', 'show_admin_bar'), 'super admin should keep the admin bar when hide_admin_bar is off'); // 5) Dashboard widget removal edits the dashboard meta boxes only in the normal context. $tools = SystemTools::get_instance(); $GLOBALS['wp_meta_boxes'] = [ 'dashboard' => [ 'normal' => [ 'high' => ['dashboard_php_nag' => ['id' => 'dashboard_php_nag']], 'core' => ['dashboard_site_health' => ['id' => 'dashboard_site_health']], ], 'side' => [ 'core' => ['dashboard_primary' => ['id' => 'dashboard_primary']], ], ], ]; $tools->remove_dashboard_widgets('dashboard', 'normal'); system_tools_check(!isset($GLOBALS['wp_meta_boxes']['dashboard']['normal']['high']['dashboard_php_nag']), 'php nag widget should be removed'); system_tools_check(!isset($GLOBALS['wp_meta_boxes']['dashboard']['normal']['core']['dashboard_site_health']), 'site health widget should be removed'); system_tools_check(!isset($GLOBALS['wp_meta_boxes']['dashboard']['side']['core']['dashboard_primary']), 'primary widget should be removed'); $GLOBALS['wp_meta_boxes']['dashboard']['side']['core']['dashboard_primary'] = ['id' => 'dashboard_primary']; $tools->remove_dashboard_widgets('dashboard', 'side'); system_tools_check(isset($GLOBALS['wp_meta_boxes']['dashboard']['side']['core']['dashboard_primary']), 'non-normal context should be ignored'); // 6) Site status tests drop page cache and php version probes. $tests = $tools->filter_site_status_tests([ 'async' => ['page_cache' => [], 'dilation' => []], 'direct' => ['php_version' => [], 'updates' => []], ]); system_tools_check(!isset($tests['async']['page_cache']) && isset($tests['async']['dilation']), 'page_cache test should be dropped'); system_tools_check(!isset($tests['direct']['php_version']) && isset($tests['direct']['updates']), 'php_version test should be dropped'); // 7) Health endpoint blocking is scoped to version/browser/credits checks. $blocked = $tools->block_site_health_requests(null, [], 'https://api.wordpress.org/core/serve-happy/1.0/'); system_tools_check(is_array($blocked) && $blocked['body'] === '', 'serve-happy requests should be blocked'); $blocked = $tools->block_site_health_requests(null, [], 'https://api.wordpress.org/core/browse-happy/1.0/'); system_tools_check(is_array($blocked) && $blocked['body'] === '', 'browse-happy requests should be blocked'); $passed = $tools->block_site_health_requests('passthrough', [], 'https://api.wordpress.org/plugins/update-check/1.0/'); system_tools_check($passed === 'passthrough', 'update checks should pass through the blocker'); // 8) Large thumbnail pruning removes the reference theme's size list. $GLOBALS['aksrt_system_added'] = []; $tools->disable_large_thumbnail(); $sizes_filter = null; foreach ($GLOBALS['aksrt_system_added'] as $row) { if ($row[0] === 'filter' && $row[1] === 'intermediate_image_sizes') { $sizes_filter = $row[2]; } } system_tools_check(is_callable($sizes_filter), 'intermediate_image_sizes filter should be registered'); system_tools_check($sizes_filter(['medium_large', '1536x1536', '2048x2048', 'thumbnail']) === ['thumbnail'], 'medium_large/1536x1536/2048x2048 should be pruned'); // 9) Schema registry exposes the 系统工具 page with all fields. $sections = SchemaExtensions::build()['sections']; system_tools_check(isset($sections['system']) && $sections['system']['title'] === '系统工具', 'system section should register under extensions'); $keys = []; foreach ($sections['system']['groups'] as $group) { foreach ($group['fields'] as $field) { $keys[] = $field['key']; } } system_tools_check(count($keys) === count(array_unique($keys)), 'system schema field keys must be unique'); foreach (array_keys($expected) as $key) { system_tools_check(in_array($key, $keys, true), "system schema missing field {$key}"); } $client_defaults = array_keys($expected); system_tools_check(count(SchemaExtensionsSystem::build()['groups']) === 3, 'system schema should keep three groups'); // 10) aksrt_time_ago honors the 倒计时显示 switch and custom format. $past = date('Y-m-d H:i:s', strtotime('-3 days')); $GLOBALS['aksrt_system_settings'] = []; system_tools_check(strpos(aksrt_time_ago($past), '天前') !== false, 'relative time should be used by default'); $GLOBALS['aksrt_system_settings'] = ['time_ago_s' => 0, 'time_format' => 'Y年n月j日']; $stamp = strtotime('-3 days'); system_tools_check(aksrt_time_ago(date('Y-m-d H:i:s', $stamp)) === date('Y年n月j日', $stamp), 'custom time format should apply when countdown display is off'); $GLOBALS['aksrt_system_settings'] = ['time_ago_s' => 0, 'time_format' => '']; system_tools_check(strpos(aksrt_time_ago($past), '天前') !== false, 'empty custom format should fall back to relative time'); $GLOBALS['aksrt_system_settings'] = ['time_ago_s' => 1]; system_tools_check(strpos(aksrt_time_ago($past), '天前') !== false, 'countdown display should stay relative when enabled'); echo "System tools harness passed\n"; }