queue as $handle) { if (str_starts_with($handle, 'wp-block-')) { wp_dequeue_style($handle); wp_deregister_style($style); } } // Remove block-specific scripts and modules if (!is_admin()) { wp_deregister_script('heartbeat'); } wp_dequeue_script('wp-block-template-skip-link'); // Remove WordPress 6.5+ script modules wp_dequeue_script_module('@wordpress/interactivity'); wp_deregister_script_module('@wordpress/interactivity'); wp_dequeue_script_module('@wordpress/block-library/navigation/view'); wp_deregister_script_module('@wordpress/block-library/navigation/view'); // Remove block template skip link remove_action('wp_footer', 'the_block_template_skip_link'); // Remove third-party styles wp_deregister_style('akismet-widget-style-inline-css'); } add_action('wp_enqueue_scripts', 'jvbRemoveBlockAssets', 9999); /******************************************************************************* WORDPRESS HEAD CLEANUP *******************************************************************************/ /** * Remove unnecessary WordPress head elements * Cleans up HTML head for better performance and security */ function jvbCleanWordPressHead(): void { // Remove version info and meta tags remove_action('wp_head', 'wp_generator'); remove_action('wp_head', 'rsd_link'); remove_action('wp_head', 'wlwmanifest_link'); remove_action('wp_head', 'wp_shortlink_wp_head'); // Remove emoji support remove_action('wp_head', 'print_emoji_detection_script', 7); remove_action('wp_print_styles', 'print_emoji_styles'); // Remove REST API and oEmbed discovery links remove_action('wp_head', 'rest_output_link_wp_head'); remove_action('template_redirect', 'rest_output_link_header', 11); remove_action('wp_head', 'wp_oembed_add_discovery_links'); remove_action('wp_head', 'wp_oembed_add_host_js'); } add_action('init', 'jvbCleanWordPressHead'); /******************************************************************************* SECURITY OPTIMIZATIONS *******************************************************************************/ /** * Apply security hardening measures * Removes version info, disables XML-RPC, and hardens WordPress */ function jvbSecurityOptimizations(): void { // Hide WordPress version from scripts and styles add_filter('style_loader_src', 'jvbRemoveVersionFromUrl', 9999); add_filter('script_loader_src', 'jvbRemoveVersionFromUrl', 9999); // Disable XML-RPC (often targeted by attackers) add_filter('xmlrpc_enabled', '__return_false'); // Remove security headers that reveal info add_filter('wp_headers', 'jvbRemovePingbackHeader'); // Remove WordPress version from admin footer add_filter('update_footer', '__return_empty_string', 11); // Block user enumeration add_action('init', 'jvbBlockUserEnumeration'); add_filter('rest_endpoints', 'jvbDisableUserEndpoints'); add_filter('author_rewrite_rules', '__return_empty_array'); // Disable file editing in admin (if not already set) if (!defined('DISALLOW_FILE_EDIT')) { define('DISALLOW_FILE_EDIT', true); } // Shorten password reset expiration (15 minutes) add_filter('password_reset_expiration', function() { return 900; }); } add_action('init', 'jvbSecurityOptimizations'); /** * Remove version query strings from static assets */ function jvbRemoveVersionFromUrl(string $src): string { return strpos($src, 'ver=') ? remove_query_arg('ver', $src) : $src; } /** * Remove X-Pingback header */ function jvbRemovePingbackHeader(array $headers): array { unset($headers['X-Pingback']); return $headers; } /** * Block user enumeration attempts * Prevents discovery of usernames via URL manipulation */ function jvbBlockUserEnumeration(): void { // Block ?author queries and author archives if (!is_admin() && (isset($_GET['author']) || is_author())) { wp_redirect(home_url(), 301); exit; } } /** * Remove user endpoints from REST API * Prevents user enumeration via REST API */ function jvbDisableUserEndpoints(array $endpoints): array { $user_endpoints = [ '/wp/v2/users', '/wp/v2/users/(?P[\d]+)' ]; foreach ($user_endpoints as $endpoint) { if (isset($endpoints[$endpoint])) { unset($endpoints[$endpoint]); } } return $endpoints; } /******************************************************************************* CONTENT MANAGEMENT *******************************************************************************/ /** * Clean up attachments when posts are deleted * Automatically removes associated media to prevent orphaned files */ function jvbCleanupPostDeletion(int $post_id): void { // Delete attached media $attachments = get_attached_media('', $post_id); foreach ($attachments as $attachment) { wp_delete_attachment($attachment->ID, true); } // Delete custom meta attachments $meta_fields = [ BASE . 'image', BASE . 'gallery' ]; //TODO: Dynamically use Meta.php to get any image or gallery fields foreach ($meta_fields as $meta_key) { $meta_value = get_post_meta($post_id, $meta_key, true); if (empty($meta_value)) { continue; } // Handle comma-separated IDs $attachment_ids = str_contains($meta_value, ',') ? explode(',', $meta_value) : [$meta_value]; foreach ($attachment_ids as $attachment_id) { if (is_numeric($attachment_id)) { wp_delete_attachment((int)$attachment_id, true); } } } } add_action('before_delete_post', 'jvbCleanupPostDeletion'); /******************************************************************************* THEME CUSTOMIZATION *******************************************************************************/ /** * Clean up body classes for simpler CSS targeting * Removes WordPress defaults and adds only relevant classes */ function jvbBodyClasses(array $classes): array { // Start with empty array - only add what we need $clean_classes = []; // Add contextual classes if (is_front_page()) { $clean_classes[] = 'home'; } if (function_exists('jvbIsDirectory') && jvbIsDirectory()) { $clean_classes[] = 'is-directory'; } elseif (is_tax()) { $clean_classes[] = str_replace(BASE, '', get_queried_object()->taxonomy); } elseif (is_singular() && !is_singular('page')) { $clean_classes[] = str_replace(BASE, '', get_queried_object()->post_type); } elseif (is_post_type_archive()) { $clean_classes[] = str_replace(BASE, '', get_queried_object()->name); } return $clean_classes; } add_filter('body_class', 'jvbBodyClasses'); add_action('admin_init', function () { // Redirect any user trying to access comments page global $pagenow; if ($pagenow === 'edit-comments.php') { wp_redirect(admin_url()); exit; } // Remove comments metabox from dashboard remove_meta_box('dashboard_recent_comments', 'dashboard', 'normal'); // Disable support for comments and trackbacks in post types foreach (get_post_types() as $post_type) { if (post_type_supports($post_type, 'comments')) { remove_post_type_support($post_type, 'comments'); remove_post_type_support($post_type, 'trackbacks'); } } }); // Close comments on the front-end add_filter('comments_open', '__return_false', 20, 2); add_filter('pings_open', '__return_false', 20, 2); // Hide existing comments add_filter('comments_array', '__return_empty_array', 10, 2); // Remove comments page in menu add_action('admin_menu', function () { remove_menu_page('edit-comments.php'); }); // Remove comments links from admin bar add_action('init', function () { if (is_admin_bar_showing()) { remove_action('admin_bar_menu', 'wp_admin_bar_comments_menu', 60); } }); // Remove comments links from admin bar add_action('add_admin_bar_menus', function () { remove_action('admin_bar_menu', 'wp_admin_bar_comments_menu', 60); });