| @@ -1,49 +1,93 @@ | ||
| 1 | 1 | <?php |
| 2 | -defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' ); | |
| 3 | 2 | |
| 3 | +use Imagify\Stats\OptimizedMediaWithoutNextGen; | |
| 4 | +use Imagify\Webp\Display; | |
| 5 | + | |
| 6 | +defined( 'ABSPATH' ) || exit; | |
| 7 | + | |
| 4 | 8 | $settings = Imagify_Settings::get_instance(); |
| 5 | 9 | ?> |
| 6 | 10 | <div> |
| 7 | - <h3 class="imagify-options-subtitle"><?php _e( 'WebP format', 'imagify' ); ?></h3> | |
| 11 | + <h3 class="imagify-options-subtitle"><?php esc_html_e( 'Next-Gen image format', 'imagify' ); ?></h3> | |
| 8 | 12 | |
| 9 | 13 | <div class="imagify-setting-line"> |
| 10 | 14 | <?php |
| 11 | - $settings->field_checkbox( [ | |
| 12 | - 'option_name' => 'convert_to_webp', | |
| 13 | - 'label' => __( 'Create WebP versions of images', 'imagify' ), | |
| 14 | - 'attributes' => [ | |
| 15 | - 'aria-describedby' => 'describe-convert_to_webp', | |
| 16 | - ], | |
| 17 | - ] ); | |
| 15 | + $message = __( 'Select WebP for high compatibility, AVIF for superior compression. Please note that the generation process will start automatically after saving the settings.', 'imagify' ); | |
| 16 | + $message_class = 'info'; | |
| 17 | + $disabled = false; | |
| 18 | + | |
| 19 | + if ( has_filter( 'imagify_nextgen_images_formats' ) ) { | |
| 20 | + $message = sprintf( | |
| 21 | + // translators: %1$s and %2$s are <code> tag opening and closing, %3$s and %4$s are <a> tag opening and closing. | |
| 22 | + __( 'Next-Gen Images format is currently defined by the %1$simagify_nextgen_images_format%2$s filter. %3$sRead more%4$s', 'imagify' ), | |
| 23 | + '<code>', | |
| 24 | + '</code>', | |
| 25 | + '<a href="https://imagify.io/documentation/how-to-use-the-next-gen-image-format-filter/" target="_blank">', | |
| 26 | + '</a>' | |
| 27 | + ); | |
| 28 | + | |
| 29 | + $message_class = 'error'; | |
| 30 | + $disabled = true; | |
| 31 | + } | |
| 32 | + | |
| 33 | + $attributes = [ | |
| 34 | + 'aria-describedby' => 'describe-optimization_format', | |
| 35 | + ]; | |
| 36 | + | |
| 37 | + if ( $disabled ) { | |
| 38 | + $attributes['disabled'] = true; | |
| 39 | + } | |
| 40 | + | |
| 41 | + $settings->field_inline_radio_list( | |
| 42 | + [ | |
| 43 | + 'option_name' => 'optimization_format', | |
| 44 | + 'legend' => __( 'Next-gen image format', 'imagify' ), | |
| 45 | + 'info' => $message, | |
| 46 | + 'info_class' => $message_class, | |
| 47 | + 'values' => [ | |
| 48 | + 'off' => __( 'Off', 'imagify' ), | |
| 49 | + 'avif' => __( 'AVIF', 'imagify' ), | |
| 50 | + 'webp' => __( 'WebP', 'imagify' ), | |
| 51 | + ], | |
| 52 | + 'attributes' => $attributes, | |
| 53 | + ] | |
| 54 | + ); | |
| 18 | 55 | ?> |
| 56 | + </div> | |
| 19 | 57 | |
| 58 | + <div class="imagify-setting-line"> | |
| 59 | + | |
| 20 | 60 | <div class="imagify-options-line"> |
| 21 | 61 | <?php |
| 22 | - $settings->field_checkbox( [ | |
| 23 | - 'option_name' => 'display_webp', | |
| 24 | - 'label' => __( 'Display images in WebP format on the site', 'imagify' ), | |
| 25 | - ] ); | |
| 62 | + $settings->field_checkbox( | |
| 63 | + [ | |
| 64 | + 'option_name' => 'display_nextgen', | |
| 65 | + 'label' => __( 'Display images in Next-Gen format on the site', 'imagify' ), | |
| 66 | + ] | |
| 67 | + ); | |
| 26 | 68 | ?> |
| 27 | 69 | |
| 28 | 70 | <div class="imagify-options-line"> |
| 29 | 71 | <?php |
| 30 | - $settings->field_radio_list( [ | |
| 31 | - 'option_name' => 'display_webp_method', | |
| 32 | - 'values' => [ | |
| 33 | - 'rewrite' => __( 'Use rewrite rules', 'imagify' ), | |
| 34 | - /* translators: 1 and 2 are <em> tag opening and closing. */ | |
| 35 | - 'picture' => sprintf( __( 'Use <picture> tags %1$s(preferred)%2$s', 'imagify' ), '<em>', '</em>' ), | |
| 36 | - ], | |
| 37 | - 'attributes' => [ | |
| 38 | - 'aria-describedby' => 'describe-convert_to_webp', | |
| 39 | - ], | |
| 40 | - ] ); | |
| 72 | + $settings->field_radio_list( | |
| 73 | + [ | |
| 74 | + 'option_name' => 'display_nextgen_method', | |
| 75 | + 'values' => [ | |
| 76 | + 'rewrite' => __( 'Use rewrite rules', 'imagify' ), | |
| 77 | + /* translators: 1 and 2 are <em> tag opening and closing. */ | |
| 78 | + 'picture' => sprintf( __( 'Use <picture> tags %1$s(preferred)%2$s', 'imagify' ), '<em>', '</em>' ), | |
| 79 | + ], | |
| 80 | + 'attributes' => [ | |
| 81 | + 'aria-describedby' => 'describe-convert_to_webp', | |
| 82 | + ], | |
| 83 | + ] | |
| 84 | + ); | |
| 41 | 85 | ?> |
| 42 | 86 | |
| 43 | 87 | <div class="imagify-options-line"> |
| 44 | 88 | <?php |
| 45 | - $cdn_source = \Imagify\Webp\Picture\Display::get_instance()->get_cdn_source(); | |
| 89 | + $cdn_source = apply_filters( 'imagify_cdn_source_url', '' ); | |
| 46 | 90 | |
| 47 | 91 | if ( 'option' !== $cdn_source['source'] ) { |
| 48 | 92 | if ( 'constant' === $cdn_source['source'] ) { |
| 49 | 93 | printf( |
| @@ -66,30 +110,34 @@ | ||
| 66 | 110 | '<code>' . esc_url( $cdn_source['url'] ) . '</code>' |
| 67 | 111 | ); |
| 68 | 112 | } |
| 69 | 113 | |
| 70 | - $settings->field_hidden( [ | |
| 71 | - 'option_name' => 'cdn_url', | |
| 72 | - 'current_value' => $cdn_source['url'], | |
| 73 | - ] ); | |
| 114 | + $settings->field_hidden( | |
| 115 | + [ | |
| 116 | + 'option_name' => 'cdn_url', | |
| 117 | + 'current_value' => $cdn_source['url'], | |
| 118 | + ] | |
| 119 | + ); | |
| 74 | 120 | } else { |
| 75 | - $settings->field_text_box( [ | |
| 76 | - 'option_name' => 'cdn_url', | |
| 77 | - 'label' => __( 'If you use a CDN, specify the URL:', 'imagify' ), | |
| 78 | - 'attributes' => [ | |
| 79 | - 'size' => 30, | |
| 80 | - 'placeholder' => __( 'https://cdn.example.com', 'imagify' ), | |
| 81 | - ], | |
| 82 | - ] ); | |
| 121 | + $settings->field_text_box( | |
| 122 | + [ | |
| 123 | + 'option_name' => 'cdn_url', | |
| 124 | + 'label' => __( 'If you use a CDN, specify the URL:', 'imagify' ), | |
| 125 | + 'attributes' => [ | |
| 126 | + 'size' => 30, | |
| 127 | + 'placeholder' => __( 'https://cdn.example.com', 'imagify' ), | |
| 128 | + ], | |
| 129 | + ] | |
| 130 | + ); | |
| 83 | 131 | } |
| 84 | 132 | ?> |
| 85 | 133 | </div> |
| 86 | 134 | </div> |
| 87 | 135 | |
| 88 | - <div id="describe-display_webp_method" class="imagify-info"> | |
| 136 | + <div id="describe-display_nextgen_method" class="imagify-info"> | |
| 89 | 137 | <span class="dashicons dashicons-info"></span> |
| 90 | 138 | <?php |
| 91 | - $conf_file_path = \Imagify\Webp\Display::get_instance()->get_file_path( true ); | |
| 139 | + $conf_file_path = Display::get_instance()->get_file_path( true ); | |
| 92 | 140 | |
| 93 | 141 | if ( $conf_file_path ) { |
| 94 | 142 | printf( |
| 95 | 143 | /* translators: 1 is a file name, 2 is a <strong> tag opening, 3 is the <strong> tag closing. */ |
| @@ -124,33 +172,66 @@ | ||
| 124 | 172 | </div> |
| 125 | 173 | </div> |
| 126 | 174 | |
| 127 | 175 | <?php |
| 128 | - $count = \Imagify\Stats\OptimizedMediaWithoutWebp::get_instance()->get_cached_stat(); | |
| 176 | + $count = OptimizedMediaWithoutNextGen::get_instance()->get_cached_stat(); | |
| 129 | 177 | |
| 130 | 178 | if ( $count ) { |
| 131 | 179 | ?> |
| 132 | - <div class="imagify-options-line hide-if-no-js"> | |
| 133 | - <p> | |
| 134 | - <?php | |
| 135 | - echo esc_html( | |
| 136 | - sprintf( | |
| 137 | - /* translators: %s is a formatted number (don’t use %d). */ | |
| 138 | - _n( 'It seems that you have %s optimized image without WebP versions. You can generate them here if a backup copy is available.', 'It seems that you have %s optimized images without WebP versions. You can generate them here if backup copies are available.', $count, 'imagify' ), | |
| 139 | - number_format_i18n( $count ) | |
| 140 | - ) | |
| 141 | - ); | |
| 142 | - ?> | |
| 143 | - </p> | |
| 180 | + <div class="imagify-options-line hide-if-no-js generate-missing-webp"> | |
| 181 | + <?php $this->print_template( 'part-settings-webp-missing-message', [ 'count' => $count ] ); ?> | |
| 144 | 182 | |
| 145 | 183 | <button id="imagify-generate-webp-versions" class="button imagify-button-primary imagify-button-mini" type="button"> |
| 146 | 184 | <span class="dashicons dashicons-admin-generic"></span> |
| 147 | - <span class="button-text"><?php esc_html_e( 'Generate missing WebP versions', 'imagify' ); ?></span> | |
| 185 | + <?php | |
| 186 | + /* | |
| 187 | + * Keep this string byte-identical to the ability label in | |
| 188 | + * classes/Abilities/GenerateMissingNextgen.php: same wording means one shared | |
| 189 | + * entry on translate.wordpress.org rather than two. The casing looks off next | |
| 190 | + * to the rest of the UI, but the button is uppercased by CSS, so it renders as | |
| 191 | + * "GENERATE MISSING NEXT-GEN VERSIONS" either way. Re-casing it here would | |
| 192 | + * silently fork the two into separate strings to translate. | |
| 193 | + */ | |
| 194 | + ?> | |
| 195 | + <span class="button-text"><?php esc_html_e( 'Generate missing next-gen versions', 'imagify' ); ?></span> | |
| 148 | 196 | </button> |
| 149 | 197 | |
| 150 | - <div aria-hidden="true" class="imagify-progress hidden"> | |
| 198 | + <?php | |
| 199 | + $remaining = OptimizedMediaWithoutNextGen::get_instance()->get_stat(); | |
| 200 | + $total = get_transient( 'imagify_missing_next_gen_total' ); | |
| 201 | + $progress = 0; | |
| 202 | + $aria = ' aria-hidden="true"'; | |
| 203 | + $class = 'hidden'; | |
| 204 | + $style = ''; | |
| 205 | + | |
| 206 | + if ( | |
| 207 | + false !== $total | |
| 208 | + && | |
| 209 | + $total > 0 | |
| 210 | + ) { | |
| 211 | + $aria = ''; | |
| 212 | + $class = ''; | |
| 213 | + | |
| 214 | + /* | |
| 215 | + * `$total` is a snapshot taken when the run started, while `$remaining` is | |
| 216 | + * recounted on every page load. Anything growing the workload mid-run (new | |
| 217 | + * uploads, or switching the Next-Gen format so every media is missing one) | |
| 218 | + * pushes `$remaining` above `$total`, and `$total - $remaining` goes negative. | |
| 219 | + * Report against the largest workload seen instead. Mirrors getProgress() in | |
| 220 | + * assets/js/options.js. | |
| 221 | + */ | |
| 222 | + $remaining = max( (int) $remaining, 0 ); | |
| 223 | + $effective_total = max( (int) $total, $remaining ); | |
| 224 | + $processed = $effective_total - $remaining; | |
| 225 | + $progress = $processed . '/' . $effective_total; | |
| 226 | + $percent = $effective_total > 0 ? floor( $processed / $effective_total * 100 ) : 0; | |
| 227 | + $style = 'style="width:' . $percent . '%;"'; | |
| 228 | + } | |
| 229 | + ?> | |
| 230 | + | |
| 231 | + <div <?php echo $aria; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> class="imagify-progress <?php echo esc_attr( $class ); ?>"> | |
| 151 | 232 | <div class="progress"> |
| 152 | - <div class="bar"><div class="percent">0</div></div> | |
| 233 | + <div class="bar" <?php echo $style; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>><div class="percent"><?php echo esc_html( $progress ); ?></div></div> | |
| 153 | 234 | </div> |
| 154 | 235 | </div> |
| 155 | 236 | </div> |
| 156 | 237 | <?php |