diff --git a/CHANGELOG.md b/CHANGELOG.md index 4769c84..730282e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,21 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## 1.4.0 (2026-06-26) - -### Fixed +## 1.5.0 (2026-06-26) -- `use_block_editor_for_post` filter was incorrectly registered as `add_action` — now uses proper `add_filter` (#19) -- Plugin deactivation never cleaned up options — `delete_option()` was wrapped in `add_action('init', ...)` which never runs during deactivation -- `update_option('default_ping_status')` and `update_option('default_comment_status')` ran on every admin page load — moved to activation hook, runs once -- `uninstall.php` now cleans up `ct-optimization` and `ct_optimization_activation_flushed` options from database - -### Performance +### Added -- Centralized option loading: new `Codetot_Optimization::get_options()` parses options once per request with static cache. Process, Gravity Forms, and Assets classes share the same instance instead of each calling `get_option()` independently -- Reduced DB queries: `get_option('ct-optimization')` called 1× per request instead of 3×+ +- **Remove query strings** (`?ver=`) from enqueued scripts and styles — improves cache hit rate on CDN and proxy caches +- **Disable self pingbacks** — prevents WordPress from sending pingbacks to your own domain +- **Disable REST API for non-authenticated users** — returns 401 for unauthenticated REST requests; keeps public endpoints intact +- **Remove default dashboard widgets** — cleans up Quick Draft, WP News, Site Health, At a Glance, Activity, and Welcome panel +- **Disable attachment pages** — 301 redirects attachment pages to parent post (or homepage if no parent) +- **Remove jQuery Migrate** — removes the jquery-migrate dependency from jquery on front-end +- **Disable native XML sitemaps** — disables WordPress 5.5+ built-in sitemaps (let SEO plugins handle it) +- **Remove front-end dashicons** — dequeues dashicons stylesheet on front-end when not used by theme -## 1.3.0 (2026-06-26) +## 1.4.0 (2026-06-26) ### Added diff --git a/README.txt b/README.txt index 4575785..fe80697 100644 --- a/README.txt +++ b/README.txt @@ -4,7 +4,7 @@ Donate link: https://codetot.com Tags: optimization, compress, settings, codetot Requires at least: 6.0 Tested up to: 6.8 -Stable tag: 1.4.0 +Stable tag: 1.5.0 Requires PHP: 8.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -78,13 +78,22 @@ Yes, if you are using our themes. == Changelog == += 1.5.0 = +* **[New]** Remove query strings (`?ver=`) from static assets for improved cache hit rate +* **[New]** Disable self pingbacks to reduce server load +* **[New]** Disable REST API for non-authenticated users (returns 401) +* **[New]** Remove default dashboard widgets (Quick Draft, WP News, etc.) +* **[New]** Disable attachment pages (301 redirect to parent post or home) +* **[New]** Remove jQuery Migrate script from front-end +* **[New]** Disable native WordPress XML sitemaps (WP 5.5+) +* **[New]** Remove dashicons styles on front-end when not used by theme + = 1.4.0 = -* **[Fix]** `use_block_editor_for_post` filter was incorrectly registered as `add_action` → now uses proper `add_filter` (B1) -* **[Fix]** Plugin deactivation never cleaned up options — `delete_option()` was wrapped in an `add_action('init', ...)` that never runs during deactivation (B2) -* **[Fix]** `update_option('default_ping_status')` and `update_option('default_comment_status')` ran on **every admin page load** → moved to activation hook, runs once (B3) -* **[Fix]** `uninstall.php` now cleans up `ct-optimization` and `ct_optimization_activation_flushed` options (B4) -* **[Perf]** Centralized option loading — `Codetot_Optimization::get_options()` parses options once per request with static cache; Process, Gravity Forms, and Assets classes share the same call instead of each calling `get_option()` independently (P1) -* **[Perf]** Reduced DB queries: `get_option('ct-optimization')` now called 1× per request instead of 3×+ +* **[Fix]** `use_block_editor_for_post` filter was incorrectly registered as `add_action` → now uses proper `add_filter` +* **[Fix]** Plugin deactivation never cleaned up options — `delete_option()` was wrapped in `add_action('init', ...)` that never runs during deactivation +* **[Fix]** `update_option()` calls for default comment/ping statuses moved from per-request admin to activation hook (runs once) +* **[Fix]** `uninstall.php` now cleans up plugin options from database +* **[Perf]** Centralized option loading — `Codetot_Optimization::get_options()` with static cache; 1 DB call per request instead of 3 = 1.3.0 = * Official PHP 8.0-8.4 support, bumped Requires PHP to 8.0 diff --git a/admin/class-codetot-optimization-admin.php b/admin/class-codetot-optimization-admin.php index 7982ff5..0293dec 100644 --- a/admin/class-codetot-optimization-admin.php +++ b/admin/class-codetot-optimization-admin.php @@ -104,7 +104,15 @@ public function get_global_keys() 'disable_feed' => __('Feed', 'codetot-optimization'), 'disable_shortlink' => __('Shortlink', 'codetot-optimization'), 'disable_wlw_manifest' => __('WLW Manifest', 'codetot-optimization'), - 'disable_inline_comment_style' => __('Inline Comment Style', 'codetot-optimization') + 'disable_inline_comment_style' => __('Inline Comment Style', 'codetot-optimization'), + 'disable_query_strings' => __('Query Strings from Assets', 'codetot-optimization'), + 'disable_self_pingbacks' => __('Self Pingbacks', 'codetot-optimization'), + 'disable_rest_api' => __('REST API (non-auth)', 'codetot-optimization'), + 'remove_dashboard_widgets' => __('Dashboard Widgets', 'codetot-optimization'), + 'disable_attachment_pages' => __('Attachment Pages', 'codetot-optimization'), + 'remove_jquery_migrate' => __('jQuery Migrate', 'codetot-optimization'), + 'disable_xml_sitemaps' => __('XML Sitemaps', 'codetot-optimization'), + 'remove_frontend_dashicons' => __('Front-end Dashicons', 'codetot-optimization'), ]; } diff --git a/codetot-optimization.php b/codetot-optimization.php index 5df5b98..cada763 100644 --- a/codetot-optimization.php +++ b/codetot-optimization.php @@ -8,7 +8,7 @@ * Plugin Name: CT Optimization * Plugin URI: https://codetot.com * Description: Provides settings for enable/disable WordPress core features and some tweaks for ACF, Gravity Forms, such like Enable CDN, Lazyload assets. - * Version: 1.4.0 + * Version: 1.5.0 * Requires at least: 6.0 * Requires PHP: 8.0 * Author: CODE TOT JSC @@ -24,7 +24,7 @@ die; } -define( 'CODETOT_OPTIMIZATION_VERSION', '1.4.0' ); +define( 'CODETOT_OPTIMIZATION_VERSION', '1.5.0' ); define( 'CODETOT_OPTIMIZATION_PATH', plugin_dir_path(__FILE__) ); define( 'CODETOT_OPTIMIZATION_URL', plugin_dir_url(__FILE__) ); diff --git a/includes/class-codetot-optimization-process.php b/includes/class-codetot-optimization-process.php index 118923d..4f3e51a 100644 --- a/includes/class-codetot-optimization-process.php +++ b/includes/class-codetot-optimization-process.php @@ -76,6 +76,17 @@ public function __construct() // Advanced Settings add_action('init', array($this, 'check_cdn')); + + // New Optimization Features + add_filter('script_loader_src', array($this, 'remove_query_strings'), 15, 1); + add_filter('style_loader_src', array($this, 'remove_query_strings'), 15, 1); + add_action('init', array($this, 'check_self_pingbacks')); + add_action('init', array($this, 'check_rest_api')); + add_action('init', array($this, 'check_dashboard_widgets')); + add_action('init', array($this, 'check_attachment_pages')); + add_action('init', array($this, 'check_jquery_migrate')); + add_action('init', array($this, 'check_xml_sitemaps')); + add_action('wp_enqueue_scripts', array($this, 'check_frontend_dashicons'), 100); } public function check_gutenberg() @@ -429,4 +440,155 @@ public function calculate_image_srcset($sources) } return $sources; } + + // ========================================================================== + // Phase 2: New Optimization Features + // ========================================================================== + + /** + * Remove query strings (?ver=) from enqueued scripts and styles. + * + * @since 1.5.0 + * @param string $src + * @return string + */ + public function remove_query_strings($src) + { + if (!empty($this->options['disable_query_strings'])) { + $src = remove_query_arg('ver', $src); + } + return $src; + } + + /** + * Disable self pingbacks. + * + * @since 1.5.0 + */ + public function check_self_pingbacks() + { + if (!empty($this->options['disable_self_pingbacks'])) { + add_action('pre_ping', function (&$links) { + $home = get_option('home'); + foreach ($links as $l => $link) { + if (strpos($link, $home) === 0) { + unset($links[$l]); + } + } + }); + } + } + + /** + * Disable REST API for non-authenticated users. + * + * @since 1.5.0 + */ + public function check_rest_api() + { + if (!empty($this->options['disable_rest_api'])) { + add_filter('rest_authentication_errors', function ($result) { + if (!empty($result)) { + return $result; + } + if (!is_user_logged_in()) { + return new WP_Error( + 'rest_not_logged_in', + __('You are not currently logged in.', 'codetot-optimization'), + array('status' => 401) + ); + } + return $result; + }); + } + } + + /** + * Remove default dashboard widgets. + * + * @since 1.5.0 + */ + public function check_dashboard_widgets() + { + if (!empty($this->options['remove_dashboard_widgets'])) { + add_action('wp_dashboard_setup', function () { + remove_meta_box('dashboard_quick_press', 'dashboard', 'side'); + remove_meta_box('dashboard_primary', 'dashboard', 'side'); + remove_meta_box('dashboard_secondary', 'dashboard', 'side'); + remove_meta_box('dashboard_site_health', 'dashboard', 'normal'); + remove_meta_box('dashboard_right_now', 'dashboard', 'normal'); + remove_meta_box('dashboard_activity', 'dashboard', 'normal'); + remove_meta_box('dashboard_incoming_links', 'dashboard', 'normal'); + remove_meta_box('dashboard_plugins', 'dashboard', 'normal'); + remove_meta_box('dashboard_recent_comments', 'dashboard', 'normal'); + remove_meta_box('dashboard_recent_drafts', 'dashboard', 'normal'); + remove_action('welcome_panel', 'wp_welcome_panel'); + }); + } + } + + /** + * Disable attachment pages — redirect to parent or home. + * + * @since 1.5.0 + */ + public function check_attachment_pages() + { + if (!empty($this->options['disable_attachment_pages'])) { + add_action('template_redirect', function () { + if (is_attachment()) { + global $post; + if ($post && $post->post_parent) { + wp_redirect(get_permalink($post->post_parent), 301); + } else { + wp_redirect(home_url(), 301); + } + exit; + } + }); + } + } + + /** + * Remove jQuery Migrate script. + * + * @since 1.5.0 + */ + public function check_jquery_migrate() + { + if (!empty($this->options['remove_jquery_migrate'])) { + add_action('wp_default_scripts', function ($scripts) { + if (!empty($scripts->registered['jquery'])) { + $jquery_deps = $scripts->registered['jquery']->deps; + $scripts->registered['jquery']->deps = array_diff($jquery_deps, array('jquery-migrate')); + } + }); + } + } + + /** + * Disable native WordPress XML sitemaps (WP 5.5+). + * + * @since 1.5.0 + */ + public function check_xml_sitemaps() + { + if (!empty($this->options['disable_xml_sitemaps'])) { + add_filter('wp_sitemaps_enabled', '__return_false'); + } + } + + /** + * Remove dashicons styles on front-end when not used by theme. + * + * @since 1.5.0 + */ + public function check_frontend_dashicons() + { + if (!empty($this->options['remove_frontend_dashicons'])) { + if (!is_admin() && !is_customize_preview()) { + wp_dequeue_style('dashicons'); + } + } + } }