X7ROOT File Manager
Current Path:
/home/gfecatvj/sites/radon/wp-content/plugins/w3-total-cache
home
/
gfecatvj
/
sites
/
radon
/
wp-content
/
plugins
/
w3-total-cache
/
📁
..
📄
AGENTS.md
(3.19 KB)
📄
Base_Page_Settings.php
(6.82 KB)
📄
BrowserCache_ConfigLabels.php
(14.29 KB)
📄
BrowserCache_Core.php
(3.19 KB)
📄
BrowserCache_Environment.php
(31.64 KB)
📄
BrowserCache_Environment_Apache.php
(3.38 KB)
📄
BrowserCache_Environment_LiteSpeed.php
(8.41 KB)
📄
BrowserCache_Environment_Nginx.php
(26.05 KB)
📄
BrowserCache_Page.php
(3.28 KB)
📄
BrowserCache_Page_View_QuickReference.php
(2.58 KB)
📄
BrowserCache_Page_View_SectionSecurity.php
(61.6 KB)
📄
BrowserCache_Plugin.php
(15.38 KB)
📄
BrowserCache_Plugin_Admin.php
(1.33 KB)
📄
Cache.php
(4.52 KB)
📄
CacheFlush.php
(8.16 KB)
📄
CacheFlush_Locally.php
(12.6 KB)
📄
CacheGroups_Plugin_Admin.php
(7.98 KB)
📄
CacheGroups_Plugin_Admin_View.js
(17.23 KB)
📄
CacheGroups_Plugin_Admin_View.php
(15.17 KB)
📄
Cache_Apc.php
(7.75 KB)
📄
Cache_Apcu.php
(7.77 KB)
📄
Cache_Base.php
(6.49 KB)
📄
Cache_Eaccelerator.php
(7.58 KB)
📄
Cache_File.php
(21.3 KB)
📄
Cache_File_Cleaner.php
(2.8 KB)
📄
Cache_File_Cleaner_Generic.php
(4.05 KB)
📄
Cache_File_Cleaner_Generic_HardDelete.php
(1.05 KB)
📄
Cache_File_Generic.php
(13.22 KB)
📄
Cache_Memcache.php
(14.69 KB)
📄
Cache_Memcached.php
(20.52 KB)
📄
Cache_Memcached_Stats.php
(3.52 KB)
📄
Cache_Nginx_Memcached.php
(13.55 KB)
📄
Cache_Redis.php
(16.6 KB)
📄
Cache_Wincache.php
(12.72 KB)
📄
Cache_Xcache.php
(11.55 KB)
📄
CdnEngine.php
(2.54 KB)
📄
CdnEngine_Azure.php
(12.65 KB)
📄
CdnEngine_Azure_MI.php
(12.28 KB)
📄
CdnEngine_Azure_MI_Utility.php
(18.19 KB)
📄
CdnEngine_Base.php
(16.37 KB)
📄
CdnEngine_CloudFront.php
(12.38 KB)
📄
CdnEngine_Ftp.php
(21.08 KB)
📄
CdnEngine_GoogleDrive.php
(24.14 KB)
📄
CdnEngine_Mirror.php
(2.46 KB)
📄
CdnEngine_Mirror_Akamai.php
(3.52 KB)
📄
CdnEngine_Mirror_Att.php
(293 B)
📄
CdnEngine_Mirror_BunnyCdn.php
(4.3 KB)
📄
CdnEngine_Mirror_CloudFront.php
(10.48 KB)
📄
CdnEngine_Mirror_Cotendo.php
(3.72 KB)
📄
CdnEngine_Mirror_Edgecast.php
(4.46 KB)
📄
CdnEngine_Mirror_RackSpaceCdn.php
(6.57 KB)
📄
CdnEngine_RackSpaceCloudFiles.php
(12.01 KB)
📄
CdnEngine_S3.php
(17.55 KB)
📄
CdnEngine_S3_Compatible.php
(10.36 KB)
📄
Cdn_AdminActions.php
(16.93 KB)
📄
Cdn_AdminNotes.php
(13.71 KB)
📄
Cdn_BunnyCdn_Api.php
(15.67 KB)
📄
Cdn_BunnyCdn_Page.php
(7.54 KB)
📄
Cdn_BunnyCdn_Page_View.js
(7.36 KB)
📄
Cdn_BunnyCdn_Page_View.php
(3.6 KB)
📄
Cdn_BunnyCdn_Page_View_Purge_Urls.php
(2.19 KB)
📄
Cdn_BunnyCdn_Popup.php
(10.83 KB)
📄
Cdn_BunnyCdn_Popup_View_Configured.php
(864 B)
📄
Cdn_BunnyCdn_Popup_View_Deauthorize.php
(2.15 KB)
📄
Cdn_BunnyCdn_Popup_View_Deauthorized.php
(1.54 KB)
📄
Cdn_BunnyCdn_Popup_View_Intro.php
(1.83 KB)
📄
Cdn_BunnyCdn_Popup_View_Pull_Zones.php
(5.16 KB)
📄
Cdn_BunnyCdn_Widget.php
(2.25 KB)
📄
Cdn_BunnyCdn_Widget_View.css
(1.26 KB)
📄
Cdn_BunnyCdn_Widget_View_Authorized.php
(1.9 KB)
📄
Cdn_BunnyCdn_Widget_View_Unauthorized.php
(6.1 KB)
📄
Cdn_CacheFlush.php
(2.64 KB)
📄
Cdn_ConfigLabels.php
(6.89 KB)
📄
Cdn_Core.php
(33.06 KB)
📄
Cdn_Core_Admin.php
(27.2 KB)
📄
Cdn_Environment.php
(19.29 KB)
📄
Cdn_Environment_LiteSpeed.php
(5.19 KB)
📄
Cdn_Environment_Nginx.php
(3.92 KB)
📄
Cdn_GeneralPage_View.php
(4.05 KB)
📄
Cdn_GoogleDrive_AdminActions.php
(3.53 KB)
📄
Cdn_GoogleDrive_Page.php
(2.03 KB)
📄
Cdn_GoogleDrive_Page_View.js
(488 B)
📄
Cdn_GoogleDrive_Page_View.php
(1.36 KB)
📄
Cdn_GoogleDrive_Popup_AuthReturn.php
(1.61 KB)
📄
Cdn_GoogleDrive_Popup_AuthReturn_View.php
(1.66 KB)
📄
Cdn_Page.php
(3.5 KB)
📄
Cdn_Page_View_Fsd_HeaderActions.php
(760 B)
📄
Cdn_Plugin.php
(43.91 KB)
📄
Cdn_Plugin_Admin.php
(7.72 KB)
📄
Cdn_RackSpaceCdn_AdminActions.php
(1.28 KB)
📄
Cdn_RackSpaceCdn_Page.php
(2.05 KB)
📄
Cdn_RackSpaceCdn_Page_View.js
(4.28 KB)
📄
Cdn_RackSpaceCdn_Page_View.php
(5.22 KB)
📄
Cdn_RackSpaceCdn_Popup.php
(21.49 KB)
📄
Cdn_RackSpaceCdn_Popup_View_ConfigureDomains.php
(1.87 KB)
📄
Cdn_RackSpaceCdn_Popup_View_Intro.php
(1.71 KB)
📄
Cdn_RackSpaceCdn_Popup_View_Regions.php
(1.76 KB)
📄
Cdn_RackSpaceCdn_Popup_View_Service_Actualize.php
(2.04 KB)
📄
Cdn_RackSpaceCdn_Popup_View_Service_Create.php
(4.41 KB)
📄
Cdn_RackSpaceCdn_Popup_View_Service_Created.php
(2.48 KB)
📄
Cdn_RackSpaceCdn_Popup_View_Services.php
(1.99 KB)
📄
Cdn_RackSpaceCloudFiles_Page.php
(1.67 KB)
📄
Cdn_RackSpaceCloudFiles_Page_View.js
(681 B)
📄
Cdn_RackSpaceCloudFiles_Page_View.php
(4.91 KB)
📄
Cdn_RackSpaceCloudFiles_Popup.php
(7.62 KB)
📄
Cdn_RackSpaceCloudFiles_Popup_View_Containers.php
(2.06 KB)
📄
Cdn_RackSpaceCloudFiles_Popup_View_Intro.php
(1.71 KB)
📄
Cdn_RackSpaceCloudFiles_Popup_View_Regions.php
(1.78 KB)
📄
Cdn_RackSpace_Api_CaCert-example.pem
(195.74 KB)
📄
Cdn_RackSpace_Api_Cdn.php
(10.72 KB)
📄
Cdn_RackSpace_Api_CloudFiles.php
(8.38 KB)
📄
Cdn_RackSpace_Api_CloudFilesCdn.php
(8.48 KB)
📄
Cdn_RackSpace_Api_Tokens.php
(6.78 KB)
📄
Cdn_Util.php
(6.73 KB)
📄
Cdnfsd_BunnyCdn_Engine.php
(2.03 KB)
📄
Cdnfsd_BunnyCdn_Page.php
(683 B)
📄
Cdnfsd_BunnyCdn_Page_View.js
(3.92 KB)
📄
Cdnfsd_BunnyCdn_Page_View.php
(3.72 KB)
📄
Cdnfsd_BunnyCdn_Popup.php
(10.39 KB)
📄
Cdnfsd_BunnyCdn_Popup_View_Configured.php
(1.3 KB)
📄
Cdnfsd_BunnyCdn_Popup_View_Deauthorize.php
(2.17 KB)
📄
Cdnfsd_BunnyCdn_Popup_View_Deauthorized.php
(1.56 KB)
📄
Cdnfsd_BunnyCdn_Popup_View_Intro.php
(1.85 KB)
📄
Cdnfsd_BunnyCdn_Popup_View_Pull_Zones.php
(5.57 KB)
📄
Cdnfsd_CacheFlush.php
(8.25 KB)
📄
Cdnfsd_CloudFront_Engine.php
(3.38 KB)
📄
Cdnfsd_CloudFront_Page.php
(741 B)
📄
Cdnfsd_CloudFront_Page_View.js
(2.73 KB)
📄
Cdnfsd_CloudFront_Page_View.php
(2.04 KB)
📄
Cdnfsd_CloudFront_Popup.php
(15.46 KB)
📄
Cdnfsd_CloudFront_Popup_View_Distribution.php
(3.34 KB)
📄
Cdnfsd_CloudFront_Popup_View_Distributions.php
(1.72 KB)
📄
Cdnfsd_CloudFront_Popup_View_Intro.php
(1.65 KB)
📄
Cdnfsd_CloudFront_Popup_View_Success.php
(976 B)
📄
Cdnfsd_Core.php
(1.96 KB)
📄
Cdnfsd_GeneralPage_View.php
(4.02 KB)
📄
Cdnfsd_Plugin.php
(1.98 KB)
📄
Cdnfsd_Plugin_Admin.php
(2.63 KB)
📄
Cdnfsd_TransparentCDN_Engine.php
(7.97 KB)
📄
Cdnfsd_TransparentCDN_Page.php
(1.55 KB)
📄
Cdnfsd_TransparentCDN_Page_View.js
(1.36 KB)
📄
Cdnfsd_TransparentCDN_Page_View.php
(2.33 KB)
📄
Cdnfsd_Util.php
(834 B)
📄
Cli.php
(17.33 KB)
📄
Config.php
(16.8 KB)
📄
ConfigCache.php
(4.67 KB)
📄
ConfigCompiler.php
(17.87 KB)
📄
ConfigDbStorage.php
(15.87 KB)
📄
ConfigKeys.php
(69.97 KB)
📄
ConfigSettingsTabs.php
(1.18 KB)
📄
ConfigSettingsTabsKeys.php
(23.62 KB)
📄
ConfigState.php
(6.16 KB)
📄
ConfigStateNote.php
(1.94 KB)
📄
ConfigUtil.php
(3.45 KB)
📄
DbCache_ConfigLabels.php
(1.62 KB)
📄
DbCache_Core.php
(2.05 KB)
📄
DbCache_Environment.php
(6.41 KB)
📄
DbCache_Page.php
(1.1 KB)
📄
DbCache_Plugin.php
(9.93 KB)
📄
DbCache_Plugin_Admin.php
(5.08 KB)
📄
DbCache_Wpdb.php
(1.63 KB)
📄
DbCache_WpdbBase.php
(346 B)
📄
DbCache_WpdbInjection.php
(7.15 KB)
📄
DbCache_WpdbInjection_QueryCaching.php
(26.39 KB)
📄
DbCache_WpdbLegacy.php
(22.61 KB)
📄
DbCache_WpdbNew.php
(22.42 KB)
📄
Dispatcher.php
(8.21 KB)
📄
Enterprise_CacheFlush_MakeSnsEvent.php
(7.47 KB)
📄
Enterprise_Dbcache_WpdbInjection_Cluster.php
(30.34 KB)
📄
Enterprise_SnsBase.php
(3.07 KB)
📄
Enterprise_SnsServer.php
(5.17 KB)
📄
Extension_AlwaysCached_AdminActions.php
(2.36 KB)
📄
Extension_AlwaysCached_Environment.php
(2.87 KB)
📄
Extension_AlwaysCached_Page.php
(4 KB)
📄
Extension_AlwaysCached_Page_Queue_View.php
(3.14 KB)
📄
Extension_AlwaysCached_Page_View.js
(7.26 KB)
📄
Extension_AlwaysCached_Page_View.php
(2.51 KB)
📄
Extension_AlwaysCached_Page_View_BoxCron.php
(2.92 KB)
📄
Extension_AlwaysCached_Page_View_BoxFlushAll.php
(3.28 KB)
📄
Extension_AlwaysCached_Page_View_BoxQueue.php
(4.35 KB)
📄
Extension_AlwaysCached_Page_View_Exclusions.php
(1.11 KB)
📄
Extension_AlwaysCached_Plugin.php
(12.2 KB)
📄
Extension_AlwaysCached_Plugin_Admin.php
(3.06 KB)
📄
Extension_AlwaysCached_Queue.php
(10.22 KB)
📄
Extension_AlwaysCached_Worker.php
(2.93 KB)
📄
Extension_Amp_Page_View.php
(1.26 KB)
📄
Extension_Amp_Plugin.php
(11.1 KB)
📄
Extension_Amp_Plugin_Admin.php
(2.19 KB)
📄
Extension_CloudFlare_AdminActions.php
(1.57 KB)
📄
Extension_CloudFlare_Api.php
(12.19 KB)
📄
Extension_CloudFlare_Cdn_Page_View.php
(625 B)
📄
Extension_CloudFlare_GeneralPage_View.php
(3.05 KB)
📄
Extension_CloudFlare_Page.php
(4.32 KB)
📄
Extension_CloudFlare_Page_View.js
(1.15 KB)
📄
Extension_CloudFlare_Page_View.php
(27.38 KB)
📄
Extension_CloudFlare_Plugin.php
(15.22 KB)
📄
Extension_CloudFlare_Plugin_Admin.php
(14.6 KB)
📄
Extension_CloudFlare_Popup.php
(4.21 KB)
📄
Extension_CloudFlare_Popup_View_Intro.php
(1.75 KB)
📄
Extension_CloudFlare_Popup_View_Zones.php
(2.09 KB)
📄
Extension_CloudFlare_SettingsForUi.php
(4.84 KB)
📄
Extension_CloudFlare_View_Dashboard.js
(730 B)
📄
Extension_CloudFlare_Widget.php
(4.63 KB)
📄
Extension_CloudFlare_Widget_Logo.png
(6.96 KB)
📄
Extension_CloudFlare_Widget_View.css
(683 B)
📄
Extension_CloudFlare_Widget_View.php
(1.65 KB)
📄
Extension_FragmentCache_Api.php
(7.01 KB)
📄
Extension_FragmentCache_Core.php
(3.38 KB)
📄
Extension_FragmentCache_Environment.php
(1.41 KB)
📄
Extension_FragmentCache_GeneralPage.php
(1.27 KB)
📄
Extension_FragmentCache_GeneralPage_View.php
(2.53 KB)
📄
Extension_FragmentCache_Page.php
(697 B)
📄
Extension_FragmentCache_Page_View.php
(5.25 KB)
📄
Extension_FragmentCache_Plugin.php
(8.21 KB)
📄
Extension_FragmentCache_Plugin_Admin.php
(9.21 KB)
📄
Extension_FragmentCache_WpObjectCache.php
(16.91 KB)
📄
Extension_Genesis_Page.php
(409 B)
📄
Extension_Genesis_Page_View.php
(11.12 KB)
📄
Extension_Genesis_Plugin.php
(14.46 KB)
📄
Extension_Genesis_Plugin_Admin.php
(5.45 KB)
📄
Extension_ImageService_Api.php
(14.89 KB)
📄
Extension_ImageService_Cron.php
(13.7 KB)
📄
Extension_ImageService_Environment.php
(8.52 KB)
📄
Extension_ImageService_Page_View.php
(10.03 KB)
📄
Extension_ImageService_Plugin.php
(1.44 KB)
📄
Extension_ImageService_Plugin_Admin.css
(2.34 KB)
📄
Extension_ImageService_Plugin_Admin.js
(25.71 KB)
📄
Extension_ImageService_Plugin_Admin.php
(71.88 KB)
📄
Extension_ImageService_Widget.js
(6.17 KB)
📄
Extension_ImageService_Widget.php
(3.34 KB)
📄
Extension_ImageService_Widget_View.php
(1.59 KB)
📄
Extension_NewRelic_AdminActions.php
(1.11 KB)
📄
Extension_NewRelic_AdminNotes.php
(2.11 KB)
📄
Extension_NewRelic_Api.php
(4.34 KB)
📄
Extension_NewRelic_Core.php
(1.33 KB)
📄
Extension_NewRelic_GeneralPage.php
(1.53 KB)
📄
Extension_NewRelic_GeneralPage_View.php
(2.84 KB)
📄
Extension_NewRelic_Page.php
(1.35 KB)
📄
Extension_NewRelic_Page_View_Apm.php
(12.97 KB)
📄
Extension_NewRelic_Plugin.php
(7.07 KB)
📄
Extension_NewRelic_Plugin_Admin.php
(8.1 KB)
📄
Extension_NewRelic_Popup.php
(6.05 KB)
📄
Extension_NewRelic_Popup_View.js
(2.84 KB)
📄
Extension_NewRelic_Popup_View_Intro.php
(1.37 KB)
📄
Extension_NewRelic_Popup_View_ListApplications.php
(4.2 KB)
📄
Extension_NewRelic_Service.php
(23.65 KB)
📄
Extension_NewRelic_Widget.php
(10.85 KB)
📄
Extension_NewRelic_Widget_View.css
(1.37 KB)
📄
Extension_NewRelic_Widget_View.js
(2.24 KB)
📄
Extension_NewRelic_Widget_View_Apm.php
(2.91 KB)
📄
Extension_NewRelic_Widget_View_Browser.php
(436 B)
📄
Extension_NewRelic_Widget_View_NotConfigured.php
(233 B)
📄
Extension_Swarmify_AdminActions.php
(793 B)
📄
Extension_Swarmify_Core.php
(748 B)
📄
Extension_Swarmify_Page.php
(708 B)
📄
Extension_Swarmify_Page_View.php
(2.78 KB)
📄
Extension_Swarmify_Plugin.php
(4.63 KB)
📄
Extension_Swarmify_Plugin_Admin.php
(2.63 KB)
📄
Extension_WordPressSeo_Plugin.php
(1.39 KB)
📄
Extension_WordPressSeo_Plugin_Admin.php
(5.25 KB)
📄
Extension_Wpml_Plugin.php
(1.34 KB)
📄
Extension_Wpml_Plugin_Admin.php
(7.45 KB)
📄
Extensions_AdminActions.php
(943 B)
📄
Extensions_Page.php
(4.06 KB)
📄
Extensions_Plugin_Admin.php
(9.67 KB)
📄
Extensions_Util.php
(4.43 KB)
📄
FeatureShowcase_Plugin_Admin.php
(29.12 KB)
📄
FeatureShowcase_Plugin_Admin_View.php
(2.82 KB)
📄
Generic_AdminActions_Config.php
(6.61 KB)
📄
Generic_AdminActions_Default.php
(21.84 KB)
📄
Generic_AdminActions_Flush.php
(11.19 KB)
📄
Generic_AdminActions_Test.php
(6.19 KB)
📄
Generic_AdminNotes.php
(13.88 KB)
📄
Generic_ConfigLabels.php
(4.08 KB)
📄
Generic_Environment.php
(6.67 KB)
📄
Generic_Faq.php
(2.27 KB)
📄
Generic_GeneralPage_View_ShowEdge.js
(314 B)
📄
Generic_Page_About.php
(503 B)
📄
Generic_Page_Dashboard.php
(1.66 KB)
📄
Generic_Page_Dashboard_View.css
(6.33 KB)
📄
Generic_Page_General.php
(2.88 KB)
📄
Generic_Page_Install.php
(913 B)
📄
Generic_Page_PurgeLog.php
(2.81 KB)
📄
Generic_Page_PurgeLog_View.php
(2.97 KB)
📄
Generic_Plugin.php
(34.74 KB)
📄
Generic_Plugin_Admin.php
(50.76 KB)
📄
Generic_Plugin_AdminCompatibility.php
(4.02 KB)
📄
Generic_Plugin_AdminNotices.css
(188 B)
📄
Generic_Plugin_AdminNotices.js
(1.66 KB)
📄
Generic_Plugin_AdminNotices.php
(12.19 KB)
📄
Generic_Plugin_AdminRowActions.php
(2.43 KB)
📄
Generic_Plugin_Admin_View_Faq.php
(1007 B)
📄
Generic_Plugin_Survey.php
(4.8 KB)
📄
Generic_WidgetAccount.php
(1.05 KB)
📄
Generic_WidgetAccount_View.php
(2.1 KB)
📄
Generic_WidgetBoldGrid.php
(1.97 KB)
📄
Generic_WidgetBoldGrid_AdminActions.php
(912 B)
📄
Generic_WidgetBoldGrid_Logo.svg
(4.28 KB)
📄
Generic_WidgetBoldGrid_View.js
(625 B)
📄
Generic_WidgetBoldGrid_View.php
(872 B)
📄
Generic_WidgetPartners.php
(1.08 KB)
📄
Generic_WidgetPartners_View.php
(1.73 KB)
📄
Generic_WidgetServices.php
(1.66 KB)
📄
Generic_WidgetServices_View.php
(501 B)
📄
Generic_WidgetSettings.php
(1.05 KB)
📄
Generic_WidgetSettings_View.php
(3.37 KB)
📄
Generic_WidgetSpreadTheWord.js
(879 B)
📄
Generic_WidgetSpreadTheWord_Plugin.php
(2.03 KB)
📄
Generic_WidgetSpreadTheWord_View.php
(579 B)
📄
Generic_WidgetStats.js
(3.3 KB)
📄
Generic_WidgetStats.php
(4.84 KB)
📄
LICENSE
(17.67 KB)
📄
Licensing_AdminActions.php
(4.22 KB)
📄
Licensing_Core.php
(6.24 KB)
📄
Licensing_Plugin_Admin.php
(36.41 KB)
📄
Minify_AutoCss.php
(8.83 KB)
📄
Minify_AutoJs.php
(13.36 KB)
📄
Minify_ConfigLabels.php
(12.84 KB)
📄
Minify_ContentMinifier.php
(10.24 KB)
📄
Minify_Core.php
(7.42 KB)
📄
Minify_Environment.php
(26.91 KB)
📄
Minify_Environment_LiteSpeed.php
(977 B)
📄
Minify_Extract.php
(2.8 KB)
📄
Minify_GeneralPage_View_ShowHelp.js
(1.12 KB)
📄
Minify_GeneralPage_View_ShowHelpForce.js
(51 B)
📄
Minify_HelpPopup_View.php
(5.01 KB)
📄
Minify_MinifiedFileRequestHandler.php
(33.92 KB)
📄
Minify_Page.php
(18.5 KB)
📄
Minify_Plugin.php
(43.49 KB)
📄
Minify_Plugin_Admin.php
(12.92 KB)
📄
Mobile_Base.php
(6.85 KB)
📄
Mobile_Redirect.php
(1.85 KB)
📄
Mobile_Referrer.php
(2.4 KB)
📄
Mobile_UserAgent.php
(971 B)
📄
ModuleStatus.php
(4.37 KB)
📄
ObjectCache_ConfigLabels.php
(1.58 KB)
📄
ObjectCache_DiskPopup.js
(2.41 KB)
📄
ObjectCache_DiskPopup_View.php
(1.85 KB)
📄
ObjectCache_Environment.php
(6.79 KB)
📄
ObjectCache_Page.php
(560 B)
📄
ObjectCache_Page_View_PurgeLog.php
(1.01 KB)
📄
ObjectCache_Plugin.php
(6.63 KB)
📄
ObjectCache_Plugin_Admin.php
(6.97 KB)
📄
ObjectCache_WpObjectCache.php
(10.17 KB)
📄
ObjectCache_WpObjectCache_Regular.php
(39.6 KB)
📄
PageSpeed_Api.php
(12.12 KB)
📄
PageSpeed_Data.php
(15.23 KB)
📄
PageSpeed_Instructions.php
(41.99 KB)
📄
PageSpeed_Page.php
(8.76 KB)
📄
PageSpeed_Page_View.css
(7.34 KB)
📄
PageSpeed_Page_View.js
(9.48 KB)
📄
PageSpeed_Page_View.php
(2.08 KB)
📄
PageSpeed_Page_View_FromAPI.php
(7.65 KB)
📄
PageSpeed_Widget.php
(7.03 KB)
📄
PageSpeed_Widget_View.css
(2.62 KB)
📄
PageSpeed_Widget_View.js
(2.08 KB)
📄
PageSpeed_Widget_View.php
(1.09 KB)
📄
PageSpeed_Widget_View_FromApi.php
(3.71 KB)
📄
PgCache_ConfigLabels.php
(7.8 KB)
📄
PgCache_ContentGrabber.php
(71.49 KB)
📄
PgCache_Environment.php
(52.36 KB)
📄
PgCache_Flush.php
(16.32 KB)
📄
PgCache_Page.php
(1.6 KB)
📄
PgCache_Page_View.js
(553 B)
📄
PgCache_Plugin.php
(14.33 KB)
📄
PgCache_Plugin_Admin.php
(14.93 KB)
📄
PgCache_QsExempts.php
(1.88 KB)
📄
Root_AdminActions.php
(3.05 KB)
📄
Root_AdminActivation.php
(6.52 KB)
📄
Root_AdminMenu.php
(8.37 KB)
📄
Root_Environment.php
(7.81 KB)
📄
Root_Loader.php
(6.94 KB)
📄
SetupGuide_Plugin_Admin.php
(57.96 KB)
📄
Support_AdminActions.php
(6.14 KB)
📄
Support_Page.php
(3.08 KB)
📄
Support_Page_View_DoneContent.php
(353 B)
📄
Support_Page_View_PageContent.php
(1.39 KB)
📄
SystemOpCache_AdminActions.php
(1.18 KB)
📄
SystemOpCache_Core.php
(2.48 KB)
📄
SystemOpCache_GeneralPage_View.php
(2.27 KB)
📄
SystemOpCache_Plugin_Admin.php
(3.37 KB)
📄
UsageStatistics_AdminActions.php
(1.14 KB)
📄
UsageStatistics_Core.php
(3.39 KB)
📄
UsageStatistics_GeneralPage.php
(1.6 KB)
📄
UsageStatistics_GeneralPage_View.php
(6.18 KB)
📄
UsageStatistics_Page.php
(8.4 KB)
📄
UsageStatistics_Page_DbRequests_View.php
(1.79 KB)
📄
UsageStatistics_Page_ObjectCacheLog_View.php
(1.97 KB)
📄
UsageStatistics_Page_PageCacheRequests_View.php
(1.86 KB)
📄
UsageStatistics_Page_View.css
(2.73 KB)
📄
UsageStatistics_Page_View.js
(21.37 KB)
📄
UsageStatistics_Page_View.php
(17.13 KB)
📄
UsageStatistics_Page_View_Ad.php
(688 B)
📄
UsageStatistics_Page_View_Disabled.php
(610 B)
📄
UsageStatistics_Page_View_Free.php
(635 B)
📄
UsageStatistics_Page_View_NoDebugMode.php
(615 B)
📄
UsageStatistics_Plugin.php
(2.89 KB)
📄
UsageStatistics_Plugin_Admin.php
(5.65 KB)
📄
UsageStatistics_Source_AccessLog.php
(17.47 KB)
📄
UsageStatistics_Source_DbQueriesLog.php
(6.04 KB)
📄
UsageStatistics_Source_ObjectCacheLog.php
(5.57 KB)
📄
UsageStatistics_Source_PageCacheLog.php
(6.11 KB)
📄
UsageStatistics_Source_Wpdb.php
(3.49 KB)
📄
UsageStatistics_Sources.php
(5.41 KB)
📄
UsageStatistics_Sources_Apc.php
(3.39 KB)
📄
UsageStatistics_Sources_Memcached.php
(4.58 KB)
📄
UsageStatistics_Sources_Redis.php
(4.69 KB)
📄
UsageStatistics_StorageReader.php
(2.81 KB)
📄
UsageStatistics_StorageWriter.php
(14.38 KB)
📄
UserExperience_DeferScripts_Extension.php
(7.04 KB)
📄
UserExperience_DeferScripts_Mutator.php
(2.78 KB)
📄
UserExperience_DeferScripts_Page_View.php
(3.91 KB)
📄
UserExperience_DeferScripts_Script.js
(373 B)
📄
UserExperience_Emoji_Extension.php
(3.04 KB)
📄
UserExperience_GeneralPage.php
(1.72 KB)
📄
UserExperience_GeneralPage_View.php
(8.21 KB)
📄
UserExperience_LazyLoad_GoogleMaps_GoogleMapsEasy.php
(3.89 KB)
📄
UserExperience_LazyLoad_GoogleMaps_WPGoogleMapPlugin.php
(2.14 KB)
📄
UserExperience_LazyLoad_GoogleMaps_WPGoogleMaps.php
(3.94 KB)
📄
UserExperience_LazyLoad_Mutator.php
(9.36 KB)
📄
UserExperience_LazyLoad_Mutator_Picture.php
(2.52 KB)
📄
UserExperience_LazyLoad_Mutator_Unmutable.php
(2.88 KB)
📄
UserExperience_LazyLoad_Page_View.php
(6.46 KB)
📄
UserExperience_LazyLoad_Plugin.php
(9.17 KB)
📄
UserExperience_OEmbed_Extension.php
(795 B)
📄
UserExperience_Page.php
(527 B)
📄
UserExperience_Page_View.php
(695 B)
📄
UserExperience_Plugin_Admin.php
(3.49 KB)
📄
UserExperience_Plugin_Jquery.php
(1.4 KB)
📄
UserExperience_Preload_Requests_Extension.php
(6.15 KB)
📄
UserExperience_Preload_Requests_Page_View.php
(8.79 KB)
📄
UserExperience_Remove_CssJs_Extension.php
(6.79 KB)
📄
UserExperience_Remove_CssJs_Mutator.php
(4.45 KB)
📄
UserExperience_Remove_CssJs_Page_View.js
(10.2 KB)
📄
UserExperience_Remove_CssJs_Page_View.php
(14.59 KB)
📄
Util_Activation.php
(10.38 KB)
📄
Util_Admin.php
(25.03 KB)
📄
Util_AttachToActions.php
(7.65 KB)
📄
Util_Bus.php
(832 B)
📄
Util_ConfigLabel.php
(1.57 KB)
📄
Util_Content.php
(3.03 KB)
📄
Util_Debug.php
(6.38 KB)
📄
Util_DebugPurgeLog_Reader.php
(3.36 KB)
📄
Util_Environment.php
(43.16 KB)
📄
Util_Environment_Exception.php
(719 B)
📄
Util_Environment_Exceptions.php
(1.42 KB)
📄
Util_File.php
(13.43 KB)
📄
Util_Http.php
(6.63 KB)
📄
Util_Installed.php
(4.24 KB)
📄
Util_Mime.php
(2.9 KB)
📄
Util_PageSpeed.php
(44.06 KB)
📄
Util_PageUrls.php
(32.57 KB)
📄
Util_Request.php
(3.52 KB)
📄
Util_Rule.php
(13.83 KB)
📄
Util_Theme.php
(3.87 KB)
📄
Util_Ui.php
(83.76 KB)
📄
Util_UsageStatistics.php
(13.6 KB)
📄
Util_Widget.php
(7.94 KB)
📄
Util_WpFile.php
(16.48 KB)
📄
Util_WpFile_FilesystemChmodException.php
(1.66 KB)
📄
Util_WpFile_FilesystemCopyException.php
(1.79 KB)
📄
Util_WpFile_FilesystemMkdirException.php
(1.14 KB)
📄
Util_WpFile_FilesystemModifyException.php
(2.35 KB)
📄
Util_WpFile_FilesystemOperationException.php
(1.29 KB)
📄
Util_WpFile_FilesystemRmException.php
(1.14 KB)
📄
Util_WpFile_FilesystemRmdirException.php
(1.19 KB)
📄
Util_WpFile_FilesystemWriteException.php
(1.57 KB)
📄
Util_WpmuBlogmap.php
(8.06 KB)
📄
Varnish_Flush.php
(18.63 KB)
📄
Varnish_Plugin.php
(3.3 KB)
📄
changelog.txt
(42.56 KB)
📁
extension-example
📁
inc
📄
index.html
(0 B)
📁
ini
📁
languages
📁
lib
📄
press.txt
(45.78 KB)
📁
pub
📄
readme.txt
(40.82 KB)
📄
security.md
(416 B)
📁
vendor
📄
w3-total-cache-api.php
(22.51 KB)
📄
w3-total-cache-old-php.php
(1.25 KB)
📄
w3-total-cache.php
(2.83 KB)
📁
wp-content
Editing: Extension_ImageService_Plugin_Admin.php
<?php /** * File: Extension_ImageService_Plugin_Admin.php * * @since 2.2.0 * * @package W3TC */ namespace W3TC; /** * Class: Extension_ImageService_Plugin_Admin * * @since 2.2.0 * * phpcs:disable Squiz.PHP.EmbeddedPhp.ContentBeforeOpen * phpcs:disable Squiz.PHP.EmbeddedPhp.ContentAfterEnd * phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter */ class Extension_ImageService_Plugin_Admin { /** * Image MIME types available for optimization. * * @since 2.2.0 * @static * * @var array */ public static $mime_types = array( 'gif' => 'image/gif', 'jpeg' => 'image/jpeg', 'jpg' => 'image/jpg', 'png' => 'image/png', ); /** * Configuration. * * @since 2.2.0 * @access private * * @var Config */ private $config; /** * Image Service API class object. * * @since 2.2.0 * @access private * * @var Extension_ImageService_API */ private $api; /** * Was the WP Cron error notice already printed? * * @since 2.8.0 * @static * @access private * * @var bool */ private static $wpcron_notice_printed = false; /** * Constructor. * * @since 2.2.0 */ public function __construct() { $this->config = Dispatcher::config(); } /** * Get config. * * @since 2.8.0 * * @return Config */ public function get_config(): Config { return $this->config; } /** * Get extension information. * * @since 2.2.0 * @static * * @global $wp_version WordPress core version. * * @param array $extensions Extensions. * @param array $config Configuration. * @return array */ public static function w3tc_extensions( $extensions, $config ) { global $wp_version; $description = __( 'Adds the ability to convert images in the Media Library to modern formats (like WebP or AVIF) for better performance.', 'w3-total-cache' ); if ( version_compare( $wp_version, '5.8', '<' ) ) { $description .= sprintf( // translators: 1: HTML break, 2: WordPress version string, 3: HTML archor open tag, 4: HTML archor close tag. __( '%1$sThis extension works best in WordPress version 5.8 and higher. You are running WordPress version %2$s. Please %3$supdate now%4$s to benefit from this feature.', 'w3-total-cache' ), '<br />', $wp_version, '<a href="' . esc_url( admin_url( 'update-core.php' ) ) . '">', '</a>' ); } $settings_url = esc_url( Util_Ui::admin_url( 'upload.php?page=w3tc_extension_page_imageservice&w3tc_imageservice_action=dismiss_activation_notice' ) ); $library_url = esc_url( Util_Ui::admin_url( 'upload.php?mode=list' ) ); $extensions['imageservice'] = array( 'name' => 'Image Converter', 'author' => 'BoldGrid', 'description' => esc_html( $description ), 'author_uri' => 'https://www.boldgrid.com/', 'extension_uri' => 'https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=extension_admin&utm_campaign=imageservice', 'extension_id' => 'imageservice', 'settings_exists' => false, 'version' => '1.0', 'enabled' => true, 'disabled_message' => '', 'requirements' => '', 'path' => 'w3-total-cache/Extension_ImageService_Plugin.php', 'notice' => sprintf( // translators: 1: HTML anchor open tag, 2: HTML anchor close tag, 3: HTML anchor open tag, 4: HTML anchor open tag. __( 'Total Cache Image Converter has been activated. Now, you can %1$sadjust the settings%2$s or go to the %3$sMedia Library%2$s to convert images to modern formats like WebP or AVIF. %4$sLearn more%2$s.', 'w3-total-cache' ), '<a class="edit" href="' . $settings_url . '">', '</a>', '<a class="edit" href="' . $library_url . '">', '<a target="_blank" href="' . esc_url( 'https://www.boldgrid.com/support/w3-total-cache/image-service/?utm_source=w3tc&utm_medium=activation_notice&utm_campaign=imageservice' ) . '">' ), ); // The settings and Media Library links are only valid for single and network sites; not the admin section. if ( ! is_network_admin() ) { $extensions['imageservice']['extra_links'] = array( '<a class="edit" href="' . $settings_url . '">' . esc_html__( 'Settings', 'w3-total-cache' ) . '</a>', '<a class="edit" href="' . $library_url . '">' . esc_html__( 'Media Library', 'w3-total-cache' ) . '</a>', ); } return $extensions; } /** * Load the admin extension. * * Runs on the "wp_loaded" action. * * @since 2.2.0 * @static */ public static function w3tc_extension_load_admin() { $o = new Extension_ImageService_Plugin_Admin(); // Enqueue scripts. add_action( 'admin_enqueue_scripts', array( $o, 'admin_enqueue_scripts' ) ); /** * Filters the Media list table columns. * * @since 2.5.0 * * @param string[] $posts_columns An array of columns displayed in the Media list table. * @param bool $detached Whether the list table contains media not attached * to any posts. Default true. */ add_filter( 'manage_media_columns', array( $o, 'add_media_column' ) ); /** * Fires for each custom column in the Media list table. * * Custom columns are registered using the {@see 'manage_media_columns'} filter. * * @since 2.5.0 * * @param string $column_name Name of the custom column. * @param int $post_id Attachment ID. */ add_action( 'manage_media_custom_column', array( $o, 'media_column_row' ), 10, 2 ); // AJAX hooks. add_action( 'wp_ajax_w3tc_imageservice_submit', array( $o, 'ajax_submit' ) ); add_action( 'wp_ajax_w3tc_imageservice_postmeta', array( $o, 'ajax_get_postmeta' ) ); add_action( 'wp_ajax_w3tc_imageservice_revert', array( $o, 'ajax_revert' ) ); add_action( 'wp_ajax_w3tc_imageservice_all', array( $o, 'ajax_convert_all' ) ); add_action( 'wp_ajax_w3tc_imageservice_revertall', array( $o, 'ajax_revert_all' ) ); add_action( 'wp_ajax_w3tc_imageservice_counts', array( $o, 'ajax_get_counts' ) ); add_action( 'wp_ajax_w3tc_imageservice_usage', array( $o, 'ajax_get_usage' ) ); // Admin notices. add_action( 'admin_notices', array( $o, 'display_notices' ) ); /** * Ensure all network sites include support for modern image formats (e.g., WebP/AVIF). * * @link https://make.wordpress.org/core/2021/06/07/wordpress-5-8-adds-webp-support/ */ add_filter( 'site_option_upload_filetypes', function ( $filetypes ) { $filetypes = explode( ' ', $filetypes ); if ( ! in_array( 'webp', $filetypes, true ) ) { $filetypes[] = 'webp'; } return implode( ' ', $filetypes ); } ); // Add bulk actions. add_filter( 'bulk_actions-upload', array( $o, 'add_bulk_actions' ) ); /** * Fires when a custom bulk action should be handled. * * The redirect link should be modified with success or failure feedback * from the action to be used to display feedback to the user. * * The dynamic portion of the hook name, `$screen`, refers to the current screen ID. * * @since 4.7.0 * * @link https://core.trac.wordpress.org/browser/tags/5.8/src/wp-admin/upload.php#L206 * * @param string $sendback The redirect URL. * @param string $doaction The action being taken. * @param array $items The items to take the action on. Accepts an array of IDs of posts, * comments, terms, links, plugins, attachments, or users. */ add_filter( 'handle_bulk_actions-upload', array( $o, 'handle_bulk_actions' ), 10, 3 ); /** * Handle auto-optimization on upload. * * @link https://core.trac.wordpress.org/browser/tags/5.8/src/wp-includes/post.php#L4401 * @link https://developer.wordpress.org/reference/hooks/add_attachment/ * * Fires once an attachment has been added. * * @since 2.0.0 * * @param int $post_ID Attachment ID. */ add_action( 'add_attachment', array( $o, 'auto_convert' ) ); /** * Delete optimizations on parent image delation. * * @link https://core.trac.wordpress.org/browser/tags/5.8/src/wp-includes/post.php#L6134 * @link https://developer.wordpress.org/reference/hooks/pre_delete_attachment/ * * Filters whether an attachment deletion should take place. * * @since 5.5.0 * * @param bool|null $delete Whether to go forward with deletion. * @param WP_Post $post Post object. * @param bool $force_delete Whether to bypass the Trash. */ add_filter( 'pre_delete_attachment', array( $o, 'cleanup_optimizations' ), 10, 3 ); // Add admin menu items. add_action( 'admin_menu', array( $o, 'admin_menu' ) ); // If auto-convert is enabled, then check WP Cron. if ( ! empty( $o->get_config()->get_array( 'imageservice' )['auto'] ) && 'enabled' === $o->get_config()->get_array( 'imageservice' )['auto'] ) { add_action( 'pre-upload-ui', array( $o, 'check_wpcron' ) ); } } /** * Get all images with postmeta key "w3tc_imageservice". * * @since 2.2.0 * @static * * @link https://developer.wordpress.org/reference/classes/wp_query/ * * @return WP_Query WP_Query object containing post IDs in the posts property (due to the "fields" argument with value "ids"). */ public static function get_imageservice_attachments(): \WP_Query { return new \WP_Query( array( 'post_type' => 'attachment', 'post_status' => 'inherit', 'post_mime_type' => self::$mime_types, 'posts_per_page' => -1, 'ignore_sticky_posts' => true, 'suppress_filters' => true, // phpcs:ignore WordPressVIPMinimum 'meta_key' => 'w3tc_imageservice', // phpcs:ignore WordPress.DB.SlowDBQuery 'fields' => 'ids', 'no_found_rows' => true, 'update_post_term_cache' => false, 'update_post_meta_cache' => false, 'cache_results' => false, ) ); } /** * Get all images without postmeta key "w3tc_imageservice". * * @since 2.2.0 * @static * * @link https://developer.wordpress.org/reference/classes/wp_query/ * * @return WP_Query WP_Query object containing post IDs in the posts property (due to the "fields" argument with value "ids"). */ public static function get_eligible_attachments(): \WP_Query { return new \WP_Query( array( 'post_type' => 'attachment', 'post_status' => 'inherit', 'post_mime_type' => self::$mime_types, 'posts_per_page' => -1, 'ignore_sticky_posts' => true, 'suppress_filters' => true, // phpcs:ignore WordPressVIPMinimum 'meta_key' => 'w3tc_imageservice', // phpcs:ignore WordPress.DB.SlowDBQuery 'meta_compare' => 'NOT EXISTS', 'fields' => 'ids', 'no_found_rows' => true, 'update_post_term_cache' => false, 'update_post_meta_cache' => false, 'cache_results' => false, ) ); } /** * Get an attachment filesize. * * @since 2.2.0 * * @global $wp_filesystem * * @param int $post_id Post id. * @return int */ public function get_attachment_filesize( $post_id ) { WP_Filesystem(); global $wp_filesystem; $size = 0; $filepath = get_attached_file( $post_id ); if ( $wp_filesystem->exists( $filepath ) ) { $size = $wp_filesystem->size( $filepath ); } return $size; } /** * Get image counts by status. * * @since 2.2.0 * * @see self::get_imageservice_attachments() * @see self::get_eligible_attachments() * * @return array */ public function get_counts() { $unconverted_posts = self::get_eligible_attachments(); $counts = array( 'sending' => 0, 'processing' => 0, 'converted' => 0, 'notconverted' => 0, 'unconverted' => $unconverted_posts->post_count, 'total' => 0, ); $bytes = array( 'sending' => 0, 'processing' => 0, 'converted' => 0, 'notconverted' => 0, 'unconverted' => 0, 'total' => 0, ); $imageservice_posts = self::get_imageservice_attachments()->posts; foreach ( $imageservice_posts as $post_id ) { $imageservice_data = get_post_meta( $post_id, 'w3tc_imageservice', true ); $status = isset( $imageservice_data['status'] ) ? $imageservice_data['status'] : null; $filesize_in = isset( $imageservice_data['download']["\0*\0data"]['x-filesize-in'] ) ? $imageservice_data['download']["\0*\0data"]['x-filesize-in'] : 0; $filesize_out = isset( $imageservice_data['download']["\0*\0data"]['x-filesize-out'] ) ? $imageservice_data['download']["\0*\0data"]['x-filesize-out'] : 0; switch ( $status ) { case 'sending': $size = $this->get_attachment_filesize( $post_id ); ++$counts['sending']; $bytes['sending'] += $size; $bytes['total'] += $size; break; case 'processing': $size = $this->get_attachment_filesize( $post_id ); ++$counts['processing']; $bytes['processing'] += $size; $bytes['total'] += $size; break; case 'converted': ++$counts['converted']; $bytes['converted'] += $filesize_in - $filesize_out; $bytes['total'] += $filesize_in - $filesize_out; break; case 'notconverted': $size = $this->get_attachment_filesize( $post_id ); ++$counts['notconverted']; $bytes['notconverted'] += $size; $bytes['total'] += $size; break; case 'unconverted': $size = $this->get_attachment_filesize( $post_id ); ++$counts['unconverted']; $bytes['unconverted'] += $size; $bytes['total'] += $size; break; default: break; } } foreach ( $unconverted_posts->posts as $post_id ) { $size = $this->get_attachment_filesize( $post_id ); if ( $size ) { $bytes['unconverted'] += $size; $bytes['total'] += $size; } } $counts['total'] = array_sum( $counts ); $counts['totalbytes'] = $bytes['total']; $counts['sendingbytes'] = $bytes['sending']; $counts['processingbytes'] = $bytes['processing']; $counts['convertedbytes'] = $bytes['converted']; $counts['notconvertedbytes'] = $bytes['notconverted']; $counts['unconvertedbytes'] = $bytes['unconverted']; return $counts; } /** * Load the extension settings page view. * * @since 2.2.0 * * @see Extension_ImageService_Plugin::get_api() * @see Extension_ImageService_Api::get_usage() */ public function settings_page() { $c = $this->config; $counts = $this->get_counts(); // Delete transient for displaying activation notice. delete_transient( 'w3tc_activation_imageservice' ); // Save submitted settings. $nonce_val = Util_Request::get_string( '_wpnonce' ); $imageservice_compression_val = Util_Request::get_string( 'imageservice___compression' ); if ( ! empty( $imageservice_compression_val ) && ! empty( $nonce_val ) && wp_verify_nonce( $nonce_val, 'w3tc' ) ) { $settings = $c->get_array( 'imageservice' ); $settings['compression'] = $imageservice_compression_val; $imageservice_auto_val = Util_Request::get_string( 'imageservice___auto' ); if ( ! empty( $imageservice_auto_val ) ) { $settings['auto'] = $imageservice_auto_val; } $imageservice_visibility_val = Util_Request::get_string( 'imageservice___visibility' ); if ( ! empty( $imageservice_visibility_val ) ) { $settings['visibility'] = $imageservice_visibility_val; } $imageservice_webp_val = Util_Request::get_string( 'imageservice___webp' ); $settings['webp'] = ! empty( $imageservice_webp_val ); $imageservice_avif_val = Util_Request::get_string( 'imageservice___avif' ); // Only allow AVIF for Pro license holders. if ( Util_Environment::is_w3tc_pro( $c ) ) { $settings['avif'] = ! empty( $imageservice_avif_val ); } else { $settings['avif'] = false; } $c->set( 'imageservice', $settings ); $c->save(); // Display notice when saving settings. ?> <div class="notice notice-success is-dismissible"> <p><?php esc_html_e( 'Settings saved.', 'w3-total-cache' ); ?></p> </div> <?php } // Get Image Service usage from the API. $usage = Extension_ImageService_Plugin::get_api()->get_usage(); // Ensure that the monthly limit is represented correctly. $usage['limit_monthly'] = $usage['limit_monthly'] ? $usage['limit_monthly'] : __( 'Unlimited', 'w3-total-cache' ); // Display a notice if WP Cron is not working as expected. $this->check_wpcron(); // Load the page view. require W3TC_DIR . '/Extension_ImageService_Page_View.php'; } /** * Add admin menu items (administrators only). * * @since 2.2.0 * * @return void */ public function admin_menu(): void { // Check if the current user is a contributor or higher. if ( ! \user_can( \get_current_user_id(), 'manage_options' ) ) { return; } // Add settings submenu to Media top-level menu. add_submenu_page( 'upload.php', esc_html__( 'Total Cache Image Converter', 'w3-total-cache' ), esc_html__( 'Total Cache Image Converter', 'w3-total-cache' ), 'edit_posts', 'w3tc_extension_page_imageservice', array( $this, 'settings_page' ) ); } /** * Enqueue scripts and styles for admin pages (author or higher). * * Runs on the "admin_enqueue_scripts" action. * * @since 2.2.0 * * @see Util_Ui::admin_url() * @see Licensing_Core::get_tos_choice() */ public function admin_enqueue_scripts() { if ( ! \user_can( \get_current_user_id(), 'upload_files' ) ) { return; } // Enqueue JavaScript for the Media Library (upload) and extension settings admin pages. $page_val = Util_Request::get_string( 'page' ); $is_settings_page = ! empty( $page_val ) && 'w3tc_extension_page_imageservice' === $page_val && \user_can( \get_current_user_id(), 'manage_options' ); // Administrators only. $is_media_page = 'upload' === get_current_screen()->id; if ( $is_settings_page ) { wp_enqueue_style( 'w3tc-options' ); wp_enqueue_style( 'w3tc-bootstrap-css' ); wp_enqueue_script( 'w3tc-options' ); wp_localize_script( 'w3tc-lightbox', 'w3tc_nonce', array( wp_create_nonce( 'w3tc' ) ) ); wp_enqueue_script( 'w3tc-lightbox' ); wp_enqueue_style( 'w3tc-lightbox' ); } if ( $is_settings_page || $is_media_page ) { wp_register_script( 'w3tc-imageservice', esc_url( plugin_dir_url( __FILE__ ) . 'Extension_ImageService_Plugin_Admin.js' ), array( 'jquery' ), W3TC_VERSION, true ); wp_localize_script( 'w3tc-imageservice', 'w3tcData', array( 'nonces' => array( 'submit' => wp_create_nonce( 'w3tc_imageservice_submit' ), 'postmeta' => wp_create_nonce( 'w3tc_imageservice_postmeta' ), 'revert' => wp_create_nonce( 'w3tc_imageservice_revert' ), ), 'lang' => array( 'convert' => __( 'Convert', 'w3-total-cache' ), 'convertToWebp' => __( 'Convert to WebP', 'w3-total-cache' ), 'convertToAvif' => __( 'Convert to AVIF', 'w3-total-cache' ), 'sending' => __( 'Sending...', 'w3-total-cache' ), 'submitted' => __( 'Submitted', 'w3-total-cache' ), 'processing' => __( 'Processing...', 'w3-total-cache' ), 'converted' => __( 'Converted', 'w3-total-cache' ), 'notConverted' => __( 'Not converted', 'w3-total-cache' ), 'reverting' => __( 'Reverting...', 'w3-total-cache' ), 'reverted' => __( 'Reverted', 'w3-total-cache' ), 'revert' => __( 'Revert', 'w3-total-cache' ), 'error' => __( 'Error', 'w3-total-cache' ), 'ajaxFail' => __( 'Failed to retrieve a response. Please reload the page to try again.', 'w3-total-cache' ), 'apiError' => __( 'API error. Please reload the page to try again,', 'w3-total-cache' ), 'refresh' => __( 'Refresh', 'w3-total-cache' ), 'refreshing' => __( 'Refreshing...', 'w3-total-cache' ), 'settings' => __( 'Settings', 'w3-total-cache' ), 'submittedAllDesc' => sprintf( // translators: 1: HTML anchor open tag, 2: HTML anchor close tag. __( 'Images queued for conversion. Progress can be seen in the %1$sMedia Library%2$s.', 'w3-total-cache' ), '<a href="' . esc_url( Util_Ui::admin_url( 'upload.php?mode=list' ) ) . '">', '</a>' ), 'notConvertedDesc' => sprintf( // translators: 1: HTML anchor open tag, 2: HTML anchor close tag. __( 'The converted image would be larger than the original; conversion canceled. %1$sLearn more%2$s.', 'w3-total-cache' ), '<a target="_blank" href="' . esc_url( 'https://www.boldgrid.com/support/w3-total-cache/image-service/?utm_source=w3tc&utm_medium=conversion_canceled&utm_campaign=imageservice#conversion-canceled' ) . '">', '</a>' ), ), 'tos_choice' => Licensing_Core::get_tos_choice(), 'track_usage' => $this->config->get_boolean( 'common.track_usage' ), 'ga_profile' => ( defined( 'W3TC_DEVELOPER' ) && W3TC_DEVELOPER ) ? 'G-Q3CHQJWERM' : 'G-5TFS8M5TTY', 'isPro' => Util_Environment::is_w3tc_pro( $this->config ), 'settings' => $this->config->get_array( 'imageservice' ), 'settingsUrl' => esc_url( Util_Ui::admin_url( 'upload.php?page=w3tc_extension_page_imageservice' ) ), ) ); wp_enqueue_script( 'w3tc-imageservice' ); wp_enqueue_style( 'w3tc-imageservice', esc_url( plugin_dir_url( __FILE__ ) . 'Extension_ImageService_Plugin_Admin.css' ), array(), W3TC_VERSION, 'all' ); } } /** * Add image service controls to the Media Library table in list view. * * Runs on the "manage_media_columns" filter. * * @since 2.2.0 * * @param string[] $posts_columns An array of columns displayed in the Media list table. * @param bool $detached Whether the list table contains media not attached * to any posts. Default true. */ public function add_media_column( $posts_columns, $detached = true ) { // Delete transient for displaying activation notice. delete_transient( 'w3tc_activation_imageservice' ); $posts_columns['imageservice'] = '<span class="w3tc-convert"></span> ' . esc_html__( 'Image Converter', 'w3-total-cache' ); return $posts_columns; } /** * Fires for each custom column in the Media list table. * * Custom columns are registered using the {@see 'manage_media_columns'} filter. * Runs on the "manage_media_custom_column" action. * * @since 2.5.0 * * @see self::remove_optimizations() * * @link https://developer.wordpress.org/reference/functions/size_format/ * * @param string $column_name Name of the custom column. * @param int $post_id Attachment ID. */ public function media_column_row( $column_name, $post_id ) { static $settings; if ( 'imageservice' === $column_name ) { $post = get_post( $post_id ); $imageservice_data = get_post_meta( $post_id, 'w3tc_imageservice', true ); $settings = isset( $settings ) ? $settings : $this->config->get_array( 'imageservice' ); // Display controls and info for eligible images. if ( in_array( $post->post_mime_type, self::$mime_types, true ) ) { $filepath = get_attached_file( $post_id ); $status = isset( $imageservice_data['status'] ) ? $imageservice_data['status'] : null; // Check for old format conversion (backward compatibility). // If post_child exists and is valid, treat it as converted regardless of current status. if ( isset( $imageservice_data['post_child'] ) && ! empty( $imageservice_data['post_child'] ) ) { $child_id = $imageservice_data['post_child']; // Verify the child attachment still exists. $child_post = get_post( $child_id ); if ( $child_post ) { $child_data = get_post_meta( $child_id, 'w3tc_imageservice', true ); if ( ! empty( $child_data['is_converted_file'] ) ) { $status = 'converted'; // Update status in database if it wasn't set, so it's recognized consistently. if ( empty( $imageservice_data['status'] ) || 'converted' !== $imageservice_data['status'] ) { self::update_postmeta( $post_id, array( 'status' => 'converted' ) ); } } } } // Check if image still has the converted file(s). It could have been deleted. if ( 'converted' === $status ) { $has_valid_conversion = false; // Check new structure (multiple formats). if ( isset( $imageservice_data['post_children'] ) && is_array( $imageservice_data['post_children'] ) ) { foreach ( $imageservice_data['post_children'] as $format_key => $child_id ) { if ( $child_id ) { $child_data = get_post_meta( $child_id, 'w3tc_imageservice', true ); if ( ! empty( $child_data['is_converted_file'] ) ) { $has_valid_conversion = true; break; } } } } // Check old structure (backward compatibility). if ( ! $has_valid_conversion && isset( $imageservice_data['post_child'] ) ) { $child_data = get_post_meta( $imageservice_data['post_child'], 'w3tc_imageservice', true ); if ( ! empty( $child_data['is_converted_file'] ) ) { $has_valid_conversion = true; } } if ( ! $has_valid_conversion ) { $status = null; $this->remove_optimizations( $post_id ); } } // If processed, then show information. if ( 'converted' === $status ) { // Check if this is an old format conversion (has post_child but not post_children with data). $has_old_format_only = isset( $imageservice_data['post_child'] ) && ! empty( $imageservice_data['post_child'] ) && ( ! isset( $imageservice_data['post_children'] ) || empty( $imageservice_data['post_children'] ) ); // Handle multiple formats (new structure). if ( ! $has_old_format_only && isset( $imageservice_data['downloads'] ) && is_array( $imageservice_data['downloads'] ) && ! empty( $imageservice_data['downloads'] ) ) { // Sort formats to maintain order: WEBP first, then AVIF. $sorted_downloads = $imageservice_data['downloads']; uksort( $sorted_downloads, function( $a, $b ) { // Define order: webp first, then avif, then others. $order = array( 'webp' => 1, 'avif' => 2 ); $a_order = isset( $order[ $a ] ) ? $order[ $a ] : 99; $b_order = isset( $order[ $b ] ) ? $order[ $b ] : 99; return $a_order - $b_order; } ); // Show all formats that have download info, not just those with post_children. // This includes formats that failed or didn't reduce size. foreach ( $sorted_downloads as $format_key => $download_data ) { // Skip if download_data is an error string and we don't have a post_child for it. if ( is_string( $download_data ) && ( ! isset( $imageservice_data['post_children'][ $format_key ] ) || ! $imageservice_data['post_children'][ $format_key ] ) ) { // Show error message for failed formats. ?> <div class="w3tc-converted-error"> <?php printf( '%1$s: %2$s', esc_html( strtoupper( $format_key ) ), esc_html( $download_data ) ); ?> </div> <?php continue; } if ( ! is_array( $download_data ) ) { continue; } if ( is_array( $download_data ) ) { // Headers are now stored normalized (lowercase keys) from cron. // Handle both new normalized format and old format for backward compatibility. $download_headers = $download_data; // If old format with special structure, extract it. if ( isset( $download_data["\0*\0data"] ) ) { $download_headers = $download_data["\0*\0data"]; } // Normalize keys to lowercase for case-insensitive access. $normalized_headers = array(); foreach ( $download_headers as $key => $value ) { // Skip special WordPress array keys. if ( "\0" !== substr( $key, 0, 1 ) ) { $normalized_headers[ strtolower( $key ) ] = $value; } } $reduced_percent = isset( $normalized_headers['x-filesize-reduced'] ) ? $normalized_headers['x-filesize-reduced'] : null; $filesize_in = isset( $normalized_headers['x-filesize-in'] ) ? $normalized_headers['x-filesize-in'] : null; $filesize_out = isset( $normalized_headers['x-filesize-out'] ) ? $normalized_headers['x-filesize-out'] : null; // Check if this format was actually converted (exists in post_children). $post_children = isset( $imageservice_data['post_children'] ) && is_array( $imageservice_data['post_children'] ) ? $imageservice_data['post_children'] : array(); $was_converted = isset( $post_children[ $format_key ] ) && ! empty( $post_children[ $format_key ] ); // If not converted, show "not converted" message instead of statistics. if ( ! $was_converted ) { ?> <div class="w3tc-notconverted"> <?php printf( '%1$s: %2$s', esc_html( strtoupper( $format_key ) ), esc_html__( 'Not converted', 'w3-total-cache' ) ); ?> </div> <?php continue; } // Display if we have the necessary data and the format was converted. if ( $filesize_in && $filesize_out && $reduced_percent ) { $reduced_numeric = rtrim( $reduced_percent, '%' ); $converted_class = (float) $reduced_numeric < 100 ? 'w3tc-converted-reduced' : 'w3tc-converted-increased'; ?> <div class="<?php echo esc_attr( $converted_class ); ?>"> <?php printf( '%1$s: %2$s → %3$s (%4$s)', esc_html( strtoupper( $format_key ) ), esc_html( size_format( $filesize_in ) ), esc_html( size_format( $filesize_out ) ), esc_html( $reduced_percent ) ); ?> </div> <?php } } } } else { // Handle single format (backward compatibility - old format). // Check if old format conversion exists (post_child). $has_old_conversion = isset( $imageservice_data['post_child'] ) && ! empty( $imageservice_data['post_child'] ); if ( $has_old_conversion ) { $download_data = isset( $imageservice_data['download'] ) ? $imageservice_data['download'] : null; $has_download_data = false; // Determine format from child post mime type or default to WEBP. $format_label = 'WEBP'; $child_id = $imageservice_data['post_child']; $child_post = get_post( $child_id ); if ( $child_post && isset( $child_post->post_mime_type ) ) { $format_label = strtoupper( str_replace( 'image/', '', $child_post->post_mime_type ) ); } if ( is_array( $download_data ) ) { // Headers may be in special WordPress structure. $download_headers = isset( $download_data["\0*\0data"] ) ? $download_data["\0*\0data"] : $download_data; // Normalize keys to lowercase for case-insensitive access. $normalized_headers = array(); foreach ( $download_headers as $key => $value ) { // Skip special WordPress array keys. if ( "\0" !== substr( $key, 0, 1 ) ) { $normalized_headers[ strtolower( $key ) ] = $value; } } $reduced_percent = isset( $normalized_headers['x-filesize-reduced'] ) ? $normalized_headers['x-filesize-reduced'] : null; $filesize_in = isset( $normalized_headers['x-filesize-in'] ) ? $normalized_headers['x-filesize-in'] : null; $filesize_out = isset( $normalized_headers['x-filesize-out'] ) ? $normalized_headers['x-filesize-out'] : null; // If reduced_percent is missing but we have file sizes, calculate it. if ( ! $reduced_percent && $filesize_in && $filesize_out ) { $filesize_in_int = (int) $filesize_in; $filesize_out_int = (int) $filesize_out; if ( $filesize_in_int > 0 ) { $reduction = ( ( $filesize_in_int - $filesize_out_int ) / $filesize_in_int ) * 100; $reduced_percent = number_format( $reduction, 2 ) . '%'; } } // Display if we have the necessary data. if ( $filesize_in && $filesize_out ) { $has_download_data = true; $reduced_numeric = $reduced_percent ? (float) rtrim( $reduced_percent, '%' ) : 0; $converted_class = $reduced_numeric > 100 ? 'w3tc-converted-increased' : 'w3tc-converted-reduced'; // Show statistics with or without percentage. ?> <div class="<?php echo esc_attr( $converted_class ); ?>"> <?php if ( $reduced_percent ) { printf( '%1$s: %2$s → %3$s (%4$s)', esc_html( $format_label ), esc_html( size_format( $filesize_in ) ), esc_html( size_format( $filesize_out ) ), esc_html( $reduced_percent ) ); } else { printf( '%1$s: %2$s → %3$s', esc_html( $format_label ), esc_html( size_format( $filesize_in ) ), esc_html( size_format( $filesize_out ) ) ); } ?> </div> <?php } } elseif ( $child_post ) { // Try to get file sizes from the actual files if download data is missing. $original_filepath = get_attached_file( $post_id ); $converted_filepath = get_attached_file( $child_id ); if ( $original_filepath && $converted_filepath && file_exists( $original_filepath ) && file_exists( $converted_filepath ) ) { $filesize_in = filesize( $original_filepath ); $filesize_out = filesize( $converted_filepath ); if ( $filesize_in > 0 && $filesize_out > 0 ) { $has_download_data = true; $reduction = ( ( $filesize_in - $filesize_out ) / $filesize_in ) * 100; $reduced_percent = number_format( $reduction, 2 ) . '%'; $reduced_numeric = (float) $reduction; $converted_class = $reduced_numeric > 100 ? 'w3tc-converted-increased' : 'w3tc-converted-reduced'; ?> <div class="<?php echo esc_attr( $converted_class ); ?>"> <?php printf( '%1$s: %2$s → %3$s (%4$s)', esc_html( $format_label ), esc_html( size_format( $filesize_in ) ), esc_html( size_format( $filesize_out ) ), esc_html( $reduced_percent ) ); ?> </div> <?php } } } // If no download data but conversion exists, show basic converted message. if ( ! $has_download_data ) { ?> <div class="w3tc-converted-reduced"> <?php printf( '%1$s: %2$s', esc_html__( 'WEBP', 'w3-total-cache' ), esc_html__( 'Converted', 'w3-total-cache' ) ); ?> </div> <?php } } } } elseif ( 'notconverted' === $status ) { ?> <div class="w3tc-notconverted"> <?php printf( // translators: 1: HTML anchor open tag, 2: HTML anchor close tag. esc_html__( 'The converted image would be larger than the original; conversion canceled. %1$sLearn more%2$s.', 'w3-total-cache' ), '<a target="_blank" href="' . esc_url( 'https://www.boldgrid.com/support/w3-total-cache/image-service/?utm_source=w3tc&utm_medium=conversion_canceled&utm_campaign=imageservice#conversion-canceled' ) . '">', '</a>' ); ?> </div> <?php } // Determine classes. $link_classes = 'w3tc-convert'; switch ( $status ) { case 'processing': $link_classes .= ' w3tc-convert-processing'; $disabled_class = 'w3tc-disabled'; $aria_attr = 'true'; break; case 'converted': $disabled_class = 'w3tc-disabled'; $aria_attr = 'true'; break; default: $disabled_class = ''; $aria_attr = 'false'; break; } // Print action links. ?> <span class="<?php echo esc_attr( $disabled_class ); ?>"> <a class="<?php echo esc_attr( $link_classes ); ?>" data-post-id="<?php echo esc_attr( $post_id ); ?>" data-status="<?php echo esc_attr( $status ); ?>" aria-disabled="<?php echo esc_attr( $aria_attr ); ?>"> <?php // phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact switch ( $status ) { case 'sending': esc_html_e( 'Sending...', 'w3-total-cache' ); break; case 'processing': esc_html_e( 'Processing...', 'w3-total-cache' ); break; case 'converted': // Show which format(s) were converted. $converted_formats = array(); // Check new format (post_children). if ( isset( $imageservice_data['post_children'] ) && is_array( $imageservice_data['post_children'] ) ) { foreach ( $imageservice_data['post_children'] as $format_key => $child_id ) { if ( $child_id ) { $child_data = get_post_meta( $child_id, 'w3tc_imageservice', true ); if ( ! empty( $child_data['is_converted_file'] ) ) { $converted_formats[] = strtoupper( $format_key ); } } } } // Check old format (post_child). if ( empty( $converted_formats ) && isset( $imageservice_data['post_child'] ) && ! empty( $imageservice_data['post_child'] ) ) { $child_post = get_post( $imageservice_data['post_child'] ); if ( $child_post && isset( $child_post->post_mime_type ) ) { $format_label = strtoupper( str_replace( 'image/', '', $child_post->post_mime_type ) ); $converted_formats[] = $format_label; } } // Sort formats to maintain order: WEBP first, then AVIF. if ( ! empty( $converted_formats ) ) { usort( $converted_formats, function( $a, $b ) { $order = array( 'WEBP' => 1, 'AVIF' => 2 ); $a_order = isset( $order[ $a ] ) ? $order[ $a ] : 99; $b_order = isset( $order[ $b ] ) ? $order[ $b ] : 99; return $a_order - $b_order; } ); echo esc_html( implode( '/', $converted_formats ) . ' ' . __( 'Converted', 'w3-total-cache' ) ); } else { esc_html_e( 'Converted', 'w3-total-cache' ); } break; case 'notconverted': case 'notfound': if ( isset( $settings['compression'] ) && 'lossless' === $settings['compression'] ) { esc_html_e( 'Settings', 'w3-total-cache' ); } else { esc_html_e( 'Convert', 'w3-total-cache' ); } break; default: esc_html_e( 'Convert', 'w3-total-cache' ); break; } // phpcs:enable Generic.WhiteSpace.ScopeIndent.IncorrectExact ?> </a> </span> <?php // If converted, then show revert link. if ( 'converted' === $status ) { ?> <span class="w3tc-revert"> | <a><?php esc_attr_e( 'Revert', 'w3-total-cache' ); ?></a></span> <?php // Check if WEBP and AVIF already exist. $has_webp = false; $has_avif = false; if ( isset( $imageservice_data['post_children']['webp'] ) && ! empty( $imageservice_data['post_children']['webp'] ) ) { $has_webp = true; } if ( isset( $imageservice_data['post_children']['avif'] ) && ! empty( $imageservice_data['post_children']['avif'] ) ) { $has_avif = true; } // Check old format (post_child). if ( isset( $imageservice_data['post_child'] ) && ! empty( $imageservice_data['post_child'] ) ) { $child_id = $imageservice_data['post_child']; $child_post = get_post( $child_id ); if ( $child_post && 'image/webp' === $child_post->post_mime_type ) { $has_webp = true; } elseif ( $child_post && 'image/avif' === $child_post->post_mime_type ) { $has_avif = true; } } $settings = isset( $settings ) ? $settings : $this->config->get_array( 'imageservice' ); $webp_enabled = isset( $settings['webp'] ) && ! empty( $settings['webp'] ); $avif_enabled = ! isset( $settings['avif'] ) || true === $settings['avif'] || '1' === $settings['avif'] || 1 === $settings['avif']; $has_pro = Util_Environment::is_w3tc_pro( $this->config ); $avif_enabled = $avif_enabled && $has_pro; // Show additional convert links only when the format is enabled. if ( $has_webp && ! $has_avif && $avif_enabled ) { ?> <span class="w3tc-convert-avif"> | <a class="w3tc-convert-format" data-post-id="<?php echo esc_attr( $post_id ); ?>" data-status="<?php echo esc_attr( $status ); ?>" data-format="avif" aria-disabled="false"><?php esc_html_e( 'Convert to AVIF', 'w3-total-cache' ); ?></a></span> <?php } if ( $has_avif && ! $has_webp && $webp_enabled ) { ?> <span class="w3tc-convert-webp"> | <a class="w3tc-convert-format" data-post-id="<?php echo esc_attr( $post_id ); ?>" data-status="<?php echo esc_attr( $status ); ?>" data-format="webp" aria-disabled="false"><?php esc_html_e( 'Convert to WebP', 'w3-total-cache' ); ?></a></span> <?php } } } elseif ( isset( $imageservice_data['is_converted_file'] ) && $imageservice_data['is_converted_file'] ) { // W3TC converted image. echo esc_html__( 'Attachment id: ', 'w3-total-cache' ) . esc_html( $post->post_parent ); } } } /** * Add bulk actions. * * @since 2.2.0 * * @param array $actions Bulk actions. * @return array */ public function add_bulk_actions( array $actions ) { $actions['w3tc_imageservice_convert'] = 'W3 Total Convert'; $actions['w3tc_imageservice_revert'] = 'W3 Total Convert Revert'; return $actions; } /** * Handle bulk actions. * * @since 2.2.0 * * @see self::submit_images() * @see self::revert_optimizations() * * @link https://developer.wordpress.org/reference/hooks/handle_bulk_actions-screen/ * @link https://make.wordpress.org/core/2016/10/04/custom-bulk-actions/ * @link https://core.trac.wordpress.org/browser/tags/5.8/src/wp-admin/upload.php#L206 * * @since WordPress 4.7.0 * * @param string $location The redirect URL. * @param string $doaction The action being taken. * @param array $post_ids The items to take the action on. Accepts an array of IDs of attachments. * @return string */ public function handle_bulk_actions( $location, $doaction, array $post_ids ) { // Remove custom query args. $location = remove_query_arg( array( 'w3tc_imageservice_submitted', 'w3tc_imageservice_reverted' ), $location ); switch ( $doaction ) { case 'w3tc_imageservice_convert': $stats = $this->submit_images( $post_ids ); $location = add_query_arg( array( 'w3tc_imageservice_submitted' => $stats['submitted'], 'w3tc_imageservice_successful' => $stats['successful'], 'w3tc_imageservice_skipped' => $stats['skipped'], 'w3tc_imageservice_errored' => $stats['errored'], 'w3tc_imageservice_invalid' => $stats['invalid'], ), $location ); break; case 'w3tc_imageservice_revert': $this->revert_optimizations( $post_ids ); $location = add_query_arg( 'w3tc_imageservice_reverted', 1, $location ); break; default: break; } return $location; } /** * Display bulk action results admin notice. * * @since 2.2.0 * * @see Util_Environment::is_wpcron_working() * @see self::check_wpcron() * * @uses $_GET['w3tc_imageservice_submitted'] Number of submittions. * @uses $_GET['w3tc_imageservice_successful'] Number of successful submissions. * @uses $_GET['w3tc_imageservice_skipped'] Number of skipped submissions. * @uses $_GET['w3tc_imageservice_errored'] Number of errored submissions. * @uses $_GET['w3tc_imageservice_invalid'] Number of invalid submissions. */ public function display_notices() { $submitted = Util_Request::get_integer( 'w3tc_imageservice_submitted' ); $is_auto = ! empty( $this->config->get_array( 'imageservice' )['auto'] ) && 'enabled' === $this->config->get_array( 'imageservice' )['auto']; if ( ! empty( $submitted ) ) { $successful_val = Util_Request::get_integer( 'w3tc_imageservice_successful' ); $successful = ! empty( $successful_val ) ? $successful_val : 0; $skipped_val = Util_Request::get_integer( 'w3tc_imageservice_skipped' ); $skipped = ! empty( $skipped_val ) ? $skipped_val : 0; $errored_val = Util_Request::get_integer( 'w3tc_imageservice_errored' ); $errored = ! empty( $errored_val ) ? $errored_val : 0; $invalid_val = Util_Request::get_integer( 'w3tc_imageservice_invalid' ); $invalid = ! empty( $invalid_val ) ? $invalid_val : 0; ?> <script>history.pushState( null, '', location.href.split( '?' )[0] );</script> <div class="updated notice notice-success is-dismissible"> <p>Total Cache Image Converter</p> <p> <?php printf( esc_html( // translators: 1: Submissions. _n( 'Submitted %1$u image for processing.', 'Submitted %1$u images for processing.', $submitted, 'w3-total-cache' ) ) . '</p>', esc_attr( $submitted ) ); // Print extra stats if debug is on. if ( defined( 'W3TC_DEBUG' ) && W3TC_DEBUG ) { ?> <p> <?php printf( // translators: 1: Successes, 2: Skipped, 3: Errored, 4: Invalid. esc_html__( 'Successful: %1$u | Skipped: %2$u | Errored: %3$u | Invalid: %4$u', 'w3-total-cache' ), esc_attr( $successful ), esc_attr( $skipped ), esc_attr( $errored ), esc_attr( $invalid ) ); } ?> </p> </div> <?php } elseif ( ! empty( Util_Request::get_string( 'w3tc_imageservice_reverted' ) ) ) { ?> <script>history.pushState( null, '', location.href.split( '?' )[0] );</script> <div class="updated notice notice-success is-dismissible"><p>Total Cache Image Converter</p> <p><?php esc_html_e( 'All selected optimizations have been reverted.', 'w3-total-cache' ); ?></p> </div> <?php } elseif ( 'upload' === get_current_screen()->id ) { // Media Library: Get the display mode. $mode = get_user_option( 'media_library_mode', get_current_user_id() ) ? get_user_option( 'media_library_mode', get_current_user_id() ) : 'grid'; // If not in list mode, then print a notice to switch to it. if ( 'list' !== $mode ) { ?> <div class="notice notice-warning is-dismissible"><p>Total Cache Image Converter - <?php printf( // translators: 1: HTML anchor open tag, 2: HTML anchor close tag. esc_html__( 'Switch to %1$slist mode%2$s for image format conversions.', 'w3-total-cache' ), '<a href="' . esc_attr( Util_Ui::admin_url( 'upload.php?mode=list' ) ) . '">', '</a>' ); ?> </p> </div> <?php } else { $this->check_wpcron(); } } elseif ( $is_auto && 'media' === get_current_screen()->id ) { $this->check_wpcron(); } } /** * Submit images to the API for processing. * * @since 2.2.0 * * @global $wp_filesystem * * @see Extension_ImageService_Plugin::get_api() * * @param array $post_ids Post ids. * @return array */ /** * Check if WEBP conversion already exists for an image. * * @since 2.2.0 * * @param int $post_id Post id. * @return bool True if WEBP conversion exists, false otherwise. */ private function has_webp_conversion( $post_id ) { $imageservice_data = get_post_meta( $post_id, 'w3tc_imageservice', true ); // Check new format (post_children). if ( isset( $imageservice_data['post_children']['webp'] ) && ! empty( $imageservice_data['post_children']['webp'] ) ) { $child_id = $imageservice_data['post_children']['webp']; $child_data = get_post_meta( $child_id, 'w3tc_imageservice', true ); if ( ! empty( $child_data['is_converted_file'] ) ) { return true; } } // Check old format (post_child). if ( isset( $imageservice_data['post_child'] ) && ! empty( $imageservice_data['post_child'] ) ) { $child_id = $imageservice_data['post_child']; $child_post = get_post( $child_id ); if ( $child_post && 'image/webp' === $child_post->post_mime_type ) { $child_data = get_post_meta( $child_id, 'w3tc_imageservice', true ); if ( ! empty( $child_data['is_converted_file'] ) ) { return true; } } } return false; } /** * Remove a single format optimization without deleting other converted formats. * * @since 2.2.0 * * @param int $post_id Parent post id. * @param string $format_key Format key (e.g. 'webp', 'avif'). * @return void */ private function remove_optimization_format( $post_id, $format_key ) { $postmeta = (array) get_post_meta( $post_id, 'w3tc_imageservice', true ); // New structure: remove a specific format child attachment. if ( isset( $postmeta['post_children'] ) && is_array( $postmeta['post_children'] ) && isset( $postmeta['post_children'][ $format_key ] ) ) { $child_id = $postmeta['post_children'][ $format_key ]; if ( $child_id ) { wp_delete_attachment( $child_id, true ); } unset( $postmeta['post_children'][ $format_key ] ); } // Old structure: if post_child is the requested format, remove it. if ( isset( $postmeta['post_child'] ) && $postmeta['post_child'] ) { $child_post = get_post( $postmeta['post_child'] ); if ( $child_post && isset( $child_post->post_mime_type ) ) { $child_format_key = strtolower( str_replace( 'image/', '', $child_post->post_mime_type ) ); if ( $child_format_key === $format_key ) { wp_delete_attachment( $postmeta['post_child'], true ); unset( $postmeta['post_child'] ); } } } // Clean related per-format metadata. if ( isset( $postmeta['downloads'] ) && is_array( $postmeta['downloads'] ) ) { unset( $postmeta['downloads'][ $format_key ] ); } if ( isset( $postmeta['jobs_status'] ) && is_array( $postmeta['jobs_status'] ) ) { unset( $postmeta['jobs_status'][ $format_key ] ); } if ( isset( $postmeta['processing_jobs'] ) && is_array( $postmeta['processing_jobs'] ) ) { unset( $postmeta['processing_jobs'][ $format_key ] ); } update_post_meta( $post_id, 'w3tc_imageservice', $postmeta ); } /** * Submit images for conversion. * * @since 2.2.0 * * @param array $post_ids Post ids. * @return array */ public function submit_images( array $post_ids ) { // Check WP_Filesystem credentials. Util_WpFile::ajax_check_credentials( sprintf( // translators: 1: HTML achor open tag, 2: HTML anchor close tag. __( '%1$sLearn more%2$s.', 'w3-total-cache' ), '<a target="_blank" href="' . esc_url( 'https://www.boldgrid.com/support/w3-total-cache/image-service/?utm_source=w3tc&utm_medium=conversion_error&utm_campaign=imageservice#unable-to-connect-to-the-filesystem-error' ) . '">', '</a>' ) ); global $wp_filesystem; $stats = array( 'skipped' => 0, 'submitted' => 0, 'successful' => 0, 'errored' => 0, 'invalid' => 0, ); foreach ( $post_ids as $post_id ) { // Skip silently (do not count) if not an allowed MIME type. if ( ! in_array( get_post_mime_type( $post_id ), self::$mime_types, true ) ) { continue; } $filepath = get_attached_file( $post_id ); // Skip if attachment file does not exist. if ( ! $wp_filesystem->exists( $filepath ) ) { ++$stats['skipped']; continue; } // Check if WEBP already exists - if so, only request AVIF. $convert_options = array(); if ( $this->has_webp_conversion( $post_id ) && Util_Environment::is_w3tc_pro( $this->config ) ) { // Only request AVIF since WEBP already exists. $convert_options['formats'] = array( 'image/avif' ); } // Submit current image. $response = Extension_ImageService_Plugin::get_api()->convert( $filepath, $convert_options ); ++$stats['submitted']; if ( isset( $response['error'] ) ) { ++$stats['errored']; continue; } // Handle new API2 response format with jobs array. $jobs = isset( $response['jobs'] ) && is_array( $response['jobs'] ) ? $response['jobs'] : array(); // Backward compatibility: if no jobs array, check for single job_id/signature. if ( empty( $jobs ) ) { if ( empty( $response['job_id'] ) || empty( $response['signature'] ) ) { ++$stats['invalid']; continue; } // Convert old format to new format for consistency. $jobs = array( array( 'job_id' => $response['job_id'], 'signature' => $response['signature'], 'mime_type' => 'image/webp', // Default for old format. 'status' => isset( $response['status'] ) ? $response['status'] : 'queued', 'status_url' => isset( $response['status_url'] ) ? $response['status_url'] : '', 'download_url' => isset( $response['download_url'] ) ? $response['download_url'] : '', ), ); } if ( empty( $jobs ) ) { ++$stats['invalid']; continue; } // Remove old optimizations unless we are only converting a single format. $requested_format = null; if ( isset( $convert_options['formats'] ) && is_array( $convert_options['formats'] ) && 1 === count( $convert_options['formats'] ) ) { $requested_format = reset( $convert_options['formats'] ); } if ( $requested_format ) { $format_key = str_replace( 'image/', '', strtolower( $requested_format ) ); // Only remove the requested format so other formats remain intact. $this->remove_optimization_format( $post_id, $format_key ); } else { $this->remove_optimizations( $post_id ); } // Get requested formats from convert options or settings to store in postmeta. $requested_formats = array(); if ( isset( $convert_options['formats'] ) && is_array( $convert_options['formats'] ) ) { // Use formats from convert options (e.g., only AVIF if WEBP already exists). $requested_formats = $convert_options['formats']; } else { // Get requested formats from settings. $settings = $this->config->get_array( 'imageservice' ); // Check webp setting - handle both boolean and string values, default to true if not set. $webp_enabled = ! isset( $settings['webp'] ) || ( true === $settings['webp'] || '1' === $settings['webp'] || 1 === $settings['webp'] ); if ( $webp_enabled ) { $requested_formats[] = 'image/webp'; } // Check avif setting - handle both boolean and string values, default to true if not set. // Only allow AVIF for Pro license holders. $avif_enabled = ! isset( $settings['avif'] ) || ( true === $settings['avif'] || '1' === $settings['avif'] || 1 === $settings['avif'] ); if ( $avif_enabled && Util_Environment::is_w3tc_pro( $this->config ) ) { $requested_formats[] = 'image/avif'; } // If no formats are selected, default to WebP for backward compatibility. if ( empty( $requested_formats ) ) { $requested_formats[] = 'image/webp'; } } // Store jobs by format for easy lookup. // If we explicitly requested a single format, force the key to that format (API may not echo it back correctly). $jobs_by_format = array(); $forced_mime_type = null; if ( isset( $convert_options['formats'] ) && is_array( $convert_options['formats'] ) && 1 === count( $convert_options['formats'] ) ) { $forced_mime_type = reset( $convert_options['formats'] ); } if ( $forced_mime_type && ! empty( $jobs ) ) { $forced_key = str_replace( 'image/', '', strtolower( $forced_mime_type ) ); $job0 = $jobs[0]; $job0['mime_type'] = $forced_mime_type; $jobs_by_format[ $forced_key ] = $job0; } else { foreach ( $jobs as $job ) { $mime_type = null; if ( isset( $job['mime_type'] ) ) { $mime_type = $job['mime_type']; } elseif ( isset( $job['mimeTypeOut'] ) ) { $mime_type = $job['mimeTypeOut']; } elseif ( isset( $job['mime_type_out'] ) ) { $mime_type = $job['mime_type_out']; } // Some APIs may return arrays for mime type; use the first value. if ( is_array( $mime_type ) ) { $mime_type = reset( $mime_type ); } if ( $mime_type && isset( $job['job_id'] ) && isset( $job['signature'] ) ) { $format_key = str_replace( 'image/', '', strtolower( $mime_type ) ); $job['mime_type'] = $mime_type; // Normalize key for downstream usage. $jobs_by_format[ $format_key ] = $job; } } } // Save the job info and requested formats. self::update_postmeta( $post_id, array( 'status' => 'processing', 'processing' => $response, // Store full response for backward compatibility. 'processing_jobs' => $jobs_by_format, // Store jobs by format. 'requested_formats' => $requested_formats, 'jobs_status' => array(), ) ); ++$stats['successful']; } return $stats; } /** * Revert optimizations of images. * * @since 2.2.0 * * @param array $post_ids Attachment post ids. */ public function revert_optimizations( array $post_ids ) { foreach ( $post_ids as $post_id ) { // Skip if not an allowed MIME type. if ( ! in_array( get_post_mime_type( $post_id ), self::$mime_types, true ) ) { continue; } $this->remove_optimizations( $post_id ); } } /** * Update postmeta. * * @since 2.2.0 * @static * * @link https://developer.wordpress.org/reference/functions/update_post_meta/ * * @param int $post_id Post id. * @param array $data Postmeta data. * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure or if the value * passed to the function is the same as the one that is already in the database. */ public static function update_postmeta( $post_id, array $data ) { $postmeta = (array) get_post_meta( $post_id, 'w3tc_imageservice', true ); $postmeta = array_merge( $postmeta, $data ); return update_post_meta( $post_id, 'w3tc_imageservice', $postmeta ); } /** * Copy postmeta from one post to another. * * @since 2.2.0 * @static * * @link https://developer.wordpress.org/reference/functions/update_post_meta/ * * @param int $post_id_1 Post id 1. * @param int $post_id_2 Post id 2. * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure or if the value * passed to the function is the same as the one that is already in the database. */ public static function copy_postmeta( $post_id_1, $post_id_2 ) { $postmeta = (array) get_post_meta( $post_id_1, 'w3tc_imageservice', true ); // Do not copy "post_child" or "post_children". unset( $postmeta['post_child'] ); unset( $postmeta['post_children'] ); unset( $postmeta['downloads'] ); return update_post_meta( $post_id_2, 'w3tc_imageservice', $postmeta ); } /** * Remove optimizations. * * @since 2.2.0 * * @link https://developer.wordpress.org/reference/functions/wp_delete_attachment/ * * @param int $post_id Parent post id. * @return bool|WP_Post|false|null True if optimizations were removed, false or null on failure, or WP_Post for backward compatibility. */ public function remove_optimizations( $post_id ) { $result = null; $has_optimizations = false; // Get child post ids. $postmeta = (array) get_post_meta( $post_id, 'w3tc_imageservice', true ); // Handle multiple formats (new structure). if ( isset( $postmeta['post_children'] ) && is_array( $postmeta['post_children'] ) ) { foreach ( $postmeta['post_children'] as $format_key => $child_id ) { if ( $child_id ) { // Delete optimization. wp_delete_attachment( $child_id, true ); $has_optimizations = true; } } } // Handle single format (backward compatibility). $child_id = isset( $postmeta['post_child'] ) ? $postmeta['post_child'] : null; if ( $child_id ) { // Delete optimization. $result = wp_delete_attachment( $child_id, true ); $has_optimizations = true; } // Delete postmeta if there were any optimizations. if ( $has_optimizations || ! empty( $postmeta ) ) { delete_post_meta( $post_id, 'w3tc_imageservice' ); } // Return true if optimizations were removed, or the result for backward compatibility. return $has_optimizations ? ( false !== $result ? true : $result ) : $result; } /** * Handle auto-optimization on image upload. * * @since 2.2.0 * * @param int $post_id Post id. */ public function auto_convert( $post_id ) { $settings = $this->config->get_array( 'imageservice' ); $enabled = isset( $settings['auto'] ) && 'enabled' === $settings['auto']; if ( $enabled && in_array( get_post_mime_type( $post_id ), self::$mime_types, true ) ) { $this->submit_images( array( $post_id ) ); } } /** * Delete optimizations on parent image delation. * * Does not filter the WordPress operation. We use this as an action trigger. * * @since 2.2.0 * * @param bool|null $delete Whether to go forward with deletion. * @param WP_Post $post Post object. * @param bool $force_delete Whether to bypass the Trash. * @return null */ public function cleanup_optimizations( $delete, $post, $force_delete ) { if ( $force_delete ) { $this->remove_optimizations( $post->ID ); } return $delete; } /** * AJAX: Submit an image for processing. * * @since 2.2.0 * * @global $wp_filesystem * * @see Extension_ImageService_Plugin::get_api() * * @uses $_POST['post_id'] Post id. */ public function ajax_submit() { check_ajax_referer( 'w3tc_imageservice_submit' ); // Check WP_Filesystem credentials. Util_WpFile::ajax_check_credentials( sprintf( // translators: 1: HTML achor open tag, 2: HTML anchor close tag. __( '%1$sLearn more%2$s.', 'w3-total-cache' ), '<a target="_blank" href="' . esc_url( 'https://www.boldgrid.com/support/w3-total-cache/image-service/?utm_source=w3tc&utm_medium=conversion_error&utm_campaign=imageservice#unable-to-connect-to-the-filesystem-error' ) . '">', '</a>' ) ); // Check for post id. $post_id_val = Util_Request::get_integer( 'post_id' ); $post_id = ! empty( $post_id_val ) ? $post_id_val : null; if ( ! $post_id ) { wp_send_json_error( array( 'error' => __( 'Missing input post id.', 'w3-total-cache' ), ), 400 ); } global $wp_filesystem; // Verify the image file exists. $filepath = get_attached_file( $post_id ); if ( ! $wp_filesystem->exists( $filepath ) ) { wp_send_json_error( array( 'error' => sprintf( // translators: 1: Image filepath. __( 'File "%1$s" does not exist.', 'w3-total-cache' ), $filepath ), ), 412 ); } // Check if a specific format was requested (from data-format attribute). $format = Util_Request::get_string( 'format' ); $convert_options = array(); // If format is specified, only request that format. if ( 'avif' === $format && Util_Environment::is_w3tc_pro( $this->config ) ) { $convert_options['formats'] = array( 'image/avif' ); } elseif ( 'webp' === $format ) { $convert_options['formats'] = array( 'image/webp' ); } elseif ( $this->has_webp_conversion( $post_id ) && Util_Environment::is_w3tc_pro( $this->config ) ) { // If WEBP already exists and no format specified, only request AVIF. $convert_options['formats'] = array( 'image/avif' ); } // Submit the job request. $response = Extension_ImageService_Plugin::get_api()->convert( $filepath, $convert_options ); // Check for non-200 status code. if ( isset( $response['code'] ) && 200 !== $response['code'] ) { wp_send_json_error( $response, $response['code'] ); } // Check for error. if ( isset( $response['error'] ) ) { wp_send_json_error( $response, 417 ); } // Handle new API2 response format with jobs array. $jobs = isset( $response['jobs'] ) && is_array( $response['jobs'] ) ? $response['jobs'] : array(); // Backward compatibility: if no jobs array, check for single job_id/signature. if ( empty( $jobs ) ) { if ( empty( $response['job_id'] ) || empty( $response['signature'] ) ) { wp_send_json_error( array( 'error' => __( 'Invalid API response.', 'w3-total-cache' ), ), 417 ); } // Convert old format to new format for consistency. $jobs = array( array( 'job_id' => $response['job_id'], 'signature' => $response['signature'], 'mime_type' => 'image/webp', // Default for old format. 'status' => isset( $response['status'] ) ? $response['status'] : 'queued', 'status_url' => isset( $response['status_url'] ) ? $response['status_url'] : '', 'download_url' => isset( $response['download_url'] ) ? $response['download_url'] : '', ), ); } if ( empty( $jobs ) ) { wp_send_json_error( array( 'error' => __( 'Invalid API response.', 'w3-total-cache' ), ), 417 ); } // Remove old optimizations unless we are only converting a single format. $requested_format = null; if ( isset( $convert_options['formats'] ) && is_array( $convert_options['formats'] ) && 1 === count( $convert_options['formats'] ) ) { $requested_format = reset( $convert_options['formats'] ); } if ( $requested_format ) { $format_key = str_replace( 'image/', '', strtolower( $requested_format ) ); // Only remove the requested format so other formats remain intact. $this->remove_optimization_format( $post_id, $format_key ); } else { $this->remove_optimizations( $post_id ); } // Get requested formats from convert options or settings to store in postmeta. $requested_formats = array(); if ( isset( $convert_options['formats'] ) && is_array( $convert_options['formats'] ) ) { // Use formats from convert options (e.g., only AVIF if WEBP already exists). $requested_formats = $convert_options['formats']; } else { // Get requested formats from settings. $settings = $this->config->get_array( 'imageservice' ); // Check webp setting - handle both boolean and string values, default to true if not set. $webp_enabled = ! isset( $settings['webp'] ) || ( true === $settings['webp'] || '1' === $settings['webp'] || 1 === $settings['webp'] ); if ( $webp_enabled ) { $requested_formats[] = 'image/webp'; } // Check avif setting - handle both boolean and string values, default to true if not set. // Only allow AVIF for Pro license holders. $avif_enabled = ! isset( $settings['avif'] ) || ( true === $settings['avif'] || '1' === $settings['avif'] || 1 === $settings['avif'] ); if ( $avif_enabled && Util_Environment::is_w3tc_pro( $this->config ) ) { $requested_formats[] = 'image/avif'; } // If no formats are selected, default to WebP for backward compatibility. if ( empty( $requested_formats ) ) { $requested_formats[] = 'image/webp'; } } // Store jobs by format for easy lookup. // If we explicitly requested a single format, force the key to that format (API may not echo it back correctly). $jobs_by_format = array(); $forced_mime_type = null; if ( isset( $convert_options['formats'] ) && is_array( $convert_options['formats'] ) && 1 === count( $convert_options['formats'] ) ) { $forced_mime_type = reset( $convert_options['formats'] ); } if ( $forced_mime_type && ! empty( $jobs ) ) { $forced_key = str_replace( 'image/', '', strtolower( $forced_mime_type ) ); $job0 = $jobs[0]; $job0['mime_type'] = $forced_mime_type; $jobs_by_format[ $forced_key ] = $job0; } else { foreach ( $jobs as $job ) { $mime_type = null; if ( isset( $job['mime_type'] ) ) { $mime_type = $job['mime_type']; } elseif ( isset( $job['mimeTypeOut'] ) ) { $mime_type = $job['mimeTypeOut']; } elseif ( isset( $job['mime_type_out'] ) ) { $mime_type = $job['mime_type_out']; } if ( is_array( $mime_type ) ) { $mime_type = reset( $mime_type ); } if ( $mime_type && isset( $job['job_id'] ) && isset( $job['signature'] ) ) { $format_key = str_replace( 'image/', '', strtolower( $mime_type ) ); $job['mime_type'] = $mime_type; $jobs_by_format[ $format_key ] = $job; } } } // Save the job info and requested formats. self::update_postmeta( $post_id, array( 'status' => 'processing', 'processing' => $response, // Store full response for backward compatibility. 'processing_jobs' => $jobs_by_format, // Store jobs by format. 'requested_formats' => $requested_formats, 'jobs_status' => array(), ) ); wp_send_json_success( $response ); } /** * AJAX: Get the status of an image, from postmeta. * * @since 2.2.0 * * @uses $_POST['post_id'] Post id. */ public function ajax_get_postmeta() { check_ajax_referer( 'w3tc_imageservice_postmeta' ); $post_id_val = Util_Request::get_integer( 'post_id' ); $post_id = ! empty( $post_id_val ) ? $post_id_val : null; if ( $post_id ) { wp_send_json_success( (array) get_post_meta( $post_id, 'w3tc_imageservice', true ) ); } else { wp_send_json_error( array( 'error' => __( 'Missing input post id.', 'w3-total-cache' ), ), 400 ); } } /** * AJAX: Revert an optimization. * * @since 2.2.0 * * @uses $_POST['post_id'] Parent post id. */ public function ajax_revert() { check_ajax_referer( 'w3tc_imageservice_revert' ); $post_id_val = Util_Request::get_integer( 'post_id' ); $post_id = ! empty( $post_id_val ) ? $post_id_val : null; if ( $post_id ) { // Check if there are any optimizations to revert. $postmeta = (array) get_post_meta( $post_id, 'w3tc_imageservice', true ); $has_optimizations = false; if ( isset( $postmeta['post_children'] ) && is_array( $postmeta['post_children'] ) && ! empty( $postmeta['post_children'] ) ) { $has_optimizations = true; } elseif ( isset( $postmeta['post_child'] ) && $postmeta['post_child'] ) { $has_optimizations = true; } if ( ! $has_optimizations ) { wp_send_json_error( array( 'error' => __( 'No converted images found to revert.', 'w3-total-cache' ), ), 404 ); return; } $this->remove_optimizations( $post_id ); // Always return success if we had optimizations to remove. wp_send_json_success( array( 'removed' => true ) ); } else { wp_send_json_error( array( 'error' => __( 'Missing input post id.', 'w3-total-cache' ), ), 400 ); } } /** * AJAX: Convert all images. * * @since 2.2.0 * * @see self::get_eligible_attachments() * @see self::submit_images() */ public function ajax_convert_all() { check_ajax_referer( 'w3tc_imageservice_submit' ); $results = $this->get_eligible_attachments(); $post_ids = array(); // Allow plenty of time to complete. ignore_user_abort( true ); set_time_limit( 0 ); // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged foreach ( $results->posts as $post_id ) { $post_ids[] = $post_id; } $stats = $this->submit_images( $post_ids ); wp_send_json_success( $stats ); } /** * AJAX: Revert all converted images. * * @since 2.2.0 * * @see self::get_imageservice_attachments() * @see self::remove_optimizations() */ public function ajax_revert_all() { check_ajax_referer( 'w3tc_imageservice_submit' ); $results = $this->get_imageservice_attachments(); $revert_count = 0; // Allow plenty of time to complete. ignore_user_abort( true ); set_time_limit( 0 ); // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged foreach ( $results->posts as $post_id ) { if ( $this->remove_optimizations( $post_id ) ) { ++$revert_count; } } wp_send_json_success( array( 'revert_count' => $revert_count ) ); } /** * AJAX: Get image counts by status. * * @since 2.2.0 * * @see get_counts() */ public function ajax_get_counts() { check_ajax_referer( 'w3tc_imageservice_submit' ); wp_send_json_success( $this->get_counts() ); } /** * AJAX: Get image API usage. * * @since 2.2.0 * * @see Extension_ImageService_Plugin::get_api() * @see Extension_ImageService_Api::get_usage() */ public function ajax_get_usage() { check_ajax_referer( 'w3tc_imageservice_submit' ); wp_send_json_success( Extension_ImageService_Plugin::get_api()->get_usage( true ) ); } /** * Check if WP Cron is working as expected and print an error notice if not. * * @since 2.8.0 * * @see Util_Environment::is_wpcron_working() * * @return bool */ public function check_wpcron(): bool { if ( ! self::$wpcron_notice_printed && ! Util_Environment::is_wpcron_working() ) { ?> <div class="notice notice-error is-dismissible"> <p> <?php printf( // translators: 1: HTML anchor open tag, 2: HTML anchor close tag. esc_html__( 'WP Cron is not working as expected, which is required for image format conversions. %2$sLearn more%3$s.', 'w3-total-cache' ), 'W3 Total Cache', '<a target="_blank" href="' . esc_url( 'https://www.boldgrid.com/support/enable-wp-cron/?utm_source=w3tc&utm_medium=wp_cron&utm_campaign=imageservice' ) . '">', '</a>' ); ?> </p> </div> <?php self::$wpcron_notice_printed = true; return false; } else { return true; } } }
Upload File
Create Folder