Plugin Directory

Changeset 3789337


Ignore:
Timestamp:
11/07/2026 10:23:07 AM (less than one hour ago)
Author:
kgmservizi
Message:

Release 0.8.0: require PHP 8.0 / WP 5.6, fix fatal errors

Location:
disable-thumbnails-and-threshold
Files:
6 edited
9 copied

Legend:

Unmodified
Added
Removed
  • disable-thumbnails-and-threshold/tags/0.8.0/disable-thumbnails-and-thresold.php

    r3504636 r3789337  
    11<?php
    2 /*
    3 Plugin Name: Disable Thumbnails, Threshold and Image Options
    4 Version: 0.7.0
    5 Description: Disable Thumbnails, Threshold and Image Options
    6 Author: KGM Servizi
    7 Author URI: https://kgmservizi.com
    8 License: GPLv2 or later
    9 License URI: https://www.gnu.org/licenses/gpl-2.0.html
    10 Text Domain: disable-thumbnails-and-threshold
    11 Requires at least: 5.4
    12 Requires PHP: 7.4
    13 */
     2/**
     3 * Plugin Name: Disable Thumbnails, Threshold and Image Options
     4 * Version: 0.8.0
     5 * Description: Disable Thumbnails, Threshold and Image Options
     6 * Author: KGM Servizi
     7 * Author URI: https://kgmservizi.com
     8 * License: GPLv2 or later
     9 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
     10 * Text Domain: disable-thumbnails-and-threshold
     11 * Requires at least: 5.6
     12 * Requires PHP: 8.0
     13 *
     14 * @package Disable_Thumbnails_Threshold
     15 */
    1416
    1517if ( ! defined( 'ABSPATH' ) ) {
    16         exit; // Exit if accessed directly
    17 }
    18 
    19 // Define plugin constants for better maintainability
     18        exit; // Exit if accessed directly.
     19}
     20
     21// Define plugin constants for better maintainability.
    2022define( 'DTAT_QUALITY_OPTION', 'dtat_imgquality_option_name' );
    2123define( 'DTAT_THRESHOLD_OPTION', 'dtat_disablethreshold_option_name' );
    2224define( 'DTAT_THUMBNAILS_OPTION', 'dtat_disablethumbnails_option_name' );
    2325define( 'DTAT_MIGRATION_OPTION', 'dtat_migration_done' );
    24 define( 'DTAT_VERSION', '0.7.0' );
    25 
    26 /**
    27  * PHPCS Suppressions
    28  *
    29  * This file contains phpcs:ignore comments for the following cases:
    30  * - Line 151, 131 (option-quality.php): WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
    31  *   Reason: Using WordPress core hook (jpeg_quality) which doesn't require plugin prefix
    32  * - Line 174, 172 (option-threshold-exif.php), 206 (option-threshold-exif.php): WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
    33  *   Reason: Using WordPress core hook (big_image_size_threshold) which doesn't require plugin prefix
    34  * - Line 241 (option-threshold-exif.php): WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
    35  *   Reason: Using WordPress core hook (wp_image_maybe_exif_rotate) which doesn't require plugin prefix
    36  */
    37 
    38 // Check WordPress version compatibility - requires WordPress 5.4+ for PHP 7.4+ support
    39 // Use admin_init hook to ensure WordPress is fully loaded
     26define( 'DTAT_VERSION', '0.8.0' );
     27define( 'DTAT_MIN_WP_VERSION', '5.6' );
     28define( 'DTAT_MIN_PHP_VERSION', '8.0' );
     29
     30// Check WordPress version compatibility - WordPress 5.6 is the first release that supports PHP 8.0.
     31// Use admin_init hook to ensure WordPress is fully loaded.
    4032add_action( 'admin_init', 'dtat_check_wordpress_version' );
    4133
    … …  
    5042
    5143/**
    52  * 
     44 *
    5345 * Retrieve options for quality and threshold
    5446 * Cache options globally to avoid multiple database calls
    55  *
    5647 */
    5748$GLOBALS['dtat_imgquality_options']        = get_option( DTAT_QUALITY_OPTION );
    … …  
    7768        $processed = true;
    7869
     70        // admin_init also fires for logged-out admin-ajax.php/admin-post.php requests.
     71        if ( ! current_user_can( 'manage_options' ) ) {
     72                return;
     73        }
     74
    7975        // Skip migration if already completed for this plugin version.
    8076        if ( get_option( DTAT_MIGRATION_OPTION ) === DTAT_VERSION ) {
    … …  
    8278        }
    8379
    84         $option_map = [
    85                 DTAT_QUALITY_OPTION     => 'kgmimgquality_option_name',
    86                 DTAT_THRESHOLD_OPTION   => 'kgmdisablethreshold_option_name',
    87                 DTAT_THUMBNAILS_OPTION  => 'kgmdisablethumbnails_option_name',
    88         ];
     80        $option_map = array(
     81                DTAT_QUALITY_OPTION    => 'kgmimgquality_option_name',
     82                DTAT_THRESHOLD_OPTION  => 'kgmdisablethreshold_option_name',
     83                DTAT_THUMBNAILS_OPTION => 'kgmdisablethumbnails_option_name',
     84        );
    8985
    9086        foreach ( $option_map as $new_option => $legacy_option ) {
    … …  
    105101        }
    106102
     103        /*
     104         * The globals were cached at load time, before the migration. Without a refresh,
     105         * dtat_initialize_options() (same hook, later) sees them empty and overwrites the
     106         * migrated values with defaults, after the legacy rows are already deleted.
     107         */
     108        $GLOBALS['dtat_imgquality_options']        = get_option( DTAT_QUALITY_OPTION );
     109        $GLOBALS['dtat_disablethreshold_options']  = get_option( DTAT_THRESHOLD_OPTION );
     110        $GLOBALS['dtat_disablethumbnails_options'] = get_option( DTAT_THUMBNAILS_OPTION );
     111
    107112        update_option( DTAT_MIGRATION_OPTION, DTAT_VERSION );
    108113}
    109114
    110115
    111 // Initialize with current WordPress values if options don't exist
    112 // This will be handled in the admin_init hook to ensure WordPress is fully loaded
     116// Initialize with current WordPress values if options don't exist.
     117// This will be handled in the admin_init hook to ensure WordPress is fully loaded.
    113118add_action( 'admin_init', 'dtat_initialize_options' );
    114119
    115 // Hook to apply filters after themes are loaded to ensure priority
     120// Hook to apply filters after themes are loaded to ensure priority.
    116121add_action( 'after_setup_theme', 'dtat_apply_filters', 20 );
    117122
    … …  
    126131 */
    127132function dtat_check_wordpress_version(): void {
    128         // Only run in admin
     133        // Only run in admin.
    129134        if ( ! is_admin() ) {
    130135                return;
    131136        }
    132        
    133         // Check if WordPress version is compatible
    134         if ( version_compare( get_bloginfo( 'version' ), '5.4', '<' ) ) {
     137
     138        // Check if WordPress version is compatible.
     139        if ( version_compare( get_bloginfo( 'version' ), DTAT_MIN_WP_VERSION, '<' ) ) {
    135140                add_action( 'admin_notices', 'dtat_wordpress_version_notice' );
    136141        }
    … …  
    146151function dtat_wordpress_version_notice(): void {
    147152        printf(
    148                 '<div class="notice notice-error"><p><strong>%s</strong> %s</p></div>',
    149                 esc_html__( 'Disable Thumbnails, Threshold and Image Options', 'disable-thumbnails-and-threshold' ),
    150                 esc_html__( 'requires WordPress 5.4 or higher (PHP 7.4+). Please update WordPress.', 'disable-thumbnails-and-threshold' )
     153                '<div class="notice notice-error"><p>%s</p></div>',
     154                esc_html(
     155                        sprintf(
     156                                /* translators: 1: Plugin name, 2: Minimum WordPress version, 3: Minimum PHP version. */
     157                                __( '%1$s requires WordPress %2$s or higher and PHP %3$s or higher. Please update.', 'disable-thumbnails-and-threshold' ),
     158                                'Disable Thumbnails, Threshold and Image Options',
     159                                DTAT_MIN_WP_VERSION,
     160                                DTAT_MIN_PHP_VERSION
     161                        )
     162                )
    151163        );
    152164}
    … …  
    162174 */
    163175function dtat_initialize_options(): void {
    164         // Only run in admin and if user has proper capabilities
     176        // Only run in admin and if user has proper capabilities.
    165177        if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) {
    166178                return;
    167179        }
    168        
    169         // Initialize JPEG quality option if it doesn't exist or is invalid
    170         if ( ! $GLOBALS['dtat_imgquality_options'] ||
    171                  ! is_array( $GLOBALS['dtat_imgquality_options'] ) ||
    172                  ! isset( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) ||
    173                  ! is_numeric( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) ||
    174                  intval( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) < 1 ||
    175                  intval( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) > 100 ) {
    176                
    177                 // Get current WordPress JPEG quality (respects existing filters/plugins)
    178                 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WordPress core hook
    179                 $current_quality = apply_filters( 'jpeg_quality', 82 );
    180                
    181                 // Validate the quality value from filters
     180
     181        // Initialize JPEG quality option if it doesn't exist or is invalid.
     182        if ( ! $GLOBALS['dtat_imgquality_options'] ||
     183                ! is_array( $GLOBALS['dtat_imgquality_options'] ) ||
     184                ! isset( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) ||
     185                ! is_numeric( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) ||
     186                intval( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) < 1 ||
     187                intval( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) > 100 ) {
     188                /*
     189                 * Get current WordPress JPEG quality (respects existing filters/plugins).
     190                 * Pass every argument core passes: on PHP 8 a third-party callback with a
     191                 * required $context would otherwise throw ArgumentCountError here.
     192                 */
     193                try {
     194                        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WordPress core hook
     195                        $current_quality = apply_filters( 'jpeg_quality', 82, 'image_resize' );
     196                } catch ( Throwable $e ) {
     197                        $current_quality = 82;
     198                }
     199
     200                // Validate the quality value from filters.
    182201                if ( ! is_numeric( $current_quality ) || $current_quality < 1 || $current_quality > 100 ) {
    183                         $current_quality = 82; // Fallback to WordPress default
    184                 }
    185                
    186                 // Preserve existing options and only update jpeg_quality
     202                        $current_quality = 82; // Fallback to WordPress default.
     203                }
     204
     205                // Preserve existing options and only update jpeg_quality.
    187206                if ( ! is_array( $GLOBALS['dtat_imgquality_options'] ) ) {
    188                         $GLOBALS['dtat_imgquality_options'] = [];
     207                        $GLOBALS['dtat_imgquality_options'] = array();
    189208                }
    190209                $GLOBALS['dtat_imgquality_options']['jpeg_quality'] = intval( $current_quality );
    191210                update_option( DTAT_QUALITY_OPTION, $GLOBALS['dtat_imgquality_options'] );
    192211        }
    193        
    194         // Initialize threshold option if it doesn't exist or is invalid
    195         if ( ! $GLOBALS['dtat_disablethreshold_options'] ||
    196                  ! is_array( $GLOBALS['dtat_disablethreshold_options'] ) ||
    197                  ! isset( $GLOBALS['dtat_disablethreshold_options']['new_threshold'] ) ||
    198                  ! is_numeric( $GLOBALS['dtat_disablethreshold_options']['new_threshold'] ) ||
    199                  intval( $GLOBALS['dtat_disablethreshold_options']['new_threshold'] ) <= 0 ) {
    200                
    201                 // Get current WordPress big image threshold (respects existing filters/plugins)
    202                 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WordPress core hook
    203                 $current_threshold = apply_filters( 'big_image_size_threshold', 2560 );
    204                
    205                 // Validate the threshold value from filters
     212
     213        // Initialize threshold option if it doesn't exist or is invalid.
     214        if ( ! $GLOBALS['dtat_disablethreshold_options'] ||
     215                ! is_array( $GLOBALS['dtat_disablethreshold_options'] ) ||
     216                ! isset( $GLOBALS['dtat_disablethreshold_options']['new_threshold'] ) ||
     217                ! is_numeric( $GLOBALS['dtat_disablethreshold_options']['new_threshold'] ) ||
     218                intval( $GLOBALS['dtat_disablethreshold_options']['new_threshold'] ) <= 0 ) {
     219                /*
     220                 * Get current WordPress big image threshold (respects existing filters/plugins).
     221                 * Core passes $imagesize, $file and $attachment_id; there is no real image here,
     222                 * so neutral values are passed and any callback failure falls back to the default.
     223                 */
     224                try {
     225                        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WordPress core hook
     226                        $current_threshold = apply_filters( 'big_image_size_threshold', 2560, array( 0, 0 ), '', 0 );
     227                } catch ( Throwable $e ) {
     228                        $current_threshold = 2560;
     229                }
     230
     231                // Validate the threshold value from filters.
    206232                if ( ! is_numeric( $current_threshold ) || $current_threshold <= 0 ) {
    207                         $current_threshold = 2560; // Fallback to WordPress default
    208                 }
    209                
    210                 // Preserve existing options and only update new_threshold
     233                        $current_threshold = 2560; // Fallback to WordPress default.
     234                }
     235
     236                // Preserve existing options and only update new_threshold.
    211237                if ( ! is_array( $GLOBALS['dtat_disablethreshold_options'] ) ) {
    212                         $GLOBALS['dtat_disablethreshold_options'] = [];
     238                        $GLOBALS['dtat_disablethreshold_options'] = array();
    213239                }
    214240                $GLOBALS['dtat_disablethreshold_options']['new_threshold'] = intval( $current_threshold );
    … …  
    225251 */
    226252function dtat_jpeg_quality_filter(): int {
    227         $dtat_imgquality_options = $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION, [] );
    228        
     253        $dtat_imgquality_options = $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION, array() );
     254
    229255        if ( ! is_array( $dtat_imgquality_options ) || ! isset( $dtat_imgquality_options['jpeg_quality'] ) ) {
    230                 return 82; // WordPress default
    231         }
    232        
     256                return 82; // WordPress default.
     257        }
     258
    233259        $quality = intval( $dtat_imgquality_options['jpeg_quality'] );
    234        
    235         // Validate quality range (0-100)
    236         if ( $quality < 0 || $quality > 100 ) {
    237                 return 82; // WordPress default
    238         }
    239        
     260
     261        // Same 1-100 range accepted by the settings page.
     262        if ( $quality < 1 || $quality > 100 ) {
     263                return 82; // WordPress default.
     264        }
     265
    240266        return $quality;
    241267}
    … …  
    249275 */
    250276function dtat_big_image_threshold_filter(): int {
    251         $dtat_disablethreshold_options = $GLOBALS['dtat_disablethreshold_options'] ?? get_option( DTAT_THRESHOLD_OPTION, [] );
    252        
     277        $dtat_disablethreshold_options = $GLOBALS['dtat_disablethreshold_options'] ?? get_option( DTAT_THRESHOLD_OPTION, array() );
     278
    253279        if ( ! is_array( $dtat_disablethreshold_options ) || ! isset( $dtat_disablethreshold_options['new_threshold'] ) ) {
    254                 return 2560; // WordPress default
    255         }
    256        
     280                return 2560; // WordPress default.
     281        }
     282
    257283        $threshold = intval( $dtat_disablethreshold_options['new_threshold'] );
    258        
    259         // Validate threshold is positive
     284
     285        // Validate threshold is positive.
    260286        if ( $threshold <= 0 ) {
    261                 return 2560; // WordPress default
    262         }
    263        
     287                return 2560; // WordPress default.
     288        }
     289
    264290        return $threshold;
    265291}
    … …  
    270296 * @since   0.1
    271297 * @package Disable_Thumbnails_Threshold
    272  * @param   array $sizes Registered intermediate image sizes.
    273  * @return  array Filtered image sizes with disabled ones removed.
    274  */
    275 function dtat_thumbnail_sizes_filter( array $sizes ): array {
    276         $dtat_disablethumbnails_options = $GLOBALS['dtat_disablethumbnails_options'] ?? get_option( DTAT_THUMBNAILS_OPTION, [] );
    277        
     298 * @param   mixed $sizes Registered intermediate image sizes (an array, unless another filter broke it).
     299 * @return  mixed Filtered image sizes with disabled ones removed.
     300 */
     301function dtat_thumbnail_sizes_filter( $sizes ) {
     302        // Untyped on purpose: a TypeError here would break every media upload.
     303        if ( ! is_array( $sizes ) ) {
     304                return $sizes;
     305        }
     306
     307        $dtat_disablethumbnails_options = $GLOBALS['dtat_disablethumbnails_options'] ?? get_option( DTAT_THUMBNAILS_OPTION, array() );
     308
    278309        if ( ! is_array( $dtat_disablethumbnails_options ) || empty( $dtat_disablethumbnails_options ) ) {
    279310                return $sizes;
    280311        }
    281        
    282         // Validate that all values in the array are strings (security check)
     312
     313        // Validate that all values in the array are strings (security check).
    283314        $valid_options = array_filter( $dtat_disablethumbnails_options, 'is_string' );
    284        
     315
    285316        return array_diff( $sizes, $valid_options );
    286317}
    … …  
    294325 */
    295326function dtat_apply_filters(): void {
    296         // Prevent multiple applications
     327        // Prevent multiple applications.
    297328        static $applied = false;
    298329        if ( $applied ) {
    … …  
    300331        }
    301332        $applied = true;
    302        
    303         // Remove any existing filters to prevent accumulation
     333
     334        // Remove any existing filters to prevent accumulation.
    304335        remove_filter( 'jpeg_quality', 'dtat_jpeg_quality_filter' );
    305336        remove_filter( 'big_image_size_threshold', 'dtat_big_image_threshold_filter' );
    306337        remove_filter( 'intermediate_image_sizes', 'dtat_thumbnail_sizes_filter' );
    307        
    308         // Safely get options with fallback
    309         $dtat_imgquality_options = $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION, [] );
    310         $dtat_disablethreshold_options = $GLOBALS['dtat_disablethreshold_options'] ?? get_option( DTAT_THRESHOLD_OPTION, [] );
    311         $dtat_disablethumbnails_options = $GLOBALS['dtat_disablethumbnails_options'] ?? get_option( DTAT_THUMBNAILS_OPTION, [] );
    312        
    313         // Apply JPEG quality filter
     338
     339        // Safely get options with fallback.
     340        $dtat_imgquality_options        = $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION, array() );
     341        $dtat_disablethreshold_options  = $GLOBALS['dtat_disablethreshold_options'] ?? get_option( DTAT_THRESHOLD_OPTION, array() );
     342        $dtat_disablethumbnails_options = $GLOBALS['dtat_disablethumbnails_options'] ?? get_option( DTAT_THUMBNAILS_OPTION, array() );
     343
     344        // Apply JPEG quality filter.
    314345        $jpeg_quality = null;
    315346        if ( is_array( $dtat_imgquality_options ) ) {
    316347                $jpeg_quality = $dtat_imgquality_options['jpeg_quality'] ?? null;
    317348        }
    318        
     349
    319350        $quality = $jpeg_quality ? intval( $jpeg_quality ) : 0;
    320351        if ( $jpeg_quality && is_numeric( $jpeg_quality ) && $quality > 0 && $quality <= 100 ) {
    … …  
    322353        }
    323354
    324         // Apply threshold filters
     355        // Apply threshold filters.
    325356        if ( is_array( $dtat_disablethreshold_options ) ) {
    326                 // Set new threshold
     357                // Set new threshold.
    327358                if ( ! empty( $dtat_disablethreshold_options['new_threshold'] )
    328359                        && is_numeric( $dtat_disablethreshold_options['new_threshold'] ) ) {
    … …  
    333364                }
    334365
    335                 // Disable threshold
     366                // Disable threshold.
    336367                if ( 'disable_threshold' === ( $dtat_disablethreshold_options['disable_threshold'] ?? null ) ) {
    337368                        add_filter( 'big_image_size_threshold', '__return_false', 100 );
    338369                }
    339370
    340                 // Disable EXIF rotation
     371                // Disable EXIF rotation.
    341372                if ( 'disable_image_rotation_exif' === ( $dtat_disablethreshold_options['disable_image_rotation_exif'] ?? null ) ) {
    342373                        add_filter( 'wp_image_maybe_exif_rotate', '__return_zero', 100, 2 );
    … …  
    344375        }
    345376
    346         // Apply thumbnail size filters
     377        // Apply thumbnail size filters.
    347378        if ( ! empty( $dtat_disablethumbnails_options ) ) {
    348379                add_filter( 'intermediate_image_sizes', 'dtat_thumbnail_sizes_filter', 100 );
    … …  
    350381}
    351382
    352 // All filters are now applied in dtat_apply_filters() function after themes are loaded
     383// All filters are now applied in dtat_apply_filters() function after themes are loaded.
    353384
    354385/**
    … …  
    361392 */
    362393function dtat_action_links( array $actions ): array {
    363         // Check if user has proper capabilities before showing action links
     394        // Check if user has proper capabilities before showing action links.
    364395        if ( ! current_user_can( 'manage_options' ) ) {
    365396                return $actions;
    366397        }
    367        
    368         $mylinks = [
     398
     399        $mylinks = array(
    369400                '<a href="' . esc_url( get_admin_url( null, 'tools.php?page=kgmdisablethumbnails' ) ) . '">' . esc_html__( 'Image sizes', 'disable-thumbnails-and-threshold' ) . '</a>',
    370401                '<a href="' . esc_url( get_admin_url( null, 'tools.php?page=kgmimgquality' ) ) . '">' . esc_html__( 'Image Quality', 'disable-thumbnails-and-threshold' ) . '</a>',
    371402                '<a href="' . esc_url( get_admin_url( null, 'tools.php?page=kgmdisablethreshold' ) ) . '">' . esc_html__( 'Threshold & EXIF', 'disable-thumbnails-and-threshold' ) . '</a>',
    372         ];
     403        );
    373404        return array_merge( $mylinks, $actions );
    374405}
    … …  
    383414 */
    384415function dtat_admin_styles( string $hook ): void {
    385         /**
    386          * Check if in plugin options page and user has proper capabilities
    387          */
    388416        if ( ! current_user_can( 'manage_options' ) ) {
    389417                return;
    390418        }
    391        
    392         $screen = get_current_screen();
    393         if ( ! $screen ) {
    394                 return;
    395         }
    396        
    397         if ( 'tools_page_kgmdisablethumbnails' === $screen->base || 'tools_page_kgmdisablethreshold' === $screen->base ) {
    398                 wp_enqueue_style( 'dtat-admin-css', plugins_url( 'includes/admin.css', __FILE__ ), [], DTAT_VERSION );
    399         }
    400 }
     419
     420        $plugin_pages = array( 'tools_page_kgmdisablethumbnails', 'tools_page_kgmdisablethreshold', 'tools_page_kgmimgquality' );
     421        if ( in_array( $hook, $plugin_pages, true ) ) {
     422                wp_enqueue_style( 'dtat-admin-css', plugins_url( 'includes/admin.css', __FILE__ ), array(), DTAT_VERSION );
     423        }
     424}
     425
     426register_uninstall_hook( __FILE__, 'dtat_plugin_uninstall' );
    401427
    402428/**
    403429 * Clean up plugin options on uninstall.
    404430 *
    405  * @since   0.1
    406  * @package Disable_Thumbnails_Threshold
    407  * @return  void
    408  */
    409 register_uninstall_hook( __FILE__, 'dtat_plugin_uninstall' );
     431 * Also removes the pre-0.6.5 `kgm*` options, which survive when the migration never ran.
     432 *
     433 * @since   0.1
     434 * @package Disable_Thumbnails_Threshold
     435 * @return  void
     436 */
    410437function dtat_plugin_uninstall(): void {
    411438        delete_option( DTAT_THUMBNAILS_OPTION );
    … …  
    413440        delete_option( DTAT_QUALITY_OPTION );
    414441        delete_option( DTAT_MIGRATION_OPTION );
    415 }
     442        delete_option( 'kgmimgquality_option_name' );
     443        delete_option( 'kgmdisablethreshold_option_name' );
     444        delete_option( 'kgmdisablethumbnails_option_name' );
     445}
  • disable-thumbnails-and-threshold/tags/0.8.0/includes/admin.css

    r3504636 r3789337  
    11.switch { position: relative; display: inline-block; width: 33px; height: 17px; margin-right: 0.4em; }
    22.switch input { position: absolute; opacity: 0; width: 1px; height: 1px; clip: rect(0 0 0 0); overflow: hidden; }
    3 .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; -webkit-transition: 0.5s; transition: 0.5s; border-radius: 18px; display:inline; }
     3/* Inset border #757575: 4.05:1 on the form-table background #f0f0f1 (SC 1.4.11 needs 3:1). */
     4.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; box-shadow: inset 0 0 0 1px #757575; -webkit-transition: 0.5s; transition: 0.5s; border-radius: 18px; display:inline; }
    45.slider::before { position: absolute; content: ""; height: 10px; width: 10px; left: 4px; bottom: 4px; background-color: #fff; -webkit-transition: 0.5s; transition: 0.5s; border-radius: 50%; }
    56input:checked + .screen-reader-text + .slider,
    67input:checked + .slider { background-color: #b12222; }
     8/* Transparent outline: box-shadow is dropped in forced-colors mode, the outline is not. */
    79input:focus + .screen-reader-text + .slider,
    8 input:focus + .slider { box-shadow: 0 0 0 3px #005fcc; }
     10input:focus + .slider { outline: 2px solid transparent; outline-offset: 2px; box-shadow: inset 0 0 0 1px #757575, 0 0 0 3px #005fcc; }
    911input:checked + .screen-reader-text + .slider::before,
    1012input:checked + .slider::before { -webkit-transform: translateX(16px); -ms-transform: translateX(16px); transform: translateX(16px); }
    11 .dtat-notice-warning { color: #d63638; }
    12 .dtat-notice-caution { color: #dba617; }
     13@media (forced-colors: active) {
     14        .slider { border: 1px solid ButtonText; }
     15        .slider::before { background-color: ButtonText; }
     16        input:checked + .screen-reader-text + .slider,
     17        input:checked + .slider { background-color: Highlight; }
     18}
     19/* Ratios on #f0f0f1: warning 5.53:1, caution 4.86:1, info 5.04:1 (SC 1.4.3 needs 4.5:1). */
     20.dtat-notice-warning { color: #b32d2e; }
     21.dtat-notice-caution { color: #8a6100; }
    1322.dtat-notice-info { color: #666; }
  • disable-thumbnails-and-threshold/tags/0.8.0/includes/option-quality.php

    r3504636 r3789337  
    1212
    1313if ( ! defined( 'ABSPATH' ) ) {
    14         exit; // Exit if accessed directly
     14        exit; // Exit if accessed directly.
    1515}
    1616
     17/**
     18 * Image Quality settings page.
     19 *
     20 * @since 0.2
     21 */
    1722class DTAT_Img_Quality {
    18         private array|false $dtat_imgquality_options;
     23        /**
     24         * Stored option value. Untyped on purpose: whatever the database holds must not raise a TypeError.
     25         *
     26         * @var array|false
     27         */
     28        private $dtat_imgquality_options = false;
    1929
    2030        /**
    … …  
    2434         */
    2535        public function __construct() {
    26                 add_action( 'admin_menu', [ $this, 'add_plugin_page' ] );
    27                 add_action( 'admin_init', [ $this, 'page_init' ] );
     36                add_action( 'admin_menu', array( $this, 'add_plugin_page' ) );
     37                add_action( 'admin_init', array( $this, 'page_init' ) );
    2838        }
    2939
    … …  
    4050                        'manage_options',
    4151                        'kgmimgquality',
    42                         [ $this, 'create_admin_page' ]
     52                        array( $this, 'create_admin_page' )
    4353                );
    4454        }
    … …  
    5161         */
    5262        public function create_admin_page() {
    53                 // Check user capabilities for security
     63                // Check user capabilities for security.
    5464                if ( ! current_user_can( 'manage_options' ) ) {
    5565                        wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'disable-thumbnails-and-threshold' ) );
    5666                }
    57                
    58                 // Use cached options to avoid database calls
     67
     68                // Use cached options to avoid database calls.
    5969                $this->dtat_imgquality_options = $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION ); ?>
    6070
    6171                <div class="wrap">
    62                         <h2><?php echo esc_html__( 'Image Quality', 'disable-thumbnails-and-threshold' ); ?></h2>
     72                        <h1><?php echo esc_html__( 'Image Quality', 'disable-thumbnails-and-threshold' ); ?></h1>
    6373                        <p><strong><?php echo esc_html__( 'Remember you need to regenerate thumbnails for delete old thumbnails image already generated.', 'disable-thumbnails-and-threshold' ); ?></strong></p>
    64                         <p><?php echo esc_html__( 'Plugin recommended for regenerate thumbnails', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://uskgm.it/reg-thumb' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Regenerate Thumbnails', 'disable-thumbnails-and-threshold' ); ?></a></p>
    65                         <p><?php echo esc_html__( 'WP-CLI media regeneration', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://uskgm.it/WP-CLI-thumb-rgnrt' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Documentation', 'disable-thumbnails-and-threshold' ); ?></a></p>
     74                        <p><?php echo esc_html__( 'Plugin recommended for regenerate thumbnails', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://wordpress.org/plugins/regenerate-thumbnails/' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Regenerate Thumbnails', 'disable-thumbnails-and-threshold' ); ?></a></p>
     75                        <p><?php echo esc_html__( 'WP-CLI media regeneration', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://developer.wordpress.org/cli/commands/media/regenerate/' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Documentation', 'disable-thumbnails-and-threshold' ); ?></a></p>
    6676                        <?php settings_errors(); ?>
    6777
    … …  
    7484                        </form>
    7585                </div>
    76         <?php }
     86                <?php
     87        }
    7788
    7889        /**
    … …  
    8697                        'kgmimgquality_option_group',
    8798                        DTAT_QUALITY_OPTION,
    88                         [ $this, 'sanitize' ]
     99                        array( $this, 'sanitize' )
    89100                );
    90101
    91102                add_settings_section(
    92103                        'kgmimgquality_setting_section',
    93                         esc_html__( 'Settings', 'disable-thumbnails-and-threshold' ), 
    94                         [ $this, 'section_info' ],
    95                         'kgmimgquality-admin' 
     104                        esc_html__( 'Settings', 'disable-thumbnails-and-threshold' ),
     105                        array( $this, 'section_info' ),
     106                        'kgmimgquality-admin'
    96107                );
    97108
    … …  
    99110                        'jpeg_quality',
    100111                        esc_html__( 'JPEG Quality', 'disable-thumbnails-and-threshold' ) . ' <br> <small>' . esc_html__( 'Default WordPress: 82%', 'disable-thumbnails-and-threshold' ) . '</small>',
    101                         [ $this, 'jpeg_quality_callback' ],
     112                        array( $this, 'jpeg_quality_callback' ),
    102113                        'kgmimgquality-admin',
    103                         'kgmimgquality_setting_section'
     114                        'kgmimgquality_setting_section',
     115                        array( 'label_for' => 'jpeg_quality' )
    104116                );
    105117        }
    … …  
    108120         * Sanitize and validate form input before saving.
    109121         *
    110          * @since  0.2
    111          * @param  array $input Raw form input values.
     122         * Runs on every update_option() of this option, not only on form submit, so it
     123         * must not depend on the current user: options.php already enforces the nonce
     124         * and the manage_options capability before saving.
     125         *
     126         * @since  0.2
     127         * @param  mixed $input Raw value; null when the field is missing from the request.
    112128         * @return array Sanitized values.
    113129         */
    114         public function sanitize( array $input ): array {
    115                 // Check user capabilities for security
    116                 if ( ! current_user_can( 'manage_options' ) ) {
    117                         return $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION, [] );
    118                 }
    119                
    120                 // Nonce is already verified by WordPress options.php handler via settings_fields().
    121                 $sanitary_values = [];
     130        public function sanitize( $input ): array {
     131                if ( ! is_array( $input ) ) {
     132                        $input = array();
     133                }
     134
     135                $sanitary_values = array();
    122136
    123137                if ( isset( $input['jpeg_quality'] ) ) {
    124                         $quality = sanitize_text_field( $input['jpeg_quality'] );
     138                        $quality     = sanitize_text_field( $input['jpeg_quality'] );
    125139                        $quality_int = intval( $quality );
    126140                        if ( is_numeric( $quality ) && $quality_int >= 1 && $quality_int <= 100 ) {
    … …  
    128142                        } else {
    129143                                add_settings_error( 'kgmimgquality_option_notice', 'invalid_quality', esc_html__( 'JPEG quality must be a number between 1 and 100.', 'disable-thumbnails-and-threshold' ) );
    130                                 $existing = $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION, [] );
     144                                $existing = $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION, array() );
    131145                                if ( is_array( $existing ) && isset( $existing['jpeg_quality'] ) ) {
    132                                         return [ 'jpeg_quality' => absint( $existing['jpeg_quality'] ) ];
     146                                        return array( 'jpeg_quality' => absint( $existing['jpeg_quality'] ) );
    133147                                }
    134                                 return [];
     148                                return array();
    135149                        }
    136150                }
    … …  
    162176                        esc_html__( '%', 'disable-thumbnails-and-threshold' )
    163177                );
    164                
     178
    165179                // Compare plugin value against WordPress default.
    166180                // We avoid calling apply_filters() here because the jpeg_quality filter expects
    … …  
    173187
    174188                if ( $plugin_quality && $plugin_quality !== $wp_default_quality ) {
    175                         printf( '<br><small class="description dtat-notice-warning">%s %s</small>',
     189                        printf(
     190                                '<br><small class="description dtat-notice-warning">%s %s</small>',
    176191                                esc_html( '⚠️' ),
    177                                 // translators: %1$d: Plugin quality percentage, %2$d: WordPress default quality percentage
     192                                /* translators: %1$d: Plugin quality percentage, %2$d: WordPress default quality percentage */
    178193                                esc_html( sprintf( __( 'Plugin quality (%1$d%%) differs from WordPress default (%2$d%%)', 'disable-thumbnails-and-threshold' ), $plugin_quality, $wp_default_quality ) )
    179194                        );
    180195                } else {
    181                         printf( '<br><small class="description dtat-notice-info">%s</small>',
    182                                 // translators: %d: WordPress default JPEG quality percentage
     196                        printf(
     197                                '<br><small class="description dtat-notice-info">%s</small>',
     198                                /* translators: %d: WordPress default JPEG quality percentage */
    183199                                esc_html( sprintf( __( 'WordPress default JPEG quality: %d%%', 'disable-thumbnails-and-threshold' ), $wp_default_quality ) )
    184200                        );
    185201                }
    186202        }
    187 
    188203}
    189204if ( is_admin() ) {
    190         $DTAT_Img_Quality = new DTAT_Img_Quality();
     205        $dtat_img_quality = new DTAT_Img_Quality();
    191206}
  • disable-thumbnails-and-threshold/tags/0.8.0/includes/option-threshold-exif.php

    r3504636 r3789337  
    1212
    1313if ( ! defined( 'ABSPATH' ) ) {
    14         exit; // Exit if accessed directly
     14        exit; // Exit if accessed directly.
    1515}
    1616
     17/**
     18 * Threshold & EXIF settings page.
     19 *
     20 * @since 0.1
     21 */
    1722class DTAT_Disable_Threshold {
    18         private array|false $dtat_disablethreshold_options;
     23        /**
     24         * Stored option value. Untyped on purpose: whatever the database holds must not raise a TypeError.
     25         *
     26         * @var array|false
     27         */
     28        private $dtat_disablethreshold_options = false;
    1929
    2030        /**
    … …  
    2434         */
    2535        public function __construct() {
    26                 add_action( 'admin_menu', [ $this, 'add_plugin_page' ] );
    27                 add_action( 'admin_init', [ $this, 'page_init' ] );
     36                add_action( 'admin_menu', array( $this, 'add_plugin_page' ) );
     37                add_action( 'admin_init', array( $this, 'page_init' ) );
    2838        }
    2939
    … …  
    4050                        'manage_options',
    4151                        'kgmdisablethreshold',
    42                         [ $this, 'create_admin_page' ]
     52                        array( $this, 'create_admin_page' )
    4353                );
    4454        }
    … …  
    5161         */
    5262        public function create_admin_page() {
    53                 // Check user capabilities for security
     63                // Check user capabilities for security.
    5464                if ( ! current_user_can( 'manage_options' ) ) {
    5565                        wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'disable-thumbnails-and-threshold' ) );
    5666                }
    57                
    58                 // Use cached options to avoid database calls
     67
     68                // Use cached options to avoid database calls.
    5969                $this->dtat_disablethreshold_options = $GLOBALS['dtat_disablethreshold_options'] ?? get_option( DTAT_THRESHOLD_OPTION ); ?>
    6070
    6171                <div class="wrap">
    62                         <h2><?php echo esc_html__( 'Disable Threshold&EXIF', 'disable-thumbnails-and-threshold' ); ?></h2>
     72                        <h1><?php echo esc_html__( 'Disable Threshold&EXIF', 'disable-thumbnails-and-threshold' ); ?></h1>
    6373                        <p><strong><?php echo esc_html__( 'Remember you need to regenerate thumbnails for delete old thumbnails image already generated.', 'disable-thumbnails-and-threshold' ); ?></strong></p>
    64                         <p><?php echo esc_html__( 'Plugin recommended for regenerate thumbnails', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://uskgm.it/reg-thumb' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Regenerate Thumbnails', 'disable-thumbnails-and-threshold' ); ?></a></p>
    65                         <p><?php echo esc_html__( 'WP-CLI media regeneration', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://uskgm.it/WP-CLI-thumb-rgnrt' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Documentation', 'disable-thumbnails-and-threshold' ); ?></a></p>
     74                        <p><?php echo esc_html__( 'Plugin recommended for regenerate thumbnails', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://wordpress.org/plugins/regenerate-thumbnails/' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Regenerate Thumbnails', 'disable-thumbnails-and-threshold' ); ?></a></p>
     75                        <p><?php echo esc_html__( 'WP-CLI media regeneration', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://developer.wordpress.org/cli/commands/media/regenerate/' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Documentation', 'disable-thumbnails-and-threshold' ); ?></a></p>
    6676                        <?php settings_errors(); ?>
    6777
    … …  
    7484                        </form>
    7585                </div>
    76         <?php }
     86                <?php
     87        }
    7788
    7889        /**
    … …  
    8697                        'kgmdisablethreshold_option_group',
    8798                        DTAT_THRESHOLD_OPTION,
    88                         [ $this, 'sanitize' ]
     99                        array( $this, 'sanitize' )
    89100                );
    90101
    91102                add_settings_section(
    92103                        'kgmdisablethreshold_setting_section',
    93                         esc_html__( 'Settings', 'disable-thumbnails-and-threshold' ), 
    94                         [ $this, 'section_info' ],
    95                         'kgmdisablethreshold-admin' 
     104                        esc_html__( 'Settings', 'disable-thumbnails-and-threshold' ),
     105                        array( $this, 'section_info' ),
     106                        'kgmdisablethreshold-admin'
    96107                );
    97108
    … …  
    99110                        'new_threshold',
    100111                        esc_html__( 'New Size Threshold', 'disable-thumbnails-and-threshold' ) . ' <br> <small>' . esc_html__( 'Default WordPress: 2560px', 'disable-thumbnails-and-threshold' ) . '</small>',
    101                         [ $this, 'new_threshold_callback' ],
     112                        array( $this, 'new_threshold_callback' ),
    102113                        'kgmdisablethreshold-admin',
    103                         'kgmdisablethreshold_setting_section'
     114                        'kgmdisablethreshold_setting_section',
     115                        array( 'label_for' => 'new_threshold' )
    104116                );
    105117                add_settings_field(
    106118                        'disable_threshold',
    107119                        esc_html__( 'Disable Threshold', 'disable-thumbnails-and-threshold' ),
    108                         [ $this, 'disable_threshold_callback' ],
     120                        array( $this, 'disable_threshold_callback' ),
    109121                        'kgmdisablethreshold-admin',
    110122                        'kgmdisablethreshold_setting_section'
    … …  
    113125                        'disable_image_rotation_exif',
    114126                        esc_html__( 'Disable Image Rotation by EXIF', 'disable-thumbnails-and-threshold' ),
    115                         [ $this, 'disable_image_rotation_exif_callback' ],
     127                        array( $this, 'disable_image_rotation_exif_callback' ),
    116128                        'kgmdisablethreshold-admin',
    117129                        'kgmdisablethreshold_setting_section'
    … …  
    122134         * Sanitize and validate form input before saving.
    123135         *
    124          * @since  0.1
    125          * @param  array $input Raw form input values.
     136         * Runs on every update_option() of this option, not only on form submit, so it
     137         * must not depend on the current user: options.php already enforces the nonce
     138         * and the manage_options capability before saving.
     139         *
     140         * @since  0.1
     141         * @param  mixed $input Raw value; null when no field is present in the request.
    126142         * @return array Sanitized values.
    127143         */
    128         public function sanitize( array $input ): array {
    129                 // Check user capabilities for security
    130                 if ( ! current_user_can( 'manage_options' ) ) {
    131                         return $GLOBALS['dtat_disablethreshold_options'] ?? get_option( DTAT_THRESHOLD_OPTION, [] );
    132                 }
    133                
    134                 // Nonce is already verified by WordPress options.php handler via settings_fields().
    135                 $sanitary_values = [];
     144        public function sanitize( $input ): array {
     145                if ( ! is_array( $input ) ) {
     146                        $input = array();
     147                }
     148
     149                $sanitary_values = array();
    136150
    137151                if ( isset( $input['new_threshold'] ) ) {
    … …  
    183197                        esc_html__( 'px', 'disable-thumbnails-and-threshold' )
    184198                );
    185                
    186                 // Check if plugin disables threshold
     199
     200                // Check if plugin disables threshold.
    187201                $plugin_disables_threshold = false;
    188202                if ( is_array( $this->dtat_disablethreshold_options ) && isset( $this->dtat_disablethreshold_options['disable_threshold'] ) ) {
    189                         $plugin_disables_threshold = ( $this->dtat_disablethreshold_options['disable_threshold'] === 'disable_threshold' );
    190                 }
    191                
    192                 // Show yellow warning message if plugin disables threshold
     203                        $plugin_disables_threshold = ( 'disable_threshold' === $this->dtat_disablethreshold_options['disable_threshold'] );
     204                }
     205
     206                // Show yellow warning message if plugin disables threshold.
    193207                if ( $plugin_disables_threshold ) {
    194                         printf( '<br><small class="description dtat-notice-caution">%s %s</small>',
     208                        printf(
     209                                '<br><small class="description dtat-notice-caution">%s %s</small>',
    195210                                esc_html( '⚠️' ),
    196211                                esc_html__( 'Disabled by plugin', 'disable-thumbnails-and-threshold' )
    … …  
    207222
    208223                        if ( $plugin_threshold && $plugin_threshold !== $wp_default_threshold ) {
    209                                 printf( '<br><small class="description dtat-notice-warning">%s %s</small>',
     224                                printf(
     225                                        '<br><small class="description dtat-notice-warning">%s %s</small>',
    210226                                        esc_html( '⚠️' ),
    211                                         // translators: %1$d: Plugin threshold value in pixels, %2$d: WordPress default threshold value in pixels
     227                                        /* translators: %1$d: Plugin threshold value in pixels, %2$d: WordPress default threshold value in pixels */
    212228                                        esc_html( sprintf( __( 'Plugin threshold (%1$dpx) differs from WordPress default (%2$dpx)', 'disable-thumbnails-and-threshold' ), $plugin_threshold, $wp_default_threshold ) )
    213229                                );
    214230                        } else {
    215                                 // translators: %d: WordPress default big image threshold value in pixels
     231                                /* translators: %d: WordPress default big image threshold value in pixels */
    216232                                printf( '<br><small class="description dtat-notice-info">%s</small>', esc_html( sprintf( __( 'WordPress default big image threshold: %dpx', 'disable-thumbnails-and-threshold' ), $wp_default_threshold ) ) );
    217233                        }
    … …  
    229245                        '<label class="switch"><input type="checkbox" name="%s[disable_threshold]" id="disable_threshold" value="disable_threshold" %s><span class="screen-reader-text">%s</span><span class="slider" aria-hidden="true"></span></label>',
    230246                        esc_attr( DTAT_THRESHOLD_OPTION ),
    231                         ( is_array( $this->dtat_disablethreshold_options ) && isset( $this->dtat_disablethreshold_options['disable_threshold'] ) && $this->dtat_disablethreshold_options['disable_threshold'] === 'disable_threshold' ) ? 'checked' : '',
     247                        ( is_array( $this->dtat_disablethreshold_options ) && isset( $this->dtat_disablethreshold_options['disable_threshold'] ) && 'disable_threshold' === $this->dtat_disablethreshold_options['disable_threshold'] ) ? 'checked' : '',
    232248                        esc_html__( 'Disable Threshold', 'disable-thumbnails-and-threshold' )
    233249                );
    234                
     250
    235251                // Show informational status based on plugin's stored setting.
    236252                // We avoid calling apply_filters('big_image_size_threshold') here because it expects
    … …  
    238254                $plugin_intends_to_disable = false;
    239255                if ( is_array( $this->dtat_disablethreshold_options ) && isset( $this->dtat_disablethreshold_options['disable_threshold'] ) ) {
    240                         $plugin_intends_to_disable = ( $this->dtat_disablethreshold_options['disable_threshold'] === 'disable_threshold' );
     256                        $plugin_intends_to_disable = ( 'disable_threshold' === $this->dtat_disablethreshold_options['disable_threshold'] );
    241257                }
    242258
    243259                if ( $plugin_intends_to_disable ) {
    244                         printf( '<br><small class="description dtat-notice-info">%s</small>',
     260                        printf(
     261                                '<br><small class="description dtat-notice-info">%s</small>',
    245262                                esc_html__( 'Threshold is disabled by this plugin.', 'disable-thumbnails-and-threshold' )
    246263                        );
    … …  
    258275                        '<label class="switch"><input type="checkbox" name="%s[disable_image_rotation_exif]" id="disable_image_rotation_exif" value="disable_image_rotation_exif" %s><span class="screen-reader-text">%s</span><span class="slider" aria-hidden="true"></span></label>',
    259276                        esc_attr( DTAT_THRESHOLD_OPTION ),
    260                         ( is_array( $this->dtat_disablethreshold_options ) && isset( $this->dtat_disablethreshold_options['disable_image_rotation_exif'] ) && $this->dtat_disablethreshold_options['disable_image_rotation_exif'] === 'disable_image_rotation_exif' ) ? 'checked' : '',
     277                        ( is_array( $this->dtat_disablethreshold_options ) && isset( $this->dtat_disablethreshold_options['disable_image_rotation_exif'] ) && 'disable_image_rotation_exif' === $this->dtat_disablethreshold_options['disable_image_rotation_exif'] ) ? 'checked' : '',
    261278                        esc_html__( 'Disable Image Rotation by EXIF', 'disable-thumbnails-and-threshold' )
    262279                );
    263                
     280
    264281                // Show informational status based on plugin's stored setting.
    265282                // We avoid calling apply_filters('wp_image_maybe_exif_rotate') here because it expects
    … …  
    267284                $plugin_exif_disabled = false;
    268285                if ( is_array( $this->dtat_disablethreshold_options ) && isset( $this->dtat_disablethreshold_options['disable_image_rotation_exif'] ) ) {
    269                         $plugin_exif_disabled = ( $this->dtat_disablethreshold_options['disable_image_rotation_exif'] === 'disable_image_rotation_exif' );
     286                        $plugin_exif_disabled = ( 'disable_image_rotation_exif' === $this->dtat_disablethreshold_options['disable_image_rotation_exif'] );
    270287                }
    271288
    272289                if ( $plugin_exif_disabled ) {
    273                         printf( '<br><small class="description dtat-notice-info">%s</small>',
     290                        printf(
     291                                '<br><small class="description dtat-notice-info">%s</small>',
    274292                                esc_html__( 'EXIF rotation is disabled by this plugin.', 'disable-thumbnails-and-threshold' )
    275293                        );
    276294                }
    277295        }
    278 
    279296}
    280297if ( is_admin() ) {
    281         $DTAT_Disable_Threshold = new DTAT_Disable_Threshold();
     298        $dtat_disable_threshold = new DTAT_Disable_Threshold();
    282299}
  • disable-thumbnails-and-threshold/tags/0.8.0/includes/option-thumbnails.php

    r3504636 r3789337  
    1212
    1313if ( ! defined( 'ABSPATH' ) ) {
    14         exit; // Exit if accessed directly
     14        exit; // Exit if accessed directly.
    1515}
    1616
     17/**
     18 * Image Sizes settings page.
     19 *
     20 * @since 0.1
     21 */
    1722class DTAT_Disable_Thumbnails {
    18         private array|false $dtat_disablethumbnails_options;
     23        /**
     24         * Stored option value. Untyped on purpose: whatever the database holds must not raise a TypeError.
     25         *
     26         * @var array|false
     27         */
     28        private $dtat_disablethumbnails_options = false;
    1929
    2030        /**
    … …  
    2434         */
    2535        public function __construct() {
    26                 add_action( 'admin_menu', [ $this, 'add_plugin_page' ] );
    27                 add_action( 'admin_init', [ $this, 'page_init' ] );
     36                add_action( 'admin_menu', array( $this, 'add_plugin_page' ) );
     37                add_action( 'admin_init', array( $this, 'page_init' ) );
    2838        }
    2939
    … …  
    3646        public function add_plugin_page() {
    3747                add_management_page(
    38                         esc_html__( 'Image Sizes', 'disable-thumbnails-and-threshold' ), 
    39                         esc_html__( 'Image Sizes', 'disable-thumbnails-and-threshold' ), 
    40                         'manage_options', 
    41                         'kgmdisablethumbnails', 
    42                         [ $this, 'create_admin_page' ]
     48                        esc_html__( 'Image Sizes', 'disable-thumbnails-and-threshold' ),
     49                        esc_html__( 'Image Sizes', 'disable-thumbnails-and-threshold' ),
     50                        'manage_options',
     51                        'kgmdisablethumbnails',
     52                        array( $this, 'create_admin_page' )
    4353                );
    4454        }
    … …  
    5161         */
    5262        public function create_admin_page() {
    53                 // Check user capabilities for security
     63                // Check user capabilities for security.
    5464                if ( ! current_user_can( 'manage_options' ) ) {
    5565                        wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'disable-thumbnails-and-threshold' ) );
    5666                }
    57                
    58                 // Use cached options to avoid database calls
     67
     68                // Use cached options to avoid database calls.
    5969                $this->dtat_disablethumbnails_options = $GLOBALS['dtat_disablethumbnails_options'] ?? get_option( DTAT_THUMBNAILS_OPTION ); ?>
    6070
    6171                <div class="wrap">
    62                         <h2><?php echo esc_html__( 'Image Thumbnails', 'disable-thumbnails-and-threshold' ); ?></h2>
     72                        <h1><?php echo esc_html__( 'Image Thumbnails', 'disable-thumbnails-and-threshold' ); ?></h1>
    6373                        <p><strong><?php echo esc_html__( 'Remember you need to regenerate thumbnails for delete old thumbnails image already generated.', 'disable-thumbnails-and-threshold' ); ?></strong></p>
    64                         <p><?php echo esc_html__( 'Plugin recommended for regenerate thumbnails', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://uskgm.it/reg-thumb' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Regenerate Thumbnails', 'disable-thumbnails-and-threshold' ); ?></a></p>
    65                         <p><?php echo esc_html__( 'WP-CLI media regeneration', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://uskgm.it/WP-CLI-thumb-rgnrt' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Documentation', 'disable-thumbnails-and-threshold' ); ?></a></p>
     74                        <p><?php echo esc_html__( 'Plugin recommended for regenerate thumbnails', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://wordpress.org/plugins/regenerate-thumbnails/' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Regenerate Thumbnails', 'disable-thumbnails-and-threshold' ); ?></a></p>
     75                        <p><?php echo esc_html__( 'WP-CLI media regeneration', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://developer.wordpress.org/cli/commands/media/regenerate/' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Documentation', 'disable-thumbnails-and-threshold' ); ?></a></p>
    6676                        <p><?php echo esc_html__( 'Flagged image sizes will be disabled.', 'disable-thumbnails-and-threshold' ); ?></p>
    6777                        <?php settings_errors(); ?>
    … …  
    7585                        </form>
    7686                </div>
    77         <?php }
     87                <?php
     88        }
    7889
    7990        /**
    … …  
    8697                register_setting(
    8798                        'kgmdisablethumbnails_option_group',
    88                         DTAT_THUMBNAILS_OPTION, 
    89                         [ $this, 'sanitize' ]
     99                        DTAT_THUMBNAILS_OPTION,
     100                        array( $this, 'sanitize' )
    90101                );
    91102
    92103                add_settings_section(
    93                         'kgmdisablethumbnails_setting_section', 
    94                         esc_html__( 'Settings', 'disable-thumbnails-and-threshold' ), 
    95                         [ $this, 'section_info' ],
    96                         'kgmdisablethumbnails-admin' 
     104                        'kgmdisablethumbnails_setting_section',
     105                        esc_html__( 'Settings', 'disable-thumbnails-and-threshold' ),
     106                        array( $this, 'section_info' ),
     107                        'kgmdisablethumbnails-admin'
    97108                );
    98109
    99110                add_settings_field(
    100111                        'thumbnail',
    101                         esc_html__( 'Thumbnail', 'disable-thumbnails-and-threshold' ), 
    102                         [ $this, 'thumbnail_callback' ],
    103                         'kgmdisablethumbnails-admin', 
    104                         'kgmdisablethumbnails_setting_section' 
     112                        esc_html__( 'Thumbnail', 'disable-thumbnails-and-threshold' ),
     113                        array( $this, 'thumbnail_callback' ),
     114                        'kgmdisablethumbnails-admin',
     115                        'kgmdisablethumbnails_setting_section'
    105116                );
    106117                add_settings_field(
    107118                        'medium',
    108                         esc_html__( 'Medium', 'disable-thumbnails-and-threshold' ), 
    109                         [ $this, 'medium_callback' ],
    110                         'kgmdisablethumbnails-admin', 
    111                         'kgmdisablethumbnails_setting_section' 
     119                        esc_html__( 'Medium', 'disable-thumbnails-and-threshold' ),
     120                        array( $this, 'medium_callback' ),
     121                        'kgmdisablethumbnails-admin',
     122                        'kgmdisablethumbnails_setting_section'
    112123                );
    113124                add_settings_field(
    114125                        'medium_large',
    115126                        esc_html__( 'Medium Large', 'disable-thumbnails-and-threshold' ),
    116                         [ $this, 'medium_large_callback' ],
    117                         'kgmdisablethumbnails-admin',
    118                         'kgmdisablethumbnails_setting_section' 
    119                 );
    120                 add_settings_field(
    121                         'large', 
    122                         esc_html__( 'Large', 'disable-thumbnails-and-threshold' ), 
    123                         [ $this, 'large_callback' ],
    124                         'kgmdisablethumbnails-admin', 
    125                         'kgmdisablethumbnails_setting_section' 
     127                        array( $this, 'medium_large_callback' ),
     128                        'kgmdisablethumbnails-admin',
     129                        'kgmdisablethumbnails_setting_section'
     130                );
     131                add_settings_field(
     132                        'large',
     133                        esc_html__( 'Large', 'disable-thumbnails-and-threshold' ),
     134                        array( $this, 'large_callback' ),
     135                        'kgmdisablethumbnails-admin',
     136                        'kgmdisablethumbnails_setting_section'
    126137                );
    127138
    128139                $image_sizes = wp_get_additional_image_sizes();
    129140                foreach ( $image_sizes as $key => $image_size ) {
    130                         if ( 1 === $image_size['crop'] ) {
     141                        if ( ! empty( $image_size['crop'] ) ) {
    131142                                $crop = esc_html__( 'cropped', 'disable-thumbnails-and-threshold' );
    132143                        } else {
    … …  
    135146                        add_settings_field(
    136147                                $key,
    137                                 esc_html( $key ) . '<br><small>(' . esc_attr( $image_size['width'] ) . 'x' . esc_attr( $image_size['height'] ) . ')</small><br><small>' . esc_html( $crop ) . '</small>',
    138                                 [ $this, 'ext_callback' ],
     148                                esc_html( $key ) . '<br><small>(' . absint( $image_size['width'] ) . 'x' . absint( $image_size['height'] ) . ')</small><br><small>' . esc_html( $crop ) . '</small>',
     149                                array( $this, 'ext_callback' ),
    139150                                'kgmdisablethumbnails-admin',
    140151                                'kgmdisablethumbnails_setting_section',
    141                                 [ 'name' => $key ]
     152                                array( 'name' => $key )
    142153                        );
    143154                }
    … …  
    147158         * Sanitize and validate form input before saving.
    148159         *
    149          * @since  0.1
    150          * @param  array $input Raw form input values.
     160         * Runs on every update_option() of this option, not only on form submit, so it
     161         * must not depend on the current user: options.php already enforces the nonce
     162         * and the manage_options capability before saving.
     163         *
     164         * Each checkbox posts its own size name as value, so only "size => size" pairs
     165         * for sizes registered on this site are kept.
     166         *
     167         * @since  0.1
     168         * @param  mixed $input Raw value; null when every checkbox is unchecked.
    151169         * @return array Sanitized values.
    152170         */
    153         public function sanitize( array $input ): array {
    154                 // Check user capabilities for security
    155                 if ( ! current_user_can( 'manage_options' ) ) {
    156                         return $GLOBALS['dtat_disablethumbnails_options'] ?? get_option( DTAT_THUMBNAILS_OPTION, [] );
    157                 }
    158                
    159                 // Nonce is already verified by WordPress options.php handler via settings_fields().
    160                 $sanitary_values = [];
    161 
    162                 if ( isset( $input['thumbnail'] ) ) {
    163                         $sanitary_values['thumbnail'] = sanitize_text_field( $input['thumbnail'] );
    164                 }
    165                 if ( isset( $input['medium'] ) ) {
    166                         $sanitary_values['medium'] = sanitize_text_field( $input['medium'] );
    167                 }
    168                 if ( isset( $input['medium_large'] ) ) {
    169                         $sanitary_values['medium_large'] = sanitize_text_field( $input['medium_large'] );
    170                 }
    171                 if ( isset( $input['large'] ) ) {
    172                         $sanitary_values['large'] = sanitize_text_field( $input['large'] );
    173                 }
    174 
    175                 $image_sizes = wp_get_additional_image_sizes();
    176                 foreach ( $image_sizes as $key => $image_size ) {
    177                         if ( isset( $input[ $key ] ) ) {
    178                                 $sanitary_values[ $key ] = sanitize_text_field( $input[ $key ] );
     171        public function sanitize( $input ): array {
     172                if ( ! is_array( $input ) ) {
     173                        return array();
     174                }
     175
     176                $sanitary_values = array();
     177                $known_sizes     = array_merge(
     178                        array( 'thumbnail', 'medium', 'medium_large', 'large' ),
     179                        array_keys( wp_get_additional_image_sizes() )
     180                );
     181
     182                foreach ( $known_sizes as $size ) {
     183                        if ( isset( $input[ $size ] ) && sanitize_text_field( $input[ $size ] ) === (string) $size ) {
     184                                $sanitary_values[ $size ] = (string) $size;
    179185                        }
    180186                }
    … …  
    190196         */
    191197        public function section_info() {
    192 
    193198        }
    194199
    … …  
    203208                        '<label class="switch"><input type="checkbox" name="%s[thumbnail]" id="thumbnail" value="thumbnail" %s><span class="screen-reader-text">%s</span><span class="slider" aria-hidden="true"></span></label>',
    204209                        esc_attr( DTAT_THUMBNAILS_OPTION ),
    205                         ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['thumbnail'] ) && $this->dtat_disablethumbnails_options['thumbnail'] === 'thumbnail' ) ? 'checked' : '',
     210                        ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['thumbnail'] ) && 'thumbnail' === $this->dtat_disablethumbnails_options['thumbnail'] ) ? 'checked' : '',
    206211                        esc_html__( 'Disable Thumbnail size', 'disable-thumbnails-and-threshold' )
    207212                );
    … …  
    218223                        '<label class="switch"><input type="checkbox" name="%s[medium]" id="medium" value="medium" %s><span class="screen-reader-text">%s</span><span class="slider" aria-hidden="true"></span></label>',
    219224                        esc_attr( DTAT_THUMBNAILS_OPTION ),
    220                         ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['medium'] ) && $this->dtat_disablethumbnails_options['medium'] === 'medium' ) ? 'checked' : '',
     225                        ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['medium'] ) && 'medium' === $this->dtat_disablethumbnails_options['medium'] ) ? 'checked' : '',
    221226                        esc_html__( 'Disable Medium size', 'disable-thumbnails-and-threshold' )
    222227                );
    … …  
    233238                        '<label class="switch"><input type="checkbox" name="%s[medium_large]" id="medium_large" value="medium_large" %s><span class="screen-reader-text">%s</span><span class="slider" aria-hidden="true"></span></label>',
    234239                        esc_attr( DTAT_THUMBNAILS_OPTION ),
    235                         ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['medium_large'] ) && $this->dtat_disablethumbnails_options['medium_large'] === 'medium_large' ) ? 'checked' : '',
     240                        ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['medium_large'] ) && 'medium_large' === $this->dtat_disablethumbnails_options['medium_large'] ) ? 'checked' : '',
    236241                        esc_html__( 'Disable Medium Large size', 'disable-thumbnails-and-threshold' )
    237242                );
    … …  
    248253                        '<label class="switch"><input type="checkbox" name="%s[large]" id="large" value="large" %s><span class="screen-reader-text">%s</span><span class="slider" aria-hidden="true"></span></label>',
    249254                        esc_attr( DTAT_THUMBNAILS_OPTION ),
    250                         ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['large'] ) && $this->dtat_disablethumbnails_options['large'] === 'large' ) ? 'checked' : '',
     255                        ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['large'] ) && 'large' === $this->dtat_disablethumbnails_options['large'] ) ? 'checked' : '',
    251256                        esc_html__( 'Disable Large size', 'disable-thumbnails-and-threshold' )
    252257                );
    … …  
    268273                        esc_attr( $name ),
    269274                        esc_attr( $name ),
    270                         ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options[$name] ) && $this->dtat_disablethumbnails_options[$name] === $name ) ? 'checked' : '',
     275                        ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options[ $name ] ) && $name === $this->dtat_disablethumbnails_options[ $name ] ) ? 'checked' : '',
    271276                        /* translators: %s: Image size name */
    272277                        esc_html( sprintf( __( 'Disable %s size', 'disable-thumbnails-and-threshold' ), $name ) )
    273278                );
    274279        }
    275 
    276280}
    277281if ( is_admin() ) {
    278         $DTAT_Disable_Thumbnails = new DTAT_Disable_Thumbnails();
     282        $dtat_disable_thumbnails = new DTAT_Disable_Thumbnails();
    279283}
  • disable-thumbnails-and-threshold/tags/0.8.0/readme.txt

    r3504636 r3789337  
    33Donate link: https://kgmservizi.com
    44Tags: thumbnails, disable thumbnails, disable threshold, disable images, image options
    5 Requires at least: 5.4
    6 Tested up to: 6.8
    7 Requires PHP: 7.4
    8 Stable tag: 0.7.0
     5Requires at least: 5.6
     6Tested up to: 7.1
     7Requires PHP: 8.0
     8Stable tag: 0.8.0
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    7676== Changelog ==
    7777
     78= 0.8.0 =
     79* Requirements: minimum PHP raised to 8.0 and minimum WordPress to 5.6 (the first release with PHP 8.0 support).
     80* Fix: saving the Image Sizes page with every size unchecked caused a fatal error.
     81* Fix: settings saved through WP-CLI were silently discarded.
     82* Fix: the "cropped" label now appears for custom image sizes registered with cropping.
     83* Fix: no fatal error when another plugin hooks `jpeg_quality` or `big_image_size_threshold` with required extra arguments.
     84* Coding standards cleanup.
     85
    7886= 0.7.0 =
    7987* Improved accessibility: toggle switches are now fully keyboard-navigable with visible focus indicators and screen-reader labels.
    … …  
    98106== Upgrade Notice ==
    99107
     108= 0.8.0 =
     109Requires PHP 8.0+ and WordPress 5.6+. Fixes a fatal error when unchecking every image size.
     110
    100111= 0.7.0 =
    101112Accessibility, compatibility and performance improvements. No breaking changes — all settings and URLs are preserved. Recommended update for all users.
  • disable-thumbnails-and-threshold/trunk/disable-thumbnails-and-thresold.php

    r3504636 r3789337  
    11<?php
    2 /*
    3 Plugin Name: Disable Thumbnails, Threshold and Image Options
    4 Version: 0.7.0
    5 Description: Disable Thumbnails, Threshold and Image Options
    6 Author: KGM Servizi
    7 Author URI: https://kgmservizi.com
    8 License: GPLv2 or later
    9 License URI: https://www.gnu.org/licenses/gpl-2.0.html
    10 Text Domain: disable-thumbnails-and-threshold
    11 Requires at least: 5.4
    12 Requires PHP: 7.4
    13 */
     2/**
     3 * Plugin Name: Disable Thumbnails, Threshold and Image Options
     4 * Version: 0.8.0
     5 * Description: Disable Thumbnails, Threshold and Image Options
     6 * Author: KGM Servizi
     7 * Author URI: https://kgmservizi.com
     8 * License: GPLv2 or later
     9 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
     10 * Text Domain: disable-thumbnails-and-threshold
     11 * Requires at least: 5.6
     12 * Requires PHP: 8.0
     13 *
     14 * @package Disable_Thumbnails_Threshold
     15 */
    1416
    1517if ( ! defined( 'ABSPATH' ) ) {
    16         exit; // Exit if accessed directly
    17 }
    18 
    19 // Define plugin constants for better maintainability
     18        exit; // Exit if accessed directly.
     19}
     20
     21// Define plugin constants for better maintainability.
    2022define( 'DTAT_QUALITY_OPTION', 'dtat_imgquality_option_name' );
    2123define( 'DTAT_THRESHOLD_OPTION', 'dtat_disablethreshold_option_name' );
    2224define( 'DTAT_THUMBNAILS_OPTION', 'dtat_disablethumbnails_option_name' );
    2325define( 'DTAT_MIGRATION_OPTION', 'dtat_migration_done' );
    24 define( 'DTAT_VERSION', '0.7.0' );
    25 
    26 /**
    27  * PHPCS Suppressions
    28  *
    29  * This file contains phpcs:ignore comments for the following cases:
    30  * - Line 151, 131 (option-quality.php): WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
    31  *   Reason: Using WordPress core hook (jpeg_quality) which doesn't require plugin prefix
    32  * - Line 174, 172 (option-threshold-exif.php), 206 (option-threshold-exif.php): WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
    33  *   Reason: Using WordPress core hook (big_image_size_threshold) which doesn't require plugin prefix
    34  * - Line 241 (option-threshold-exif.php): WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
    35  *   Reason: Using WordPress core hook (wp_image_maybe_exif_rotate) which doesn't require plugin prefix
    36  */
    37 
    38 // Check WordPress version compatibility - requires WordPress 5.4+ for PHP 7.4+ support
    39 // Use admin_init hook to ensure WordPress is fully loaded
     26define( 'DTAT_VERSION', '0.8.0' );
     27define( 'DTAT_MIN_WP_VERSION', '5.6' );
     28define( 'DTAT_MIN_PHP_VERSION', '8.0' );
     29
     30// Check WordPress version compatibility - WordPress 5.6 is the first release that supports PHP 8.0.
     31// Use admin_init hook to ensure WordPress is fully loaded.
    4032add_action( 'admin_init', 'dtat_check_wordpress_version' );
    4133
    … …  
    5042
    5143/**
    52  * 
     44 *
    5345 * Retrieve options for quality and threshold
    5446 * Cache options globally to avoid multiple database calls
    55  *
    5647 */
    5748$GLOBALS['dtat_imgquality_options']        = get_option( DTAT_QUALITY_OPTION );
    … …  
    7768        $processed = true;
    7869
     70        // admin_init also fires for logged-out admin-ajax.php/admin-post.php requests.
     71        if ( ! current_user_can( 'manage_options' ) ) {
     72                return;
     73        }
     74
    7975        // Skip migration if already completed for this plugin version.
    8076        if ( get_option( DTAT_MIGRATION_OPTION ) === DTAT_VERSION ) {
    … …  
    8278        }
    8379
    84         $option_map = [
    85                 DTAT_QUALITY_OPTION     => 'kgmimgquality_option_name',
    86                 DTAT_THRESHOLD_OPTION   => 'kgmdisablethreshold_option_name',
    87                 DTAT_THUMBNAILS_OPTION  => 'kgmdisablethumbnails_option_name',
    88         ];
     80        $option_map = array(
     81                DTAT_QUALITY_OPTION    => 'kgmimgquality_option_name',
     82                DTAT_THRESHOLD_OPTION  => 'kgmdisablethreshold_option_name',
     83                DTAT_THUMBNAILS_OPTION => 'kgmdisablethumbnails_option_name',
     84        );
    8985
    9086        foreach ( $option_map as $new_option => $legacy_option ) {
    … …  
    105101        }
    106102
     103        /*
     104         * The globals were cached at load time, before the migration. Without a refresh,
     105         * dtat_initialize_options() (same hook, later) sees them empty and overwrites the
     106         * migrated values with defaults, after the legacy rows are already deleted.
     107         */
     108        $GLOBALS['dtat_imgquality_options']        = get_option( DTAT_QUALITY_OPTION );
     109        $GLOBALS['dtat_disablethreshold_options']  = get_option( DTAT_THRESHOLD_OPTION );
     110        $GLOBALS['dtat_disablethumbnails_options'] = get_option( DTAT_THUMBNAILS_OPTION );
     111
    107112        update_option( DTAT_MIGRATION_OPTION, DTAT_VERSION );
    108113}
    109114
    110115
    111 // Initialize with current WordPress values if options don't exist
    112 // This will be handled in the admin_init hook to ensure WordPress is fully loaded
     116// Initialize with current WordPress values if options don't exist.
     117// This will be handled in the admin_init hook to ensure WordPress is fully loaded.
    113118add_action( 'admin_init', 'dtat_initialize_options' );
    114119
    115 // Hook to apply filters after themes are loaded to ensure priority
     120// Hook to apply filters after themes are loaded to ensure priority.
    116121add_action( 'after_setup_theme', 'dtat_apply_filters', 20 );
    117122
    … …  
    126131 */
    127132function dtat_check_wordpress_version(): void {
    128         // Only run in admin
     133        // Only run in admin.
    129134        if ( ! is_admin() ) {
    130135                return;
    131136        }
    132        
    133         // Check if WordPress version is compatible
    134         if ( version_compare( get_bloginfo( 'version' ), '5.4', '<' ) ) {
     137
     138        // Check if WordPress version is compatible.
     139        if ( version_compare( get_bloginfo( 'version' ), DTAT_MIN_WP_VERSION, '<' ) ) {
    135140                add_action( 'admin_notices', 'dtat_wordpress_version_notice' );
    136141        }
    … …  
    146151function dtat_wordpress_version_notice(): void {
    147152        printf(
    148                 '<div class="notice notice-error"><p><strong>%s</strong> %s</p></div>',
    149                 esc_html__( 'Disable Thumbnails, Threshold and Image Options', 'disable-thumbnails-and-threshold' ),
    150                 esc_html__( 'requires WordPress 5.4 or higher (PHP 7.4+). Please update WordPress.', 'disable-thumbnails-and-threshold' )
     153                '<div class="notice notice-error"><p>%s</p></div>',
     154                esc_html(
     155                        sprintf(
     156                                /* translators: 1: Plugin name, 2: Minimum WordPress version, 3: Minimum PHP version. */
     157                                __( '%1$s requires WordPress %2$s or higher and PHP %3$s or higher. Please update.', 'disable-thumbnails-and-threshold' ),
     158                                'Disable Thumbnails, Threshold and Image Options',
     159                                DTAT_MIN_WP_VERSION,
     160                                DTAT_MIN_PHP_VERSION
     161                        )
     162                )
    151163        );
    152164}
    … …  
    162174 */
    163175function dtat_initialize_options(): void {
    164         // Only run in admin and if user has proper capabilities
     176        // Only run in admin and if user has proper capabilities.
    165177        if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) {
    166178                return;
    167179        }
    168        
    169         // Initialize JPEG quality option if it doesn't exist or is invalid
    170         if ( ! $GLOBALS['dtat_imgquality_options'] ||
    171                  ! is_array( $GLOBALS['dtat_imgquality_options'] ) ||
    172                  ! isset( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) ||
    173                  ! is_numeric( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) ||
    174                  intval( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) < 1 ||
    175                  intval( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) > 100 ) {
    176                
    177                 // Get current WordPress JPEG quality (respects existing filters/plugins)
    178                 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WordPress core hook
    179                 $current_quality = apply_filters( 'jpeg_quality', 82 );
    180                
    181                 // Validate the quality value from filters
     180
     181        // Initialize JPEG quality option if it doesn't exist or is invalid.
     182        if ( ! $GLOBALS['dtat_imgquality_options'] ||
     183                ! is_array( $GLOBALS['dtat_imgquality_options'] ) ||
     184                ! isset( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) ||
     185                ! is_numeric( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) ||
     186                intval( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) < 1 ||
     187                intval( $GLOBALS['dtat_imgquality_options']['jpeg_quality'] ) > 100 ) {
     188                /*
     189                 * Get current WordPress JPEG quality (respects existing filters/plugins).
     190                 * Pass every argument core passes: on PHP 8 a third-party callback with a
     191                 * required $context would otherwise throw ArgumentCountError here.
     192                 */
     193                try {
     194                        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WordPress core hook
     195                        $current_quality = apply_filters( 'jpeg_quality', 82, 'image_resize' );
     196                } catch ( Throwable $e ) {
     197                        $current_quality = 82;
     198                }
     199
     200                // Validate the quality value from filters.
    182201                if ( ! is_numeric( $current_quality ) || $current_quality < 1 || $current_quality > 100 ) {
    183                         $current_quality = 82; // Fallback to WordPress default
    184                 }
    185                
    186                 // Preserve existing options and only update jpeg_quality
     202                        $current_quality = 82; // Fallback to WordPress default.
     203                }
     204
     205                // Preserve existing options and only update jpeg_quality.
    187206                if ( ! is_array( $GLOBALS['dtat_imgquality_options'] ) ) {
    188                         $GLOBALS['dtat_imgquality_options'] = [];
     207                        $GLOBALS['dtat_imgquality_options'] = array();
    189208                }
    190209                $GLOBALS['dtat_imgquality_options']['jpeg_quality'] = intval( $current_quality );
    191210                update_option( DTAT_QUALITY_OPTION, $GLOBALS['dtat_imgquality_options'] );
    192211        }
    193        
    194         // Initialize threshold option if it doesn't exist or is invalid
    195         if ( ! $GLOBALS['dtat_disablethreshold_options'] ||
    196                  ! is_array( $GLOBALS['dtat_disablethreshold_options'] ) ||
    197                  ! isset( $GLOBALS['dtat_disablethreshold_options']['new_threshold'] ) ||
    198                  ! is_numeric( $GLOBALS['dtat_disablethreshold_options']['new_threshold'] ) ||
    199                  intval( $GLOBALS['dtat_disablethreshold_options']['new_threshold'] ) <= 0 ) {
    200                
    201                 // Get current WordPress big image threshold (respects existing filters/plugins)
    202                 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WordPress core hook
    203                 $current_threshold = apply_filters( 'big_image_size_threshold', 2560 );
    204                
    205                 // Validate the threshold value from filters
     212
     213        // Initialize threshold option if it doesn't exist or is invalid.
     214        if ( ! $GLOBALS['dtat_disablethreshold_options'] ||
     215                ! is_array( $GLOBALS['dtat_disablethreshold_options'] ) ||
     216                ! isset( $GLOBALS['dtat_disablethreshold_options']['new_threshold'] ) ||
     217                ! is_numeric( $GLOBALS['dtat_disablethreshold_options']['new_threshold'] ) ||
     218                intval( $GLOBALS['dtat_disablethreshold_options']['new_threshold'] ) <= 0 ) {
     219                /*
     220                 * Get current WordPress big image threshold (respects existing filters/plugins).
     221                 * Core passes $imagesize, $file and $attachment_id; there is no real image here,
     222                 * so neutral values are passed and any callback failure falls back to the default.
     223                 */
     224                try {
     225                        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WordPress core hook
     226                        $current_threshold = apply_filters( 'big_image_size_threshold', 2560, array( 0, 0 ), '', 0 );
     227                } catch ( Throwable $e ) {
     228                        $current_threshold = 2560;
     229                }
     230
     231                // Validate the threshold value from filters.
    206232                if ( ! is_numeric( $current_threshold ) || $current_threshold <= 0 ) {
    207                         $current_threshold = 2560; // Fallback to WordPress default
    208                 }
    209                
    210                 // Preserve existing options and only update new_threshold
     233                        $current_threshold = 2560; // Fallback to WordPress default.
     234                }
     235
     236                // Preserve existing options and only update new_threshold.
    211237                if ( ! is_array( $GLOBALS['dtat_disablethreshold_options'] ) ) {
    212                         $GLOBALS['dtat_disablethreshold_options'] = [];
     238                        $GLOBALS['dtat_disablethreshold_options'] = array();
    213239                }
    214240                $GLOBALS['dtat_disablethreshold_options']['new_threshold'] = intval( $current_threshold );
    … …  
    225251 */
    226252function dtat_jpeg_quality_filter(): int {
    227         $dtat_imgquality_options = $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION, [] );
    228        
     253        $dtat_imgquality_options = $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION, array() );
     254
    229255        if ( ! is_array( $dtat_imgquality_options ) || ! isset( $dtat_imgquality_options['jpeg_quality'] ) ) {
    230                 return 82; // WordPress default
    231         }
    232        
     256                return 82; // WordPress default.
     257        }
     258
    233259        $quality = intval( $dtat_imgquality_options['jpeg_quality'] );
    234        
    235         // Validate quality range (0-100)
    236         if ( $quality < 0 || $quality > 100 ) {
    237                 return 82; // WordPress default
    238         }
    239        
     260
     261        // Same 1-100 range accepted by the settings page.
     262        if ( $quality < 1 || $quality > 100 ) {
     263                return 82; // WordPress default.
     264        }
     265
    240266        return $quality;
    241267}
    … …  
    249275 */
    250276function dtat_big_image_threshold_filter(): int {
    251         $dtat_disablethreshold_options = $GLOBALS['dtat_disablethreshold_options'] ?? get_option( DTAT_THRESHOLD_OPTION, [] );
    252        
     277        $dtat_disablethreshold_options = $GLOBALS['dtat_disablethreshold_options'] ?? get_option( DTAT_THRESHOLD_OPTION, array() );
     278
    253279        if ( ! is_array( $dtat_disablethreshold_options ) || ! isset( $dtat_disablethreshold_options['new_threshold'] ) ) {
    254                 return 2560; // WordPress default
    255         }
    256        
     280                return 2560; // WordPress default.
     281        }
     282
    257283        $threshold = intval( $dtat_disablethreshold_options['new_threshold'] );
    258        
    259         // Validate threshold is positive
     284
     285        // Validate threshold is positive.
    260286        if ( $threshold <= 0 ) {
    261                 return 2560; // WordPress default
    262         }
    263        
     287                return 2560; // WordPress default.
     288        }
     289
    264290        return $threshold;
    265291}
    … …  
    270296 * @since   0.1
    271297 * @package Disable_Thumbnails_Threshold
    272  * @param   array $sizes Registered intermediate image sizes.
    273  * @return  array Filtered image sizes with disabled ones removed.
    274  */
    275 function dtat_thumbnail_sizes_filter( array $sizes ): array {
    276         $dtat_disablethumbnails_options = $GLOBALS['dtat_disablethumbnails_options'] ?? get_option( DTAT_THUMBNAILS_OPTION, [] );
    277        
     298 * @param   mixed $sizes Registered intermediate image sizes (an array, unless another filter broke it).
     299 * @return  mixed Filtered image sizes with disabled ones removed.
     300 */
     301function dtat_thumbnail_sizes_filter( $sizes ) {
     302        // Untyped on purpose: a TypeError here would break every media upload.
     303        if ( ! is_array( $sizes ) ) {
     304                return $sizes;
     305        }
     306
     307        $dtat_disablethumbnails_options = $GLOBALS['dtat_disablethumbnails_options'] ?? get_option( DTAT_THUMBNAILS_OPTION, array() );
     308
    278309        if ( ! is_array( $dtat_disablethumbnails_options ) || empty( $dtat_disablethumbnails_options ) ) {
    279310                return $sizes;
    280311        }
    281        
    282         // Validate that all values in the array are strings (security check)
     312
     313        // Validate that all values in the array are strings (security check).
    283314        $valid_options = array_filter( $dtat_disablethumbnails_options, 'is_string' );
    284        
     315
    285316        return array_diff( $sizes, $valid_options );
    286317}
    … …  
    294325 */
    295326function dtat_apply_filters(): void {
    296         // Prevent multiple applications
     327        // Prevent multiple applications.
    297328        static $applied = false;
    298329        if ( $applied ) {
    … …  
    300331        }
    301332        $applied = true;
    302        
    303         // Remove any existing filters to prevent accumulation
     333
     334        // Remove any existing filters to prevent accumulation.
    304335        remove_filter( 'jpeg_quality', 'dtat_jpeg_quality_filter' );
    305336        remove_filter( 'big_image_size_threshold', 'dtat_big_image_threshold_filter' );
    306337        remove_filter( 'intermediate_image_sizes', 'dtat_thumbnail_sizes_filter' );
    307        
    308         // Safely get options with fallback
    309         $dtat_imgquality_options = $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION, [] );
    310         $dtat_disablethreshold_options = $GLOBALS['dtat_disablethreshold_options'] ?? get_option( DTAT_THRESHOLD_OPTION, [] );
    311         $dtat_disablethumbnails_options = $GLOBALS['dtat_disablethumbnails_options'] ?? get_option( DTAT_THUMBNAILS_OPTION, [] );
    312        
    313         // Apply JPEG quality filter
     338
     339        // Safely get options with fallback.
     340        $dtat_imgquality_options        = $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION, array() );
     341        $dtat_disablethreshold_options  = $GLOBALS['dtat_disablethreshold_options'] ?? get_option( DTAT_THRESHOLD_OPTION, array() );
     342        $dtat_disablethumbnails_options = $GLOBALS['dtat_disablethumbnails_options'] ?? get_option( DTAT_THUMBNAILS_OPTION, array() );
     343
     344        // Apply JPEG quality filter.
    314345        $jpeg_quality = null;
    315346        if ( is_array( $dtat_imgquality_options ) ) {
    316347                $jpeg_quality = $dtat_imgquality_options['jpeg_quality'] ?? null;
    317348        }
    318        
     349
    319350        $quality = $jpeg_quality ? intval( $jpeg_quality ) : 0;
    320351        if ( $jpeg_quality && is_numeric( $jpeg_quality ) && $quality > 0 && $quality <= 100 ) {
    … …  
    322353        }
    323354
    324         // Apply threshold filters
     355        // Apply threshold filters.
    325356        if ( is_array( $dtat_disablethreshold_options ) ) {
    326                 // Set new threshold
     357                // Set new threshold.
    327358                if ( ! empty( $dtat_disablethreshold_options['new_threshold'] )
    328359                        && is_numeric( $dtat_disablethreshold_options['new_threshold'] ) ) {
    … …  
    333364                }
    334365
    335                 // Disable threshold
     366                // Disable threshold.
    336367                if ( 'disable_threshold' === ( $dtat_disablethreshold_options['disable_threshold'] ?? null ) ) {
    337368                        add_filter( 'big_image_size_threshold', '__return_false', 100 );
    338369                }
    339370
    340                 // Disable EXIF rotation
     371                // Disable EXIF rotation.
    341372                if ( 'disable_image_rotation_exif' === ( $dtat_disablethreshold_options['disable_image_rotation_exif'] ?? null ) ) {
    342373                        add_filter( 'wp_image_maybe_exif_rotate', '__return_zero', 100, 2 );
    … …  
    344375        }
    345376
    346         // Apply thumbnail size filters
     377        // Apply thumbnail size filters.
    347378        if ( ! empty( $dtat_disablethumbnails_options ) ) {
    348379                add_filter( 'intermediate_image_sizes', 'dtat_thumbnail_sizes_filter', 100 );
    … …  
    350381}
    351382
    352 // All filters are now applied in dtat_apply_filters() function after themes are loaded
     383// All filters are now applied in dtat_apply_filters() function after themes are loaded.
    353384
    354385/**
    … …  
    361392 */
    362393function dtat_action_links( array $actions ): array {
    363         // Check if user has proper capabilities before showing action links
     394        // Check if user has proper capabilities before showing action links.
    364395        if ( ! current_user_can( 'manage_options' ) ) {
    365396                return $actions;
    366397        }
    367        
    368         $mylinks = [
     398
     399        $mylinks = array(
    369400                '<a href="' . esc_url( get_admin_url( null, 'tools.php?page=kgmdisablethumbnails' ) ) . '">' . esc_html__( 'Image sizes', 'disable-thumbnails-and-threshold' ) . '</a>',
    370401                '<a href="' . esc_url( get_admin_url( null, 'tools.php?page=kgmimgquality' ) ) . '">' . esc_html__( 'Image Quality', 'disable-thumbnails-and-threshold' ) . '</a>',
    371402                '<a href="' . esc_url( get_admin_url( null, 'tools.php?page=kgmdisablethreshold' ) ) . '">' . esc_html__( 'Threshold & EXIF', 'disable-thumbnails-and-threshold' ) . '</a>',
    372         ];
     403        );
    373404        return array_merge( $mylinks, $actions );
    374405}
    … …  
    383414 */
    384415function dtat_admin_styles( string $hook ): void {
    385         /**
    386          * Check if in plugin options page and user has proper capabilities
    387          */
    388416        if ( ! current_user_can( 'manage_options' ) ) {
    389417                return;
    390418        }
    391        
    392         $screen = get_current_screen();
    393         if ( ! $screen ) {
    394                 return;
    395         }
    396        
    397         if ( 'tools_page_kgmdisablethumbnails' === $screen->base || 'tools_page_kgmdisablethreshold' === $screen->base ) {
    398                 wp_enqueue_style( 'dtat-admin-css', plugins_url( 'includes/admin.css', __FILE__ ), [], DTAT_VERSION );
    399         }
    400 }
     419
     420        $plugin_pages = array( 'tools_page_kgmdisablethumbnails', 'tools_page_kgmdisablethreshold', 'tools_page_kgmimgquality' );
     421        if ( in_array( $hook, $plugin_pages, true ) ) {
     422                wp_enqueue_style( 'dtat-admin-css', plugins_url( 'includes/admin.css', __FILE__ ), array(), DTAT_VERSION );
     423        }
     424}
     425
     426register_uninstall_hook( __FILE__, 'dtat_plugin_uninstall' );
    401427
    402428/**
    403429 * Clean up plugin options on uninstall.
    404430 *
    405  * @since   0.1
    406  * @package Disable_Thumbnails_Threshold
    407  * @return  void
    408  */
    409 register_uninstall_hook( __FILE__, 'dtat_plugin_uninstall' );
     431 * Also removes the pre-0.6.5 `kgm*` options, which survive when the migration never ran.
     432 *
     433 * @since   0.1
     434 * @package Disable_Thumbnails_Threshold
     435 * @return  void
     436 */
    410437function dtat_plugin_uninstall(): void {
    411438        delete_option( DTAT_THUMBNAILS_OPTION );
    … …  
    413440        delete_option( DTAT_QUALITY_OPTION );
    414441        delete_option( DTAT_MIGRATION_OPTION );
    415 }
     442        delete_option( 'kgmimgquality_option_name' );
     443        delete_option( 'kgmdisablethreshold_option_name' );
     444        delete_option( 'kgmdisablethumbnails_option_name' );
     445}
  • disable-thumbnails-and-threshold/trunk/includes/admin.css

    r3504636 r3789337  
    11.switch { position: relative; display: inline-block; width: 33px; height: 17px; margin-right: 0.4em; }
    22.switch input { position: absolute; opacity: 0; width: 1px; height: 1px; clip: rect(0 0 0 0); overflow: hidden; }
    3 .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; -webkit-transition: 0.5s; transition: 0.5s; border-radius: 18px; display:inline; }
     3/* Inset border #757575: 4.05:1 on the form-table background #f0f0f1 (SC 1.4.11 needs 3:1). */
     4.slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; box-shadow: inset 0 0 0 1px #757575; -webkit-transition: 0.5s; transition: 0.5s; border-radius: 18px; display:inline; }
    45.slider::before { position: absolute; content: ""; height: 10px; width: 10px; left: 4px; bottom: 4px; background-color: #fff; -webkit-transition: 0.5s; transition: 0.5s; border-radius: 50%; }
    56input:checked + .screen-reader-text + .slider,
    67input:checked + .slider { background-color: #b12222; }
     8/* Transparent outline: box-shadow is dropped in forced-colors mode, the outline is not. */
    79input:focus + .screen-reader-text + .slider,
    8 input:focus + .slider { box-shadow: 0 0 0 3px #005fcc; }
     10input:focus + .slider { outline: 2px solid transparent; outline-offset: 2px; box-shadow: inset 0 0 0 1px #757575, 0 0 0 3px #005fcc; }
    911input:checked + .screen-reader-text + .slider::before,
    1012input:checked + .slider::before { -webkit-transform: translateX(16px); -ms-transform: translateX(16px); transform: translateX(16px); }
    11 .dtat-notice-warning { color: #d63638; }
    12 .dtat-notice-caution { color: #dba617; }
     13@media (forced-colors: active) {
     14        .slider { border: 1px solid ButtonText; }
     15        .slider::before { background-color: ButtonText; }
     16        input:checked + .screen-reader-text + .slider,
     17        input:checked + .slider { background-color: Highlight; }
     18}
     19/* Ratios on #f0f0f1: warning 5.53:1, caution 4.86:1, info 5.04:1 (SC 1.4.3 needs 4.5:1). */
     20.dtat-notice-warning { color: #b32d2e; }
     21.dtat-notice-caution { color: #8a6100; }
    1322.dtat-notice-info { color: #666; }
  • disable-thumbnails-and-threshold/trunk/includes/option-quality.php

    r3504636 r3789337  
    1212
    1313if ( ! defined( 'ABSPATH' ) ) {
    14         exit; // Exit if accessed directly
     14        exit; // Exit if accessed directly.
    1515}
    1616
     17/**
     18 * Image Quality settings page.
     19 *
     20 * @since 0.2
     21 */
    1722class DTAT_Img_Quality {
    18         private array|false $dtat_imgquality_options;
     23        /**
     24         * Stored option value. Untyped on purpose: whatever the database holds must not raise a TypeError.
     25         *
     26         * @var array|false
     27         */
     28        private $dtat_imgquality_options = false;
    1929
    2030        /**
    … …  
    2434         */
    2535        public function __construct() {
    26                 add_action( 'admin_menu', [ $this, 'add_plugin_page' ] );
    27                 add_action( 'admin_init', [ $this, 'page_init' ] );
     36                add_action( 'admin_menu', array( $this, 'add_plugin_page' ) );
     37                add_action( 'admin_init', array( $this, 'page_init' ) );
    2838        }
    2939
    … …  
    4050                        'manage_options',
    4151                        'kgmimgquality',
    42                         [ $this, 'create_admin_page' ]
     52                        array( $this, 'create_admin_page' )
    4353                );
    4454        }
    … …  
    5161         */
    5262        public function create_admin_page() {
    53                 // Check user capabilities for security
     63                // Check user capabilities for security.
    5464                if ( ! current_user_can( 'manage_options' ) ) {
    5565                        wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'disable-thumbnails-and-threshold' ) );
    5666                }
    57                
    58                 // Use cached options to avoid database calls
     67
     68                // Use cached options to avoid database calls.
    5969                $this->dtat_imgquality_options = $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION ); ?>
    6070
    6171                <div class="wrap">
    62                         <h2><?php echo esc_html__( 'Image Quality', 'disable-thumbnails-and-threshold' ); ?></h2>
     72                        <h1><?php echo esc_html__( 'Image Quality', 'disable-thumbnails-and-threshold' ); ?></h1>
    6373                        <p><strong><?php echo esc_html__( 'Remember you need to regenerate thumbnails for delete old thumbnails image already generated.', 'disable-thumbnails-and-threshold' ); ?></strong></p>
    64                         <p><?php echo esc_html__( 'Plugin recommended for regenerate thumbnails', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://uskgm.it/reg-thumb' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Regenerate Thumbnails', 'disable-thumbnails-and-threshold' ); ?></a></p>
    65                         <p><?php echo esc_html__( 'WP-CLI media regeneration', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://uskgm.it/WP-CLI-thumb-rgnrt' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Documentation', 'disable-thumbnails-and-threshold' ); ?></a></p>
     74                        <p><?php echo esc_html__( 'Plugin recommended for regenerate thumbnails', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://wordpress.org/plugins/regenerate-thumbnails/' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Regenerate Thumbnails', 'disable-thumbnails-and-threshold' ); ?></a></p>
     75                        <p><?php echo esc_html__( 'WP-CLI media regeneration', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://developer.wordpress.org/cli/commands/media/regenerate/' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Documentation', 'disable-thumbnails-and-threshold' ); ?></a></p>
    6676                        <?php settings_errors(); ?>
    6777
    … …  
    7484                        </form>
    7585                </div>
    76         <?php }
     86                <?php
     87        }
    7788
    7889        /**
    … …  
    8697                        'kgmimgquality_option_group',
    8798                        DTAT_QUALITY_OPTION,
    88                         [ $this, 'sanitize' ]
     99                        array( $this, 'sanitize' )
    89100                );
    90101
    91102                add_settings_section(
    92103                        'kgmimgquality_setting_section',
    93                         esc_html__( 'Settings', 'disable-thumbnails-and-threshold' ), 
    94                         [ $this, 'section_info' ],
    95                         'kgmimgquality-admin' 
     104                        esc_html__( 'Settings', 'disable-thumbnails-and-threshold' ),
     105                        array( $this, 'section_info' ),
     106                        'kgmimgquality-admin'
    96107                );
    97108
    … …  
    99110                        'jpeg_quality',
    100111                        esc_html__( 'JPEG Quality', 'disable-thumbnails-and-threshold' ) . ' <br> <small>' . esc_html__( 'Default WordPress: 82%', 'disable-thumbnails-and-threshold' ) . '</small>',
    101                         [ $this, 'jpeg_quality_callback' ],
     112                        array( $this, 'jpeg_quality_callback' ),
    102113                        'kgmimgquality-admin',
    103                         'kgmimgquality_setting_section'
     114                        'kgmimgquality_setting_section',
     115                        array( 'label_for' => 'jpeg_quality' )
    104116                );
    105117        }
    … …  
    108120         * Sanitize and validate form input before saving.
    109121         *
    110          * @since  0.2
    111          * @param  array $input Raw form input values.
     122         * Runs on every update_option() of this option, not only on form submit, so it
     123         * must not depend on the current user: options.php already enforces the nonce
     124         * and the manage_options capability before saving.
     125         *
     126         * @since  0.2
     127         * @param  mixed $input Raw value; null when the field is missing from the request.
    112128         * @return array Sanitized values.
    113129         */
    114         public function sanitize( array $input ): array {
    115                 // Check user capabilities for security
    116                 if ( ! current_user_can( 'manage_options' ) ) {
    117                         return $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION, [] );
    118                 }
    119                
    120                 // Nonce is already verified by WordPress options.php handler via settings_fields().
    121                 $sanitary_values = [];
     130        public function sanitize( $input ): array {
     131                if ( ! is_array( $input ) ) {
     132                        $input = array();
     133                }
     134
     135                $sanitary_values = array();
    122136
    123137                if ( isset( $input['jpeg_quality'] ) ) {
    124                         $quality = sanitize_text_field( $input['jpeg_quality'] );
     138                        $quality     = sanitize_text_field( $input['jpeg_quality'] );
    125139                        $quality_int = intval( $quality );
    126140                        if ( is_numeric( $quality ) && $quality_int >= 1 && $quality_int <= 100 ) {
    … …  
    128142                        } else {
    129143                                add_settings_error( 'kgmimgquality_option_notice', 'invalid_quality', esc_html__( 'JPEG quality must be a number between 1 and 100.', 'disable-thumbnails-and-threshold' ) );
    130                                 $existing = $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION, [] );
     144                                $existing = $GLOBALS['dtat_imgquality_options'] ?? get_option( DTAT_QUALITY_OPTION, array() );
    131145                                if ( is_array( $existing ) && isset( $existing['jpeg_quality'] ) ) {
    132                                         return [ 'jpeg_quality' => absint( $existing['jpeg_quality'] ) ];
     146                                        return array( 'jpeg_quality' => absint( $existing['jpeg_quality'] ) );
    133147                                }
    134                                 return [];
     148                                return array();
    135149                        }
    136150                }
    … …  
    162176                        esc_html__( '%', 'disable-thumbnails-and-threshold' )
    163177                );
    164                
     178
    165179                // Compare plugin value against WordPress default.
    166180                // We avoid calling apply_filters() here because the jpeg_quality filter expects
    … …  
    173187
    174188                if ( $plugin_quality && $plugin_quality !== $wp_default_quality ) {
    175                         printf( '<br><small class="description dtat-notice-warning">%s %s</small>',
     189                        printf(
     190                                '<br><small class="description dtat-notice-warning">%s %s</small>',
    176191                                esc_html( '⚠️' ),
    177                                 // translators: %1$d: Plugin quality percentage, %2$d: WordPress default quality percentage
     192                                /* translators: %1$d: Plugin quality percentage, %2$d: WordPress default quality percentage */
    178193                                esc_html( sprintf( __( 'Plugin quality (%1$d%%) differs from WordPress default (%2$d%%)', 'disable-thumbnails-and-threshold' ), $plugin_quality, $wp_default_quality ) )
    179194                        );
    180195                } else {
    181                         printf( '<br><small class="description dtat-notice-info">%s</small>',
    182                                 // translators: %d: WordPress default JPEG quality percentage
     196                        printf(
     197                                '<br><small class="description dtat-notice-info">%s</small>',
     198                                /* translators: %d: WordPress default JPEG quality percentage */
    183199                                esc_html( sprintf( __( 'WordPress default JPEG quality: %d%%', 'disable-thumbnails-and-threshold' ), $wp_default_quality ) )
    184200                        );
    185201                }
    186202        }
    187 
    188203}
    189204if ( is_admin() ) {
    190         $DTAT_Img_Quality = new DTAT_Img_Quality();
     205        $dtat_img_quality = new DTAT_Img_Quality();
    191206}
  • disable-thumbnails-and-threshold/trunk/includes/option-threshold-exif.php

    r3504636 r3789337  
    1212
    1313if ( ! defined( 'ABSPATH' ) ) {
    14         exit; // Exit if accessed directly
     14        exit; // Exit if accessed directly.
    1515}
    1616
     17/**
     18 * Threshold & EXIF settings page.
     19 *
     20 * @since 0.1
     21 */
    1722class DTAT_Disable_Threshold {
    18         private array|false $dtat_disablethreshold_options;
     23        /**
     24         * Stored option value. Untyped on purpose: whatever the database holds must not raise a TypeError.
     25         *
     26         * @var array|false
     27         */
     28        private $dtat_disablethreshold_options = false;
    1929
    2030        /**
    … …  
    2434         */
    2535        public function __construct() {
    26                 add_action( 'admin_menu', [ $this, 'add_plugin_page' ] );
    27                 add_action( 'admin_init', [ $this, 'page_init' ] );
     36                add_action( 'admin_menu', array( $this, 'add_plugin_page' ) );
     37                add_action( 'admin_init', array( $this, 'page_init' ) );
    2838        }
    2939
    … …  
    4050                        'manage_options',
    4151                        'kgmdisablethreshold',
    42                         [ $this, 'create_admin_page' ]
     52                        array( $this, 'create_admin_page' )
    4353                );
    4454        }
    … …  
    5161         */
    5262        public function create_admin_page() {
    53                 // Check user capabilities for security
     63                // Check user capabilities for security.
    5464                if ( ! current_user_can( 'manage_options' ) ) {
    5565                        wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'disable-thumbnails-and-threshold' ) );
    5666                }
    57                
    58                 // Use cached options to avoid database calls
     67
     68                // Use cached options to avoid database calls.
    5969                $this->dtat_disablethreshold_options = $GLOBALS['dtat_disablethreshold_options'] ?? get_option( DTAT_THRESHOLD_OPTION ); ?>
    6070
    6171                <div class="wrap">
    62                         <h2><?php echo esc_html__( 'Disable Threshold&EXIF', 'disable-thumbnails-and-threshold' ); ?></h2>
     72                        <h1><?php echo esc_html__( 'Disable Threshold&EXIF', 'disable-thumbnails-and-threshold' ); ?></h1>
    6373                        <p><strong><?php echo esc_html__( 'Remember you need to regenerate thumbnails for delete old thumbnails image already generated.', 'disable-thumbnails-and-threshold' ); ?></strong></p>
    64                         <p><?php echo esc_html__( 'Plugin recommended for regenerate thumbnails', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://uskgm.it/reg-thumb' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Regenerate Thumbnails', 'disable-thumbnails-and-threshold' ); ?></a></p>
    65                         <p><?php echo esc_html__( 'WP-CLI media regeneration', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://uskgm.it/WP-CLI-thumb-rgnrt' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Documentation', 'disable-thumbnails-and-threshold' ); ?></a></p>
     74                        <p><?php echo esc_html__( 'Plugin recommended for regenerate thumbnails', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://wordpress.org/plugins/regenerate-thumbnails/' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Regenerate Thumbnails', 'disable-thumbnails-and-threshold' ); ?></a></p>
     75                        <p><?php echo esc_html__( 'WP-CLI media regeneration', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://developer.wordpress.org/cli/commands/media/regenerate/' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Documentation', 'disable-thumbnails-and-threshold' ); ?></a></p>
    6676                        <?php settings_errors(); ?>
    6777
    … …  
    7484                        </form>
    7585                </div>
    76         <?php }
     86                <?php
     87        }
    7788
    7889        /**
    … …  
    8697                        'kgmdisablethreshold_option_group',
    8798                        DTAT_THRESHOLD_OPTION,
    88                         [ $this, 'sanitize' ]
     99                        array( $this, 'sanitize' )
    89100                );
    90101
    91102                add_settings_section(
    92103                        'kgmdisablethreshold_setting_section',
    93                         esc_html__( 'Settings', 'disable-thumbnails-and-threshold' ), 
    94                         [ $this, 'section_info' ],
    95                         'kgmdisablethreshold-admin' 
     104                        esc_html__( 'Settings', 'disable-thumbnails-and-threshold' ),
     105                        array( $this, 'section_info' ),
     106                        'kgmdisablethreshold-admin'
    96107                );
    97108
    … …  
    99110                        'new_threshold',
    100111                        esc_html__( 'New Size Threshold', 'disable-thumbnails-and-threshold' ) . ' <br> <small>' . esc_html__( 'Default WordPress: 2560px', 'disable-thumbnails-and-threshold' ) . '</small>',
    101                         [ $this, 'new_threshold_callback' ],
     112                        array( $this, 'new_threshold_callback' ),
    102113                        'kgmdisablethreshold-admin',
    103                         'kgmdisablethreshold_setting_section'
     114                        'kgmdisablethreshold_setting_section',
     115                        array( 'label_for' => 'new_threshold' )
    104116                );
    105117                add_settings_field(
    106118                        'disable_threshold',
    107119                        esc_html__( 'Disable Threshold', 'disable-thumbnails-and-threshold' ),
    108                         [ $this, 'disable_threshold_callback' ],
     120                        array( $this, 'disable_threshold_callback' ),
    109121                        'kgmdisablethreshold-admin',
    110122                        'kgmdisablethreshold_setting_section'
    … …  
    113125                        'disable_image_rotation_exif',
    114126                        esc_html__( 'Disable Image Rotation by EXIF', 'disable-thumbnails-and-threshold' ),
    115                         [ $this, 'disable_image_rotation_exif_callback' ],
     127                        array( $this, 'disable_image_rotation_exif_callback' ),
    116128                        'kgmdisablethreshold-admin',
    117129                        'kgmdisablethreshold_setting_section'
    … …  
    122134         * Sanitize and validate form input before saving.
    123135         *
    124          * @since  0.1
    125          * @param  array $input Raw form input values.
     136         * Runs on every update_option() of this option, not only on form submit, so it
     137         * must not depend on the current user: options.php already enforces the nonce
     138         * and the manage_options capability before saving.
     139         *
     140         * @since  0.1
     141         * @param  mixed $input Raw value; null when no field is present in the request.
    126142         * @return array Sanitized values.
    127143         */
    128         public function sanitize( array $input ): array {
    129                 // Check user capabilities for security
    130                 if ( ! current_user_can( 'manage_options' ) ) {
    131                         return $GLOBALS['dtat_disablethreshold_options'] ?? get_option( DTAT_THRESHOLD_OPTION, [] );
    132                 }
    133                
    134                 // Nonce is already verified by WordPress options.php handler via settings_fields().
    135                 $sanitary_values = [];
     144        public function sanitize( $input ): array {
     145                if ( ! is_array( $input ) ) {
     146                        $input = array();
     147                }
     148
     149                $sanitary_values = array();
    136150
    137151                if ( isset( $input['new_threshold'] ) ) {
    … …  
    183197                        esc_html__( 'px', 'disable-thumbnails-and-threshold' )
    184198                );
    185                
    186                 // Check if plugin disables threshold
     199
     200                // Check if plugin disables threshold.
    187201                $plugin_disables_threshold = false;
    188202                if ( is_array( $this->dtat_disablethreshold_options ) && isset( $this->dtat_disablethreshold_options['disable_threshold'] ) ) {
    189                         $plugin_disables_threshold = ( $this->dtat_disablethreshold_options['disable_threshold'] === 'disable_threshold' );
    190                 }
    191                
    192                 // Show yellow warning message if plugin disables threshold
     203                        $plugin_disables_threshold = ( 'disable_threshold' === $this->dtat_disablethreshold_options['disable_threshold'] );
     204                }
     205
     206                // Show yellow warning message if plugin disables threshold.
    193207                if ( $plugin_disables_threshold ) {
    194                         printf( '<br><small class="description dtat-notice-caution">%s %s</small>',
     208                        printf(
     209                                '<br><small class="description dtat-notice-caution">%s %s</small>',
    195210                                esc_html( '⚠️' ),
    196211                                esc_html__( 'Disabled by plugin', 'disable-thumbnails-and-threshold' )
    … …  
    207222
    208223                        if ( $plugin_threshold && $plugin_threshold !== $wp_default_threshold ) {
    209                                 printf( '<br><small class="description dtat-notice-warning">%s %s</small>',
     224                                printf(
     225                                        '<br><small class="description dtat-notice-warning">%s %s</small>',
    210226                                        esc_html( '⚠️' ),
    211                                         // translators: %1$d: Plugin threshold value in pixels, %2$d: WordPress default threshold value in pixels
     227                                        /* translators: %1$d: Plugin threshold value in pixels, %2$d: WordPress default threshold value in pixels */
    212228                                        esc_html( sprintf( __( 'Plugin threshold (%1$dpx) differs from WordPress default (%2$dpx)', 'disable-thumbnails-and-threshold' ), $plugin_threshold, $wp_default_threshold ) )
    213229                                );
    214230                        } else {
    215                                 // translators: %d: WordPress default big image threshold value in pixels
     231                                /* translators: %d: WordPress default big image threshold value in pixels */
    216232                                printf( '<br><small class="description dtat-notice-info">%s</small>', esc_html( sprintf( __( 'WordPress default big image threshold: %dpx', 'disable-thumbnails-and-threshold' ), $wp_default_threshold ) ) );
    217233                        }
    … …  
    229245                        '<label class="switch"><input type="checkbox" name="%s[disable_threshold]" id="disable_threshold" value="disable_threshold" %s><span class="screen-reader-text">%s</span><span class="slider" aria-hidden="true"></span></label>',
    230246                        esc_attr( DTAT_THRESHOLD_OPTION ),
    231                         ( is_array( $this->dtat_disablethreshold_options ) && isset( $this->dtat_disablethreshold_options['disable_threshold'] ) && $this->dtat_disablethreshold_options['disable_threshold'] === 'disable_threshold' ) ? 'checked' : '',
     247                        ( is_array( $this->dtat_disablethreshold_options ) && isset( $this->dtat_disablethreshold_options['disable_threshold'] ) && 'disable_threshold' === $this->dtat_disablethreshold_options['disable_threshold'] ) ? 'checked' : '',
    232248                        esc_html__( 'Disable Threshold', 'disable-thumbnails-and-threshold' )
    233249                );
    234                
     250
    235251                // Show informational status based on plugin's stored setting.
    236252                // We avoid calling apply_filters('big_image_size_threshold') here because it expects
    … …  
    238254                $plugin_intends_to_disable = false;
    239255                if ( is_array( $this->dtat_disablethreshold_options ) && isset( $this->dtat_disablethreshold_options['disable_threshold'] ) ) {
    240                         $plugin_intends_to_disable = ( $this->dtat_disablethreshold_options['disable_threshold'] === 'disable_threshold' );
     256                        $plugin_intends_to_disable = ( 'disable_threshold' === $this->dtat_disablethreshold_options['disable_threshold'] );
    241257                }
    242258
    243259                if ( $plugin_intends_to_disable ) {
    244                         printf( '<br><small class="description dtat-notice-info">%s</small>',
     260                        printf(
     261                                '<br><small class="description dtat-notice-info">%s</small>',
    245262                                esc_html__( 'Threshold is disabled by this plugin.', 'disable-thumbnails-and-threshold' )
    246263                        );
    … …  
    258275                        '<label class="switch"><input type="checkbox" name="%s[disable_image_rotation_exif]" id="disable_image_rotation_exif" value="disable_image_rotation_exif" %s><span class="screen-reader-text">%s</span><span class="slider" aria-hidden="true"></span></label>',
    259276                        esc_attr( DTAT_THRESHOLD_OPTION ),
    260                         ( is_array( $this->dtat_disablethreshold_options ) && isset( $this->dtat_disablethreshold_options['disable_image_rotation_exif'] ) && $this->dtat_disablethreshold_options['disable_image_rotation_exif'] === 'disable_image_rotation_exif' ) ? 'checked' : '',
     277                        ( is_array( $this->dtat_disablethreshold_options ) && isset( $this->dtat_disablethreshold_options['disable_image_rotation_exif'] ) && 'disable_image_rotation_exif' === $this->dtat_disablethreshold_options['disable_image_rotation_exif'] ) ? 'checked' : '',
    261278                        esc_html__( 'Disable Image Rotation by EXIF', 'disable-thumbnails-and-threshold' )
    262279                );
    263                
     280
    264281                // Show informational status based on plugin's stored setting.
    265282                // We avoid calling apply_filters('wp_image_maybe_exif_rotate') here because it expects
    … …  
    267284                $plugin_exif_disabled = false;
    268285                if ( is_array( $this->dtat_disablethreshold_options ) && isset( $this->dtat_disablethreshold_options['disable_image_rotation_exif'] ) ) {
    269                         $plugin_exif_disabled = ( $this->dtat_disablethreshold_options['disable_image_rotation_exif'] === 'disable_image_rotation_exif' );
     286                        $plugin_exif_disabled = ( 'disable_image_rotation_exif' === $this->dtat_disablethreshold_options['disable_image_rotation_exif'] );
    270287                }
    271288
    272289                if ( $plugin_exif_disabled ) {
    273                         printf( '<br><small class="description dtat-notice-info">%s</small>',
     290                        printf(
     291                                '<br><small class="description dtat-notice-info">%s</small>',
    274292                                esc_html__( 'EXIF rotation is disabled by this plugin.', 'disable-thumbnails-and-threshold' )
    275293                        );
    276294                }
    277295        }
    278 
    279296}
    280297if ( is_admin() ) {
    281         $DTAT_Disable_Threshold = new DTAT_Disable_Threshold();
     298        $dtat_disable_threshold = new DTAT_Disable_Threshold();
    282299}
  • disable-thumbnails-and-threshold/trunk/includes/option-thumbnails.php

    r3504636 r3789337  
    1212
    1313if ( ! defined( 'ABSPATH' ) ) {
    14         exit; // Exit if accessed directly
     14        exit; // Exit if accessed directly.
    1515}
    1616
     17/**
     18 * Image Sizes settings page.
     19 *
     20 * @since 0.1
     21 */
    1722class DTAT_Disable_Thumbnails {
    18         private array|false $dtat_disablethumbnails_options;
     23        /**
     24         * Stored option value. Untyped on purpose: whatever the database holds must not raise a TypeError.
     25         *
     26         * @var array|false
     27         */
     28        private $dtat_disablethumbnails_options = false;
    1929
    2030        /**
    … …  
    2434         */
    2535        public function __construct() {
    26                 add_action( 'admin_menu', [ $this, 'add_plugin_page' ] );
    27                 add_action( 'admin_init', [ $this, 'page_init' ] );
     36                add_action( 'admin_menu', array( $this, 'add_plugin_page' ) );
     37                add_action( 'admin_init', array( $this, 'page_init' ) );
    2838        }
    2939
    … …  
    3646        public function add_plugin_page() {
    3747                add_management_page(
    38                         esc_html__( 'Image Sizes', 'disable-thumbnails-and-threshold' ), 
    39                         esc_html__( 'Image Sizes', 'disable-thumbnails-and-threshold' ), 
    40                         'manage_options', 
    41                         'kgmdisablethumbnails', 
    42                         [ $this, 'create_admin_page' ]
     48                        esc_html__( 'Image Sizes', 'disable-thumbnails-and-threshold' ),
     49                        esc_html__( 'Image Sizes', 'disable-thumbnails-and-threshold' ),
     50                        'manage_options',
     51                        'kgmdisablethumbnails',
     52                        array( $this, 'create_admin_page' )
    4353                );
    4454        }
    … …  
    5161         */
    5262        public function create_admin_page() {
    53                 // Check user capabilities for security
     63                // Check user capabilities for security.
    5464                if ( ! current_user_can( 'manage_options' ) ) {
    5565                        wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'disable-thumbnails-and-threshold' ) );
    5666                }
    57                
    58                 // Use cached options to avoid database calls
     67
     68                // Use cached options to avoid database calls.
    5969                $this->dtat_disablethumbnails_options = $GLOBALS['dtat_disablethumbnails_options'] ?? get_option( DTAT_THUMBNAILS_OPTION ); ?>
    6070
    6171                <div class="wrap">
    62                         <h2><?php echo esc_html__( 'Image Thumbnails', 'disable-thumbnails-and-threshold' ); ?></h2>
     72                        <h1><?php echo esc_html__( 'Image Thumbnails', 'disable-thumbnails-and-threshold' ); ?></h1>
    6373                        <p><strong><?php echo esc_html__( 'Remember you need to regenerate thumbnails for delete old thumbnails image already generated.', 'disable-thumbnails-and-threshold' ); ?></strong></p>
    64                         <p><?php echo esc_html__( 'Plugin recommended for regenerate thumbnails', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://uskgm.it/reg-thumb' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Regenerate Thumbnails', 'disable-thumbnails-and-threshold' ); ?></a></p>
    65                         <p><?php echo esc_html__( 'WP-CLI media regeneration', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://uskgm.it/WP-CLI-thumb-rgnrt' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Documentation', 'disable-thumbnails-and-threshold' ); ?></a></p>
     74                        <p><?php echo esc_html__( 'Plugin recommended for regenerate thumbnails', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://wordpress.org/plugins/regenerate-thumbnails/' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Regenerate Thumbnails', 'disable-thumbnails-and-threshold' ); ?></a></p>
     75                        <p><?php echo esc_html__( 'WP-CLI media regeneration', 'disable-thumbnails-and-threshold' ); ?> -> <a href="<?php echo esc_url( 'https://developer.wordpress.org/cli/commands/media/regenerate/' ); ?>" target="_blank" rel="noopener"><?php echo esc_html__( 'Documentation', 'disable-thumbnails-and-threshold' ); ?></a></p>
    6676                        <p><?php echo esc_html__( 'Flagged image sizes will be disabled.', 'disable-thumbnails-and-threshold' ); ?></p>
    6777                        <?php settings_errors(); ?>
    … …  
    7585                        </form>
    7686                </div>
    77         <?php }
     87                <?php
     88        }
    7889
    7990        /**
    … …  
    8697                register_setting(
    8798                        'kgmdisablethumbnails_option_group',
    88                         DTAT_THUMBNAILS_OPTION, 
    89                         [ $this, 'sanitize' ]
     99                        DTAT_THUMBNAILS_OPTION,
     100                        array( $this, 'sanitize' )
    90101                );
    91102
    92103                add_settings_section(
    93                         'kgmdisablethumbnails_setting_section', 
    94                         esc_html__( 'Settings', 'disable-thumbnails-and-threshold' ), 
    95                         [ $this, 'section_info' ],
    96                         'kgmdisablethumbnails-admin' 
     104                        'kgmdisablethumbnails_setting_section',
     105                        esc_html__( 'Settings', 'disable-thumbnails-and-threshold' ),
     106                        array( $this, 'section_info' ),
     107                        'kgmdisablethumbnails-admin'
    97108                );
    98109
    99110                add_settings_field(
    100111                        'thumbnail',
    101                         esc_html__( 'Thumbnail', 'disable-thumbnails-and-threshold' ), 
    102                         [ $this, 'thumbnail_callback' ],
    103                         'kgmdisablethumbnails-admin', 
    104                         'kgmdisablethumbnails_setting_section' 
     112                        esc_html__( 'Thumbnail', 'disable-thumbnails-and-threshold' ),
     113                        array( $this, 'thumbnail_callback' ),
     114                        'kgmdisablethumbnails-admin',
     115                        'kgmdisablethumbnails_setting_section'
    105116                );
    106117                add_settings_field(
    107118                        'medium',
    108                         esc_html__( 'Medium', 'disable-thumbnails-and-threshold' ), 
    109                         [ $this, 'medium_callback' ],
    110                         'kgmdisablethumbnails-admin', 
    111                         'kgmdisablethumbnails_setting_section' 
     119                        esc_html__( 'Medium', 'disable-thumbnails-and-threshold' ),
     120                        array( $this, 'medium_callback' ),
     121                        'kgmdisablethumbnails-admin',
     122                        'kgmdisablethumbnails_setting_section'
    112123                );
    113124                add_settings_field(
    114125                        'medium_large',
    115126                        esc_html__( 'Medium Large', 'disable-thumbnails-and-threshold' ),
    116                         [ $this, 'medium_large_callback' ],
    117                         'kgmdisablethumbnails-admin',
    118                         'kgmdisablethumbnails_setting_section' 
    119                 );
    120                 add_settings_field(
    121                         'large', 
    122                         esc_html__( 'Large', 'disable-thumbnails-and-threshold' ), 
    123                         [ $this, 'large_callback' ],
    124                         'kgmdisablethumbnails-admin', 
    125                         'kgmdisablethumbnails_setting_section' 
     127                        array( $this, 'medium_large_callback' ),
     128                        'kgmdisablethumbnails-admin',
     129                        'kgmdisablethumbnails_setting_section'
     130                );
     131                add_settings_field(
     132                        'large',
     133                        esc_html__( 'Large', 'disable-thumbnails-and-threshold' ),
     134                        array( $this, 'large_callback' ),
     135                        'kgmdisablethumbnails-admin',
     136                        'kgmdisablethumbnails_setting_section'
    126137                );
    127138
    128139                $image_sizes = wp_get_additional_image_sizes();
    129140                foreach ( $image_sizes as $key => $image_size ) {
    130                         if ( 1 === $image_size['crop'] ) {
     141                        if ( ! empty( $image_size['crop'] ) ) {
    131142                                $crop = esc_html__( 'cropped', 'disable-thumbnails-and-threshold' );
    132143                        } else {
    … …  
    135146                        add_settings_field(
    136147                                $key,
    137                                 esc_html( $key ) . '<br><small>(' . esc_attr( $image_size['width'] ) . 'x' . esc_attr( $image_size['height'] ) . ')</small><br><small>' . esc_html( $crop ) . '</small>',
    138                                 [ $this, 'ext_callback' ],
     148                                esc_html( $key ) . '<br><small>(' . absint( $image_size['width'] ) . 'x' . absint( $image_size['height'] ) . ')</small><br><small>' . esc_html( $crop ) . '</small>',
     149                                array( $this, 'ext_callback' ),
    139150                                'kgmdisablethumbnails-admin',
    140151                                'kgmdisablethumbnails_setting_section',
    141                                 [ 'name' => $key ]
     152                                array( 'name' => $key )
    142153                        );
    143154                }
    … …  
    147158         * Sanitize and validate form input before saving.
    148159         *
    149          * @since  0.1
    150          * @param  array $input Raw form input values.
     160         * Runs on every update_option() of this option, not only on form submit, so it
     161         * must not depend on the current user: options.php already enforces the nonce
     162         * and the manage_options capability before saving.
     163         *
     164         * Each checkbox posts its own size name as value, so only "size => size" pairs
     165         * for sizes registered on this site are kept.
     166         *
     167         * @since  0.1
     168         * @param  mixed $input Raw value; null when every checkbox is unchecked.
    151169         * @return array Sanitized values.
    152170         */
    153         public function sanitize( array $input ): array {
    154                 // Check user capabilities for security
    155                 if ( ! current_user_can( 'manage_options' ) ) {
    156                         return $GLOBALS['dtat_disablethumbnails_options'] ?? get_option( DTAT_THUMBNAILS_OPTION, [] );
    157                 }
    158                
    159                 // Nonce is already verified by WordPress options.php handler via settings_fields().
    160                 $sanitary_values = [];
    161 
    162                 if ( isset( $input['thumbnail'] ) ) {
    163                         $sanitary_values['thumbnail'] = sanitize_text_field( $input['thumbnail'] );
    164                 }
    165                 if ( isset( $input['medium'] ) ) {
    166                         $sanitary_values['medium'] = sanitize_text_field( $input['medium'] );
    167                 }
    168                 if ( isset( $input['medium_large'] ) ) {
    169                         $sanitary_values['medium_large'] = sanitize_text_field( $input['medium_large'] );
    170                 }
    171                 if ( isset( $input['large'] ) ) {
    172                         $sanitary_values['large'] = sanitize_text_field( $input['large'] );
    173                 }
    174 
    175                 $image_sizes = wp_get_additional_image_sizes();
    176                 foreach ( $image_sizes as $key => $image_size ) {
    177                         if ( isset( $input[ $key ] ) ) {
    178                                 $sanitary_values[ $key ] = sanitize_text_field( $input[ $key ] );
     171        public function sanitize( $input ): array {
     172                if ( ! is_array( $input ) ) {
     173                        return array();
     174                }
     175
     176                $sanitary_values = array();
     177                $known_sizes     = array_merge(
     178                        array( 'thumbnail', 'medium', 'medium_large', 'large' ),
     179                        array_keys( wp_get_additional_image_sizes() )
     180                );
     181
     182                foreach ( $known_sizes as $size ) {
     183                        if ( isset( $input[ $size ] ) && sanitize_text_field( $input[ $size ] ) === (string) $size ) {
     184                                $sanitary_values[ $size ] = (string) $size;
    179185                        }
    180186                }
    … …  
    190196         */
    191197        public function section_info() {
    192 
    193198        }
    194199
    … …  
    203208                        '<label class="switch"><input type="checkbox" name="%s[thumbnail]" id="thumbnail" value="thumbnail" %s><span class="screen-reader-text">%s</span><span class="slider" aria-hidden="true"></span></label>',
    204209                        esc_attr( DTAT_THUMBNAILS_OPTION ),
    205                         ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['thumbnail'] ) && $this->dtat_disablethumbnails_options['thumbnail'] === 'thumbnail' ) ? 'checked' : '',
     210                        ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['thumbnail'] ) && 'thumbnail' === $this->dtat_disablethumbnails_options['thumbnail'] ) ? 'checked' : '',
    206211                        esc_html__( 'Disable Thumbnail size', 'disable-thumbnails-and-threshold' )
    207212                );
    … …  
    218223                        '<label class="switch"><input type="checkbox" name="%s[medium]" id="medium" value="medium" %s><span class="screen-reader-text">%s</span><span class="slider" aria-hidden="true"></span></label>',
    219224                        esc_attr( DTAT_THUMBNAILS_OPTION ),
    220                         ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['medium'] ) && $this->dtat_disablethumbnails_options['medium'] === 'medium' ) ? 'checked' : '',
     225                        ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['medium'] ) && 'medium' === $this->dtat_disablethumbnails_options['medium'] ) ? 'checked' : '',
    221226                        esc_html__( 'Disable Medium size', 'disable-thumbnails-and-threshold' )
    222227                );
    … …  
    233238                        '<label class="switch"><input type="checkbox" name="%s[medium_large]" id="medium_large" value="medium_large" %s><span class="screen-reader-text">%s</span><span class="slider" aria-hidden="true"></span></label>',
    234239                        esc_attr( DTAT_THUMBNAILS_OPTION ),
    235                         ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['medium_large'] ) && $this->dtat_disablethumbnails_options['medium_large'] === 'medium_large' ) ? 'checked' : '',
     240                        ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['medium_large'] ) && 'medium_large' === $this->dtat_disablethumbnails_options['medium_large'] ) ? 'checked' : '',
    236241                        esc_html__( 'Disable Medium Large size', 'disable-thumbnails-and-threshold' )
    237242                );
    … …  
    248253                        '<label class="switch"><input type="checkbox" name="%s[large]" id="large" value="large" %s><span class="screen-reader-text">%s</span><span class="slider" aria-hidden="true"></span></label>',
    249254                        esc_attr( DTAT_THUMBNAILS_OPTION ),
    250                         ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['large'] ) && $this->dtat_disablethumbnails_options['large'] === 'large' ) ? 'checked' : '',
     255                        ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options['large'] ) && 'large' === $this->dtat_disablethumbnails_options['large'] ) ? 'checked' : '',
    251256                        esc_html__( 'Disable Large size', 'disable-thumbnails-and-threshold' )
    252257                );
    … …  
    268273                        esc_attr( $name ),
    269274                        esc_attr( $name ),
    270                         ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options[$name] ) && $this->dtat_disablethumbnails_options[$name] === $name ) ? 'checked' : '',
     275                        ( is_array( $this->dtat_disablethumbnails_options ) && isset( $this->dtat_disablethumbnails_options[ $name ] ) && $name === $this->dtat_disablethumbnails_options[ $name ] ) ? 'checked' : '',
    271276                        /* translators: %s: Image size name */
    272277                        esc_html( sprintf( __( 'Disable %s size', 'disable-thumbnails-and-threshold' ), $name ) )
    273278                );
    274279        }
    275 
    276280}
    277281if ( is_admin() ) {
    278         $DTAT_Disable_Thumbnails = new DTAT_Disable_Thumbnails();
     282        $dtat_disable_thumbnails = new DTAT_Disable_Thumbnails();
    279283}
  • disable-thumbnails-and-threshold/trunk/readme.txt

    r3504636 r3789337  
    33Donate link: https://kgmservizi.com
    44Tags: thumbnails, disable thumbnails, disable threshold, disable images, image options
    5 Requires at least: 5.4
    6 Tested up to: 6.8
    7 Requires PHP: 7.4
    8 Stable tag: 0.7.0
     5Requires at least: 5.6
     6Tested up to: 7.1
     7Requires PHP: 8.0
     8Stable tag: 0.8.0
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    7676== Changelog ==
    7777
     78= 0.8.0 =
     79* Requirements: minimum PHP raised to 8.0 and minimum WordPress to 5.6 (the first release with PHP 8.0 support).
     80* Fix: saving the Image Sizes page with every size unchecked caused a fatal error.
     81* Fix: settings saved through WP-CLI were silently discarded.
     82* Fix: the "cropped" label now appears for custom image sizes registered with cropping.
     83* Fix: no fatal error when another plugin hooks `jpeg_quality` or `big_image_size_threshold` with required extra arguments.
     84* Coding standards cleanup.
     85
    7886= 0.7.0 =
    7987* Improved accessibility: toggle switches are now fully keyboard-navigable with visible focus indicators and screen-reader labels.
    … …  
    98106== Upgrade Notice ==
    99107
     108= 0.8.0 =
     109Requires PHP 8.0+ and WordPress 5.6+. Fixes a fatal error when unchecking every image size.
     110
    100111= 0.7.0 =
    101112Accessibility, compatibility and performance improvements. No breaking changes — all settings and URLs are preserved. Recommended update for all users.
Note: See TracChangeset for help on using the changeset viewer.