The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Let
wp plugin uninstallremove every site's settings on multisite: treat the site-switch state as empty when WordPress has not set it yet, as under WP-CLI. - Say why an uninstall failed, with the site ID where one applies. A failure raised by other code keeps its own message and is not shown.
- During a network uninstall, pass over a site whose settings cannot be removed, clean the remaining sites, then fail with the affected site IDs. The plugin files are still retained.
- Return a non-array value from another plugin's filter callback unchanged in the resource-hint, TinyMCE and plugin-action-link callbacks, instead of stopping the page with a type error.
- Reject a domain with a malformed port, a colon without a port, or a bracketed domain name, instead of rewriting it.
- Stop three domain name patterns from matching text that ends in a line break.
- Mark only the
fonts.gstatic.compreconnect hint withcrossorigin. The hint forfonts.googleapis.comno longer carries it, so the stylesheet request can use the connection. - Confirm a save with "Settings saved." when the same save also reports rejected lines.
- Tell screen-reader users that the EngineScript link on the settings page opens in a new tab.
- Escape the translated menu and page titles of the settings page, so that a translation file cannot put markup into the admin menu.
- Let "Disable Jetpack Promotions" turn off Jetpack's Just-in-Time Messages: the plugin now adds its Jetpack filters when it loads, before Jetpack reads them.
- Reject a domain whose last label is a hexadecimal number, such as
cdn.0x1f, which browsers treat as an IP address. - Keep a network uninstall's memory use flat: clear WordPress's in-memory cache after each site, when the object cache supports it.
- Show WordPress's own translation of "Settings saved." beside a rejected-lines warning.
- Start Preconnect and DNS Prefetch lists empty and show optional, copyable domain suggestions below each field; preserve existing saved lists.
- Read on/off settings the way WordPress reads booleans: a stored or submitted string
falsenow means off. - Let
es_optimizer_normalize_stored_options()accept a stored value that is not an array and treat it as empty, instead of failing with a type error. - Reject the special-use names
altandonionin domain lists. - Raise the minimum WordPress version to 7.0, the version Jetpack requires. PHP 8.2 stays the minimum.
- Use one term, "domain", for an entry of the Preconnect and DNS Prefetch lists in the settings, the rejection reasons, and the documentation. The reasons now read "Invalid domain entry.", "No domain name found.", "Invalid domain name.", and "IP addresses and private, local, or reserved domain names are not allowed."
- "Remove WordPress Version" now also removes the generator tag from feeds, and "Remove Shortlink" also removes the shortlink HTTP response header.
- Stop adding the plugin's resource hints to the login screen.
- Write the reasons in a rejected-lines notice as separate sentences, say in words when further rejected lines are not listed, and drop the time-and-memory advice from the uninstall failure message, which now gives its reason.
- Name the GitHub issue tracker as the translation template's bug report address, in place of a WordPress.org support forum the plugin does not have.
- Deprecate
es_optimizer_clear_options_cache(). It has done nothing since WordPress took over the plugin's option caching; calling it now triggers WordPress's deprecation notice, and a later version removes it. - Write the plugin's PHP in PHP 8 forms: short arrays, an arrow function, and first-class callables. The uninstall builds its failures in one helper. Behavior is unchanged.
- Add a Rector check to CI that fails on PHP a current idiom would replace, require the short array syntax in PHPCS, override
smol-tomlandkatexfor their npm advisories (one advisory remains inbraces, which the Markdown linter uses, until a fixed release exists), and remove three issue templates that no workflow used.
- Remove the unused function
es_optimizer_resource_hint_exists(), the unused constantES_SITE_OPTIMIZER_PATH, and the unused$force_refreshparameter ofes_optimizer_get_options(). A call that passes that parameter by name now fails; a positional argument is ignored. - Remove the filter that took the emoji domain out of DNS prefetch hints, with its parser: WordPress 6.8 and later print no such hint. Remove the two activation and deactivation callbacks, which did nothing. The functions
es_optimizer_disable_emojis_remove_dns_prefetch(),es_optimizer_get_resource_hint_host(),es_optimizer_activate_plugin(), andes_optimizer_deactivate_plugin()no longer exist. - Remove the Update Translation File workflow. Generate the translation template locally with
composer make-potand commit it with each change.
- Correct native CI notice assertions, multisite bootstrap timing and post-by-email filter expectations.
- Use system executable paths in automation helpers and add regression checks for executable substitution through PATH.
- Document three resource-hint URL false positives for Plugin Check with line-specific exceptions; resource-hint behavior is unchanged.
- Correct optimizer packaging and isolate unit/native CI discovery, retaining the existing quality gates and dependency lanes.
- Limit domain-list work and retain previous values for oversize submissions; skip oversize saved lists without changing their stored text.
- Report rejected-line totals with at most three safe samples and avoid duplicate plugin warnings during repeated validation.
- Build exact resource-hint membership once per callback, preserving foreign entries without unsafe value conversions.
- Reject unsupported preconnect ports and skip legacy custom-port hints while preserving their saved text until an explicit save.
- Correct admin and embed emoji hooks, safely match equivalent DNS hint hosts, and apply reversible filters using the current site's settings.
- Use the core settings notice display, escape plain-text section and field titles, and associate textarea instructions with their controls.
- Read current-site options through WordPress caching and retain virtual defaults until a changed save.
- Preserve previous domain lists for malformed submissions and validate original URL text before normalization.
- Omit submitted URLs and credentials from localized rejection messages, with safe line-specific feedback.
- Remove the plugin option across multisite networks during uninstall, verify physical row deletion, restore site context, and stop file removal when cleanup fails.
- Split package validation and automation tests into focused functions while retaining all invalid-package cases.
- Align the WordPress Tested up to metadata at 7.1.
- Document per-site settings, domain-list limits and uninstall requirements; align contributor guidance and quality-check claims with the repository.
- Clarify settings help and Jetpack promotion labels without changing feature behavior or validation rules.
- Refresh the translation template from all production PHP, including uninstall messages, and declare the bundled language directory.
- Explain domain-list byte and line limits and show associated guidance for oversize saved lists.
- Retire the obsolete Windows Live Writer manifest setting; ignore its old key on reads and omit it on a normal save.
- Clarify HTTPS port requirements, hostname-only DNS prefetch behavior, and invalid-list save behavior in settings help.
- Restore optimizer package, analyzer and contributor-guidance targets while preserving locked dependency versions.
- Code Quality: Replaced PHP-native IP validation with WordPress native IP validation for resource hint host checks
- Bug: Removed a redundant
is_array()check ines_optimizer_disable_emojis_tinymce()after adding a strictarrayparameter type, resolving a PHPStan always-true warning on PHP 8.3 - Critical: Fixed License URI in plugin header and readme.txt pointing to GPL 2.0 instead of GPL 3.0
- Critical: Fixed release workflow producing incomplete zip files missing
languages/directory andreadme.txt - Bug: Fixed changelog parser in release workflow that could not match
## [VERSION]heading format in CHANGELOG.md, resulting in empty release bodies - Bug: Consolidated duplicate
msgidentries in POT translation file and corrected license header - Bug: Fixed CI lint step that never ran because it checked for
.phpcs.xmlorphpcs.xml.distbut the actual file isphpcs.xml - Bug: Fixed README.md license text incorrectly stating GPL-2.0+ instead of GPL-3.0-or-later
- Added
uninstall.phpto properly clean up plugin options from the database when the plugin is deleted - Added section headers ("Performance Optimizations", "Header Cleanup", "Additional Features") to the settings page for better UX
- Split the monolithic plugin file into focused files under
includes/
- Added
phpcompatibility/phpcompatibility-wptocomposer.jsonrequire-dev(required byphpcs.xmlruleset) - Added
scriptssection tocomposer.jsonwithlint:phpandanalyzecommands for CI integration
- Modernization: Added modern PHP type declarations (parameter types and return types) to all functions
- Modernization: Replaced
isset()ternaries with null coalescing operator (??) in render helpers - Code Quality: Standardized all option-checking to use
empty()with early-return pattern - Code Quality: Consolidated duplicate domain validation, rejection notice, and output functions into shared helpers (
es_optimizer_validate_domain_list(),es_optimizer_show_rejection_notice(),es_optimizer_get_validated_domains()) - Code Quality: Replaced hand-written resource hint output with the native WordPress
wp_resource_hintsfilter - Code Quality: Replaced deprecated HTML
valign="top"attribute with standard<tr>(WordPressform-tableCSS already handles alignment) - CI: Updated Node.js from EOL version 16 to LTS version 20 in continuous integration workflow
- Docs: Corrected
GEMINI.mdandreadme.txtfeature lists to only include actually implemented features (removed references to XML-RPC, REST API restriction, auto-embeds, and Gutenberg CSS) - Docs: Raised the documented WordPress baseline to 6.8+ across plugin metadata and contributor guidance
- Docs: Updated POT translation file with correct line references and added new translatable section header strings
- Tooling: Expanded
.gitignorecoverage for local instruction files, IDE settings, caches, logs, temporary files, dependencies, and distribution artifacts - Security: Removed
phpcs:ignoresuppression on resource hint output by using the native WordPress resource hint API - Security: Replaced fragile substring crossorigin detection (
fonts.g,gstatic) with exact hostname matching againstfonts.googleapis.comandfonts.gstatic.com
- BREAKING: Renamed plugin from "Simple WP Optimizer" to "EngineScript Site Optimizer" to comply with WordPress.org plugin directory naming restrictions (the term "wp" is not allowed in plugin names or slugs)
- Plugin slug changed from
simple-wp-optimizertoenginescript-site-optimizer - Text domain changed from
simple-wp-optimizertoenginescript-site-optimizer - Version constant renamed from
ES_WP_OPTIMIZER_VERSIONtoES_SITE_OPTIMIZER_VERSION - Package name changed from
Simple_WP_OptimizertoEngineScript_Site_Optimizer - Admin menu label changed from "WP Optimizer" to "Site Optimizer"
- Renamed 11 globally-scoped functions to use the
es_optimizer_prefix to prevent naming collisions with other plugins (disable_emojis,remove_jquery_migrate,disable_classic_theme_styles,remove_header_items,remove_recent_comments_style,add_preconnect,add_dns_prefetch,disable_jetpack_ads,disable_post_via_email,disable_emojis_tinymce,disable_emojis_remove_dns_prefetch) es_optimizer_get_options()now accepts an optional$force_refreshparameter so the static cache can be properly invalidatedes_optimizer_add_settings_page()page title and menu title are now wrapped in__()for correct translation- Settings page heading, description, and submit button value are now translatable
- All functions that previously called
get_option( 'es_optimizer_options' )directly now use thees_optimizer_get_options()caching wrapper for consistency - Render function callers now pass
__()instead ofesc_html__()to avoid double-escaping; the render functions themselves handle escaping at output - Removed redundant custom
wp_nonce_field()and its bypassable verification from the settings form; CSRF protection is already handled by WordPress Settings API viasettings_fields()
- Security: Moved
esc_textarea()escaping to the point of output for textarea values, preventing a potential XSS vector - Code Quality: Refactored textarea rendering to place PHP open/close tags on their own lines, resolving Codacy best-practice warnings
- Critical: Fixed whitespace embedded inside form field
nameattributes (checkbox and textarea) that prevented settings from ever being saved;$_POST['es_optimizer_options']was never set because browsers sent the literal newlines/tabs as part of the field name - Critical: Fixed inverted IP-validation logic in
es_optimizer_validate_single_domain()that caused every domain name (e.g.fonts.googleapis.com) to be incorrectly rejected when saving preconnect/DNS-prefetch settings - Critical: Fixed
es_optimizer_clear_options_cache()which created an independent closure-scoped static variable and therefore never cleared the cache insidees_optimizer_get_options() - Fixed textarea content containing leading whitespace (newlines/tabs between
<textarea>tag and PHP output) - Fixed missing
esc_url()andesc_html__()escaping on the Settings link rendered in the Plugins list - Removed unreachable dead code (
if ( ! is_admin() ) { return; }) insidees_optimizer_add_settings_page(), which is only ever called from theadmin_menuhook
- Added new option to remove RSD (Really Simple Discovery) link from WordPress header
- NEW FEATURE: Added separate DNS Prefetch option alongside Preconnect for better resource hint control
- DNS-prefetch performs lighter-weight DNS-only lookups for less critical domains
- Preconnect performs full connection setup (DNS + TCP + TLS) for critical domains
- Clear UI explanations help users understand when to use each option
- Added preconnect domains:
https://s.w.org,https://wordpress.com,https://cdnjs.cloudflare.com, andhttps://www.googletagmanager.com - Added DNS prefetch domain:
https://adservice.google.com
- PERFORMANCE UPGRADE: Changed from DNS-prefetch to Preconnect for better performance
- Preconnect establishes full connection (DNS + TCP + TLS) vs dns-prefetch which only does DNS lookup
- Adds
crossoriginattribute for font domains (required for CORS requests) - Improves Largest Contentful Paint (LCP) and First Contentful Paint (FCP) metrics
- Updated default preconnect domains to remove deprecated Google CDN URLs (
ajax.googleapis.comandapis.google.com) - All optimization options are now disabled by default for better user control
- Improved preconnect textarea display to eliminate extra whitespace on first line
- Fixed WordPress coding standards compliance: PHP opening and closing tags now on separate lines
- Fixed indentation in textarea rendering function (3 tabs instead of 4)
- Major Plugin Architecture Refactor: Completely restructured plugin initialization to use the WordPress
plugins_loadedhook - Improved plugin load order by removing immediate global scope execution
- Consolidated plugin initialization into proper WordPress lifecycle management
- Moved all
add_actionandadd_filtercalls into structured initialization functions - Enhanced plugin activation, deactivation, and uninstall lifecycle management
- Removed unused
es_optimizer_enqueue_admin_scripts()function (dead code removal) - Cleaned up scattered global scope function calls
- Fixed inline comment punctuation to comply with WordPress coding standards
- Improved code organization and readability
- Enhanced plugin stability and compatibility with other WordPress plugins
- Performance Optimization: Implemented conditional admin asset loading - admin scripts and styles now only load on the plugin settings page
- Option Caching System: Added
es_optimizer_get_options()function with static caching to reduce database queries throughout the plugin - DNS Prefetch Security Enhancement: Enhanced DNS prefetch validation to reject file paths, query parameters, and fragments - only clean domains are now accepted
- Documentation Enhancement: Added @since version tags to all PHPDoc blocks for better change tracking
- Developer Guidelines: Created comprehensive CONTRIBUTING.md file with development standards, security requirements, and contribution workflow
- DNS Prefetch Optimization: Improved DNS prefetch function with static caching, duplicate removal, AJAX detection, and enhanced domain validation
- Security Validation: Strengthened DNS prefetch domain validation to prevent file path injection (e.g.,
https://google.com/file.phpis now rejected) - User Experience: Updated DNS prefetch textarea description to clearly explain that only clean domains are allowed
- Code Quality: Enhanced function documentation and maintained WordPress coding standards compliance
- Testing Infrastructure: Complete test suite with fixtures, helpers, and comprehensive coverage reporting
- Domain Validation: Enhanced DNS prefetch security to block file paths, query parameters, and URL fragments
- Input Sanitization: Maintained comprehensive input validation and output escaping throughout all changes
- Clean Domain Output: DNS prefetch now automatically strips paths and returns only clean domain URLs for security
- Security Testing: Comprehensive security validation tests including XSS prevention and malicious input handling
- Reduced Database Queries: Option caching system minimizes repeated database calls
- Conditional Loading: Admin assets only load when needed, reducing unnecessary resource usage
- Optimized DNS Prefetch: Enhanced processing efficiency with static caching and validation improvements
- Testing Framework: PHPUnit with WP_Mock for WordPress-specific testing
- Code Coverage: 80% minimum coverage requirement with detailed reporting
- Quality Assurance: PHPCS, PHPMD, and PHPStan integration for code quality
- Development Workflow: Automated testing with GitHub Actions CI/CD pipeline
- Disable Post via Email: New option to disable the post-via-email feature for enhanced security and performance.
- Hardened Disabling Filters: Updated all feature-disabling filters to use
PHP_INT_MAXpriority, ensuring they cannot be overridden by other plugins or themes.
- WordPress Coding Standards: Converted all code to use spaces instead of tabs for indentation
- Code Style: Fixed file comment header to use "/**" style instead of "/*" style
- Code Style: Added proper spacing around operators (e.g.,
! definedinstead of!defined) - Code Style: Added proper full stops to inline comments for consistency
- Code Style: Removed trailing whitespace from documentation blocks
- Variable Naming: Converted variable names to use snake_case instead of camelCase for WordPress compliance
- Function Formatting: Improved function parameter spacing and alignment
- Array Formatting: Enhanced array formatting with proper alignment and trailing commas
- Updated changelog and version references across documentation files for new release
- Synced CHANGELOG.md and readme.txt as per project standards
- No code changes in this release; documentation and changelog only
- Requirements: Updated minimum WordPress version requirement to 6.5+ across all files for modern WordPress compatibility
- Internationalization: Created languages/simple-wp-optimizer.pot file for translation support
- Documentation: Updated all version references to reflect new WordPress 6.5+ minimum requirement
- Workflow: Updated GitHub Actions workflow compatibility testing from WordPress 6.0 to 6.5
- Compliance: Enhanced project structure compliance with copilot coding standards and documentation guidelines
- Enhanced code organization with single responsibility principle implementation
- Dedicated DNS domain validation functions for improved maintainability
- Proper translator comments for all internationalization strings with placeholders
- Additional sanitization layer for nonce verification using sanitize_text_field()
- WordPress Plugin Check Compliance: Resolved all WordPress.org compatibility issues
- Variable Naming: Implemented camelCase convention for all variables (nonceValue, domainsInput, etc.)
- Function Complexity: Reduced cyclomatic complexity by extracting validation logic into separate functions
- Code Standards: Fixed $_POST data handling with proper WordPress sanitization practices
- i18n Compliance: Added missing translator comments for sprintf() placeholders
- Documentation: Updated upgrade notice character limits to meet WordPress.org requirements
- Improved code architecture with es_optimizer_validate_single_domain() function
- Better error handling with es_optimizer_show_domain_rejection_notice() function
- Enhanced maintainability through function separation and reduced complexity
- Cleaner code structure following WordPress coding standards
- Optimized function organization for better testing and debugging
- Enhanced Nonce Handling: Additional sanitization layer for CSRF protection
- Improved Input Validation: Strengthened domain validation with dedicated functions
- WordPress Standards: Full compliance with WordPress security best practices
- WordPress nonce protection for CSRF security in settings forms
- Enhanced DNS prefetch security with HTTPS-only domain enforcement
- Private IP and localhost blocking for DNS prefetch domains to prevent SSRF attacks
- Comprehensive domain validation with multi-layer security checks
- User-friendly error messages for rejected domains with proper HTML escaping
- Security event notifications for administrators when domains are rejected
- Strengthened form security with wp_nonce_field() and wp_verify_nonce() implementation
- Improved DNS prefetch domain validation with parse_url() and enhanced filtering
- Enhanced error handling with proper WordPress admin notices and escaping
- Updated help text to clearly indicate HTTPS requirement for DNS prefetch domains
- Better user experience with informative security-related error messages
- Comprehensive input validation preventing malicious domain submissions
- CSRF Protection: Added WordPress nonce verification for all form submissions
- HTTPS Enforcement: DNS prefetch domains now require HTTPS protocol for security
- SSRF Prevention: Blocked private IP ranges and localhost addresses in DNS prefetch
- Input Validation: Enhanced multi-layer validation for all user-submitted domains
- Output Escaping: Improved HTML escaping for all error messages and user feedback
- Attack Surface Reduction: Eliminated potential vectors for security exploitation
- Resolved potential XSS vulnerability in error message display by adding proper HTML escaping
- Fixed domain validation to prevent bypass of security checks
- Improved error message construction to prevent information disclosure
- Enhanced GitHub Actions workflows for comprehensive plugin testing and security analysis
- PHPStan WordPress static analysis with proper WordPress stubs configuration
- WordPress Vulnerability Scanner integration for security testing
- Comprehensive WordPress security scanning using pattern analysis
- Composer support with WordPress stubs for better development experience
- PHPStan WordPress extension (szepeviktor/phpstan-wordpress) for enhanced analysis
- Comprehensive security implementation documentation following OWASP guidelines
- Detailed security implementation notes in plugin header
- Enhanced input validation with strict type checking for all user inputs
- Improved output escaping with context-appropriate WordPress functions (esc_html, esc_attr, esc_url, esc_textarea)
- Proper capability checks for all admin functions using current_user_can('manage_options')
- Secure coding patterns throughout the plugin codebase
- Multi-layer domain validation for DNS prefetch functionality
- Comprehensive code documentation with security explanations
- Fixed register_setting() function to use proper array parameters instead of string callback
- Corrected remove_action() function calls to use proper parameter count (removed invalid 4th parameter)
- Replaced non-existent wp_print_link_tag() function with proper HTML output using esc_url()
- Fixed "unreachable statement" in disable_emojis_tinymce() function by restructuring logic
- Resolved all PHPStan static analysis errors at level 5
- Fixed WordPress Plugin Check compatibility issues
- Fixed potential security vulnerabilities with proper WordPress best practices
- Updated plugin to pass PHPStan level 5 analysis with zero errors
- Improved workflow reliability by removing problematic external dependencies
- Enhanced security scanning with WordPress-specific vulnerability patterns
- Better WordPress API compliance and coding standards
- Improved code quality and maintainability
- Security headers and implementation comments for better code understanding
- DNS prefetch domain validation with enhanced security measures
- Settings validation and sanitization functions
- Code structure and organization for better maintainability
- Direct script access prevention with proper WordPress checks
- Enhanced all user input validation and output escaping
- Added security-focused code comments explaining safety measures
- Implemented OWASP-compliant security patterns throughout the codebase
- WordPress 6.8 compatibility
- WordPress Plugin Check workflow for code quality verification
- Automated GitHub issue creation for test failures
- Changed text domain from 'simple-wp-optimizer-enginescript' to 'simple-wp-optimizer' to comply with WordPress.org standards
- Updated all internationalization function calls with the correct text domain
- Added missing text domain parameter in translation functions
- Fixed issue template formatting for automated GitHub issue creation
- Made the plugin fully compatible with the WordPress Plugin Check tool
- Enhanced plugin repo compatibility
- Improved documentation and code comments
- Updated plugin name to "EngineScript: Simple WP Optimization"
- Improved code documentation and security notes
- Aligned version numbers in plugin header and constant definition
- Enhanced security implementation with detailed documentation
- Added PHPCS ignore comments with security explanations
- Improved validation for DNS prefetch domains
- Fixed potential security issues with escaped outputs
- Fixed DNS prefetch implementation for better performance
- Added Jetpack Blaze disabling feature
- Improved function documentation with security notes
- Enhanced settings page with better organization
- Updated WordPress compatibility to 6.5
- Improved code organization
- Enhanced settings validation
- Added option to disable Jetpack advertisements and promotions
- Implemented settings link in plugins page
- Refactored settings page rendering for better security
- Updated text domain for better translation support
- Enhanced DNS prefetching with better security measures
- Added proper input validation for domain entries
- Fixed escaping in DNS prefetch output
- Improved error handling for invalid domains
- Added DNS prefetching for common external domains
- Added textarea input for custom DNS prefetch domains
- Implemented domain validation and sanitization
- Improved settings organization with grouped options
- Enhanced option descriptions
- Option to disable classic theme styles (added in WordPress 6.1+)
- Improved header cleanup options
- Enhanced security for settings page
- Better user capability checks
- Option to remove recent comments widget inline CSS
- Option to remove shortlinks from WordPress header
- Improved settings validation
- Better code organization
- Option to remove WLW manifest
- Option to remove WordPress version from header
- Comprehensive settings page with checkboxes
- Switched to WordPress Settings API
- Better organization of options
- Initial release
- Option to disable WordPress emojis
- Option to remove jQuery Migrate
- Basic settings page
- Default options