get_boolean( 'config.check' ) || $force_all_checks ) { $extensions_active = $config->get_array( 'extensions.active' ); if ( array_key_exists( 'imageservice', $extensions_active ) ) { $this->rules_add( $config, $exs ); } else { $this->rules_remove( $exs ); } } if ( count( $exs->exceptions() ) > 0 ) { throw $exs; } } /** * Fixes environment once event occurs. * * @since 2.2.0 * * @param Config $config Config object. * @param mixed $event Event. * @param Config $old_config Old config object. */ public function fix_on_event( $config, $event, $old_config = null ) { } /** * Fixes environment after plugin deactivation * * @since 2.2.0 * * @throws Util_Environment_Exceptions Exceptions. */ public function fix_after_deactivation() { $exs = new Util_Environment_Exceptions(); $this->rules_remove( $exs ); if ( count( $exs->exceptions() ) > 0 ) { throw $exs; } } /** * Returns required rules for module. * * @since 2.2.0 * * @param Config $config Configuration object. * @return array */ public function get_required_rules( $config ) { return array( array( 'filename' => Util_Rule::get_browsercache_rules_cache_path(), 'content' => $this->rules_generate_avif() . $this->rules_generate_webp(), ), ); } /** * Write rewrite rules. * * @since 2.2.0 * * @param Config $config Configuration. * @param Util_Environment_Exceptions $exs Exceptions. * * @throws Util_WpFile_FilesystemOperationException S/FTP form if it can't get the required filesystem credentials. */ private function rules_add( $config, $exs ) { // Remove existing rules first to ensure correct positioning on re-add. // This is necessary because add_rules replaces in place when rules exist. Util_Rule::remove_rules( $exs, Util_Rule::get_browsercache_rules_cache_path(), W3TC_MARKER_BEGIN_AVIF, W3TC_MARKER_END_AVIF ); Util_Rule::remove_rules( $exs, Util_Rule::get_browsercache_rules_cache_path(), W3TC_MARKER_BEGIN_WEBP, W3TC_MARKER_END_WEBP ); // Add AVIF rules first (higher priority). // Position before Page Cache so image requests are handled before Page Cache location blocks. Util_Rule::add_rules( $exs, Util_Rule::get_browsercache_rules_cache_path(), $this->rules_generate_avif(), W3TC_MARKER_BEGIN_AVIF, W3TC_MARKER_END_AVIF, array( W3TC_MARKER_BEGIN_PGCACHE_CACHE => 0, W3TC_MARKER_BEGIN_PGCACHE_CORE => 0, W3TC_MARKER_BEGIN_BROWSERCACHE_CACHE => 0, W3TC_MARKER_BEGIN_WORDPRESS => 0, ) ); // Add WebP rules (lower priority than AVIF). // Position before Page Cache so image requests are handled before Page Cache location blocks. Util_Rule::add_rules( $exs, Util_Rule::get_browsercache_rules_cache_path(), $this->rules_generate_webp(), W3TC_MARKER_BEGIN_WEBP, W3TC_MARKER_END_WEBP, array( W3TC_MARKER_BEGIN_PGCACHE_CACHE => 0, W3TC_MARKER_BEGIN_PGCACHE_CORE => 0, W3TC_MARKER_BEGIN_BROWSERCACHE_CACHE => 0, W3TC_MARKER_BEGIN_WORDPRESS => 0, ) ); } /** * Generate AVIF rewrite rules (higher priority). * * @since 2.9.1 * * @see Dispatcher::nginx_rules_for_browsercache_section() * * @return string */ private function rules_generate_avif() { switch ( true ) { case Util_Environment::is_apache(): case Util_Environment::is_litespeed(): return ' # BEGIN W3TC AVIF AddType image/avif .avif RewriteEngine On RewriteCond %{HTTP_ACCEPT} image/avif RewriteCond %{REQUEST_FILENAME} (.+)\.(jpe?g|png|gif)$ RewriteCond %1\.avif -f RewriteCond %{QUERY_STRING} !type=original RewriteRule (.+)\.(jpe?g|png|gif)$ $1.avif [NC,T=image/avif,E=avif,L] Header append Vary Accept # END W3TC AVIF '; case Util_Environment::is_nginx(): $config = Dispatcher::config(); /* * Add Nginx rules only if Browser Cache is disabled. * Otherwise, the rules are added in "BrowserCache_Environment_Nginx.php". * @see BrowserCache_Environment_Nginx::generate_section() */ if ( ! $config->get_boolean( 'browsercache.enabled' ) ) { if ( $config->get_boolean( 'browsercache.no404wp' ) ) { $fallback = '=404'; } else { $fallback = '/index.php$is_args$args'; } return ' # BEGIN W3TC AVIF location ~* ^(?.+)\.(jpe?g|png|gif)$ { ' . implode( "\n ", Dispatcher::nginx_rules_for_browsercache_section( $config, 'other' ) ) . ' add_header Vary Accept; # Initialize variables. set $avif_ok 0; set $webp_ok 0; set $want_avif 0; set $want_webp 0; set $serve_avif 0; set $serve_webp 0; # Check file existence. if ( -f $document_root${path}.avif ) { set $avif_ok 1; } if ( -f $document_root${path}.webp ) { set $webp_ok 1; } # Check Accept header. if ( $http_accept ~* "image/avif" ) { set $want_avif 1; } if ( $http_accept ~* "image/webp" ) { set $want_webp 1; } # Combine conditions: serve AVIF if both accepted and file exists. if ( $want_avif = 1 ) { set $serve_avif $avif_ok; } if ( $serve_avif = 1 ) { rewrite ^ ${path}.avif last; } # Serve WEBP if accepted and file exists (only if AVIF wasn\'t served). if ( $want_webp = 1 ) { set $serve_webp $webp_ok; } if ( $serve_webp = 1 ) { rewrite ^ ${path}.webp last; } # Default: serve original file. try_files $uri ' . $fallback . '; } location ~* \.(avif|avifs)$ { default_type image/avif; } # END W3TC AVIF '; } else { return ''; } default: return ''; } } /** * Generate WebP rewrite rules (lower priority than AVIF). * * @since 2.9.1 * * @see Dispatcher::nginx_rules_for_browsercache_section() * * @return string */ private function rules_generate_webp() { switch ( true ) { case Util_Environment::is_apache(): case Util_Environment::is_litespeed(): return ' # BEGIN W3TC WEBP AddType image/webp .webp RewriteEngine On RewriteCond %{HTTP_ACCEPT} image/webp RewriteCond %{REQUEST_FILENAME} (.+)\.(jpe?g|png|gif)$ RewriteCond %1\.webp -f RewriteCond %{QUERY_STRING} !type=original RewriteRule (.+)\.(jpe?g|png|gif)$ $1.webp [NC,T=image/webp,E=webp,L] Header append Vary Accept # END W3TC WEBP '; case Util_Environment::is_nginx(): $config = Dispatcher::config(); /* * Add Nginx rules only if Browser Cache is disabled. * Otherwise, the rules are added in "BrowserCache_Environment_Nginx.php". * @see BrowserCache_Environment_Nginx::generate_section() */ if ( ! $config->get_boolean( 'browsercache.enabled' ) ) { if ( $config->get_boolean( 'browsercache.no404wp' ) ) { $fallback = '=404'; } else { $fallback = '/index.php?$args'; } return ' # BEGIN W3TC WEBP location ~* \.webp$ { default_type image/webp; } # END W3TC WEBP '; } else { return ''; } default: return ''; } } /** * Removes cache directives * * @since 2.2.0 * * @param Util_Environment_Exceptions $exs Exceptions. * * @throws Util_WpFile_FilesystemOperationException S/FTP form if it can't get the required filesystem credentials. */ private function rules_remove( $exs ) { // Remove AVIF rules. Util_Rule::remove_rules( $exs, Util_Rule::get_pgcache_rules_core_path(), W3TC_MARKER_BEGIN_AVIF, W3TC_MARKER_END_AVIF ); // Remove WebP rules. Util_Rule::remove_rules( $exs, Util_Rule::get_pgcache_rules_core_path(), W3TC_MARKER_BEGIN_WEBP, W3TC_MARKER_END_WEBP ); } }