From c874ec5a7f3b4b0b0f2279391e726164ea242627 Mon Sep 17 00:00:00 2001 From: Mehul Gohil Date: Mon, 25 May 2026 17:03:37 +0530 Subject: [PATCH] Fix 1.6.0 Plugin Check blockers --- languages/perform.pot | 346 ++++++++++++++---------- readme.txt | 4 +- src/Admin/Actions.php | 6 +- src/Admin/Filters.php | 9 +- src/Admin/Settings/Api.php | 31 ++- src/Admin/Settings/Menu.php | 9 +- src/Includes/Actions.php | 5 + src/Includes/Helpers.php | 388 ++++++++++++++------------- src/Modules/Assets/AssetsManager.php | 94 ++++--- src/Modules/CDN/CDNManager.php | 10 +- src/Modules/Cache/PageCache.php | 7 +- src/Modules/Loader.php | 104 ++++--- src/Modules/SSL/SSLManager.php | 4 +- src/Plugin.php | 58 ++-- 14 files changed, 568 insertions(+), 507 deletions(-) diff --git a/languages/perform.pot b/languages/perform.pot index 8eee6dd..f07f72f 100644 --- a/languages/perform.pot +++ b/languages/perform.pot @@ -7,7 +7,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language-Team: PerformWP \n" -"POT-Creation-Date: 2026-05-22 07:31+0000\n" +"POT-Creation-Date: 2026-05-25 11:35+0000\n" "Report-Msgid-Bugs-To: https://github.com/performwp/perform/issues/new\n" "X-Poedit-Basepath: ..\n" "X-Poedit-KeywordsList: __;_e;_ex:1,2c;_n:1,2;_n_noop:1,2;_nx:1,2,4c;_nx_noop:1,2,3c;_x:1,2c;esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c\n" @@ -16,535 +16,583 @@ msgstr "" "X-Poedit-SourceCharset: UTF-8\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: src/Admin/Actions.php:96 +#: src/Admin/Actions.php:98 msgid "Close Assets Manager" msgstr "" -#: src/Admin/Actions.php:93, src/Modules/Assets/AssetsManager.php:195 +#: src/Admin/Actions.php:95, src/Modules/Assets/AssetsManager.php:195 msgid "Assets Manager" msgstr "" -#: src/Admin/Actions.php:103, src/Admin/Settings/Menu.php:40, src/Admin/Settings/Menu.php:41, src/Modules/Assets/AssetsManager.php:178 +#: src/Admin/Actions.php:105, src/Admin/Settings/Menu.php:40, src/Admin/Settings/Menu.php:41, src/Modules/Assets/AssetsManager.php:178 msgid "Perform" msgstr "" -#: src/Admin/Actions.php:123 +#: src/Admin/Actions.php:125 msgid "Support Forum" msgstr "" -#: src/Admin/Filters.php:49 +#: src/Admin/Filters.php:54 msgid "If you love using" msgstr "" -#: src/Admin/Filters.php:50 +#: src/Admin/Filters.php:55 msgid "Perform WordPress Plugin" msgstr "" -#: src/Admin/Filters.php:51 -msgid "please leave us a rating" +#: src/Admin/Filters.php:56 +msgid "please leave us a review" msgstr "" -#: src/Admin/Filters.php:53 +#: src/Admin/Filters.php:58 msgid ". It takes a minute and helps a lot. Thanks in advance!" msgstr "" -#: src/Admin/Filters.php:73 +#: src/Admin/Filters.php:78 msgid "Settings" msgstr "" -#: src/Admin/Filters.php:78 +#: src/Admin/Filters.php:83 msgid "Support" msgstr "" -#: src/Admin/Filters.php:98 +#: src/Admin/Filters.php:103 msgid "Manage Assets" msgstr "" -#: src/Includes/Helpers.php:303 +#: src/Includes/Helpers.php:273 +msgid "General" +msgstr "" + +#: src/Includes/Helpers.php:274 +msgid "Bloat" +msgstr "" + +#: src/Includes/Helpers.php:275 +msgid "Assets" +msgstr "" + +#: src/Includes/Helpers.php:276 +msgid "CDN" +msgstr "" + +#: src/Includes/Helpers.php:277 +msgid "Cache" +msgstr "" + +#: src/Includes/Helpers.php:278 +msgid "Advanced" +msgstr "" + +#: src/Includes/Helpers.php:281 +msgid "WooCommerce" +msgstr "" + +#: src/Includes/Helpers.php:309 msgid "General Settings" msgstr "" -#: src/Includes/Helpers.php:304 +#: src/Includes/Helpers.php:310 msgid "Configure general performance settings for your WordPress site." msgstr "" -#: src/Includes/Helpers.php:309 +#: src/Includes/Helpers.php:315 msgid "Force SSL" msgstr "" -#: src/Includes/Helpers.php:310 +#: src/Includes/Helpers.php:316 msgid "Enabling this will force all traffic to use SSL." msgstr "" -#: src/Includes/Helpers.php:321 +#: src/Includes/Helpers.php:327 msgid "Enable Menu Cache" msgstr "" -#: src/Includes/Helpers.php:322 +#: src/Includes/Helpers.php:328 msgid "Enabling this will cache your menu items for better performance." msgstr "" -#: src/Includes/Helpers.php:335 +#: src/Includes/Helpers.php:341 msgid "Frontend Optimization" msgstr "" -#: src/Includes/Helpers.php:336 +#: src/Includes/Helpers.php:342 msgid "Remove unnecessary frontend scripts and tags that add extra requests or bytes to every page. These optimizations reduce file requests, improve cacheability, and clean up redundant page elements." msgstr "" -#: src/Includes/Helpers.php:341 +#: src/Includes/Helpers.php:347 msgid "Disable Emoji's" msgstr "" -#: src/Includes/Helpers.php:342 +#: src/Includes/Helpers.php:348 msgid "Prevents WordPress from loading the emoji detection script and related styles, reducing one extra HTTP request." msgstr "" -#: src/Includes/Helpers.php:353 +#: src/Includes/Helpers.php:359 msgid "Disable Embeds" msgstr "" -#: src/Includes/Helpers.php:354 +#: src/Includes/Helpers.php:360 msgid "Removes the WordPress Embed script (wp-embed.min.js) used for embedding posts and media across sites." msgstr "" -#: src/Includes/Helpers.php:365 +#: src/Includes/Helpers.php:371 msgid "Remove Query Strings" msgstr "" -#: src/Includes/Helpers.php:366 +#: src/Includes/Helpers.php:372 msgid "Strips version query strings from static resources (?ver=) to improve caching efficiency on CDNs and browsers." msgstr "" -#: src/Includes/Helpers.php:377 +#: src/Includes/Helpers.php:383 msgid "Remove jQuery Migrate" msgstr "" -#: src/Includes/Helpers.php:378 +#: src/Includes/Helpers.php:384 msgid "Prevents loading of the legacy jquery-migrate.min.js file, used mainly for backward compatibility with outdated scripts." msgstr "" -#: src/Includes/Helpers.php:389 +#: src/Includes/Helpers.php:395 msgid "Disable Dashicons" msgstr "" -#: src/Includes/Helpers.php:390 +#: src/Includes/Helpers.php:396 msgid "Prevents loading the dashicons.css icon font on the frontend for non-logged-in visitors." msgstr "" -#: src/Includes/Helpers.php:401 +#: src/Includes/Helpers.php:407 msgid "Hide WP Version" msgstr "" -#: src/Includes/Helpers.php:402 +#: src/Includes/Helpers.php:408 msgid "Removes the WordPress version meta tag from the page source, reducing page markup size slightly." msgstr "" -#: src/Includes/Helpers.php:413 +#: src/Includes/Helpers.php:419 msgid "Remove wlwmanifest Link" msgstr "" -#: src/Includes/Helpers.php:414 +#: src/Includes/Helpers.php:420 msgid "Removes the Windows Live Writer manifest tag, an obsolete feature unused on modern sites." msgstr "" -#: src/Includes/Helpers.php:425 +#: src/Includes/Helpers.php:431 msgid "Remove RSD Link" msgstr "" -#: src/Includes/Helpers.php:426 +#: src/Includes/Helpers.php:432 msgid "Removes the Real Simple Discovery (RSD) tag used by remote publishing tools." msgstr "" -#: src/Includes/Helpers.php:437 +#: src/Includes/Helpers.php:443 msgid "Remove Shortlink" msgstr "" -#: src/Includes/Helpers.php:438 +#: src/Includes/Helpers.php:444 msgid "Removes the rel=\"shortlink\" tag generated for posts to reduce unnecessary metadata output." msgstr "" -#: src/Includes/Helpers.php:449 +#: src/Includes/Helpers.php:455 msgid "Network Requests and Endpoints" msgstr "" -#: src/Includes/Helpers.php:450 +#: src/Includes/Helpers.php:456 msgid "Disable unused services that generate background or external HTTP requests. Ideal for sites that don't rely on remote publishing or REST-based integrations." msgstr "" -#: src/Includes/Helpers.php:455 +#: src/Includes/Helpers.php:461 msgid "Disable XML-RPC" msgstr "" -#: src/Includes/Helpers.php:456 +#: src/Includes/Helpers.php:462 msgid "Disables WordPress XML-RPC functionality, which handles remote publishing and pingbacks, saving processing overhead." msgstr "" -#: src/Includes/Helpers.php:467 +#: src/Includes/Helpers.php:473 msgid "Remove REST API Links" msgstr "" -#: src/Includes/Helpers.php:468 +#: src/Includes/Helpers.php:474 msgid "Removes REST API discovery links from the site header and page responses, reducing unnecessary HTTP headers." msgstr "" -#: src/Includes/Helpers.php:479 +#: src/Includes/Helpers.php:485 msgid "Feed and Discovery Optimization" msgstr "" -#: src/Includes/Helpers.php:480 +#: src/Includes/Helpers.php:486 msgid "Stop generating feed files and related discovery tags that most modern sites don't need. Helps reduce crawl requests and prevents unnecessary feed generation." msgstr "" -#: src/Includes/Helpers.php:485 +#: src/Includes/Helpers.php:491 msgid "Disable RSS Feeds" msgstr "" -#: src/Includes/Helpers.php:486 +#: src/Includes/Helpers.php:492 msgid "Disables WordPress-generated RSS feeds and redirects feed URLs back to the homepage." msgstr "" -#: src/Includes/Helpers.php:497 +#: src/Includes/Helpers.php:503 msgid "Remove RSS Feed Links" msgstr "" -#: src/Includes/Helpers.php:498 +#: src/Includes/Helpers.php:504 msgid "Removes all RSS feed link tags from the site’s header." msgstr "" -#: src/Includes/Helpers.php:509 +#: src/Includes/Helpers.php:515 msgid "Editor and Backend Performance" msgstr "" -#: src/Includes/Helpers.php:510 +#: src/Includes/Helpers.php:516 msgid "Limit WordPress background activity during content editing to reduce CPU and database usage. These controls keep your admin fast, reduce CPU cycles, and optimize database performance." msgstr "" -#: src/Includes/Helpers.php:515 +#: src/Includes/Helpers.php:521 msgid "Disable Self Pingbacks" msgstr "" -#: src/Includes/Helpers.php:516 +#: src/Includes/Helpers.php:522 msgid "Prevents WordPress from sending self-pingbacks when linking to your own posts." msgstr "" -#: src/Includes/Helpers.php:527 +#: src/Includes/Helpers.php:533 msgid "Disable Password Strength Meter" msgstr "" -#: src/Includes/Helpers.php:528 +#: src/Includes/Helpers.php:534 msgid "Prevents loading of the password strength meter script (zxcvbn.js) on non-essential admin pages." msgstr "" -#: src/Includes/Helpers.php:539 +#: src/Includes/Helpers.php:545 msgid "Disable Heartbeat" msgstr "" -#: src/Includes/Helpers.php:541, src/Includes/Helpers.php:558, src/Includes/Helpers.php:576, src/Includes/Helpers.php:602 +#: src/Includes/Helpers.php:547, src/Includes/Helpers.php:564, src/Includes/Helpers.php:582, src/Includes/Helpers.php:608 msgid "Default" msgstr "" -#: src/Includes/Helpers.php:542 +#: src/Includes/Helpers.php:548 msgid "Disable Everywhere" msgstr "" -#: src/Includes/Helpers.php:543 +#: src/Includes/Helpers.php:549 msgid "Only Allow When Editing Posts/Pages" msgstr "" -#: src/Includes/Helpers.php:545 +#: src/Includes/Helpers.php:551 msgid "Stops or limits the WordPress Heartbeat API that sends frequent AJAX requests from the browser to the server." msgstr "" -#: src/Includes/Helpers.php:556 +#: src/Includes/Helpers.php:562 msgid "Heartbeat Frequency" msgstr "" -#: src/Includes/Helpers.php:558, src/Includes/Helpers.php:559, src/Includes/Helpers.php:560, src/Includes/Helpers.php:561 -msgid "%s Seconds" +#: src/Includes/Helpers.php:564 +msgid "15 Seconds" +msgstr "" + +#: src/Includes/Helpers.php:565 +msgid "30 Seconds" +msgstr "" + +#: src/Includes/Helpers.php:566 +msgid "45 Seconds" +msgstr "" + +#: src/Includes/Helpers.php:567 +msgid "60 Seconds" msgstr "" -#: src/Includes/Helpers.php:563 +#: src/Includes/Helpers.php:569 msgid "Adjusts how often the Heartbeat API runs (lower frequency = fewer background requests)." msgstr "" -#: src/Includes/Helpers.php:574 +#: src/Includes/Helpers.php:580 msgid "Limit Post Revisions" msgstr "" -#: src/Includes/Helpers.php:577 +#: src/Includes/Helpers.php:583 msgid "Disable Post Revisions" msgstr "" -#: src/Includes/Helpers.php:589 +#: src/Includes/Helpers.php:595 msgid "Limits the number of post revisions stored in the database to prevent bloat." msgstr "" -#: src/Includes/Helpers.php:600 +#: src/Includes/Helpers.php:606 msgid "Autosave Interval" msgstr "" -#: src/Includes/Helpers.php:602 +#: src/Includes/Helpers.php:608 msgid "1 Minute" msgstr "" -#: src/Includes/Helpers.php:603, src/Includes/Helpers.php:604, src/Includes/Helpers.php:605, src/Includes/Helpers.php:606 -msgid "%s Minutes" +#: src/Includes/Helpers.php:609 +msgid "2 Minutes" msgstr "" -#: src/Includes/Helpers.php:608 +#: src/Includes/Helpers.php:610 +msgid "3 Minutes" +msgstr "" + +#: src/Includes/Helpers.php:611 +msgid "4 Minutes" +msgstr "" + +#: src/Includes/Helpers.php:612, src/Includes/Helpers.php:747 +msgid "5 Minutes" +msgstr "" + +#: src/Includes/Helpers.php:614 msgid "Controls how often posts are autosaved while editing, reducing unnecessary database writes." msgstr "" -#: src/Includes/Helpers.php:621 +#: src/Includes/Helpers.php:627 msgid "Assets Optimization" msgstr "" -#: src/Includes/Helpers.php:622 +#: src/Includes/Helpers.php:628 msgid "Settings to manage asset loading and optimization." msgstr "" -#: src/Includes/Helpers.php:627 +#: src/Includes/Helpers.php:633 msgid "Enable Assets Manager" msgstr "" -#: src/Includes/Helpers.php:628 +#: src/Includes/Helpers.php:634 msgid "Enabling this will allow you to manage your assets more effectively." msgstr "" -#: src/Includes/Helpers.php:639 +#: src/Includes/Helpers.php:645 msgid "DNS Prefetch" msgstr "" -#: src/Includes/Helpers.php:640 +#: src/Includes/Helpers.php:646 msgid "Resolve domain names before a user clicks. Format: //domain.tld (one per line)" msgstr "" -#: src/Includes/Helpers.php:651 +#: src/Includes/Helpers.php:657 msgid "Preconnect" msgstr "" -#: src/Includes/Helpers.php:652 +#: src/Includes/Helpers.php:658 msgid "Establish a connection to another origin before a user clicks. Format: //domain.tld (one per line)" msgstr "" -#: src/Includes/Helpers.php:665 +#: src/Includes/Helpers.php:671 msgid "CDN Settings" msgstr "" -#: src/Includes/Helpers.php:666 +#: src/Includes/Helpers.php:672 msgid "Settings to manage CDN configurations." msgstr "" -#: src/Includes/Helpers.php:671 +#: src/Includes/Helpers.php:677 msgid "Enable CDN" msgstr "" -#: src/Includes/Helpers.php:672 +#: src/Includes/Helpers.php:678 msgid "Enabling this will allow you to use a CDN for your static assets." msgstr "" -#: src/Includes/Helpers.php:683 +#: src/Includes/Helpers.php:689 msgid "CDN URL" msgstr "" -#: src/Includes/Helpers.php:684 +#: src/Includes/Helpers.php:690 msgid "Enter the URL of your CDN provider." msgstr "" -#: src/Includes/Helpers.php:695 +#: src/Includes/Helpers.php:701 msgid "Included Directories" msgstr "" -#: src/Includes/Helpers.php:696 +#: src/Includes/Helpers.php:702 msgid "Enter any directories you would like to be included in CDN rewriting, separated by commas (,). Default: wp-content,wp-includes" msgstr "" -#: src/Includes/Helpers.php:707 +#: src/Includes/Helpers.php:713 msgid "CDN Exclusions" msgstr "" -#: src/Includes/Helpers.php:708 +#: src/Includes/Helpers.php:714 msgid "Enter any directories or file extensions you would like to be excluded from CDN rewriting, separated by commas (,). Default: .php" msgstr "" -#: src/Includes/Helpers.php:721 +#: src/Includes/Helpers.php:727 msgid "Full-Page Cache" msgstr "" -#: src/Includes/Helpers.php:722 +#: src/Includes/Helpers.php:728 msgid "Enable full-page caching with stale-while-revalidate and stampede protection." msgstr "" -#: src/Includes/Helpers.php:727 +#: src/Includes/Helpers.php:733 msgid "Enable Full-Page Cache" msgstr "" -#: src/Includes/Helpers.php:728 +#: src/Includes/Helpers.php:734 msgid "Caches full HTML responses for anonymous visitors." msgstr "" -#: src/Includes/Helpers.php:739 +#: src/Includes/Helpers.php:745 msgid "Cache TTL" msgstr "" -#: src/Includes/Helpers.php:741 -msgid "5 Minutes" -msgstr "" - -#: src/Includes/Helpers.php:742, src/Includes/Helpers.php:761 +#: src/Includes/Helpers.php:748, src/Includes/Helpers.php:767 msgid "15 Minutes" msgstr "" -#: src/Includes/Helpers.php:743, src/Includes/Helpers.php:762 +#: src/Includes/Helpers.php:749, src/Includes/Helpers.php:768 msgid "30 Minutes" msgstr "" -#: src/Includes/Helpers.php:744, src/Includes/Helpers.php:763 +#: src/Includes/Helpers.php:750, src/Includes/Helpers.php:769 msgid "1 Hour" msgstr "" -#: src/Includes/Helpers.php:745, src/Includes/Helpers.php:764 +#: src/Includes/Helpers.php:751, src/Includes/Helpers.php:770 msgid "6 Hours" msgstr "" -#: src/Includes/Helpers.php:746, src/Includes/Helpers.php:766 +#: src/Includes/Helpers.php:752, src/Includes/Helpers.php:772 msgid "24 Hours" msgstr "" -#: src/Includes/Helpers.php:748 +#: src/Includes/Helpers.php:754 msgid "How long a page remains fresh before becoming stale." msgstr "" -#: src/Includes/Helpers.php:759 +#: src/Includes/Helpers.php:765 msgid "Stale Revalidate Window" msgstr "" -#: src/Includes/Helpers.php:765 +#: src/Includes/Helpers.php:771 msgid "12 Hours" msgstr "" -#: src/Includes/Helpers.php:768 +#: src/Includes/Helpers.php:774 msgid "Serve stale pages while refreshing them in the background." msgstr "" -#: src/Includes/Helpers.php:779 +#: src/Includes/Helpers.php:785 msgid "Separate Query Params" msgstr "" -#: src/Includes/Helpers.php:780 +#: src/Includes/Helpers.php:786 msgid "Comma-separated query keys that should generate separate cache entries. Tracking params are ignored automatically." msgstr "" -#: src/Includes/Helpers.php:791 +#: src/Includes/Helpers.php:797 msgid "Preload and Observability" msgstr "" -#: src/Includes/Helpers.php:792 +#: src/Includes/Helpers.php:798 msgid "Warm cache from sitemaps and monitor cache effectiveness." msgstr "" -#: src/Includes/Helpers.php:797 +#: src/Includes/Helpers.php:803 msgid "Enable Adaptive Preloader" msgstr "" -#: src/Includes/Helpers.php:798 +#: src/Includes/Helpers.php:804 msgid "Preloads cache from sitemap and high-miss URLs using adaptive request rate." msgstr "" -#: src/Includes/Helpers.php:809 +#: src/Includes/Helpers.php:815 msgid "Slow Request Threshold" msgstr "" -#: src/Includes/Helpers.php:811 +#: src/Includes/Helpers.php:817 msgid "500ms" msgstr "" -#: src/Includes/Helpers.php:812 +#: src/Includes/Helpers.php:818 msgid "800ms" msgstr "" -#: src/Includes/Helpers.php:813 +#: src/Includes/Helpers.php:819 msgid "1200ms" msgstr "" -#: src/Includes/Helpers.php:814 +#: src/Includes/Helpers.php:820 msgid "2000ms" msgstr "" -#: src/Includes/Helpers.php:816 +#: src/Includes/Helpers.php:822 msgid "Tracks uncached requests slower than this value in observability stats." msgstr "" -#: src/Includes/Helpers.php:827 +#: src/Includes/Helpers.php:833 msgid "Cloudflare" msgstr "" -#: src/Includes/Helpers.php:828 +#: src/Includes/Helpers.php:834 msgid "Sync local cache purge events to Cloudflare (free-tier friendly)." msgstr "" -#: src/Includes/Helpers.php:833 +#: src/Includes/Helpers.php:839 msgid "Enable Cloudflare Cache Sync" msgstr "" -#: src/Includes/Helpers.php:834 +#: src/Includes/Helpers.php:840 msgid "Purge Cloudflare URLs when Perform purges local cache." msgstr "" -#: src/Includes/Helpers.php:845 +#: src/Includes/Helpers.php:851 msgid "Cloudflare Zone ID" msgstr "" -#: src/Includes/Helpers.php:846 +#: src/Includes/Helpers.php:852 msgid "Your Cloudflare Zone ID." msgstr "" -#: src/Includes/Helpers.php:857 +#: src/Includes/Helpers.php:863 msgid "Cloudflare API Token" msgstr "" -#: src/Includes/Helpers.php:858 +#: src/Includes/Helpers.php:864 msgid "API token with Zone:Cache Purge permission." msgstr "" -#: src/Includes/Helpers.php:871 +#: src/Includes/Helpers.php:877 msgid "Advanced Settings" msgstr "" -#: src/Includes/Helpers.php:872 +#: src/Includes/Helpers.php:878 msgid "Settings for advanced configurations." msgstr "" -#: src/Includes/Helpers.php:877 +#: src/Includes/Helpers.php:883 msgid "Remove Data on Uninstall" msgstr "" -#: src/Includes/Helpers.php:878 +#: src/Includes/Helpers.php:884 msgid "Enabling this will remove all plugin data upon uninstallation." msgstr "" -#: src/Includes/Helpers.php:891 +#: src/Includes/Helpers.php:897 msgid "WooCommerce Settings" msgstr "" -#: src/Includes/Helpers.php:892 +#: src/Includes/Helpers.php:898 msgid "Settings specific to WooCommerce." msgstr "" -#: src/Includes/Helpers.php:897 +#: src/Includes/Helpers.php:903 msgid "Enable WooCommerce Manager" msgstr "" -#: src/Includes/Helpers.php:898 +#: src/Includes/Helpers.php:904 msgid "Enabling this will allow you to manage WooCommerce specific settings." msgstr "" -#: src/Includes/Helpers.php:909 +#: src/Includes/Helpers.php:915 msgid "Enable WooCommerce Cache" msgstr "" -#: src/Includes/Helpers.php:910 +#: src/Includes/Helpers.php:916 msgid "Enabling this will cache WooCommerce pages for better performance." msgstr "" @@ -556,7 +604,7 @@ msgstr "" msgid "Saving..." msgstr "" -#: src/Admin/Settings/Api.php:138 +#: src/Admin/Settings/Api.php:145 msgid "Learn more" msgstr "" @@ -564,15 +612,15 @@ msgstr "" msgid "Insufficient permissions." msgstr "" -#: src/Admin/Settings/Menu.php:92 +#: src/Admin/Settings/Menu.php:93 msgid "Security check failed." msgstr "" -#: src/Admin/Settings/Menu.php:203 +#: src/Admin/Settings/Menu.php:204 msgid "Unable to save the settings. Please try again." msgstr "" -#: src/Admin/Settings/Menu.php:196 +#: src/Admin/Settings/Menu.php:197 msgid "Settings saved successfully." msgstr "" @@ -707,7 +755,7 @@ msgstr "" msgid "All assets in this group have been disabled. Enable the group again to manage individual assets." msgstr "" -#: src/Modules/Assets/AssetsManager.php:713, src/Modules/Assets/AssetsManager.php:802 +#: src/Modules/Assets/AssetsManager.php:713, src/Modules/Assets/AssetsManager.php:807 msgid "Current URL" msgstr "" @@ -719,19 +767,19 @@ msgstr "" msgid "Disable on" msgstr "" -#: src/Modules/Assets/AssetsManager.php:764 +#: src/Modules/Assets/AssetsManager.php:769 msgid "Asset loading status" msgstr "" -#: src/Modules/Assets/AssetsManager.php:766 +#: src/Modules/Assets/AssetsManager.php:771 msgid "ON" msgstr "" -#: src/Modules/Assets/AssetsManager.php:769 +#: src/Modules/Assets/AssetsManager.php:774 msgid "OFF" msgstr "" -#: src/Modules/Assets/AssetsManager.php:795 +#: src/Modules/Assets/AssetsManager.php:800 msgid "Exceptions" msgstr "" diff --git a/readme.txt b/readme.txt index 5761af6..3213346 100644 --- a/readme.txt +++ b/readme.txt @@ -1,9 +1,9 @@ -=== Perform – Performance Optimization for WordPress === +=== Perform - Optimize Performance === Contributors: performwp, mehul0810, ankur0812 Tags: performance, caching, cdn, assets, optimize Donate link: https://www.buymeacoffee.com/mehulgohil Requires at least: 4.8 -Tested up to: 6.9 +Tested up to: 7.0 Requires PHP: 7.4 Stable tag: 1.6.0 License: GPLv3 diff --git a/src/Admin/Actions.php b/src/Admin/Actions.php index e055456..53a1bd1 100644 --- a/src/Admin/Actions.php +++ b/src/Admin/Actions.php @@ -52,7 +52,7 @@ public function registerAssets() { wp_register_style( 'perform-admin', PERFORM_PLUGIN_URL . 'assets/dist/css/admin.css', '', PERFORM_VERSION ); wp_enqueue_style( 'perform-admin' ); - wp_register_script( 'perform-admin', PERFORM_PLUGIN_URL . 'assets/dist/js/admin.min.js', [ 'wp-element', 'wp-components', 'wp-i18n' ], PERFORM_VERSION ); + wp_register_script( 'perform-admin', PERFORM_PLUGIN_URL . 'assets/dist/js/admin.min.js', [ 'wp-element', 'wp-components', 'wp-i18n' ], PERFORM_VERSION, true ); wp_enqueue_script( 'perform-admin' ); wp_localize_script( @@ -88,7 +88,9 @@ public function add_to_admin_bar( $wp_admin_bar ) { return; } - if ( ! isset( $_GET['perform'] ) ) { + $is_assets_manager_open = isset( $_GET['perform'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display toggle. + + if ( ! $is_assets_manager_open ) { $href = add_query_arg( 'perform', '1' ); $menu_text = esc_html__( 'Assets Manager', 'perform' ); } else { diff --git a/src/Admin/Filters.php b/src/Admin/Filters.php index bfbe111..357d0ab 100644 --- a/src/Admin/Filters.php +++ b/src/Admin/Filters.php @@ -10,6 +10,11 @@ namespace Perform\Admin; +// Bailout, if accessed directly. +if ( ! defined( 'ABSPATH' ) ) { + exit; +} + class Filters { /** @@ -48,8 +53,8 @@ public function add_admin_footer_text( $footer_text ) { '%1$s %2$s %3$s %5$s', esc_html__( 'If you love using', 'perform' ), esc_html__( 'Perform WordPress Plugin', 'perform' ), - esc_html__( 'please leave us a rating', 'perform' ), - esc_url( 'https://wordpress.org/support/plugin/perform/reviews/?filter=5#postform' ), + esc_html__( 'please leave us a review', 'perform' ), + esc_url( 'https://wordpress.org/support/plugin/perform/reviews/' ), esc_html__( '. It takes a minute and helps a lot. Thanks in advance!', 'perform' ), ); diff --git a/src/Admin/Settings/Api.php b/src/Admin/Settings/Api.php index 7c49e43..81081d6 100644 --- a/src/Admin/Settings/Api.php +++ b/src/Admin/Settings/Api.php @@ -54,6 +54,7 @@ public function render_action() { - - - - - - + + + + + + render_action(); ?> @@ -107,7 +114,7 @@ public function render_fields( $all_fields = [] ) { * @return string */ private function render_field( $field ) { - $type = $field['type'] ?? 'text'; + $type = $field['type'] ?? 'text'; $method = "render_{$type}_field"; if ( method_exists( $this, $method ) ) { diff --git a/src/Admin/Settings/Menu.php b/src/Admin/Settings/Menu.php index 5cbb07d..ecd6396 100644 --- a/src/Admin/Settings/Menu.php +++ b/src/Admin/Settings/Menu.php @@ -85,7 +85,8 @@ public function save_settings() { } // Verify nonce for the AJAX request. - if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( wp_unslash( $_POST['nonce'] ), 'perform_save_settings' ) ) { + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : ''; + if ( ! wp_verify_nonce( $nonce, 'perform_save_settings' ) ) { wp_send_json_error( [ 'type' => 'error', @@ -97,16 +98,16 @@ public function save_settings() { // If the JS sent a JSON payload in `data`, decode it. Otherwise fall back to regular POST fields. $posted_data = []; if ( isset( $_POST['data'] ) ) { - $raw = wp_unslash( $_POST['data'] ); + $raw = sanitize_textarea_field( wp_unslash( $_POST['data'] ) ); $decoded = json_decode( $raw, true ); if ( is_array( $decoded ) ) { $posted_data = $decoded; } else { // Fallback: clean the entire $_POST array. - $posted_data = Helpers::clean( $_POST ); + $posted_data = Helpers::clean( wp_unslash( $_POST ) ); } } else { - $posted_data = Helpers::clean( $_POST ); + $posted_data = Helpers::clean( wp_unslash( $_POST ) ); } $settings = Helpers::get_settings(); diff --git a/src/Includes/Actions.php b/src/Includes/Actions.php index e36e5dc..924047a 100644 --- a/src/Includes/Actions.php +++ b/src/Includes/Actions.php @@ -12,6 +12,11 @@ use Perform\Includes\Helpers; +// Bailout, if accessed directly. +if ( ! defined( 'ABSPATH' ) ) { + exit; +} + class Actions { /** diff --git a/src/Includes/Helpers.php b/src/Includes/Helpers.php index ff8be27..d4d29e0 100644 --- a/src/Includes/Helpers.php +++ b/src/Includes/Helpers.php @@ -66,6 +66,7 @@ public static function has_network_access() { * * @return mixed */ + // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.defaultFound -- Preserve public parameter name for named-argument compatibility. public static function get_option( $option, $section, $default = '' ) { $options = get_option( $section ); @@ -149,6 +150,7 @@ public static function is_woocommerce_active() { * * @return string|array */ + // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.varFound -- Preserve public parameter name for named-argument compatibility. public static function clean( $var ) { if ( is_array( $var ) ) { // Recursively clean array values by calling this same method. @@ -179,7 +181,7 @@ public static function get_content_dir_name() { * @return bool */ public static function can_display_assets_manager() { - if ( isset( $_GET['perform'] ) ) { + if ( isset( $_GET['perform'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display toggle. return true; } @@ -198,7 +200,7 @@ public static function can_display_assets_manager() { */ public static function get_current_tab() { $screen = get_current_screen(); - $current_tab = ! empty( $_GET['tab'] ) ? $_GET['tab'] : ''; + $current_tab = ! empty( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only settings tab selection. if ( 'settings_page_perform_settings' === $screen->id ) { $current_tab = ! empty( $current_tab ) ? $current_tab : 'general'; @@ -266,15 +268,19 @@ public static function get_settings_tabs() { $tabs['woocommerce'] = 'WooCommerce'; } - /** - * ✅ Safe translation wrapper - * Translate only after init, otherwise return plain labels. - */ - if ( did_action( 'init' ) ) { - foreach ( $tabs as $key => $label ) { - $tabs[ $key ] = esc_html__( $label, 'perform' ); - } - } + // Translate only after init to avoid early just-in-time translation loading. + if ( did_action( 'init' ) ) { + $tabs['general'] = esc_html__( 'General', 'perform' ); + $tabs['bloat'] = esc_html__( 'Bloat', 'perform' ); + $tabs['assets'] = esc_html__( 'Assets', 'perform' ); + $tabs['cdn'] = esc_html__( 'CDN', 'perform' ); + $tabs['cache'] = esc_html__( 'Cache', 'perform' ); + $tabs['advanced'] = esc_html__( 'Advanced', 'perform' ); + + if ( isset( $tabs['woocommerce'] ) ) { + $tabs['woocommerce'] = esc_html__( 'WooCommerce', 'perform' ); + } + } //return $tabs; return apply_filters( 'perform_settings_tabs', $tabs ); @@ -298,10 +304,10 @@ public static function get_settings_fields() { // Settings Fields. return [ - 'general' => [ + 'general' => [ [ - 'title' => esc_html__('General Settings', 'perform'), - 'description' => esc_html__('Configure general performance settings for your WordPress site.', 'perform'), + 'title' => esc_html__( 'General Settings', 'perform' ), + 'description' => esc_html__( 'Configure general performance settings for your WordPress site.', 'perform' ), 'fields' => [ [ 'id' => 'enable_ssl', @@ -328,12 +334,12 @@ public static function get_settings_fields() { ), ], ], - ] + ], ], - 'bloat' => [ + 'bloat' => [ [ - 'title' => esc_html__('Frontend Optimization', 'perform'), - 'description' => esc_html__('Remove unnecessary frontend scripts and tags that add extra requests or bytes to every page. These optimizations reduce file requests, improve cacheability, and clean up redundant page elements.', 'perform'), + 'title' => esc_html__( 'Frontend Optimization', 'perform' ), + 'description' => esc_html__( 'Remove unnecessary frontend scripts and tags that add extra requests or bytes to every page. These optimizations reduce file requests, improve cacheability, and clean up redundant page elements.', 'perform' ), 'fields' => [ [ 'id' => 'disable_emojis', @@ -446,8 +452,8 @@ public static function get_settings_fields() { ], ], [ - 'title' => esc_html__('Network Requests and Endpoints', 'perform'), - 'description' => esc_html__('Disable unused services that generate background or external HTTP requests. Ideal for sites that don\'t rely on remote publishing or REST-based integrations.', 'perform'), + 'title' => esc_html__( 'Network Requests and Endpoints', 'perform' ), + 'description' => esc_html__( 'Disable unused services that generate background or external HTTP requests. Ideal for sites that don\'t rely on remote publishing or REST-based integrations.', 'perform' ), 'fields' => [ [ 'id' => 'disable_xmlrpc', @@ -476,8 +482,8 @@ public static function get_settings_fields() { ], ], [ - 'title' => esc_html__('Feed and Discovery Optimization', 'perform'), - 'description' => esc_html__('Stop generating feed files and related discovery tags that most modern sites don\'t need. Helps reduce crawl requests and prevents unnecessary feed generation.', 'perform'), + 'title' => esc_html__( 'Feed and Discovery Optimization', 'perform' ), + 'description' => esc_html__( 'Stop generating feed files and related discovery tags that most modern sites don\'t need. Helps reduce crawl requests and prevents unnecessary feed generation.', 'perform' ), 'fields' => [ [ 'id' => 'disable_rss_feeds', @@ -506,8 +512,8 @@ public static function get_settings_fields() { ], ], [ - 'title' => esc_html__('Editor and Backend Performance', 'perform'), - 'description' => esc_html__('Limit WordPress background activity during content editing to reduce CPU and database usage. These controls keep your admin fast, reduce CPU cycles, and optimize database performance.', 'perform'), + 'title' => esc_html__( 'Editor and Backend Performance', 'perform' ), + 'description' => esc_html__( 'Limit WordPress background activity during content editing to reduce CPU and database usage. These controls keep your admin fast, reduce CPU cycles, and optimize database performance.', 'perform' ), 'fields' => [ [ 'id' => 'disable_self_pingbacks', @@ -555,10 +561,10 @@ public static function get_settings_fields() { 'type' => 'select', 'name' => esc_html__( 'Heartbeat Frequency', 'perform' ), 'options' => [ - '' => sprintf( esc_html__( '%s Seconds', 'perform' ), '15' ) . ' (' . esc_html__( 'Default', 'perform' ) . ')', - '30' => sprintf( esc_html__( '%s Seconds', 'perform' ), '30' ), - '45' => sprintf( esc_html__( '%s Seconds', 'perform' ), '45' ), - '60' => sprintf( esc_html__( '%s Seconds', 'perform' ), '60' ), + '' => esc_html__( '15 Seconds', 'perform' ) . ' (' . esc_html__( 'Default', 'perform' ) . ')', + '30' => esc_html__( '30 Seconds', 'perform' ), + '45' => esc_html__( '45 Seconds', 'perform' ), + '60' => esc_html__( '60 Seconds', 'perform' ), ], 'desc' => esc_html__( 'Adjusts how often the Heartbeat API runs (lower frequency = fewer background requests).', 'perform' ), 'help_link' => esc_url( @@ -600,10 +606,10 @@ public static function get_settings_fields() { 'name' => esc_html__( 'Autosave Interval', 'perform' ), 'options' => [ '' => esc_html__( '1 Minute', 'perform' ) . ' (' . esc_html__( 'Default', 'perform' ) . ')', - '120' => sprintf( esc_html__( '%s Minutes', 'perform' ), '2' ), - '180' => sprintf( esc_html__( '%s Minutes', 'perform' ), '3' ), - '240' => sprintf( esc_html__( '%s Minutes', 'perform' ), '4' ), - '300' => sprintf( esc_html__( '%s Minutes', 'perform' ), '5' ), + '120' => esc_html__( '2 Minutes', 'perform' ), + '180' => esc_html__( '3 Minutes', 'perform' ), + '240' => esc_html__( '4 Minutes', 'perform' ), + '300' => esc_html__( '5 Minutes', 'perform' ), ], 'desc' => esc_html__( 'Controls how often posts are autosaved while editing, reducing unnecessary database writes.', 'perform' ), 'help_link' => esc_url( @@ -616,10 +622,10 @@ public static function get_settings_fields() { ], ], ], - 'assets' => [ + 'assets' => [ [ - 'title' => esc_html__('Assets Optimization', 'perform'), - 'description' => esc_html__('Settings to manage asset loading and optimization.', 'perform'), + 'title' => esc_html__( 'Assets Optimization', 'perform' ), + 'description' => esc_html__( 'Settings to manage asset loading and optimization.', 'perform' ), 'fields' => [ [ 'id' => 'enable_assets_manager', @@ -657,13 +663,13 @@ public static function get_settings_fields() { ) ), ], - ] - ] + ], + ], ], - 'cdn' => [ + 'cdn' => [ [ - 'title' => esc_html__('CDN Settings', 'perform'), - 'description' => esc_html__('Settings to manage CDN configurations.', 'perform'), + 'title' => esc_html__( 'CDN Settings', 'perform' ), + 'description' => esc_html__( 'Settings to manage CDN configurations.', 'perform' ), 'fields' => [ [ 'id' => 'enable_cdn', @@ -713,163 +719,163 @@ public static function get_settings_fields() { ) ), ], - ] - ] + ], ], - 'cache' => [ - [ - 'title' => esc_html__( 'Full-Page Cache', 'perform' ), - 'description' => esc_html__( 'Enable full-page caching with stale-while-revalidate and stampede protection.', 'perform' ), - 'fields' => [ - [ - 'id' => 'enable_page_cache', - 'type' => 'toggle', - 'name' => esc_html__( 'Enable Full-Page Cache', 'perform' ), - 'desc' => esc_html__( 'Caches full HTML responses for anonymous visitors.', 'perform' ), - 'help_link' => esc_url( - add_query_arg( - $utm_args, - 'https://performwp.com/docs/page-cache' - ) - ), - ], - [ - 'id' => 'page_cache_ttl', - 'type' => 'select', - 'name' => esc_html__( 'Cache TTL', 'perform' ), - 'options' => [ - '300' => esc_html__( '5 Minutes', 'perform' ), - '900' => esc_html__( '15 Minutes', 'perform' ), - '1800' => esc_html__( '30 Minutes', 'perform' ), - '3600' => esc_html__( '1 Hour', 'perform' ), - '21600' => esc_html__( '6 Hours', 'perform' ), - '86400' => esc_html__( '24 Hours', 'perform' ), - ], - 'desc' => esc_html__( 'How long a page remains fresh before becoming stale.', 'perform' ), - 'help_link' => esc_url( - add_query_arg( - $utm_args, - 'https://performwp.com/docs/page-cache' - ) - ), - ], - [ - 'id' => 'page_cache_swr_ttl', - 'type' => 'select', - 'name' => esc_html__( 'Stale Revalidate Window', 'perform' ), - 'options' => [ - '900' => esc_html__( '15 Minutes', 'perform' ), - '1800' => esc_html__( '30 Minutes', 'perform' ), - '3600' => esc_html__( '1 Hour', 'perform' ), - '21600' => esc_html__( '6 Hours', 'perform' ), - '43200' => esc_html__( '12 Hours', 'perform' ), - '86400' => esc_html__( '24 Hours', 'perform' ), - ], - 'desc' => esc_html__( 'Serve stale pages while refreshing them in the background.', 'perform' ), - 'help_link' => esc_url( - add_query_arg( - $utm_args, - 'https://performwp.com/docs/page-cache' - ) - ), + ], + 'cache' => [ + [ + 'title' => esc_html__( 'Full-Page Cache', 'perform' ), + 'description' => esc_html__( 'Enable full-page caching with stale-while-revalidate and stampede protection.', 'perform' ), + 'fields' => [ + [ + 'id' => 'enable_page_cache', + 'type' => 'toggle', + 'name' => esc_html__( 'Enable Full-Page Cache', 'perform' ), + 'desc' => esc_html__( 'Caches full HTML responses for anonymous visitors.', 'perform' ), + 'help_link' => esc_url( + add_query_arg( + $utm_args, + 'https://performwp.com/docs/page-cache' + ) + ), + ], + [ + 'id' => 'page_cache_ttl', + 'type' => 'select', + 'name' => esc_html__( 'Cache TTL', 'perform' ), + 'options' => [ + '300' => esc_html__( '5 Minutes', 'perform' ), + '900' => esc_html__( '15 Minutes', 'perform' ), + '1800' => esc_html__( '30 Minutes', 'perform' ), + '3600' => esc_html__( '1 Hour', 'perform' ), + '21600' => esc_html__( '6 Hours', 'perform' ), + '86400' => esc_html__( '24 Hours', 'perform' ), ], - [ - 'id' => 'cache_separate_query_params', - 'type' => 'text', - 'name' => esc_html__( 'Separate Query Params', 'perform' ), - 'desc' => esc_html__( 'Comma-separated query keys that should generate separate cache entries. Tracking params are ignored automatically.', 'perform' ), - 'help_link' => esc_url( - add_query_arg( - $utm_args, - 'https://performwp.com/docs/page-cache-query-params' - ) - ), + 'desc' => esc_html__( 'How long a page remains fresh before becoming stale.', 'perform' ), + 'help_link' => esc_url( + add_query_arg( + $utm_args, + 'https://performwp.com/docs/page-cache' + ) + ), + ], + [ + 'id' => 'page_cache_swr_ttl', + 'type' => 'select', + 'name' => esc_html__( 'Stale Revalidate Window', 'perform' ), + 'options' => [ + '900' => esc_html__( '15 Minutes', 'perform' ), + '1800' => esc_html__( '30 Minutes', 'perform' ), + '3600' => esc_html__( '1 Hour', 'perform' ), + '21600' => esc_html__( '6 Hours', 'perform' ), + '43200' => esc_html__( '12 Hours', 'perform' ), + '86400' => esc_html__( '24 Hours', 'perform' ), ], + 'desc' => esc_html__( 'Serve stale pages while refreshing them in the background.', 'perform' ), + 'help_link' => esc_url( + add_query_arg( + $utm_args, + 'https://performwp.com/docs/page-cache' + ) + ), + ], + [ + 'id' => 'cache_separate_query_params', + 'type' => 'text', + 'name' => esc_html__( 'Separate Query Params', 'perform' ), + 'desc' => esc_html__( 'Comma-separated query keys that should generate separate cache entries. Tracking params are ignored automatically.', 'perform' ), + 'help_link' => esc_url( + add_query_arg( + $utm_args, + 'https://performwp.com/docs/page-cache-query-params' + ) + ), ], ], - [ - 'title' => esc_html__( 'Preload and Observability', 'perform' ), - 'description' => esc_html__( 'Warm cache from sitemaps and monitor cache effectiveness.', 'perform' ), - 'fields' => [ - [ - 'id' => 'enable_cache_preload', - 'type' => 'toggle', - 'name' => esc_html__( 'Enable Adaptive Preloader', 'perform' ), - 'desc' => esc_html__( 'Preloads cache from sitemap and high-miss URLs using adaptive request rate.', 'perform' ), - 'help_link' => esc_url( - add_query_arg( - $utm_args, - 'https://performwp.com/docs/page-cache-preload' - ) - ), - ], - [ - 'id' => 'cache_slow_request_threshold_ms', - 'type' => 'select', - 'name' => esc_html__( 'Slow Request Threshold', 'perform' ), - 'options' => [ - '500' => esc_html__( '500ms', 'perform' ), - '800' => esc_html__( '800ms', 'perform' ), - '1200' => esc_html__( '1200ms', 'perform' ), - '2000' => esc_html__( '2000ms', 'perform' ), - ], - 'desc' => esc_html__( 'Tracks uncached requests slower than this value in observability stats.', 'perform' ), - 'help_link' => esc_url( - add_query_arg( - $utm_args, - 'https://performwp.com/docs/page-cache-observability' - ) - ), + ], + [ + 'title' => esc_html__( 'Preload and Observability', 'perform' ), + 'description' => esc_html__( 'Warm cache from sitemaps and monitor cache effectiveness.', 'perform' ), + 'fields' => [ + [ + 'id' => 'enable_cache_preload', + 'type' => 'toggle', + 'name' => esc_html__( 'Enable Adaptive Preloader', 'perform' ), + 'desc' => esc_html__( 'Preloads cache from sitemap and high-miss URLs using adaptive request rate.', 'perform' ), + 'help_link' => esc_url( + add_query_arg( + $utm_args, + 'https://performwp.com/docs/page-cache-preload' + ) + ), + ], + [ + 'id' => 'cache_slow_request_threshold_ms', + 'type' => 'select', + 'name' => esc_html__( 'Slow Request Threshold', 'perform' ), + 'options' => [ + '500' => esc_html__( '500ms', 'perform' ), + '800' => esc_html__( '800ms', 'perform' ), + '1200' => esc_html__( '1200ms', 'perform' ), + '2000' => esc_html__( '2000ms', 'perform' ), ], + 'desc' => esc_html__( 'Tracks uncached requests slower than this value in observability stats.', 'perform' ), + 'help_link' => esc_url( + add_query_arg( + $utm_args, + 'https://performwp.com/docs/page-cache-observability' + ) + ), ], ], - [ - 'title' => esc_html__( 'Cloudflare', 'perform' ), - 'description' => esc_html__( 'Sync local cache purge events to Cloudflare (free-tier friendly).', 'perform' ), - 'fields' => [ - [ - 'id' => 'enable_cloudflare_cache_sync', - 'type' => 'toggle', - 'name' => esc_html__( 'Enable Cloudflare Cache Sync', 'perform' ), - 'desc' => esc_html__( 'Purge Cloudflare URLs when Perform purges local cache.', 'perform' ), - 'help_link' => esc_url( - add_query_arg( - $utm_args, - 'https://performwp.com/docs/cloudflare-cache-sync' - ) - ), - ], - [ - 'id' => 'cloudflare_zone_id', - 'type' => 'text', - 'name' => esc_html__( 'Cloudflare Zone ID', 'perform' ), - 'desc' => esc_html__( 'Your Cloudflare Zone ID.', 'perform' ), - 'help_link' => esc_url( - add_query_arg( - $utm_args, - 'https://performwp.com/docs/cloudflare-cache-sync' - ) - ), - ], - [ - 'id' => 'cloudflare_api_token', - 'type' => 'text', - 'name' => esc_html__( 'Cloudflare API Token', 'perform' ), - 'desc' => esc_html__( 'API token with Zone:Cache Purge permission.', 'perform' ), - 'help_link' => esc_url( - add_query_arg( - $utm_args, - 'https://performwp.com/docs/cloudflare-cache-sync' - ) - ), - ], + ], + [ + 'title' => esc_html__( 'Cloudflare', 'perform' ), + 'description' => esc_html__( 'Sync local cache purge events to Cloudflare (free-tier friendly).', 'perform' ), + 'fields' => [ + [ + 'id' => 'enable_cloudflare_cache_sync', + 'type' => 'toggle', + 'name' => esc_html__( 'Enable Cloudflare Cache Sync', 'perform' ), + 'desc' => esc_html__( 'Purge Cloudflare URLs when Perform purges local cache.', 'perform' ), + 'help_link' => esc_url( + add_query_arg( + $utm_args, + 'https://performwp.com/docs/cloudflare-cache-sync' + ) + ), + ], + [ + 'id' => 'cloudflare_zone_id', + 'type' => 'text', + 'name' => esc_html__( 'Cloudflare Zone ID', 'perform' ), + 'desc' => esc_html__( 'Your Cloudflare Zone ID.', 'perform' ), + 'help_link' => esc_url( + add_query_arg( + $utm_args, + 'https://performwp.com/docs/cloudflare-cache-sync' + ) + ), + ], + [ + 'id' => 'cloudflare_api_token', + 'type' => 'text', + 'name' => esc_html__( 'Cloudflare API Token', 'perform' ), + 'desc' => esc_html__( 'API token with Zone:Cache Purge permission.', 'perform' ), + 'help_link' => esc_url( + add_query_arg( + $utm_args, + 'https://performwp.com/docs/cloudflare-cache-sync' + ) + ), ], ], ], - 'advanced' => [ + ], + 'advanced' => [ [ - 'title' => esc_html__('Advanced Settings', 'perform'), - 'description' => esc_html__('Settings for advanced configurations.', 'perform'), + 'title' => esc_html__( 'Advanced Settings', 'perform' ), + 'description' => esc_html__( 'Settings for advanced configurations.', 'perform' ), 'fields' => [ [ 'id' => 'remove_data_on_uninstall', @@ -883,13 +889,13 @@ public static function get_settings_fields() { ) ), ], - ] - ] + ], + ], ], 'woocommerce' => [ [ - 'title' => esc_html__('WooCommerce Settings', 'perform'), - 'description' => esc_html__('Settings specific to WooCommerce.', 'perform'), + 'title' => esc_html__( 'WooCommerce Settings', 'perform' ), + 'description' => esc_html__( 'Settings specific to WooCommerce.', 'perform' ), 'fields' => [ [ 'id' => 'enable_woocommerce_manager', @@ -915,8 +921,8 @@ public static function get_settings_fields() { ) ), ], - ] - ] + ], + ], ], ]; } diff --git a/src/Modules/Assets/AssetsManager.php b/src/Modules/Assets/AssetsManager.php index fbd3e99..4d94d36 100644 --- a/src/Modules/Assets/AssetsManager.php +++ b/src/Modules/Assets/AssetsManager.php @@ -83,7 +83,7 @@ public function register(): void { add_filter( 'style_loader_src', [ $this, 'dequeue_assets' ], 1000, 2 ); // Only add HTML if accessed by admin with perform param. - if ( isset( $_GET['perform'] ) && current_user_can( 'manage_options' ) ) { + if ( isset( $_GET['perform'] ) && current_user_can( 'manage_options' ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display toggle. add_action( 'wp_footer', [ $this, 'assets_manager_html' ], 1000 ); } } @@ -707,7 +707,7 @@ public function disable_group_assets_html( $type, $handle ) { * @return void */ public function disable_assets_html( $type, $handle ) { - $is_checked = ''; + $has_checked = false; $current_id = $this->get_current_object_id(); $radio_inputs = [ 'current' => esc_html__( 'Current URL', 'perform' ), @@ -722,19 +722,24 @@ public function disable_assets_html( $type, $handle ) { $value ) { $is_disabled_key = isset( $this->selected_options['disabled'][ $type ][ $handle ][ $key ] ) ? $this->selected_options['disabled'][ $type ][ $handle ][ $key ] : false; + $is_checked = false; if ( - empty( $is_checked ) && + ! $has_checked && $this->has_current_object_id( $current_id, $is_disabled_key ) ) { - $is_checked = " checked='checked'"; + $is_checked = true; } else { - $is_checked = checked( $is_disabled_key, 1, false ); + $is_checked = ! is_array( $is_disabled_key ) && (string) $is_disabled_key === '1'; + } + + if ( $is_checked ) { + $has_checked = true; } ?> selected_options['disabled'][ $type ] ); $is_disabled_handle = $is_disabled_type && isset( $this->selected_options['disabled'][ $type ][ $handle ] ); - $is_selected = ( $is_disabled_handle && is_array( $this->selected_options['disabled'][ $type ][ $handle ] ) ) ? 'selected="selected"' : ''; - $disable_class = ! empty( $is_selected ) ? 'disabled' : ''; + $is_selected = $is_disabled_handle && is_array( $this->selected_options['disabled'][ $type ][ $handle ] ); + $disable_class = $is_selected ? 'disabled' : ''; ?> @@ -786,19 +791,19 @@ public function print_assets_manager_status( $type, $handle ) { public function print_assets_manager_exceptions( $type, $handle ) { $current_id = $this->get_current_object_id(); $selected_post_types = isset( $this->selected_options['enabled'][ $type ][ $handle ]['post_types'] ) ? $this->selected_options['enabled'][ $type ][ $handle ]['post_types'] : false; - $is_selected = isset( $this->selected_options['disabled'][ $type ][ $handle ]['everywhere'] ) ? selected( $this->selected_options['disabled'][ $type ][ $handle ]['everywhere'], 1, false ) : ''; + $is_selected = isset( $this->selected_options['disabled'][ $type ][ $handle ]['everywhere'] ) && (string) $this->selected_options['disabled'][ $type ][ $handle ]['everywhere'] === '1'; $current_exception = isset( $this->selected_options['enabled'][ $type ][ $handle ]['current'] ) ? $this->selected_options['enabled'][ $type ][ $handle ]['current'] : false; - $is_current_checked = $this->has_current_object_id( $current_id, $current_exception ) ? ' checked="checked"' : ''; + $is_current_checked = $this->has_current_object_id( $current_id, $current_exception ); ?> -
> +
>
- -
@@ -844,18 +849,19 @@ public function print_assets_manager_exceptions( $type, $handle ) { * @return array */ public function save_assets_manager_settings() { - // Capability check. - if ( ! current_user_can( 'manage_options' ) ) { - return; - } - - // Require the expected nonce and verify it to protect against CSRF. - if ( ! isset( $_POST['perform_assets_manager_nonce'] ) || ! wp_verify_nonce( wp_unslash( $_POST['perform_assets_manager_nonce'] ), 'perform_assets_manager_save' ) ) { - return; - } - - $post_data = Helpers::clean( filter_input_array( INPUT_POST ) ); - $get_data = Helpers::clean( filter_input_array( INPUT_GET ) ); + // Capability check. + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + + // Require the expected nonce and verify it to protect against CSRF. + $assets_manager_nonce = isset( $_POST['perform_assets_manager_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['perform_assets_manager_nonce'] ) ) : ''; + if ( ! wp_verify_nonce( $assets_manager_nonce, 'perform_assets_manager_save' ) ) { + return; + } + + $post_data = Helpers::clean( filter_input_array( INPUT_POST ) ); + $get_data = Helpers::clean( filter_input_array( INPUT_GET ) ); if ( ! is_array( $post_data ) ) { $post_data = []; diff --git a/src/Modules/CDN/CDNManager.php b/src/Modules/CDN/CDNManager.php index f97e203..5cd9d47 100644 --- a/src/Modules/CDN/CDNManager.php +++ b/src/Modules/CDN/CDNManager.php @@ -80,7 +80,7 @@ public function rewrite_with_cdn_url( $html ) { $site_url = quotemeta( get_option( 'home' ) ); $url_regex = '(https?:|)' . substr( $site_url, strpos( $site_url, '//' ) ); $directories = 'wp\-content|wp\-includes'; - $cdn_directories = Helpers::get_option( 'cdn_directories', 'perform_settings' ); + $cdn_directories = Helpers::get_option( 'cdn_directories', 'perform_settings' ); if ( ! empty( $cdn_directories ) ) { $directory_list = array_map( 'trim', explode( ',', $cdn_directories ) ); @@ -106,10 +106,10 @@ public function rewrite_with_cdn_url( $html ) { * @return string */ public function rewrited_cdn_url( $url ) { - $cdn_url = Helpers::get_option( 'cdn_url', 'perform_settings' ); + $cdn_url = Helpers::get_option( 'cdn_url', 'perform_settings' ); if ( ! empty( $cdn_url ) ) { - $cdn_exclusions = Helpers::get_option( 'cdn_exclusions', 'perform_settings' ); + $cdn_exclusions = Helpers::get_option( 'cdn_exclusions', 'perform_settings' ); // Don't Rewrite URL, if Excluded. if ( ! empty( $cdn_exclusions ) ) { @@ -126,10 +126,10 @@ public function rewrited_cdn_url( $url ) { } // Don't Rewrite if Previewing. + $is_preview_request = isset( $_GET['preview'] ) && 'true' === sanitize_text_field( wp_unslash( $_GET['preview'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only preview bypass signal. if ( is_admin_bar_showing() && - isset( $_GET['preview'] ) && - 'true' === $_GET['preview'] + $is_preview_request ) { return $url[0]; } diff --git a/src/Modules/Cache/PageCache.php b/src/Modules/Cache/PageCache.php index 00000e1..168de96 100644 --- a/src/Modules/Cache/PageCache.php +++ b/src/Modules/Cache/PageCache.php @@ -872,7 +872,8 @@ private function is_cacheable_request() { return false; } - $path = isset( $_SERVER['REQUEST_URI'] ) ? wp_parse_url( wp_unslash( $_SERVER['REQUEST_URI'] ), PHP_URL_PATH ) : ''; + $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; + $path = '' !== $request_uri ? wp_parse_url( $request_uri, PHP_URL_PATH ) : ''; if ( is_string( $path ) ) { $path = untrailingslashit( strtolower( $path ) ); $blocked_paths = [ @@ -888,7 +889,7 @@ private function is_cacheable_request() { } } - if ( isset( $_GET['add-to-cart'] ) ) { + if ( isset( $_GET['add-to-cart'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only cache bypass signal. return false; } @@ -1164,7 +1165,7 @@ private function write_cache_body( $key, $body ) { */ private function write_file_atomically( $path, $contents ) { $directory = dirname( $path ); - if ( ! is_dir( $directory ) || ! is_writable( $directory ) ) { + if ( ! is_dir( $directory ) || ! wp_is_writable( $directory ) ) { return false; } diff --git a/src/Modules/Loader.php b/src/Modules/Loader.php index 1fb5ff0..8fe4741 100644 --- a/src/Modules/Loader.php +++ b/src/Modules/Loader.php @@ -13,67 +13,63 @@ // Bailout, if accessed directly. if ( ! defined( 'ABSPATH' ) ) { - exit; + exit; } class Loader { - /** - * Settings array passed from plugin bootstrap. - * - * @var array - */ - private $settings = []; + /** + * Settings array passed from plugin bootstrap. + * + * @var array + */ + private $settings = []; - public function __construct( array $settings = [] ) { - $this->settings = $settings ?: Helpers::get_settings() ?: []; - } + public function __construct( array $settings = [] ) { + $stored_settings = Helpers::get_settings(); + $this->settings = ! empty( $settings ) ? $settings : ( is_array( $stored_settings ) ? $stored_settings : [] ); + } - /** - * Register an array of module class names. - * - * @param array $modules List of fully-qualified class names. - * - * @return void - */ - public function register_modules( array $modules ) { - foreach ( $modules as $module_class ) { - if ( ! class_exists( $module_class ) ) { - continue; - } + /** + * Register an array of module class names. + * + * @param array $modules List of fully-qualified class names. + * + * @return void + */ + public function register_modules( array $modules ) { + foreach ( $modules as $module_class ) { + if ( ! class_exists( $module_class ) ) { + continue; + } - if ( ! is_subclass_of( $module_class, ModuleInterface::class ) ) { - if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { - error_log( sprintf( 'Perform: skipped %s because it does not implement ModuleInterface.', $module_class ) ); - } - continue; - } + if ( ! is_subclass_of( $module_class, ModuleInterface::class ) ) { + do_action( 'perform_module_invalid', $module_class, ModuleInterface::class ); + continue; + } - try { - // Modules extending AbstractModule support settings injection. - if ( is_subclass_of( $module_class, AbstractModule::class ) ) { - $module = new $module_class( $this->settings ); - } else { - $module = new $module_class(); - } - } catch ( \Throwable $e ) { - /** - * Fires when a module cannot be instantiated. - * - * @param string $module_class Module class name. - * @param string $message Error message. - * @param \Throwable $e Exception/error object. - */ - do_action( 'perform_module_load_error', $module_class, $e->getMessage(), $e ); + try { + // Modules extending AbstractModule support settings injection. + if ( is_subclass_of( $module_class, AbstractModule::class ) ) { + $module = new $module_class( $this->settings ); + } else { + $module = new $module_class(); + } + } catch ( \Throwable $e ) { + /** + * Fires when a module cannot be instantiated. + * + * @param string $module_class Module class name. + * @param string $message Error message. + * @param \Throwable $e Exception/error object. + */ + do_action( 'perform_module_load_error', $module_class, $e->getMessage(), $e ); - if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { - error_log( sprintf( 'Perform: failed to instantiate %s — %s', $module_class, $e->getMessage() ) ); - } - continue; - } + continue; + } - if ( $module->should_load() ) { - $module->register(); - } - } - } + if ( $module->should_load() ) { + $module->register(); + } + } + } } diff --git a/src/Modules/SSL/SSLManager.php b/src/Modules/SSL/SSLManager.php index deabcf1..3be9192 100644 --- a/src/Modules/SSL/SSLManager.php +++ b/src/Modules/SSL/SSLManager.php @@ -80,14 +80,14 @@ public function maybe_redirect_to_ssl() { */ public function wp_redirect_to_ssl() { // Prefer the configured site URL host instead of trusting HTTP_HOST. - $host = parse_url( home_url(), PHP_URL_HOST ); + $host = wp_parse_url( home_url(), PHP_URL_HOST ); // Fallback to server host if site URL parsing fails. if ( empty( $host ) && ! empty( $_SERVER['HTTP_HOST'] ) ) { $host = sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ); } - $uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '/'; + $uri = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '/'; $redirect_url = set_url_scheme( 'https://' . $host . $uri, 'https' ); $redirect_url = apply_filters( 'perform_wp_redirect_url_to_ssl', $redirect_url ); diff --git a/src/Plugin.php b/src/Plugin.php index 298010c..93e6d69 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -33,9 +33,6 @@ public function register() { // Register services used throughout the plugin. add_action( 'plugins_loaded', [ $this, 'register_services' ] ); - - // Load text domain. - add_action( 'init', [ $this, 'load_plugin_textdomain' ] ); } /** @@ -65,12 +62,13 @@ public function register_services() { // Centralized module loader - preserves backward compatibility with // modules that still register hooks in their constructors while // supporting new modules implementing ModuleInterface. - $settings = Helpers::get_settings() ?: []; + $settings = Helpers::get_settings(); + $settings = is_array( $settings ) ? $settings : []; - $loader = new Modules\Loader( $settings ); + $loader = new Modules\Loader( $settings ); - $loader->register_modules( Modules\Registry::all() ); - } + $loader->register_modules( Modules\Registry::all() ); + } /** * Loads the Freemius SDK. @@ -82,36 +80,22 @@ public function register_services() { */ public function load_freemius() { // Include Freemius SDK. - $perform_fs = fs_dynamic_init( array( - 'id' => '18658', - 'slug' => 'perform', - 'type' => 'plugin', - 'public_key' => 'pk_d4518e758d9fc19cb25ffe77371fa', - 'is_premium' => false, - 'has_addons' => false, - 'has_paid_plans' => false, - 'menu' => array( - 'slug' => 'perform_settings', - 'parent' => array( - 'slug' => 'options-general.php', - ), - ), - ) ); - } - - /** - * Loads the plugin's translated strings. - * - * @since 1.0.0 - * @access public - * - * @return void - */ - public function load_plugin_textdomain() { - load_plugin_textdomain( - 'perform', - false, - dirname( plugin_basename( PERFORM_PLUGIN_FILE ) ) . '/languages/' + $perform_fs = fs_dynamic_init( + [ + 'id' => '18658', + 'slug' => 'perform', + 'type' => 'plugin', + 'public_key' => 'pk_d4518e758d9fc19cb25ffe77371fa', + 'is_premium' => false, + 'has_addons' => false, + 'has_paid_plans' => false, + 'menu' => [ + 'slug' => 'perform_settings', + 'parent' => [ + 'slug' => 'options-general.php', + ], + ], + ] ); }