Files
2026-04-15 15:59:53 -04:00

597 lines
17 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* WP Smush plugin
*
* Reduce image file sizes, improve performance and boost your SEO using the free
* <a href="https://wpmudev.com/">WPMU DEV</a> WordPress Smush API.
*
* @link http://wpmudev.com/project/wp-smush-pro/
* @since 1.0.0
* @package WP_Smush
*
* @wordpress-plugin
* Plugin Name: Smush
* Plugin URI: https://wpmudev.com/project/wp-smush-pro/
* Description: Reduce image file sizes, improve performance and boost your SEO using the free <a href="https://wpmudev.com/">WPMU DEV</a> WordPress Smush API.
* Version: 3.24.0
* Requires at least: 6.4
* Requires PHP: 7.4
* Author: WPMU DEV
* Author URI: https://wpmudev.com/
* License: GPLv2
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: wp-smushit
* Domain Path: /languages/
* Network: true
*/
/*
This plugin was originally developed by Alex Dunae (http://dialect.ca/).
Copyright 2007-2022 Incsub (http://incsub.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License (Version 2 - GPLv2) as published by
the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
use Smush\Core\Membership\Membership;
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
if ( ! defined( 'WP_SMUSH_VERSION' ) ) {
define( 'WP_SMUSH_VERSION', '3.24.0' );
}
// Used to define body class.
if ( ! defined( 'WP_SHARED_UI_VERSION' ) ) {
define( 'WP_SHARED_UI_VERSION', 'sui-2-12-23' );
}
if ( ! defined( 'WP_SMUSH_BASENAME' ) ) {
define( 'WP_SMUSH_BASENAME', plugin_basename( __FILE__ ) );
}
if ( ! defined( 'WP_SMUSH_API' ) ) {
define( 'WP_SMUSH_API', 'https://smushpro.wpmudev.com/1.0/' );
}
if ( ! defined( 'WP_SMUSH_UA' ) ) {
define( 'WP_SMUSH_UA', 'WP Smush/' . WP_SMUSH_VERSION . '; ' . network_home_url() );
}
if ( ! defined( 'WP_SMUSH_DIR' ) ) {
define( 'WP_SMUSH_DIR', plugin_dir_path( __FILE__ ) );
}
if ( ! defined( 'WP_SMUSH_URL' ) ) {
define( 'WP_SMUSH_URL', plugin_dir_url( __FILE__ ) );
}
if ( ! defined( 'WP_SMUSH_MAX_BYTES' ) ) {
define( 'WP_SMUSH_MAX_BYTES', 5242880 );
}
if ( ! defined( 'WP_SMUSH_TIMEOUT' ) ) {
define( 'WP_SMUSH_TIMEOUT', 420 ); // 7 minutes
}
if ( ! defined( 'WP_SMUSH_RETRY_ATTEMPTS' ) ) {
define( 'WP_SMUSH_RETRY_ATTEMPTS', 3 );
}
if ( ! defined( 'WP_SMUSH_RETRY_WAIT' ) ) {
define( 'WP_SMUSH_RETRY_WAIT', 1 );
}
if ( ! defined( 'WP_SMUSH_PARALLEL' ) ) {
define( 'WP_SMUSH_PARALLEL', true );
}
if ( ! defined( 'WP_SMUSH_BACKGROUND' ) ) {
define( 'WP_SMUSH_BACKGROUND', false );
}
if ( ! defined( 'WP_SMUSH_MIN_PHP_VERSION' ) ) {
define( 'WP_SMUSH_MIN_PHP_VERSION', '7.4' );
}
if ( ! defined( 'WP_SMUSH_STREAMS_CUTOFF_SIZE' ) ) {
define( 'WP_SMUSH_STREAMS_CUTOFF_SIZE', 5 * 1024 * 1024 ); // 5MB
}
if ( version_compare( PHP_VERSION, WP_SMUSH_MIN_PHP_VERSION, '<' ) ) {
if ( ! function_exists( 'wp_smush_php_deprecated_notice' ) ) {
function wp_smush_php_deprecated_notice() {
// Only show the deprecated notice for admin and only network side for MU site.
if ( ! current_user_can( 'manage_options' ) || ( is_multisite() && ! is_network_admin() ) ) {
return;
}
?>
<div class="notice notice-error is-dismissible">
<p>
<?php
printf(
wp_kses( /* translators: %1$s - Requires PHP version - %2$s URL to an article about our hosting benefits. */
__( 'Your site is running an outdated version of PHP that is no longer supported or receiving security updates. Please update PHP to at least version %1$s at your hosting provider in order to activate Smush, or consider switching to <a href="%2$s" target="_blank" rel="noopener noreferrer">WPMU DEV Hosting</a>.', 'wp-smushit' ),
array(
'a' => array(
'href' => array(),
'target' => array(),
'rel' => array(),
),
'strong' => array(),
)
),
esc_html( WP_SMUSH_MIN_PHP_VERSION ),
'https://wpmudev.com/hosting/'
);
?>
</p>
</div>
<?php
// Deactivate plugin.
deactivate_plugins( WP_SMUSH_BASENAME, false, is_network_admin() );
}
}
add_action( 'admin_notices', 'wp_smush_php_deprecated_notice' );
add_action( 'network_admin_notices', 'wp_smush_php_deprecated_notice' );
return;
}
/**
* To support Smushing on staging sites like SiteGround staging where staging site urls are different
* but redirects to main site url. Remove the protocols and www, and get the domain name.*
* If Set to false, WP Smush switch backs to the Old Sync Optimisation.
*/
$site_url = str_replace( array( 'http://', 'https://', 'www.' ), '', site_url() );
// Compat with WPMU DEV staging.
$wpmu_host = isset( $_SERVER['WPMUDEV_HOSTING_ENV'] ) && 'staging' === sanitize_text_field( wp_unslash( $_SERVER['WPMUDEV_HOSTING_ENV'] ) );
if ( ! defined( 'WP_SMUSH_ASYNC' ) ) {
if ( ( ! empty( $_SERVER['SERVER_NAME'] ) && 0 !== strpos( $site_url, sanitize_text_field( wp_unslash( $_SERVER['SERVER_NAME'] ) ) ) ) || $wpmu_host ) {
define( 'WP_SMUSH_ASYNC', false );
} else {
define( 'WP_SMUSH_ASYNC', true );
}
}
/**
* If we are activating a version, while having another present and activated.
* Leave in the Pro version, if it is available.
*
* @since 2.9.1
*/
if ( WP_SMUSH_BASENAME !== plugin_basename( __FILE__ ) ) {
$pro_installed = false;
if ( file_exists( WP_PLUGIN_DIR . '/wp-smush-pro/wp-smush.php' ) ) {
$pro_installed = true;
}
if ( ! function_exists( 'is_plugin_active' ) ) {
include_once ABSPATH . 'wp-admin/includes/plugin.php';
}
if ( is_plugin_active( 'wp-smush-pro/wp-smush.php' ) ) {
deactivate_plugins( plugin_basename( __FILE__ ) );
update_site_option( 'smush_deactivated', 1 );
return; // Return to avoid errors with free-dashboard module.
} elseif ( $pro_installed && is_plugin_active( WP_SMUSH_BASENAME ) ) {
deactivate_plugins( WP_SMUSH_BASENAME );
// If WordPress is already in the process of activating - return.
if ( defined( 'WP_SANDBOX_SCRAPING' ) && WP_SANDBOX_SCRAPING ) {
return;
}
activate_plugin( plugin_basename( __FILE__ ) );
}
}
/* @noinspection PhpIncludeInspection */
require_once WP_SMUSH_DIR . 'core/class-installer.php';
register_activation_hook( __FILE__, array( 'Smush\\Core\\Installer', 'smush_activated' ) );
register_deactivation_hook( __FILE__, array( 'Smush\\Core\\Installer', 'smush_deactivated' ) );
register_activation_hook( __FILE__, function () {
update_option( 'wp-smush-plugin-activated', true );
} );
// Init the plugin and load the plugin instance for the first time.
add_action( 'plugins_loaded', array( 'WP_Smush', 'get_instance' ) );
if ( ! class_exists( 'WP_Smush' ) ) {
/**
* Class WP_Smush
*/
final class WP_Smush {
/**
* Plugin instance.
*
* @since 2.9.0
* @var null|WP_Smush
*/
private static $instance = null;
/**
* Plugin core.
*
* @since 2.9.0
* @var Smush\Core\Core
*/
private $core;
/**
* Plugin admin.
*
* @since 2.9.0
* @var Smush\App\Admin
*/
private $admin;
/**
* Plugin API.
*
* @since 3.0
* @var Smush\Core\Api\Smush_API
*/
private $api = '';
/**
* Media library UI.
*
* @since 3.4.0
* @var Smush\App\Media_Library
*/
private $library;
/**
* @var Membership
*/
private static $membership;
/**
* Return the plugin instance.
*
* @return WP_Smush
*/
public static function get_instance() {
if ( ! self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* WP_Smush constructor.
*/
private function __construct() {
spl_autoload_register( array( $this, 'autoload' ) );
/**
* Include vendor dependencies
*/
require_once __DIR__ . '/vendor_prefixed/custom-autoload.php';
// Include the WP compatibility file.
require_once WP_SMUSH_DIR . 'core/wp-compat.php';
add_action( 'admin_init', array( '\\Smush\\Core\\Installer', 'upgrade_settings' ) );
add_action( 'current_screen', array( '\\Smush\\Core\\Installer', 'maybe_create_table' ) );
// We use priority 9 to avoid conflict with old free-dashboard module <= 2.0.4.
add_action( 'admin_init', array( $this, 'register_free_modules' ), 9 );
// The dash-notification actions are hooked into "init" with a priority of 10.
add_action( 'init', array( $this, 'register_pro_modules' ), 5 );
add_action( 'init', array( $this, 'do_plugin_activated_action' ) );
add_action( 'init', array( $this, 'load_cross_sell_module' ), 5 );
$this->init();
}
public function do_plugin_activated_action() {
$transient_key = 'wp-smush-plugin-activated';
if ( ! get_option( $transient_key ) ) {
return;
}
( new \Smush\Core\Modules\Background\Mutex( $transient_key ) )
->set_break_on_timeout( true )
->execute( function () use ( $transient_key ) {
// The get_option call we made above has added the "true" value to the cache,
// get_option is always going to return true even if the option was deleted in another thread,
// now we need use a thread safe method instead
$background_utils = new \Smush\Core\Modules\Background\Background_Utils();
if ( $background_utils->get_option( $transient_key, false ) ) {
do_action( 'wp_smush_plugin_activated' );
delete_option( $transient_key );
}
} );
}
/**
* Autoload method.
*
* @since 3.1.0
* @param string $class Class name to autoload.
*/
public function autoload( $class ) {
// Project-specific namespace prefix.
$prefix = 'Smush\\';
// Does the class use the namespace prefix?
$len = strlen( $prefix );
if ( 0 !== strncmp( $prefix, $class, $len ) ) {
// Maybe require some external classes.
$external_libs = array( 'WDEV_Logger' );
if ( in_array( $class, $external_libs, true ) ) {
$lib = str_replace( '_', '-', strtolower( $class ) );
$file = WP_SMUSH_DIR . "core/external/{$lib}/{$lib}.php";
if ( file_exists( $file ) ) {
require_once $file;
}
}
// No, move to the next registered autoloader.
return;
}
// Get namespace from the full class name.
$namespace = substr( $class, 0, strrpos( $class, '\\' ) );
// Get the relative class name.
$relative_class = substr( $class, $len );
$path = explode( '\\', strtolower( str_replace( '_', '-', $relative_class ) ) );
$file = array_pop( $path );
$file = WP_SMUSH_DIR . implode( '/', $path ) . '/class-' . $file . '.php';
// If the file exists, require it.
if ( file_exists( $file ) ) {
/* @noinspection PhpIncludeInspection */
require $file;
} else if (
in_array( $class, $this->shimmed(), true ) ||
in_array( $namespace, $this->shimmed(), true )
) {
// Define a shim class inline to prevent errors.
class_alias( '\\Smush\\Core\\Shim', $class );
}
}
private function shimmed() {
return array(
'Smush\Core\LCP',
'Smush\Core\CDN',
'Smush\Core\Modules\CDN',
'Smush\Core\Avif',
'Smush\Core\Webp',
'Smush\Core\Modules\WebP',
'Smush\Core\Next_Gen',
'Smush\Core\S3',
'Smush\Core\Integrations\S3',
'Smush\Core\Integrations\NextGen', // The class and the namespace are the same.
'Smush\Core\Integrations\Nextgen',
'Smush\Core\Png2Jpg',
'Smush\Core\Modules\Png2jpg',
'Smush\Core\Resize\Auto_Resizing_Controller',
'Smush\Core\Resize\Auto_Resizing_Transform',
'Smush\Core\Image_Dimensions',
);
}
/**
* Init core module.
*
* @since 2.9.0
*/
private function init() {
try {
$this->api = new Smush\Core\Api\Smush_API( self::get_membership()->get_apikey() );
} catch ( Exception $e ) {
$this->api = '';
}
// Handle failed items, load it before validate the install.
new Smush\Core\Error_Handler();
self::get_membership()->validate_install();
$this->core = new Smush\Core\Core();
$this->library = new Smush\App\Media_Library( $this->core() );
if ( is_admin() ) {
$this->library()->init_ui();
$this->admin = Smush\App\Admin::get_instance();
}
if ( defined( 'WP_CLI' ) && WP_CLI ) {
WP_CLI::add_command( 'smush', '\\Smush\\Core\\CLI\\CLI' );
}
}
/**
* Get membership instance.
*
* @return Membership
*/
private static function get_membership() {
if ( is_null( self::$membership ) ) {
self::$membership = Membership::get_instance();
}
return self::$membership;
}
/**
* Getter method for core.
*
* @since 2.9.0
*
* @return Smush\Core\Core
*/
public function core() {
return $this->core;
}
/**
* Getter method for core.
*
* @since 2.9.0
*
* @return Smush\App\Admin
*/
public function admin() {
return $this->admin;
}
/**
* Getter method for core.
*
* @since 3.0
*
* @return Smush\Core\Api\Smush_API
*/
public function api() {
return $this->api;
}
/**
* Getter method for library.
*
* @since 3.4.0
*
* @return Smush\App\Media_Library
*/
public function library() {
return $this->library;
}
public static function is_expired() {
_deprecated_function( __METHOD__, '3.23.5' );
}
public static function is_new_user() {
_deprecated_function( __METHOD__, '3.23.5' );
}
/**
* Verify the site is connected to TFH.
*
* @since 3.12.0
*
* @return boolean
*/
public static function is_site_connected_to_tfh() {
_deprecated_function( __METHOD__, '3.23.5' );
}
public static function is_member() {
_deprecated_function( __METHOD__, '3.23.5' );
}
/**
* Register submodules.
* Only for wordpress.org members.
*/
public function register_free_modules() {
if ( false === strpos( WP_SMUSH_DIR, 'wp-smushit' ) || class_exists( 'WPMUDEV_Dashboard' ) || file_exists( WP_PLUGIN_DIR . '/wpmudev-updates/update-notifications.php' ) ) {
return;
}
/* @noinspection PhpIncludeInspection */
require_once WP_SMUSH_DIR . 'core/external/plugin-notice/notice.php';
// Recommended plugin notice.
do_action(
'wpmudev-recommended-plugins-register-notice',
WP_SMUSH_BASENAME,
__( 'Smush', 'wp-smushit' ),
\Smush\App\Admin::$plugin_pages,
array( 'before', '.sui-wrap .sui-floating-notices, .sui-wrap .sui-upgrade-page' )
);
}
/**
* Appropriate menu position for cross-sell page based on multisite settings.
*
* For single sites, returns the default position (9).
* For multisite installations, calculates position based on network access settings.
*
*/
public function load_cross_sell_module() {
$cross_sell_plugin_file = WP_SMUSH_DIR . 'core/external/plugins-cross-sell-page/plugin-cross-sell.php';
if ( ! file_exists( $cross_sell_plugin_file ) ) {
return;
}
static $cross_sell_handler = null;
if ( ! is_null( $cross_sell_handler ) ) {
return;
}
if ( ! class_exists( '\WPMUDEV\Modules\Plugin_Cross_Sell' ) ) {
require_once $cross_sell_plugin_file;
}
$submenu_params = array(
'slug' => 'wp-smushit', // Required.
'parent_slug' => 'smush', // Required.
'menu_slug' => 'smush-cross-sell', // Optional - Strongly recommended to set in order to avoid admin page conflicts with other WPMU DEV plugins.
'position' => $this->cross_sell_module_menu_position(), // Optional Usually a specific position will be required.
'translation_dir' => WP_SMUSH_DIR . 'languages', // Optional The directory where the translation files are located.
);
$cross_sell_handler = new \WPMUDEV\Modules\Plugin_Cross_Sell( $submenu_params );
}
/**
* Determines the menu position for the Cross-Sell module based on multisite and network access settings.
*
* @return int Menu position for the admin menu.
*/
public function cross_sell_module_menu_position() {
$default_position = 7;
// Return default position if not multisite
if ( ! is_multisite() ) {
return $default_position;
}
// Get network access settings
$network_access = get_site_option( 'wp-smush-networkwide' );
// Return default position if networkwide access is disabled
if ( empty( $network_access ) || $network_access == 0 ) {
return $default_position;
}
// Determine base position: 4 if enabled for all sites, 3 if custom list.
$menu_position = ( 1 == $network_access ) ? 3 : 2;
// Adjust position based on number of sites with access
if ( is_array( $network_access ) ) {
$menu_position += max( 0, 5 - count( $network_access ) );
}
return $menu_position;
}
/**
* Register sub-modules.
* Only for WPMU DEV Members.
*/
public function register_pro_modules() {
if ( ! file_exists( WP_SMUSH_DIR . 'core/external/dash-notice/wpmudev-dash-notification.php' ) ) {
return;
}
// Register items for the dashboard plugin.
global $wpmudev_notices;
$wpmudev_notices[] = array(
'id' => 912164,
'name' => 'WP Smush Pro',
'screens' => array(
'upload',
),
);
/* @noinspection PhpIncludeInspection */
require_once WP_SMUSH_DIR . 'core/external/dash-notice/wpmudev-dash-notification.php';
}
}
}