|
| 1 | +<?php |
| 2 | +/* |
| 3 | +* Tiny Compress Images - WordPress plugin. |
| 4 | +* Copyright (C) 2015-2018 Tinify B.V. |
| 5 | +* |
| 6 | +* This program is free software; you can redistribute it and/or modify it |
| 7 | +* under the terms of the GNU General Public License as published by the Free |
| 8 | +* Software Foundation; either version 2 of the License, or (at your option) |
| 9 | +* any later version. |
| 10 | +* |
| 11 | +* This program is distributed in the hope that it will be useful, but WITHOUT |
| 12 | +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 13 | +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 14 | +* more details. |
| 15 | +* |
| 16 | +* You should have received a copy of the GNU General Public License along |
| 17 | +* with this program; if not, write to the Free Software Foundation, Inc., 51 |
| 18 | +* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n*/ |
| 19 | + |
| 20 | +/** |
| 21 | + * Tiny_Apache_Rewrite |
| 22 | + * class responsible for the apache rules for image delivery. |
| 23 | + * - toggling the rules when saving settings |
| 24 | + * - inserting/removing rules from htaccess |
| 25 | + * |
| 26 | + * We are only updating rules when: |
| 27 | + * - updating the option convert_format |
| 28 | + * - uninstalling the plug-in |
| 29 | + */ |
| 30 | +class Tiny_Apache_Rewrite extends Tiny_WP_Base { |
| 31 | + |
| 32 | + /** |
| 33 | + * seperator when rules are inserted |
| 34 | + * @var string |
| 35 | + */ |
| 36 | + const MARKER = 'tiny-compress-images'; |
| 37 | + |
| 38 | + /** |
| 39 | + * Installs or uninstalls the htaccess rules |
| 40 | + * hooked into `update_option_tinypng_convert_format` |
| 41 | + * https://developer.wordpress.org/reference/hooks/update_option_option/ |
| 42 | + * |
| 43 | + * |
| 44 | + * @param mixed $old_value |
| 45 | + * @param mixed $value |
| 46 | + * @param string $option |
| 47 | + * @return void |
| 48 | + */ |
| 49 | + public static function toggle_rules( $old_value, $value, $option ) { |
| 50 | + $old_delivery = isset( $old_value['delivery_method'] ) ? |
| 51 | + $old_value['delivery_method'] : null; |
| 52 | + $new_delivery = isset( $value['delivery_method'] ) ? |
| 53 | + $value['delivery_method'] : null; |
| 54 | + |
| 55 | + if ( $old_delivery === $new_delivery ) { |
| 56 | + return; |
| 57 | + } |
| 58 | + |
| 59 | + if ( 'htaccess' === $new_delivery ) { |
| 60 | + $installed = self::install_rules(); |
| 61 | + Tiny_Logger::debug( 'htaccess rules installed: ' . $installed ); |
| 62 | + return; |
| 63 | + } |
| 64 | + |
| 65 | + // We only uninstall if we were previously using htaccess |
| 66 | + if ( 'htaccess' === $old_delivery ) { |
| 67 | + $uninstalled = self::uninstall_rules(); |
| 68 | + Tiny_Logger::debug( 'htaccess rules uninstaled: ' . $uninstalled ); |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + /** |
| 73 | + * Generate .htaccess rewrite rules for serving WebP and AVIF images. |
| 74 | + * |
| 75 | + * @return string The .htaccess rules |
| 76 | + */ |
| 77 | + private static function get_rewrite_rules() { |
| 78 | + $rules = array(); |
| 79 | + $rules[] = '<IfModule mod_rewrite.c>'; |
| 80 | + $rules[] = 'RewriteEngine On'; |
| 81 | + $rules[] = 'RewriteOptions Inherit'; |
| 82 | + |
| 83 | + $rules = array_merge( $rules, self::get_avif_rules() ); |
| 84 | + $rules = array_merge( $rules, self::get_webp_rules() ); |
| 85 | + |
| 86 | + $rules[] = '</IfModule>'; |
| 87 | + |
| 88 | + $rules[] = '<IfModule mod_headers.c>'; |
| 89 | + $rules[] = '<FilesMatch "\.(jpe?g|png)$">'; |
| 90 | + $rules[] = 'Header append Vary Accept'; |
| 91 | + $rules[] = '</FilesMatch>'; |
| 92 | + $rules[] = '</IfModule>'; |
| 93 | + |
| 94 | + $rules[] = '<IfModule mod_mime.c>'; |
| 95 | + $rules[] = 'AddType image/webp .webp'; |
| 96 | + $rules[] = 'AddType image/avif .avif'; |
| 97 | + $rules[] = '</IfModule>'; |
| 98 | + |
| 99 | + return implode( "\n", $rules ); |
| 100 | + } |
| 101 | + |
| 102 | + /** |
| 103 | + * Generate AVIF rewrite rules. |
| 104 | + * |
| 105 | + * @return array[] AVIF rewrite rules |
| 106 | + */ |
| 107 | + private static function get_avif_rules() { |
| 108 | + $rules = array(); |
| 109 | + $rules[] = 'RewriteCond %{HTTP_ACCEPT} image/avif'; |
| 110 | + $rules[] = 'RewriteCond %{REQUEST_URI} ^(.+)\.(?:jpe?g|png)$'; |
| 111 | + $rules[] = 'RewriteCond %{DOCUMENT_ROOT}/%1.avif -f'; |
| 112 | + $rules[] = 'RewriteCond %{QUERY_STRING} !type=original'; |
| 113 | + $rules[] = 'RewriteRule (.+)\.(?:jpe?g|png)$ $1.avif [T=image/avif,L]'; |
| 114 | + return $rules; |
| 115 | + } |
| 116 | + |
| 117 | + /** |
| 118 | + * Generate WebP rewrite rules. |
| 119 | + * |
| 120 | + * @return array[] WebP rewrite rules |
| 121 | + */ |
| 122 | + private static function get_webp_rules() { |
| 123 | + $rules = array(); |
| 124 | + $rules[] = 'RewriteCond %{HTTP_ACCEPT} image/webp'; |
| 125 | + $rules[] = 'RewriteCond %{REQUEST_URI} ^(.+)\.(?:jpe?g|png)$'; |
| 126 | + $rules[] = 'RewriteCond %{DOCUMENT_ROOT}/%1.webp -f'; |
| 127 | + $rules[] = 'RewriteCond %{QUERY_STRING} !type=original'; |
| 128 | + $rules[] = 'RewriteRule (.+)\.(?:jpe?g|png)$ $1.webp [T=image/webp,L]'; |
| 129 | + |
| 130 | + return $rules; |
| 131 | + } |
| 132 | + |
| 133 | + /** |
| 134 | + * Install rewrite rules to .htaccess files. |
| 135 | + * |
| 136 | + * @return bool True on success, false otherwise |
| 137 | + */ |
| 138 | + private static function install_rules() { |
| 139 | + $rules = self::get_rewrite_rules(); |
| 140 | + $upload_dir = wp_upload_dir(); |
| 141 | + if ( isset( $upload_dir['basedir'] ) && is_writable( $upload_dir['basedir'] ) ) { |
| 142 | + $htaccess_file = $upload_dir['basedir'] . '/.htaccess'; |
| 143 | + return insert_with_markers( $htaccess_file, self::MARKER, $rules ); |
| 144 | + } |
| 145 | + |
| 146 | + return false; |
| 147 | + } |
| 148 | + |
| 149 | + /** |
| 150 | + * Remove rewrite rules from .htaccess files. |
| 151 | + * |
| 152 | + * @return bool True on success, false otherwise |
| 153 | + */ |
| 154 | + public static function uninstall_rules() { |
| 155 | + $upload_dir = wp_upload_dir(); |
| 156 | + if ( |
| 157 | + file_exists( $upload_dir['basedir'] . '/.htaccess' ) |
| 158 | + ) { |
| 159 | + $htaccess_file = $upload_dir['basedir'] . '/.htaccess'; |
| 160 | + return insert_with_markers( $htaccess_file, self::MARKER, '' ); |
| 161 | + } |
| 162 | + |
| 163 | + return false; |
| 164 | + } |
| 165 | +} |
0 commit comments