Merged in feature/MAW-855-import-code-into-aws (pull request #2)

code import from pantheon

* code import from pantheon
This commit is contained in:
Tony Volpe
2023-12-04 23:08:14 +00:00
parent 8c9b1312bc
commit 8f4b5efda6
4766 changed files with 185592 additions and 239967 deletions
@@ -0,0 +1,6 @@
# Security Policy
## Reporting Security Bugs
Please report security bugs found in the site-reviews plugin's source code through the [Patchstack Vulnerability Disclosure Program](https://patchstack.com/database/vdp/imagify). The Patchstack team will assist you with verification, CVE assignment and take care of notifying the developers of this plugin.
---
@@ -0,0 +1,20 @@
/**
* @typedef {import('@roots/bud').Bud} Bud
*
* @param {Bud} bud
*/
module.exports = async bud => {
bud.externals({
jQuery: 'window.jquery',
wp: 'window.wp',
})
bud.runtime('single')
await bud
.setPath('@dist', '../assets/admin')
.entry({
chart: 'chart.js',
bulk: 'bulk.js',
})
//.when( bud.isProduction, () => bud.splitChunks().minimize() )
}
@@ -0,0 +1,15 @@
{
"name": "imagify_dev",
"version": "1.0.0",
"dependencies": {
},
"devDependencies": {
"@roots/bud": "^6.11.0",
"chart.js": "^4.4.0"
},
"scripts": {
"dev": "bud dev",
"build": "bud build",
"bud": "bud"
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,6 @@
import * as chart from 'chart.js/auto'
window.imagify = window.imagify || {};
window.imagify.Color = chart.Colors;
window.imagify.Chart = chart.Chart;
@@ -0,0 +1,14 @@
{
"chart": {
"js": [
"js/runtime.js",
"js/chart.js"
]
},
"bulk": {
"js": [
"js/runtime.js",
"js/bulk.js"
]
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
(()=>{"use strict";var r,e={},o={};function t(r){var n=o[r];if(void 0!==n)return n.exports;var s=o[r]={exports:{}};return e[r](s,s.exports,t),s.exports}t.m=e,r=[],t.O=(e,o,n,s)=>{if(!o){var a=1/0;for(u=0;u<r.length;u++){for(var[o,n,s]=r[u],i=!0,f=0;f<o.length;f++)(!1&s||a>=s)&&Object.keys(t.O).every((r=>t.O[r](o[f])))?o.splice(f--,1):(i=!1,s<a&&(a=s));if(i){r.splice(u--,1);var l=n();void 0!==l&&(e=l)}}return e}s=s||0;for(var u=r.length;u>0&&r[u-1][2]>s;u--)r[u]=r[u-1];r[u]=[o,n,s]},t.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={666:0};t.O.j=e=>0===r[e];var e=(e,o)=>{var n,s,[a,i,f]=o,l=0;if(a.some((e=>0!==r[e]))){for(n in i)t.o(i,n)&&(t.m[n]=i[n]);if(f)var u=f(t)}for(e&&e(o);l<a.length;l++)s=a[l],t.o(r,s)&&r[s]&&r[s][0](),r[s]=0;return t.O(u)},o=self.webpackChunk_roots_bud=self.webpackChunk_roots_bud||[];o.forEach(e.bind(null,0)),o.push=e.bind(null,o.push.bind(o))})()})();
@@ -0,0 +1,6 @@
{
"chart.js": "js/chart.js",
"bulk.js": "js/bulk.js",
"runtime.js": "js/runtime.js",
"entrypoints.json": "entrypoints.json"
}
@@ -160,3 +160,40 @@
color: #FFF;
text-shadow: 0 0 2px rgba(0, 0, 0, 0.2);
}
#wp-admin-bar-imagify-profile .imagify-upsell-admin-bar {
position:relative ;
background: #c51161;
margin: 10px -13px -10px -13px;
padding: 20px;
}
#wp-admin-bar-imagify-profile .imagify-upsell-admin-bar p {
color: #fff;
}
#wp-admin-bar-imagify-profile a.imagify-upsell-admin-bar-button {
display: block;
height: auto !important;
border: 1px solid #fff;
border-radius: 5px;
color: #fff !important;
padding: 5px 10px !important;
text-align: center;
text-decoration: none;
margin-top: 10px;
}
#wpadminbar #wp-admin-bar-imagify-profile a.imagify-upsell-dismiss {
display: inline !important;
height: auto !important;
}
#wpadminbar #wp-admin-bar-imagify-profile .imagify-upsell-dismiss::before {
position: absolute;
top: 5px;
right: 10px;
content: "\2715";
color: #fff;
}
@@ -1543,3 +1543,45 @@ ul.imagify-datas-details.imagify-datas-details {
padding-right: 0em;
}
}
.imagify-upsell {
position:relative;
background: #c51161;
padding: 20px 40px;
}
.imagify-upsell p {
color: #fff !important;
}
.imagify-upsell-button {
display: block;
background: #fff;
border-radius: 5px;
color: #c51161 !important;
font-weight: bold;
padding: 10px;
text-align: center;
text-decoration: none;
text-transform: uppercase;
}
.imagify-upsell-arrow::after {
content: '\2192';
font-size: large;
margin-left: 5px;
vertical-align: top;
}
.imagify-upsell-dismiss::before {
position: absolute;
top: 5px;
right: 5px;
content: "\2715";
color: #2e3243;
font-size: 2em;
}
.imagify-upsell .imagify-meteo-icon {
filter: invert(100%) sepia(100%) saturate(0%) hue-rotate(104deg) brightness(103%) contrast(103%);
}
@@ -330,7 +330,7 @@ body[class*="_imagify-ngg-bulk-optimization"] .media-item .progress .bar {
.imagify-col-content .imagify-meteo-icon {
height: 64px;
margin: 15px 15px 15px 20px;
margin: 15px 15px 15px 0;
}
.imagify-col-content .imagify-section-title + p {
@@ -936,3 +936,19 @@ input:checked + label .imagify-fake-checkbox:after,
margin-top: 20px;
}
}
.imagify-col-content .imagify-space-left {
margin: 15px 30px 15px 0;
}
.imagify-col-content .imagify-space-left p {
margin: 0 0 10px 0;
font-size: 19px;
font-weight: 500;
color: #343A49;
}
.imagify-col-content .imagify-meteo-icon {
height: 64px;
margin: 15px 15px 15px 0;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
*/
$( '.imagify-notice-dismiss' ).on( 'click.imagify', function( e ) {
var $this = $( this ),
$parent = $this.parents( '.imagify-welcome, .imagify-notice, .imagify-rkt-notice' ),
$parent = $this.parents( '.imagify-welcome, .imagify-notice, .imagify-rkt-notice, .imagify-upsell, .imagify-upsell-admin-bar' ),
href = $this.attr( 'href' );
e.preventDefault();
@@ -0,0 +1,81 @@
<?php
namespace Imagify\Admin;
use Imagify\Traits\InstanceGetterTrait;
use Imagify\User\User;
use Imagify_Views;
/**
* Admin bar handler
*/
class AdminBar {
use InstanceGetterTrait;
/**
* Launch the hooks.
*
* @return void
*/
public function init() {
if ( wp_doing_ajax() ) {
add_action( 'wp_ajax_imagify_get_admin_bar_profile', array( $this, 'get_admin_bar_profile_callback' ) );
}
}
/**
* Get admin bar profile output.
*
* @return void
*/
public function get_admin_bar_profile_callback() {
imagify_check_nonce( 'imagify-get-admin-bar-profile', 'imagifygetadminbarprofilenonce' );
if ( ! imagify_get_context( 'wp' )->current_user_can( 'manage' ) ) {
imagify_die();
}
$user = new User();
$views = Imagify_Views::get_instance();
$unconsumed_quota = $views->get_quota_percent();
$text = '';
$button_text = '';
$upgrade_link = '';
if ( $user->is_free() ) {
$text = esc_html__( 'Upgrade your plan now for more!', 'rocket' ) . '<br>' .
esc_html__( 'From $4.99/month only, keep going with image optimization!', 'rocket' );
$button_text = esc_html__( 'Upgrade My Plan', 'rocket' );
$upgrade_link = IMAGIFY_APP_DOMAIN . '/subscription/?utm_source=plugin&utm_medium=notification';
} elseif ( $user->is_growth() ) {
$text = esc_html__( 'Switch to Infinite plan for unlimited optimization:', 'rocket' ) . '<br>';
if ( $user->is_monthly ) {
$text .= esc_html__( 'For $9.99/month, optimize as many images as you like!', 'rocket' );
$upgrade_link = IMAGIFY_APP_DOMAIN . '/subscription/plan_switch/?label=infinite&payment_plan=1&utm_source=plugin&utm_medium=notification ';
} else {
$text .= esc_html__( 'For $99.9/year, optimize as many images as you like!', 'rocket' );
$upgrade_link = IMAGIFY_APP_DOMAIN . '/subscription/plan_switch/?label=infinite&payment_plan=2&utm_source=plugin&utm_medium=notification ';
}
$button_text = esc_html__( 'Switch To Infinite Plan', 'rocket' );
}
$data = [
'quota_icon' => $views->get_quota_icon(),
'quota_class' => $views->get_quota_class(),
'plan_label' => $user->plan_label,
'plan_with_quota' => $user->is_free() || $user->is_growth(),
'unconsumed_quota' => $unconsumed_quota,
'user_quota' => $user->quota,
'next_update' => $user->next_date_update,
'text' => $text,
'button_text' => $button_text,
'upgrade_link' => $upgrade_link,
];
$template = $views->get_template( 'admin/admin-bar-status', $data );
wp_send_json_success( $template );
}
}
@@ -413,13 +413,14 @@ class Bulk {
*
* @since 1.9
*
* @param string $method The method used: 'GET' (default), or 'POST'.
* @param string $parameter The name of the parameter to look for.
* @param string $method The method used: 'GET' (default), or 'POST'.
* @param string $parameter The name of the parameter to look for.
*
* @return string
*/
public function get_context( $method = 'GET', $parameter = 'context' ) {
$method = 'POST' === $method ? INPUT_POST : INPUT_GET;
$context = filter_input( $method, $parameter, FILTER_SANITIZE_STRING );
$context = 'POST' === $method ? wp_unslash( $_POST[ $parameter ] ) : wp_unslash( $_GET[ $parameter ] ); //phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
$context = htmlspecialchars( $context );
return imagify_sanitize_context( $context );
}
@@ -557,7 +558,7 @@ class Bulk {
public function bulk_get_stats_callback() {
imagify_check_nonce( 'imagify-bulk-optimize' );
$folder_types = filter_input( INPUT_GET, 'types', FILTER_SANITIZE_STRING, FILTER_REQUIRE_ARRAY );
$folder_types = filter_input( INPUT_GET, 'types', FILTER_REQUIRE_ARRAY );
$folder_types = is_array( $folder_types ) ? array_filter( $folder_types, 'is_string' ) : [];
if ( ! $folder_types ) {
@@ -95,6 +95,7 @@ class CustomFolders extends AbstractBulk {
$files_table = Imagify_Files_DB::get_instance()->get_table_name();
$folders_table = Imagify_Folders_DB::get_instance()->get_table_name();
$mime_types = Imagify_DB::get_mime_types( 'image' );
$mime_types = str_replace( ",'image/webp'", '', $mime_types );
$webp_suffix = constant( imagify_get_optimization_process_class_name( 'custom-folders' ) . '::WEBP_SUFFIX' );
$files = $wpdb->get_results( $wpdb->prepare( // WPCS: unprepared SQL ok.
"
@@ -184,6 +184,7 @@ class WP extends AbstractBulk {
$this->set_no_time_limit();
$mime_types = Imagify_DB::get_mime_types( 'image' );
$mime_types = str_replace( ",'image/webp'", '', $mime_types );
$statuses = Imagify_DB::get_post_statuses();
$nodata_join = Imagify_DB::get_required_wp_metadata_join_clause();
$nodata_where = Imagify_DB::get_required_wp_metadata_where_clause( [
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Imagify\Notices;
use Imagify\Traits\InstanceGetterTrait;
use Imagify\User\User;
/**
* Class that handles the admin notices.
@@ -66,8 +67,6 @@ class Notices {
'http-block-external',
// This warning is displayed when the grid view is active on the library. Dismissible.
'grid-view',
// This warning is displayed to warn the user that the quota is almost consumed for the current month. Dismissible.
'almost-over-quota',
// This warning is displayed if the backup folder is not writable. NOT dismissible.
'backup-folder-not-writable',
// This notice is displayed to rate the plugin after 100 optimizations & 7 days after the first installation. Dismissible.
@@ -76,6 +75,8 @@ class Notices {
'wp-rocket',
'bulk-optimization-complete',
'bulk-optimization-running',
'upsell-banner',
'upsell-admin-bar',
];
/**
@@ -250,7 +251,7 @@ class Notices {
public function renew_almost_over_quota_notice() {
global $wpdb;
$results = $wpdb->get_results( $wpdb->prepare( "SELECT umeta_id, user_id FROM $wpdb->usermeta WHERE meta_key = %s AND meta_value LIKE %s", self::DISMISS_META_NAME, '%almost-over-quota%' ) );
$results = $wpdb->get_results( $wpdb->prepare( "SELECT umeta_id, user_id FROM $wpdb->usermeta WHERE meta_key = %s AND meta_value LIKE %s", self::DISMISS_META_NAME, '%upsell%' ) );
if ( ! $results ) {
return;
@@ -271,7 +272,8 @@ class Notices {
// Renew the notice for all users.
foreach ( $results as $result ) {
self::renew_notice( 'almost-over-quota', $result->user_id );
self::renew_notice( 'upsell-banner', $result->user_id );
self::renew_notice( 'upsell-admin-bar', $result->user_id );
}
}
@@ -439,45 +441,6 @@ class Notices {
return $display;
}
/**
* Tell if the 'almost-over-quota' notice should be displayed.
*
* @since 1.7.0
*
* @return bool|object An Imagify user object. False otherwise.
*/
public function display_almost_over_quota() {
static $display;
if ( isset( $display ) ) {
return $display;
}
$display = false;
if ( ! $this->user_can( 'almost-over-quota' ) ) {
return $display;
}
if ( ! imagify_is_screen( 'imagify-settings' ) && ! imagify_is_screen( 'bulk' ) ) {
return $display;
}
if ( self::notice_is_dismissed( 'almost-over-quota' ) ) {
return $display;
}
$user = new \Imagify_User();
// Don't display the notice if the user's unconsumed quota is superior to 20%.
if ( $user->get_percent_unconsumed_quota() > 20 ) {
return $display;
}
$display = $user;
return $display;
}
/**
* Tell if the 'backup-folder-not-writable' notice should be displayed.
*
@@ -25,6 +25,7 @@ abstract class AbstractData implements DataInterface {
*/
protected $default_optimization_data = [
'status' => '',
'message' => '',
'level' => false,
'sizes' => [],
'stats' => [
@@ -159,6 +159,10 @@ class CustomFolders extends AbstractData {
$old_data['hash'] = md5_file( $file_path );
}
if ( key_exists( 'message', $data ) ) {
$old_data['message'] = $data['message'];
}
if ( ! $data['success'] ) {
/**
* Error.
@@ -93,8 +93,13 @@ class WP extends AbstractData {
'original_size' => 0,
'optimized_size' => 0,
'percent' => 0,
'message' => '',
], $old_data['stats'] );
if ( key_exists( 'message', $data ) ) {
$old_data['message'] = $data['message'];
}
if ( ! $data['success'] ) {
/**
* Error.
@@ -530,6 +530,10 @@ class File {
return new \WP_Error( 'temp_file_not_found', $temp_file->get_error_message() );
}
if ( property_exists( $response, 'message' ) ) {
$args['convert'] = '';
}
if ( 'webp' === $args['convert'] ) {
$destination_path = $this->get_path_to_webp();
$this->path = $destination_path;
@@ -656,6 +656,14 @@ abstract class AbstractProcess implements ProcessInterface {
'non_webp_file_path' => $sizes[ $thumb_size ]['path'], // Don't use $path nor $file->get_path(), it may return the path to a temporary file.
'optimization_level' => $optimization_level,
] );
if ( property_exists( $response, 'message' ) ) {
$path_is_temp = false;
if ( $path !== $sizes[ $thumb_size ]['path'] ) {
$this->filesystem->delete( $path );
}
$path = $sizes[ $thumb_size ]['path'];
}
}
}
}
@@ -731,7 +739,7 @@ abstract class AbstractProcess implements ProcessInterface {
}
// Optimization succeeded.
if ( $args['is_webp'] ) {
if ( ! property_exists( $args['response'], 'message' ) && $args['is_webp'] ) {
/**
* We just created a WebP version:
* Check if it is lighter than the (maybe optimized) non-WebP file.
@@ -776,7 +784,7 @@ abstract class AbstractProcess implements ProcessInterface {
$webp_size = $args['non_webp_thumb_size'] . static::WEBP_SUFFIX;
$webp_file_size = $this->get_data()->get_size_data( $webp_size, 'optimized_size' );
if ( ! $webp_file_size || $webp_file_size < $args['response']->new_size ) {
if ( property_exists( $args['response'], 'message' ) || ! $webp_file_size || $webp_file_size < $args['response']->new_size ) {
// The WebP file is lighter than this one.
return $args['response'];
}
@@ -1531,6 +1539,38 @@ abstract class AbstractProcess implements ProcessInterface {
return is_string( $data ) && strpos( $data, $needle );
}
/**
* Tell if the media has all WebP versions.
*
* @return bool
*/
public function is_full_webp() {
if ( ! $this->is_valid() ) {
return false;
}
if ( ! $this->get_media()->is_image() ) {
return false;
}
$data = $this->get_data()->get_optimization_data();
$sizes = $data['sizes'];
if ( empty( $sizes ) ) {
return false;
}
$keys = array_keys( $sizes );
$non_webp_keys = array_values(array_filter($keys, function ( $key ) {
return strpos( $key, static::WEBP_SUFFIX ) === false;
}));
return array_reduce($non_webp_keys, function ( $is_fully, $key ) use ( $sizes ) {
return key_exists( $key . self::WEBP_SUFFIX, $sizes ) && $is_fully;
}, true);
}
/**
* Tell if a WebP version can be created for the given file.
* Make sure the file is an image before using this method.
@@ -1757,6 +1797,9 @@ abstract class AbstractProcess implements ProcessInterface {
// Size data.
$data['success'] = true;
if ( property_exists( $response, 'message' ) ) {
$data['message'] = imagify_translate_api_message( $response->message );
}
$data['original_size'] = $response->original_size;
$data['optimized_size'] = $response->new_size;
}
@@ -1785,6 +1828,9 @@ abstract class AbstractProcess implements ProcessInterface {
*/
$data = (array) apply_filters( "imagify{$_unauthorized}_file_optimization_data", $data, $response, $size, $level, $this->get_data() );
if ( property_exists( $response, 'message' ) ) {
$size = str_replace( '@imagify-webp', '', $size );
}
// Store.
$this->get_data()->update_size_optimization_data( $size, $data );
@@ -274,6 +274,13 @@ interface ProcessInterface {
*/
public function is_size_webp( $size_name );
/**
* Tell if the media has all WebP versions.
*
* @return bool
*/
public function is_full_webp();
/**
* Tell if the media has WebP versions.
*
@@ -7,6 +7,7 @@ use Imagify\Bulk\Bulk;
use Imagify\CLI\BulkOptimizeCommand;
use Imagify\CLI\GenerateMissingWebpCommand;
use Imagify\Notices\Notices;
use Imagify\Admin\AdminBar;
/**
* Main plugin class.
@@ -56,6 +57,7 @@ class Plugin {
\Imagify\Job\MediaOptimization::get_instance()->init();
\Imagify\Stats\OptimizedMediaWithoutWebp::get_instance()->init();
Bulk::get_instance()->init();
AdminBar::get_instance()->init();
if ( is_admin() ) {
Notices::get_instance()->init();
@@ -0,0 +1,292 @@
<?php
namespace Imagify\User;
use Date;
use Imagify_Data;
use WP_Error;
/**
* Imagify User class.
*
* @since 1.0
*/
class User {
/**
* The Imagify user ID.
*
* @since 1.0
*
* @var string
*/
public $id;
/**
* The user email.
*
* @since 1.0
*
* @var string
*/
public $email;
/**
* The plan ID.
*
* @since 1.0
*
* @var int
*/
public $plan_id;
/**
* The plan label.
*
* @since 1.2
*
* @var string
*/
public $plan_label;
/**
* The total quota.
*
* @since 1.0
*
* @var int
*/
public $quota;
/**
* The total extra quota (Imagify Pack).
*
* @since 1.0
*
* @var int
*/
public $extra_quota;
/**
* The extra quota consumed.
*
* @since 1.0
*
* @var int
*/
public $extra_quota_consumed;
/**
* The current month consumed quota.
*
* @since 1.0
*
* @var int
*/
public $consumed_current_month_quota;
/**
* The next month date to credit the account.
*
* @since 1.1.1
*
* @var Date
*/
public $next_date_update;
/**
* If the account is activate or not.
*
* @since 1.0.1
*
* @var bool
*/
public $is_active;
/**
* If the account is monthly or yearly.
*
* @var bool
*/
public $is_monthly;
/**
* Store a \WP_Error object if the request to fetch the user data failed.
* False overwise.
*
* @var bool|WP_Error
* @since 1.9.9
*/
private $error;
/**
* The constructor.
*
* @since 1.0
*
* @return void
*/
public function __construct() {
$user = get_imagify_user();
if ( is_wp_error( $user ) ) {
$this->error = $user;
return;
}
$this->id = $user->id;
$this->email = $user->email;
$this->plan_id = (int) $user->plan_id;
$this->plan_label = ucfirst( $user->plan_label );
$this->quota = $user->quota;
$this->extra_quota = $user->extra_quota;
$this->extra_quota_consumed = $user->extra_quota_consumed;
$this->consumed_current_month_quota = $user->consumed_current_month_quota;
$this->next_date_update = $user->next_date_update;
$this->is_active = $user->is_active;
$this->is_monthly = $user->is_monthly;
$this->error = false;
}
/**
* Get the possible error returned when fetching user data.
*
* @return bool|WP_Error A \WP_Error object if the request to fetch the user data failed. False overwise.
* @since 1.9.9
*/
public function get_error() {
return $this->error;
}
/**
* Percentage of consumed quota, including extra quota.
*
* @since 1.0
*
* @return float|int
*/
public function get_percent_consumed_quota() {
static $done = false;
if ( $this->get_error() ) {
return 0;
}
$quota = $this->quota;
$consumed_quota = $this->consumed_current_month_quota;
if ( imagify_round_half_five( $this->extra_quota_consumed ) < $this->extra_quota ) {
$quota += $this->extra_quota;
$consumed_quota += $this->extra_quota_consumed;
}
if ( ! $quota || ! $consumed_quota ) {
$percent = 0;
} else {
$percent = 100 * $consumed_quota / $quota;
$percent = round( $percent, 1 );
$percent = min( max( 0, $percent ), 100 );
}
$percent = (float) $percent;
if ( $done ) {
return $percent;
}
$previous_percent = Imagify_Data::get_instance()->get( 'previous_quota_percent' );
// Percent is not 100% anymore.
if ( 100.0 === (float) $previous_percent && $percent < 100 ) {
/**
* Triggered when the consumed quota percent decreases below 100%.
*
* @since 1.7
* @author Grégory Viguier
*
* @param float|int $percent The current percentage of consumed quota.
*/
do_action( 'imagify_not_over_quota_anymore', $percent );
}
// Percent is not >= 80% anymore.
if ( ( (float) $previous_percent >= 80.0 && $percent < 80 ) ) {
/**
* Triggered when the consumed quota percent decreases below 80%.
*
* @since 1.7
* @author Grégory Viguier
*
* @param float|int $percent The current percentage of consumed quota.
* @param float|int $previous_percent The previous percentage of consumed quota.
*/
do_action( 'imagify_not_almost_over_quota_anymore', $percent, $previous_percent );
}
if ( (float) $previous_percent !== (float) $percent ) {
Imagify_Data::get_instance()->set( 'previous_quota_percent', $percent );
}
$done = true;
return $percent;
}
/**
* Count percent of unconsumed quota.
*
* @since 1.0
*
* @return float|int
*/
public function get_percent_unconsumed_quota() {
return 100 - $this->get_percent_consumed_quota();
}
/**
* Check if the user has a free account.
*
* @since 1.1.1
*
* @return bool
*/
public function is_free() {
return 1 === $this->plan_id;
}
/**
* Check if the user is a growth account
*
* @return bool
*/
public function is_growth() {
return ( 16 === $this->plan_id || 18 === $this->plan_id );
}
/**
* Check if the user is an infinite account
*
* @return bool
*/
public function is_infinite() {
return ( 15 === $this->plan_id || 17 === $this->plan_id );
}
/**
* Check if the user has consumed all his/her quota.
*
* @since 1.1.1
* @since 1.9.9 Return false if the request to fetch the user data failed.
*
* @return bool
*/
public function is_over_quota() {
if ( $this->get_error() ) {
return false;
}
return (
$this->is_free()
&&
floatval( 100 ) === round( $this->get_percent_consumed_quota() )
);
}
}
@@ -3,6 +3,7 @@ namespace Imagify\Webp\RewriteRules;
use Imagify\Notices\Notices;
use Imagify\Traits\InstanceGetterTrait;
use Imagify\WriteFile\AbstractWriteDirConfFile;
/**
* Display WebP images on the site with rewrite rules.
@@ -12,6 +13,13 @@ use Imagify\Traits\InstanceGetterTrait;
class Display {
use InstanceGetterTrait;
/**
* Configuration file writer.
*
* @var AbstractWriteDirConfFile
*/
protected $server_conf;
/**
* Option value.
*
+3 -3
View File
@@ -3,7 +3,7 @@
* Plugin Name: Imagify
* Plugin URI: https://wordpress.org/plugins/imagify/
* Description: Dramatically reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth using Imagify, the new most advanced image optimization tool.
* Version: 2.1.1
* Version: 2.1.3
* Requires at least: 5.3
* Requires PHP: 7.0
* Author: Imagify Optimize Images & Convert WebP
@@ -13,13 +13,13 @@
* Text Domain: imagify
* Domain Path: languages
*
* Copyright 2022 WP Media
* Copyright 2023 WP Media
*/
defined( 'ABSPATH' ) || die( 'Cheatin uh?' );
// Imagify defines.
define( 'IMAGIFY_VERSION', '2.1.1' );
define( 'IMAGIFY_VERSION', '2.1.3' );
define( 'IMAGIFY_SLUG', 'imagify' );
define( 'IMAGIFY_FILE', __FILE__ );
define( 'IMAGIFY_PATH', realpath( plugin_dir_path( IMAGIFY_FILE ) ) . '/' );
@@ -123,7 +123,9 @@ function _imagify_sort_attachments_by_status( $vars ) {
),
) );
$vars['post_mime_type'] = imagify_get_mime_types();
if ( ! key_exists( 'post_mime_type', $vars ) ) {
$vars['post_mime_type'] = imagify_get_mime_types();
}
return $vars;
}
@@ -18,6 +18,13 @@ abstract class Imagify_Abstract_Background_Process extends Imagify_WP_Background
*/
protected $prefix = 'imagify';
/**
* URL to query on.
*
* @var string
*/
protected $query_url = '';
/**
* Set to true to automatically displatch at the end of the page.
*
@@ -49,7 +49,6 @@ class Imagify_Admin_Ajax_Post extends Imagify_Admin_Ajax_Post_Deprecated {
// Account.
'imagify_signup',
'imagify_check_api_key_validity',
'imagify_get_admin_bar_profile',
'imagify_get_prices',
'imagify_check_coupon',
'imagify_get_discount',
@@ -220,13 +219,13 @@ class Imagify_Admin_Ajax_Post extends Imagify_Admin_Ajax_Post_Deprecated {
$process = imagify_get_optimization_process( $media_id, $context );
if ( ! $process->is_valid() ) {
return new \WP_Error( 'invalid_media', __( 'This media is not valid.', 'imagify' ) );
return new WP_Error( 'invalid_media', __( 'This media is not valid.', 'imagify' ) );
}
$data = $process->get_data();
if ( ! $data->is_already_optimized() ) {
return new \WP_Error( 'not_already_optimized', __( 'This media does not have the right optimization status.', 'imagify' ) );
return new WP_Error( 'not_already_optimized', __( 'This media does not have the right optimization status.', 'imagify' ) );
}
if ( ! $process->has_webp() ) {
@@ -237,7 +236,7 @@ class Imagify_Admin_Ajax_Post extends Imagify_Admin_Ajax_Post_Deprecated {
$deleted = $process->delete_webp_files();
if ( is_wp_error( $deleted ) ) {
return new \WP_Error( 'webp_not_deleted', __( 'Previous WebP files could not be deleted.', 'imagify' ) );
return new WP_Error( 'webp_not_deleted', __( 'Previous WebP files could not be deleted.', 'imagify' ) );
}
return true;
@@ -829,83 +828,6 @@ class Imagify_Admin_Ajax_Post extends Imagify_Admin_Ajax_Post_Deprecated {
wp_send_json_success();
}
/**
* Get admin bar profile output.
*
* @since 1.6.11
*/
public function imagify_get_admin_bar_profile_callback() {
imagify_check_nonce( 'imagify-get-admin-bar-profile', 'imagifygetadminbarprofilenonce' );
if ( ! imagify_get_context( 'wp' )->current_user_can( 'manage' ) ) {
imagify_die();
}
$user = new Imagify_User();
$views = Imagify_Views::get_instance();
$unconsumed_quota = $views->get_quota_percent();
$message = '';
if ( $unconsumed_quota <= 20 ) {
$message = '<div class="imagify-error">';
$message .= '<p><i class="dashicons dashicons-warning" aria-hidden="true"></i><strong>' . __( 'Oops, It\'s almost over!', 'imagify' ) . '</strong></p>';
/* translators: %s is a line break. */
$message .= '<p>' . sprintf( __( 'You have almost used all your credit.%sDon\'t forget to upgrade your subscription to continue optimizing your images.', 'imagify' ), '<br/><br/>' ) . '</p>';
$message .= '<p class="center txt-center text-center"><a class="btn imagify-btn-ghost" href="' . esc_url( imagify_get_external_url( 'subscription' ) ) . '" target="_blank">' . __( 'View My Subscription', 'imagify' ) . '</a></p>';
$message .= '</div>';
}
if ( 0 === $unconsumed_quota ) {
$message = '<div class="imagify-error">';
$message .= '<p><i class="dashicons dashicons-warning" aria-hidden="true"></i><strong>' . __( 'Oops, It\'s Over!', 'imagify' ) . '</strong></p>';
$message .= '<p>' . sprintf(
/* translators: 1 is a data quota, 2 is a date. */
__( 'You have consumed all your credit for this month. You will have <strong>%1$s back on %2$s</strong>.', 'imagify' ),
imagify_size_format( $user->quota * pow( 1024, 2 ) ),
date_i18n( get_option( 'date_format' ), strtotime( $user->next_date_update ) )
) . '</p>';
$message .= '<p class="center txt-center text-center"><a class="btn imagify-btn-ghost" href="' . esc_url( imagify_get_external_url( 'subscription' ) ) . '" target="_blank">' . __( 'Upgrade My Subscription', 'imagify' ) . '</a></p>';
$message .= '</div>';
}
// Custom HTML.
$quota_section = '<div class="imagify-admin-bar-quota">';
$quota_section .= '<div class="imagify-abq-row">';
if ( 1 === $user->plan_id ) {
$quota_section .= '<div class="imagify-meteo-icon">' . $views->get_quota_icon() . '</div>';
}
$quota_section .= '<div class="imagify-account">';
$quota_section .= '<p class="imagify-meteo-title">' . __( 'Account status', 'imagify' ) . '</p>';
$quota_section .= '<p class="imagify-meteo-subs">' . __( 'Your subscription:', 'imagify' ) . '&nbsp;<strong class="imagify-user-plan">' . $user->plan_label . '</strong></p>';
$quota_section .= '</div>'; // .imagify-account
$quota_section .= '</div>'; // .imagify-abq-row
if ( 1 === $user->plan_id ) {
$quota_section .= '<div class="imagify-abq-row">';
$quota_section .= '<div class="imagify-space-left">';
/* translators: %s is a data quota. */
$quota_section .= '<p>' . sprintf( __( 'You have %s space credit left', 'imagify' ), '<span class="imagify-unconsumed-percent">' . $unconsumed_quota . '%</span>' ) . '</p>';
$quota_section .= '<div class="' . $views->get_quota_class() . '">';
$quota_section .= '<div style="width: ' . $unconsumed_quota . '%;" class="imagify-unconsumed-bar imagify-progress"></div>';
$quota_section .= '</div>'; // .imagify-bar-{negative|neutral|positive}
$quota_section .= '</div>'; // .imagify-space-left
$quota_section .= '</div>'; // .imagify-abq-row
}
$quota_section .= '<p class="imagify-abq-row">';
$quota_section .= '<a class="imagify-account-link" href="' . esc_url( imagify_get_external_url( 'subscription' ) ) . '" target="_blank">';
$quota_section .= '<span class="dashicons dashicons-admin-users"></span>';
$quota_section .= '<span class="button-text">' . __( 'View my subscription', 'imagify' ) . '</span>';
$quota_section .= '</a>'; // .imagify-account-link
$quota_section .= '</p>'; // .imagify-abq-row
$quota_section .= '</div>'; // .imagify-admin-bar-quota
$quota_section .= $message;
wp_send_json_success( $quota_section );
}
/**
* Get pricings from API for Onetime and Plans at the same time.
*
@@ -1148,7 +1070,7 @@ class Imagify_Admin_Ajax_Post extends Imagify_Admin_Ajax_Post_Deprecated {
imagify_die();
}
$notice = filter_input( INPUT_GET, 'ad', FILTER_SANITIZE_STRING );
$notice = htmlspecialchars( wp_unslash( $_GET['ad'] ) );
if ( ! $notice ) {
imagify_maybe_redirect();
@@ -1215,8 +1137,8 @@ class Imagify_Admin_Ajax_Post extends Imagify_Admin_Ajax_Post_Deprecated {
* @return string
*/
public function get_context( $method = 'GET', $parameter = 'context' ) {
$method = 'POST' === $method ? INPUT_POST : INPUT_GET;
$context = filter_input( $method, $parameter, FILTER_SANITIZE_STRING );
$context = 'POST' === $method ? wp_unslash( $_POST[ $parameter ] ) : wp_unslash( $_GET[ $parameter ] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
$context = htmlspecialchars( $context );
return imagify_sanitize_context( $context );
}
@@ -1246,14 +1168,15 @@ class Imagify_Admin_Ajax_Post extends Imagify_Admin_Ajax_Post_Deprecated {
*
* @since 1.9
*
* @param string $method The method used: 'GET' (default), or 'POST'.
* @param string $parameter The name of the parameter to look for.
* @param string $method The method used: 'GET' (default), or 'POST'.
* @param string $parameter The name of the parameter to look for.
*
* @return string
*/
public function get_folder_type( $method = 'GET', $parameter = 'folder_type' ) {
$method = 'POST' === $method ? INPUT_POST : INPUT_GET;
$folder_type = 'POST' === $method ? wp_unslash( $_POST[ $parameter ] ) : wp_unslash( $_GET[ $parameter ] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
return filter_input( $method, $parameter, FILTER_SANITIZE_STRING );
return htmlspecialchars( $folder_type );
}
/**
@@ -1261,13 +1184,14 @@ class Imagify_Admin_Ajax_Post extends Imagify_Admin_Ajax_Post_Deprecated {
*
* @since 1.9
*
* @param string $method The method used: 'GET' (default), or 'POST'.
* @param string $parameter The name of the parameter to look for.
* @param string $method The method used: 'GET' (default), or 'POST'.
* @param string $parameter The name of the parameter to look for.
*
* @return string
*/
public function get_imagify_action( $method = 'GET', $parameter = 'imagify_action' ) {
$method = 'POST' === $method ? INPUT_POST : INPUT_GET;
$action = filter_input( $method, $parameter, FILTER_SANITIZE_STRING );
$action = 'POST' === $method ? wp_unslash( $_POST[ $parameter ] ) : wp_unslash( $_GET[ $parameter ] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
$action = htmlspecialchars( $action );
return $action ? $action : 'optimize';
}
@@ -186,7 +186,8 @@ class Imagify_Assets extends Imagify_Assets_Deprecated {
$this->register_script( 'sweetalert', 'sweetalert2', [ 'promise-polyfill' ], '4.6.6' )->localize( 'imagifySwal' );
$this->register_script( 'chart', 'chart', [], '2.7.1.0' );
$this->register_bud_script( 'runtime', 'runtime' );
$this->register_bud_script( 'chart', 'chart', [ 'runtime' ], '4.4.0' );
$this->register_script( 'event-move', 'jquery.event.move', [ 'jquery' ], '2.0.1' );
@@ -211,7 +212,7 @@ class Imagify_Assets extends Imagify_Assets_Deprecated {
$this->register_script( 'async', 'imagify-gulp' );
$this->register_script( 'bulk', 'bulk', [ 'jquery', 'beat', 'underscore', 'chart', 'sweetalert', 'async', 'admin' ] )->defer_localization( 'imagifyBulk' );
$this->register_bud_script( 'bulk', 'bulk', [ 'jquery', 'beat', 'underscore', 'chart', 'sweetalert', 'async', 'admin' ] )->defer_localization( 'imagifyBulk' );
$this->register_script( 'options', 'options', [ 'jquery', 'beat', 'sweetalert', 'underscore', 'admin' ] )->defer_localization( 'imagifyOptions' );
@@ -459,6 +460,42 @@ class Imagify_Assets extends Imagify_Assets_Deprecated {
return $this;
}
/**
* Register a script.
*
* @since 1.6.10
*
* @param string $handle Name of the script. Should be unique.
* @param string|null $file_name The file name, without the extension. If null, $handle is used.
* @param array $dependencies An array of registered script handles this script depends on.
* @param string|null $version String specifying script version number. If set to null, the plugin version is used. If SCRIPT_DEBUG is true, a random string is used.
* @return object This class instance.
*/
public function register_bud_script( $handle, $file_name = null, $dependencies = [], $version = null ) {
// If we register it, it's one of our scripts.
$this->scripts[ $handle ] = 1;
// Set the current handler and handler type.
$this->current_handle = $handle;
$this->current_handle_type = 'js';
$file_name = $file_name ? $file_name : $handle;
$version = $version ? $version : IMAGIFY_VERSION;
$version = $this->is_debug() ? self::$version : $version;
$extension = '.js';
$handle = self::JS_PREFIX . $handle;
$dependencies = $this->prefix_dependencies( $dependencies );
wp_register_script(
$handle,
IMAGIFY_URL . 'assets/admin/js/' . $file_name . $extension,
$dependencies,
$version,
true
);
return $this;
}
/**
* Enqueue a script.
*
@@ -159,18 +159,20 @@ class Imagify_DB {
* It returns an empty string if the database has no attachments without the required metadada.
* It also triggers Imagify_DB::unlimit_joins().
*
* @since 1.7
* @access public
* @author Grégory Viguier
*
* @param string $id_field An ID field to match the metadata ID against in the JOIN clause.
* @param string $id_field An ID field to match the metadata ID against in the JOIN clause.
* Default is the posts table `ID` field, using the `p` alias: `p.ID`.
* In case of "false" value or PEBKAC, fallback to the same field without alias.
* @param bool $matching Set to false to get a query to fetch metas NOT matching the file extensions.
* @param bool $test Test if the site has attachments without required metadata before returning the query. False to bypass the test and get the query anyway.
* @param bool $matching Set to false to get a query to fetch metas NOT matching the file extensions.
* @param bool $test Test if the site has attachments without required metadata before returning the query. False to bypass the test and get the query anyway.
* @param string $special_join_conditions Special conditions to apply on the join.
*
* @return string
* @author Grégory Viguier
*
* @since 1.7
* @access public
*/
public static function get_required_wp_metadata_join_clause( $id_field = 'p.ID', $matching = true, $test = true ) {
public static function get_required_wp_metadata_join_clause( $id_field = 'p.ID', $matching = true, $test = true, $special_join_conditions = '' ) {
global $wpdb;
if ( $test && ! imagify_has_attachments_without_required_metadata() ) {
@@ -186,7 +188,16 @@ class Imagify_DB {
$join = $matching ? 'INNER' : 'LEFT';
$first = true;
foreach ( self::get_required_wp_metadata_aliases() as $meta_name => $alias ) {
if ( $first ) {
$first = false;
$clause .= "
$join JOIN $wpdb->postmeta AS $alias
ON ( $id_field = $alias.post_id AND $alias.meta_key = '$meta_name' $special_join_conditions )";
continue;
}
$clause .= "
$join JOIN $wpdb->postmeta AS $alias
ON ( $id_field = $alias.post_id AND $alias.meta_key = '$meta_name' )";
@@ -299,6 +310,9 @@ class Imagify_DB {
$extensions = array_keys( imagify_get_mime_types() );
$extensions = implode( '|', $extensions );
$extensions = explode( '|', $extensions );
$extensions = array_map(function ( $ex ) {
return strrev( $ex );
}, $extensions);
}
if ( ! $alias ) {
@@ -312,10 +326,12 @@ class Imagify_DB {
return $prepared ? str_replace( '%', '%%', $query[ $key ] ) : $query[ $key ];
}
$regex = '^' . implode( '\..*|^', $extensions ) . '\..*';
if ( $matching ) {
$query[ $key ] = "AND ( LOWER( $alias.meta_value ) LIKE '%." . implode( "' OR LOWER( $alias.meta_value ) LIKE '%.", $extensions ) . "' )";
$query[ $key ] = "AND REVERSE (LOWER( $alias.meta_value )) REGEXP '$regex'";
} else {
$query[ $key ] = "OR ( LOWER( $alias.meta_value ) NOT LIKE '%." . implode( "' AND LOWER( $alias.meta_value ) NOT LIKE '%.", $extensions ) . "' )";
$query[ $key ] = "AND REVERSE (LOWER( $alias.meta_value )) NOT REGEXP '$regex'";
}
return $prepared ? str_replace( '%', '%%', $query[ $key ] ) : $query[ $key ];
@@ -62,7 +62,7 @@ class Imagify_Files_Iterator extends FilterIterator {
*
* @return bool Returns whether the current element of the iterator is acceptable through this filter.
*/
public function accept() {
public function accept(): bool {
static $extensions, $has_extension_method;
$file_path = $this->current()->getPathname();
@@ -4,62 +4,54 @@ defined( 'ABSPATH' ) || die( 'Cheatin uh?' );
/**
* Class that display the "custom folders" files.
*
* @package Imagify
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*/
class Imagify_Files_List_Table extends WP_List_Table {
/**
* Class version.
*
* @var string
* @var string
* @since 1.7
* @author Grégory Viguier
*/
const VERSION = '1.1';
/**
* Class version.
*
* @var string
* @var string
* @since 1.7
* @author Grégory Viguier
*/
const PER_PAGE_OPTION = 'imagify_files_per_page';
/**
* List of the folders containing the listed files.
*
* @var array
* @since 1.7
* @author Grégory Viguier
* @var array
* @since 1.7
*/
protected $folders = array();
/**
* Filesystem object.
*
* @var object Imagify_Filesystem
* @since 1.7.1
* @author Grégory Viguier
* @var Imagify_Filesystem
* @since 1.7.1
*/
protected $filesystem;
/**
* Views object.
*
* @var object Imagify_Views
* @since 1.9
* @author Grégory Viguier
* @var Imagify_Views
* @since 1.9
*/
protected $views;
/**
* Constructor.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param array $args An associative array of arguments.
*/
@@ -80,8 +72,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Prepares the list of items for displaying.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*/
public function prepare_items() {
global $wpdb;
@@ -108,8 +99,8 @@ class Imagify_Files_List_Table extends WP_List_Table {
$file_ids = array();
$where = '';
$sent_orderby = filter_input( INPUT_GET, 'orderby', FILTER_SANITIZE_STRING );
$sent_order = filter_input( INPUT_GET, 'order', FILTER_SANITIZE_STRING );
$sent_orderby = isset( $_GET['orderby'] ) ? htmlspecialchars( wp_unslash( $_GET['orderby'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
$sent_order = isset( $_GET['order'] ) ? htmlspecialchars( wp_unslash( $_GET['order'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
$folder_filter = self::get_folder_filter();
$status_filter = self::get_status_filter();
@@ -227,8 +218,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Message to be displayed when there are no items.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*/
public function no_items() {
if ( self::get_status_filter() ) {
@@ -295,8 +285,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Display views.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*/
public function views() {
global $wpdb;
@@ -412,8 +401,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Get an associative array ( option_name => option_title ) with the list of bulk actions available on this table.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @return array
*/
@@ -427,8 +415,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
* Get a list of columns. The format is:
* 'internal-name' => 'Title'
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @return array
*/
@@ -452,8 +439,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
*
* The second format will make the initial sorting order be descending.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @return array
*/
@@ -469,8 +455,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Get a column contents.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param string $column The column "name": "cb", "title", "optimization_level", etc.
* @param object $item The current item. It must contain at least a $process property.
@@ -489,8 +474,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Handles the checkbox column output.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -505,8 +489,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Handles the title column output.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -555,8 +538,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Handles the parent folder column output.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -590,8 +572,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Handles the optimization data column output.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -642,8 +623,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Handles the status column output.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -677,8 +657,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Handles the optimization level column output.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -693,8 +672,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Handles the actions column output.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -730,8 +708,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Prints a button to optimize the file.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -758,8 +735,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Prints a button to retry to optimize the file.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -789,8 +765,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Prints buttons to re-optimize the file to other levels.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -833,8 +808,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Prints a button to generate WebP versions if they are missing.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -849,8 +823,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Prints a button to delete WebP versions when the status is "already_optimized".
*
* @since 1.9.6
* @author Grégory Viguier
* @since 1.9.6
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -865,8 +838,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Prints a button to restore the file.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -888,8 +860,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Prints a button to check if the file has been modified or not.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -905,8 +876,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Prints a button for the comparison tool (before / after optimization).
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
*/
@@ -952,8 +922,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
* Add the folder_id and folder_path properties to the $item if not set yet.
* It may happen if the $item doesn't come from the prepare() method.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param object $item The current item. It must contain at least a $process property.
* @return object The current item.
@@ -988,8 +957,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Get the name of the default primary column.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @return string Name of the default primary column, in this case, 'title'.
*/
@@ -1000,8 +968,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Get a list of CSS classes for the WP_List_Table table tag.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @return array List of CSS classes for the table tag.
*/
@@ -1012,8 +979,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Allow to save the screen options when submitted by the user.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @param bool|int $status Screen option value. Default false to skip.
* @param string $option The option name.
@@ -1031,8 +997,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Get the requested folder filter.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @return string
*/
@@ -1050,8 +1015,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
/**
* Get the requested status filter.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*
* @return string
*/
@@ -1067,7 +1031,7 @@ class Imagify_Files_List_Table extends WP_List_Table {
'unoptimized' => 1,
'errors' => 1,
);
$filter = trim( filter_input( INPUT_GET, 'status-filter', FILTER_SANITIZE_STRING ) );
$filter = isset( $_GET['status-filter'] ) ? trim( htmlspecialchars( wp_unslash( $_GET['status-filter'] ) ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
$filter = isset( $values[ $filter ] ) ? $filter : '';
return $filter;
@@ -52,7 +52,7 @@ class Imagify_Files_Recursive_Iterator extends RecursiveFilterIterator {
*
* @return bool Returns whether the current element of the iterator is acceptable through this filter.
*/
public function accept() {
public function accept(): bool {
static $extensions, $has_extension_method;
$file_path = $this->current()->getPathname();
@@ -1,4 +1,7 @@
<?php
use Imagify\User\User;
defined( 'ABSPATH' ) || die( 'Cheatin uh?' );
/**
@@ -303,7 +306,7 @@ class Imagify_Requirements {
return self::$supports['over_quota'];
}
$user = new Imagify_User();
$user = new User();
self::$supports['over_quota'] = $user->get_error() ? false : $user->is_over_quota();
@@ -131,9 +131,12 @@ class Imagify_Settings {
* @return bool
*/
public function is_form_submit() {
return filter_input( INPUT_POST, 'option_page', FILTER_SANITIZE_STRING ) === $this->settings_group && filter_input( INPUT_POST, 'action', FILTER_SANITIZE_STRING ) === 'update';
}
if ( ! isset( $_POST['option_page'], $_POST['action'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
return false;
}
return htmlspecialchars( wp_unslash( $_POST['option_page'] ) ) === $this->settings_group && htmlspecialchars( wp_unslash( $_POST['action'] ) ) === 'update'; // phpcs:ignore WordPress.Security.NonceVerification.Missing
}
/** ----------------------------------------------------------------------------------------- */
/** ON FORM SUBMIT ========================================================================== */
@@ -1,18 +1,20 @@
<?php
use Imagify\User\User;
defined( 'ABSPATH' ) || die( 'Cheatin uh?' );
/**
* Class that handles templates and menus.
*
* @since 1.7
* @author Grégory Viguier
* @since 1.7
*/
class Imagify_Views {
/**
* Class version.
*
* @var string
* @var string
* @since 1.7
*/
const VERSION = '1.1';
@@ -20,64 +22,56 @@ class Imagify_Views {
/**
* Slug used for the settings page URL.
*
* @var string
* @since 1.7
* @access protected
* @var string
* @since 1.7
*/
protected $slug_settings;
/**
* Slug used for the bulk optimization page URL.
*
* @var string
* @since 1.7
* @access protected
* @var string
* @since 1.7
*/
protected $slug_bulk;
/**
* Slug used for the "custom folders" page URL.
*
* @var string
* @since 1.7
* @access protected
* @var string
* @since 1.7
*/
protected $slug_files;
/**
* A list of JS templates to print at the end of the page.
*
* @var array
* @since 1.9
* @access protected
* @var array
* @since 1.9
*/
protected $templates_in_footer = [];
/**
* Stores the "custom folders" files list instance.
*
* @var object Imagify_Files_List_Table
* @since 1.7
* @access protected
* @var Imagify_Files_List_Table
* @since 1.7
*/
protected $list_table;
/**
* Filesystem object.
*
* @var object Imagify_Filesystem
* @since 1.7.1
* @access protected
* @author Grégory Viguier
* @var Imagify_Filesystem
* @since 1.7.1
*/
protected $filesystem;
/**
* The single instance of the class.
*
* @var object
* @since 1.7
* @access protected
* @var object
* @since 1.7
*/
protected static $_instance;
@@ -89,9 +83,7 @@ class Imagify_Views {
/**
* The constructor.
*
* @since 1.7
* @author Grégory Viguier
* @access protected
* @since 1.7
*/
protected function __construct() {
$this->slug_settings = IMAGIFY_SLUG;
@@ -103,9 +95,7 @@ class Imagify_Views {
/**
* Get the main Instance.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*
* @return object Main instance.
*/
@@ -120,9 +110,7 @@ class Imagify_Views {
/**
* Launch the hooks.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*/
public function init() {
// Menu items.
@@ -152,9 +140,7 @@ class Imagify_Views {
/**
* Add sub-menus for all sites.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*/
public function add_site_menus() {
$wp_context = imagify_get_context( 'wp' );
@@ -187,9 +173,7 @@ class Imagify_Views {
/**
* Add menu and sub-menus in the network admin when Imagify is network-activated.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*/
public function add_network_menus() {
global $submenu;
@@ -232,9 +216,7 @@ class Imagify_Views {
/**
* Add links to the plugin row in the plugins list.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*
* @param array $actions An array of action links.
* @return array
@@ -254,9 +236,7 @@ class Imagify_Views {
/**
* The main settings page.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*/
public function display_settings_page() {
$this->print_template( 'page-settings' );
@@ -265,9 +245,7 @@ class Imagify_Views {
/**
* The bulk optimization page.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*/
public function display_bulk_page() {
$types = array();
@@ -363,9 +341,7 @@ class Imagify_Views {
/**
* The page displaying the "custom folders" files.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*/
public function display_files_list() {
$this->print_template( 'page-files-list' );
@@ -374,9 +350,7 @@ class Imagify_Views {
/**
* Initiate the "custom folders" list table data.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*/
public function load_files_list() {
// Instantiate the list.
@@ -396,9 +370,7 @@ class Imagify_Views {
/**
* Get the settings page slug.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*
* @return string
*/
@@ -409,9 +381,7 @@ class Imagify_Views {
/**
* Get the bulk optimization page slug.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*
* @return string
*/
@@ -422,9 +392,7 @@ class Imagify_Views {
/**
* Get the "custom folders" files page slug.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*
* @return string
*/
@@ -440,16 +408,14 @@ class Imagify_Views {
/**
* Tell if were displaying the settings page.
*
* @since 1.9
* @author Grégory Viguier
* @access public
* @since 1.9
*
* @return bool
*/
public function is_settings_page() {
global $pagenow;
$page = filter_input( INPUT_GET, 'page', FILTER_SANITIZE_STRING );
$page = htmlspecialchars( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
if ( $this->get_settings_page_slug() !== $page ) {
return false;
@@ -465,16 +431,14 @@ class Imagify_Views {
/**
* Tell if were displaying the bulk optimization page.
*
* @since 1.9
* @author Grégory Viguier
* @access public
* @since 1.9
*
* @return bool
*/
public function is_bulk_page() {
global $pagenow;
$page = filter_input( INPUT_GET, 'page', FILTER_SANITIZE_STRING );
$page = htmlspecialchars( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
return 'upload.php' === $pagenow && $this->get_bulk_page_slug() === $page;
}
@@ -482,16 +446,14 @@ class Imagify_Views {
/**
* Tell if were displaying the custom files list page.
*
* @since 1.9
* @author Grégory Viguier
* @access public
* @since 1.9
*
* @return bool
*/
public function is_files_page() {
global $pagenow;
$page = filter_input( INPUT_GET, 'page', FILTER_SANITIZE_STRING );
$page = htmlspecialchars( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
return 'upload.php' === $pagenow && $this->get_files_page_slug() === $page;
}
@@ -499,26 +461,20 @@ class Imagify_Views {
/**
* Tell if were displaying the WP media library page.
*
* @since 1.9
* @author Grégory Viguier
* @access public
* @since 1.9
*
* @return bool
*/
public function is_wp_library_page() {
global $pagenow;
$page = filter_input( INPUT_GET, 'page', FILTER_SANITIZE_STRING );
return 'upload.php' === $pagenow && ! $page;
return 'upload.php' === $pagenow && ! isset( $_GET['page'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
/**
* Tell if were displaying a media page.
*
* @since 1.9
* @author Grégory Viguier
* @access public
* @since 1.9
*
* @return bool
*/
@@ -536,9 +492,7 @@ class Imagify_Views {
/**
* Get the remaining quota in percent.
*
* @since 1.8.1
* @author Grégory Viguier
* @access public
* @since 1.8.1
*
* @return int
*/
@@ -549,7 +503,7 @@ class Imagify_Views {
return $quota;
}
$user = new Imagify_User();
$user = new User();
$quota = $user->get_percent_unconsumed_quota();
return $quota;
@@ -558,9 +512,7 @@ class Imagify_Views {
/**
* Get the HTML class used for the quota (to change the color when out of quota for example).
*
* @since 1.8.1
* @author Grégory Viguier
* @access public
* @since 1.8.1
*
* @return string
*/
@@ -588,9 +540,7 @@ class Imagify_Views {
/**
* Get the HTML tag used for the quota (the weather-like icon).
*
* @since 1.8.1
* @author Grégory Viguier
* @access public
* @since 1.8.1
*
* @return string
*/
@@ -622,9 +572,7 @@ class Imagify_Views {
/**
* Get a template contents.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*
* @param string $template The template name.
* @param mixed $data Some data to pass to the template.
@@ -648,9 +596,7 @@ class Imagify_Views {
/**
* Print a template.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*
* @param string $template The template name.
* @param mixed $data Some data to pass to the template.
@@ -662,9 +608,7 @@ class Imagify_Views {
/**
* Add a template to the list of JS templates to print at the end of the page.
*
* @since 1.7
* @author Grégory Viguier
* @access public
* @since 1.7
*
* @param string $template The template name.
*/
@@ -691,9 +635,7 @@ class Imagify_Views {
/**
* Print the JS templates that have been added to the "queue".
*
* @since 1.9
* @author Grégory Viguier
* @access public
* @since 1.9
*/
public function print_js_templates() {
if ( ! $this->templates_in_footer ) {
@@ -717,9 +659,7 @@ class Imagify_Views {
/**
* Create HTML attributes from an array.
*
* @since 1.9
* @access public
* @author Grégory Viguier
* @since 1.9
*
* @param array $attributes A list of attribute pairs.
* @return string HTML attributes.
@@ -436,6 +436,19 @@ class Imagify {
return new WP_Error( 'curl', 'cURL isn\'t installed on the server.' );
}
/**
* Allows to mock Imagify calls to the API.
*
* @param stdClass|null $response Response from the call.
* @param string $url URL from the call.
* @param array $args Arguments from the call.
*/
$response = apply_filters( 'pre_imagify_request', null, $url, $args );
if ( $response ) {
return $response;
}
try {
$url = self::API_ENDPOINT . $url;
$ch = curl_init();
@@ -1,4 +1,7 @@
<?php
use Imagify\User\User;
defined( 'ABSPATH' ) || die( 'Cheatin uh?' );
if ( class_exists( 'C_NextGEN_Bootstrap' ) && class_exists( 'Mixin' ) && get_site_option( 'ngg_options' ) ) :
@@ -60,7 +63,7 @@ if ( class_exists( 'C_NextGEN_Bootstrap' ) && class_exists( 'Mixin' ) && get_sit
add_filter( 'imagify_count_saving_data', 'imagify_ngg_count_saving_data', 8 );
$saving_data = imagify_count_saving_data();
$user = new Imagify_User();
$user = new User();
$response['imagify_bulk_data'] = array(
// User account.
@@ -1,9 +1,10 @@
<?php
/**
* Imagify User class.
* Deprecated class that handles Imagify User class.
*
* @since 1.0
* @deprecated
*/
class Imagify_User {
/**
@@ -153,7 +154,6 @@ class Imagify_User {
*/
public function get_percent_consumed_quota() {
static $done = false;
if ( $this->get_error() ) {
return 0;
}
@@ -176,12 +176,15 @@ class Imagify_User {
$percent = (float) $percent;
$percent = 100;
if ( $done ) {
return $percent;
}
$previous_percent = Imagify_Data::get_instance()->get( 'previous_quota_percent' );
// Percent is not 100% anymore.
if ( 100.0 === (float) $previous_percent && $percent < 100 ) {
/**
@@ -33,7 +33,10 @@ function imagify_count_attachments() {
$mime_types = Imagify_DB::get_mime_types();
$statuses = Imagify_DB::get_post_statuses();
$nodata_join = Imagify_DB::get_required_wp_metadata_join_clause();
$nodata_join = Imagify_DB::get_required_wp_metadata_join_clause('p.ID', true, true,
"AND p.post_mime_type IN ( $mime_types )
AND p.post_type = 'attachment'
AND p.post_status IN ( $statuses )");
$nodata_where = Imagify_DB::get_required_wp_metadata_where_clause();
$count = (int) $wpdb->get_var( // WPCS: unprepared SQL ok.
"
@@ -42,6 +42,7 @@ function get_imagify_attachment_optimization_text( $process ) {
}
$data = $process->get_data();
$optimized_data = $data->get_optimization_data();
$attachment_id = $media->get_id();
$optimization_level = imagify_get_optimization_level_label( $data->get_optimization_level() );
@@ -49,6 +50,10 @@ function get_imagify_attachment_optimization_text( $process ) {
$output .= $output_before . '<span class="data">' . __( 'New Filesize:', 'imagify' ) . '</span> <strong class="big">' . $data->get_optimized_size() . '</strong>' . $output_after;
}
if ( key_exists( 'message', $optimized_data ) && $optimized_data['message'] ) {
$output .= $output_before . '<span class="data">' . __( 'Convert:', 'imagify' ) . '</span> <strong class="big">' . $optimized_data['message'] . '</strong>' . $output_after;
}
$chart = '';
if ( ! $is_media_page ) {
@@ -90,6 +95,10 @@ function get_imagify_attachment_optimization_text( $process ) {
if ( $media->is_image() ) {
$has_webp = $process->has_webp() ? __( 'Yes', 'imagify' ) : __( 'No', 'imagify' );
if ( $process->has_webp() ) {
$has_webp = $process->is_full_webp() ? __( 'Yes', 'imagify' ) : __( 'Partially', 'imagify' );
}
$output .= $output_before . '<span class="data">' . __( 'WebP generated:', 'imagify' ) . '</span> <strong class="big">' . esc_html( $has_webp ) . '</strong>' . $output_after;
$total_optimized_thumbnails = $data->get_optimized_sizes_count();
@@ -1,5 +1,6 @@
<?php
use Imagify\Notices\Notices;
use Imagify\User\User;
defined( 'ABSPATH' ) || die( 'Cheatin uh?' );
@@ -400,7 +401,7 @@ function imagify_cache_user() {
return false;
}
$user = new Imagify_User();
$user = new User();
$data = (object) get_object_vars( $user );
$methods = get_class_methods( $user );
@@ -164,7 +164,7 @@ function get_imagify_max_image_size() {
*/
function imagify_translate_api_message( $message ) {
if ( ! $message ) {
return imagify_translate_api_message( 'Unknown error occurred' );
$message = 'Unknown error occurred';
}
if ( is_wp_error( $message ) ) {
@@ -199,6 +199,7 @@ function imagify_translate_api_message( $message ) {
'</a>'
),
'Your image is too big to be uploaded on our server' => __( 'Your file is too big to be uploaded on our server.', 'imagify' ),
'Webp is less performant than original' => __( 'WebP file is larger than the original image', 'imagify' ),
'Our server returned an invalid response' => __( 'Our server returned an invalid response.', 'imagify' ),
'cURL isn\'t installed on the server' => __( 'cURL is not available on the server.', 'imagify' ),
// API messages.
@@ -115,7 +115,14 @@ function imagify_has_attachments_without_required_metadata() {
$mime_types = Imagify_DB::get_mime_types();
$statuses = Imagify_DB::get_post_statuses();
$nodata_join = Imagify_DB::get_required_wp_metadata_join_clause( 'p.ID', false, false );
$nodata_join = Imagify_DB::get_required_wp_metadata_join_clause(
'p.ID',
false,
false,
"AND p.post_mime_type IN ( $mime_types )
AND p.post_type = 'attachment'
AND p.post_status IN ( $statuses )"
);
$nodata_where = Imagify_DB::get_required_wp_metadata_where_clause( array(
'matching' => false,
'test' => false,
+30 -12
View File
@@ -1,8 +1,8 @@
=== Imagify Optimize Images & Convert WebP | Compress Images Easily ===
Contributors: wp_rocket, imagify
Tags: optimize images, convert webp, webp, image optimization, compress images, image compressor, resize images, reduce image size, performance, image optimizer, core web vitals, best image optimization plugin
Tested up to: 6.1
Stable tag: 2.1.1
Tags: optimize images, convert webp, webp converter, image optimization, compress images, image compressor, resize images, reduce image size, performance, image optimizer, core web vitals, best image optimization plugin
Tested up to: 6.3
Stable tag: 2.1.3
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -12,7 +12,7 @@ Compress images & convert WebP with the best WordPress image optimization plugin
= The Best Image Optimization Plugin For WordPress =
[Imagify](https://imagify.io/) is the most advanced image optimization plugin to help you resize and compress images. You can now use its power directly in WordPress to optimize images and reduce the weight of the photos you want to add to your site all in just one click and without sacrificing their quality.
[Imagify](https://imagify.io/) is the most advanced image optimization plugin to help you resize and compress images. You can now use its power directly in WordPress to optimise images and reduce the weight of the photos you want to add to your site all in just one click and without sacrificing their quality.
Imagify is the best WordPress image optimizer. The plugin lets you optimize images in one go with its asynchronous bulk optimization option. You can resize your images on the fly they will be automatically optimized at the best compression level. If needed, you can always restore your images to their original versions.
@@ -27,27 +27,27 @@ Our video explains why Imagify is the easiest image optimization plugin and show
= Resize and Compress Images Without Losing Quality =
Imagify is a great image compressor and the ultimate solution to optimize images. You are able to resize and compress images from the most common image formats as well as PDF format. In case you have many images to optimize, you can also resize images in bulk thanks to our async bulk optimization option. In just one click, you will be able to compress multiple images super easily. Imagify compresses all your images in the background, so you can leave the page and not worry about anything.
Imagify is a great image compressor and the ultimate solution to optimise images. You are able to resize and compress images from the most common image formats as well as PDF format. In case you have many images to optimize, you can also resize images in bulk thanks to our async bulk optimization option. In just one click, you will be able to compress multiple images super easily. Imagify compresses all your images in the background, so you can leave the page and not worry about anything.
Many of your high-quality images may be in sizes that are much too large. To reduce image size and compress large images, Imagify has a setting that allows you to choose a maximum width for all of your images, and if you upload images that are larger than that size, it will resize large images for you during optimization. Imagify will resize images proportionally without cropping them.
With such a great image optimizer like Imagify, youll get your images automatically optimized at the best compression level and quality thanks to the Smart Compression Mode.
When using our image compression tool, Imagify, you will enjoy smaller file sizes and faster loading times. But the best part is that you will optimize images and reduce their weight without losing quality: why should you have to choose between beauty and speed? If you want to compress images, its now easier than ever with Imagify!
When using our image compression tool, Imagify, you will enjoy smaller file sizes and faster loading times. But the best part is that you will optimise images and reduce their weight without losing quality: why should you have to choose between beauty and speed? If you want to compress images, its now easier than ever with Imagify!
= Convert WebP for Superior Image Compression =
= Convert Images to the WebP Format =
Thanks to Imagify, you can take a step further in your image optimization process. You can also convert all your images to next-gen image formats such as WebP. WebP format offers superior image compression and quality and is a way to optimize images and speed up their loading times on websites. To convert images to next-gen format, using the Imagify plugin will save you a precious amount of time.
Thanks to Imagify, you can take a step further in your image optimization process. You can also convert all your images to next-gen image formats such as WebP. WebP format offers superior image compression and quality and is a way to optimise images and speed up their loading times on websites. To convert images to next-gen format, using the Imagify plugin will save you a precious amount of time.
With Imagify, WebP compression and conversion are indeed super easy. Wondering how the convert WebP option works? If the "Create WebP versions of images" option is enabled, the WebP versions of optimized images will be created automatically. Simple as that! Thanks to the best WebP plugin for WordPress, youll be able to take advantage of the convert WebP feature in no time.
Imagify can also display these WebP images directly on your front-end. But because some browsers dont support WebP yet, Imagify lets you have both optimized versions of the original format images and the WebP versions ready. Imagify will serve the WebP versions if a visitor's browser supports them and the other optimized format if not.
WebP is definitively an excellent replacement for jpeg, png, and gif images. Imagify offers WebP conversion for all image formats: you can convert gif to webP, jpeg to WebP, and even png to WebP. Whatever your favorite image format, let Imagify optimize your images!
WebP is definitively an excellent replacement for jpeg, png, and gif images. Imagify offers WebP conversion for all image formats: you can convert gif to webP, jpeg to WebP, and even png to WebP. Whatever your favorite image format, let Imagify optimise your images!
= Optimize Images to Make Your Site Faster and Improve Core Web Vitals =
= Optimise Images to Make Your Site Faster and Improve Core Web Vitals =
Did you know that image optimization and web performance go hand in hand? In fact, when it comes to web page speed, one of the first things you should do is optimize your images. Large and heavy image sizes will indeed slow down your website and provide a bad user experience to your visitors and thats why you should compress images. On the contrary, when you optimize images and improve image loading speed, you should see a direct improvement in your website speed and performance. With Imagify, its time to say goodbye to images taking too long to load.
Did you know that image optimization and web performance go hand in hand? In fact, when it comes to web page speed, one of the first things you should do is optimize your images. Large and heavy image sizes will indeed slow down your website and provide a bad user experience to your visitors and thats why you should compress images. On the contrary, when you optimise images and improve image loading speed, you should see a direct improvement in your website speed and performance. With Imagify, its time to say goodbye to images taking too long to load.
Images are one of the largest influencing factors in the Core Web Vitals. Image compression will ensure that your images load faster and improve your overall website performance, including your Core Web Vitals metrics. If youre looking to improve user experience and speed up your WordPress site, images are a good place to start.
@@ -57,7 +57,7 @@ Even Google tells you to take care of your images! If you have ever run a perfor
Heres what our users have to say about us after optimizing their images with Imagify:
>"Images and other media are the largest parts on your web pages (most likely). Therefore don't forget to optimize images for the web before adding to your site. For WordPress there are many optimisation plugins available. My favourite is Imagify" — [Mark Wilkinson](https://twitter.com/wpmark/status/1479128422395830273)
>"Images and other media are the largest parts on your web pages (most likely). Therefore don't forget to optimise images for the web before adding to your site. For WordPress there are many optimisation plugins available. My favourite is Imagify" — [Mark Wilkinson](https://twitter.com/wpmark/status/1479128422395830273)
>
>”To give your images a slimming treatment, without altering them aesthetically, there is a great plugin on WordPress: Imagify. Simple, efficient and functional, its really worth a look.”— [WP Marmite](https://twitter.com/wpmarmite_en/status/1383072818649255937)
@@ -243,6 +243,10 @@ Yes, and no credit card is required.
No. However, you get 20MB of quota per month for free to optimize your images (around 200 images).
= Where do I report security bugs found in this plugin? =
You can report any security bugs found in the source code of the site-reviews plugin through the [Patchstack Vulnerability Disclosure Program](https://patchstack.com/database/vdp/imagify). The Patchstack team will assist you with verification, CVE assignment and take care of notifying the developers of this plugin.
== Screenshots ==
1. Bulk Optimization
@@ -254,6 +258,20 @@ No. However, you get 20MB of quota per month for free to optimize your images (a
4. Other Media Page
== Changelog ==
= 2.1.3 =
- Enhancement: Update chart.js (#742)
- Enhancement: Improve messaging around WebP images when they are larger than the original (#751)
- Enhancement: Update notices when out of quota (#727, #728)
- Bugfix: Prevent PHP deprecated notice on PHP 8.1 (#734)
- Bugfix: Improve database queries on large media libraries (#747)
= 2.1.2 =
- Bugfix: Prevent deprecation notice with PHP 8.1 & 8.2 (#721, #723)
- Bugfix: Escape error message before display (#729)
- Bugfix: Don't count WebP images in the generate missing WebP images versions (#713)
- Bugfix: Improve information related to out of quota on bulk optimization (#714)
- Bugfix: Fix optimization filter type working with file filters on media library (#670)
= 2.1.1 =
- Enhancement: Allow WebP images to be optimized by Imagify from the plugin (#611)
- Enhancement: Improve error message displayed when an unknown error occured (#637)
+1 -1
View File
@@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit4ba6376c0ffc3020053ab8c93bad1e1e::getLoader();
return ComposerAutoloaderInit49a1cdf8dc57f57539cd34f9d3c0eac1::getLoader();
+53 -55
View File
@@ -45,35 +45,34 @@ class ClassLoader
/** @var \Closure(string):void */
private static $includeFile;
/** @var ?string */
/** @var string|null */
private $vendorDir;
// PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
* @var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
* @var array<string, list<string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
* @var list<string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
* List of PSR-0 prefixes
*
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
*
* @var array<string, array<string, list<string>>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
* @var list<string>
*/
private $fallbackDirsPsr0 = array();
@@ -81,8 +80,7 @@ class ClassLoader
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
* @var array<string, string>
*/
private $classMap = array();
@@ -90,21 +88,20 @@ class ClassLoader
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
* @var array<string, bool>
*/
private $missingClasses = array();
/** @var ?string */
/** @var string|null */
private $apcuPrefix;
/**
* @var self[]
* @var array<string, self>
*/
private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
* @param string|null $vendorDir
*/
public function __construct($vendorDir = null)
{
@@ -113,7 +110,7 @@ class ClassLoader
}
/**
* @return string[]
* @return array<string, list<string>>
*/
public function getPrefixes()
{
@@ -125,8 +122,7 @@ class ClassLoader
}
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
* @return array<string, list<string>>
*/
public function getPrefixesPsr4()
{
@@ -134,8 +130,7 @@ class ClassLoader
}
/**
* @return array[]
* @psalm-return array<string, string>
* @return list<string>
*/
public function getFallbackDirs()
{
@@ -143,8 +138,7 @@ class ClassLoader
}
/**
* @return array[]
* @psalm-return array<string, string>
* @return list<string>
*/
public function getFallbackDirsPsr4()
{
@@ -152,8 +146,7 @@ class ClassLoader
}
/**
* @return string[] Array of classname => path
* @psalm-return array<string, string>
* @return array<string, string> Array of classname => path
*/
public function getClassMap()
{
@@ -161,8 +154,7 @@ class ClassLoader
}
/**
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
* @param array<string, string> $classMap Class to filename map
*
* @return void
*/
@@ -179,24 +171,25 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
* @param string $prefix The prefix
* @param list<string>|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
$paths
);
}
@@ -205,19 +198,19 @@ class ClassLoader
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
$this->prefixesPsr0[$first][$prefix] = $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
$paths
);
}
}
@@ -226,9 +219,9 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param list<string>|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
@@ -236,17 +229,18 @@ class ClassLoader
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
$paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
@@ -256,18 +250,18 @@ class ClassLoader
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
$this->prefixDirsPsr4[$prefix] = $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
$paths
);
}
}
@@ -276,8 +270,8 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
* @param string $prefix The prefix
* @param list<string>|string $paths The PSR-0 base directories
*
* @return void
*/
@@ -294,8 +288,8 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param list<string>|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
@@ -429,7 +423,8 @@ class ClassLoader
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
(self::$includeFile)($file);
$includeFile = self::$includeFile;
$includeFile($file);
return true;
}
@@ -480,9 +475,9 @@ class ClassLoader
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
* Returns the currently registered loaders keyed by their corresponding vendor directories.
*
* @return self[]
* @return array<string, self>
*/
public static function getRegisteredLoaders()
{
@@ -560,7 +555,10 @@ class ClassLoader
return false;
}
private static function initializeIncludeClosure(): void
/**
* @return void
*/
private static function initializeIncludeClosure()
{
if (self::$includeFile !== null) {
return;
@@ -574,8 +572,8 @@ class ClassLoader
* @param string $file
* @return void
*/
self::$includeFile = static function($file) {
self::$includeFile = \Closure::bind(static function($file) {
include $file;
};
}, null, null);
}
}
@@ -98,7 +98,7 @@ class InstalledVersions
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
}
}
@@ -119,7 +119,7 @@ class InstalledVersions
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints($constraint);
$constraint = $parser->parseConstraints((string) $constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
@@ -328,7 +328,9 @@ class InstalledVersions
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
$required = require $vendorDir.'/composer/installed.php';
$installed[] = self::$installedByVendor[$vendorDir] = $required;
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1];
}
@@ -340,12 +342,17 @@ class InstalledVersions
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = require __DIR__ . '/installed.php';
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
$required = require __DIR__ . '/installed.php';
self::$installed = $required;
} else {
self::$installed = array();
}
}
$installed[] = self::$installed;
if (self::$installed !== array()) {
$installed[] = self::$installed;
}
return $installed;
}
@@ -46,7 +46,7 @@ return array(
'Imagify_Regenerate_Thumbnails_Deprecated' => $baseDir . '/inc/deprecated/classes/class-imagify-regenerate-thumbnails-deprecated.php',
'Imagify_Requirements' => $baseDir . '/inc/classes/class-imagify-requirements.php',
'Imagify_Settings' => $baseDir . '/inc/classes/class-imagify-settings.php',
'Imagify_User' => $baseDir . '/inc/classes/class-imagify-user.php',
'Imagify_User' => $baseDir . '/inc/deprecated/classes/class-imagify-user.php',
'Imagify_Views' => $baseDir . '/inc/classes/class-imagify-views.php',
'Imagify_WP_Async_Request' => $baseDir . '/inc/classes/Dependencies/deliciousbrains/wp-background-processing/classes/wp-async-request.php',
'Imagify_WP_Background_Process' => $baseDir . '/inc/classes/Dependencies/deliciousbrains/wp-background-processing/classes/wp-background-process.php',
@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit4ba6376c0ffc3020053ab8c93bad1e1e
class ComposerAutoloaderInit49a1cdf8dc57f57539cd34f9d3c0eac1
{
private static $loader;
@@ -24,12 +24,12 @@ class ComposerAutoloaderInit4ba6376c0ffc3020053ab8c93bad1e1e
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit4ba6376c0ffc3020053ab8c93bad1e1e', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit49a1cdf8dc57f57539cd34f9d3c0eac1', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\AutoloadWPMediaImagifyWordPressPlugin\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit4ba6376c0ffc3020053ab8c93bad1e1e', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit49a1cdf8dc57f57539cd34f9d3c0eac1', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit4ba6376c0ffc3020053ab8c93bad1e1e::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit49a1cdf8dc57f57539cd34f9d3c0eac1::getInitializer($loader));
$loader->register(true);
@@ -7,7 +7,7 @@ namespace Composer\Autoload;
use Composer\AutoloadWPMediaImagifyWordPressPlugin\ClassLoader as ClassLoaderWPMediaImagifyWordPressPlugin;
class ComposerStaticInit4ba6376c0ffc3020053ab8c93bad1e1e
class ComposerStaticInit49a1cdf8dc57f57539cd34f9d3c0eac1
{
public static $prefixLengthsPsr4 = array (
'I' =>
@@ -115,7 +115,7 @@ class ComposerStaticInit4ba6376c0ffc3020053ab8c93bad1e1e
'Imagify_Regenerate_Thumbnails_Deprecated' => __DIR__ . '/../..' . '/inc/deprecated/classes/class-imagify-regenerate-thumbnails-deprecated.php',
'Imagify_Requirements' => __DIR__ . '/../..' . '/inc/classes/class-imagify-requirements.php',
'Imagify_Settings' => __DIR__ . '/../..' . '/inc/classes/class-imagify-settings.php',
'Imagify_User' => __DIR__ . '/../..' . '/inc/classes/class-imagify-user.php',
'Imagify_User' => __DIR__ . '/../..' . '/inc/deprecated/classes/class-imagify-user.php',
'Imagify_Views' => __DIR__ . '/../..' . '/inc/classes/class-imagify-views.php',
'Imagify_WP_Async_Request' => __DIR__ . '/../..' . '/inc/classes/Dependencies/deliciousbrains/wp-background-processing/classes/wp-async-request.php',
'Imagify_WP_Background_Process' => __DIR__ . '/../..' . '/inc/classes/Dependencies/deliciousbrains/wp-background-processing/classes/wp-background-process.php',
@@ -124,9 +124,9 @@ class ComposerStaticInit4ba6376c0ffc3020053ab8c93bad1e1e
public static function getInitializer(ClassLoaderWPMediaImagifyWordPressPlugin $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit4ba6376c0ffc3020053ab8c93bad1e1e::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit4ba6376c0ffc3020053ab8c93bad1e1e::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit4ba6376c0ffc3020053ab8c93bad1e1e::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit49a1cdf8dc57f57539cd34f9d3c0eac1::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit49a1cdf8dc57f57539cd34f9d3c0eac1::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit49a1cdf8dc57f57539cd34f9d3c0eac1::$classMap;
}, null, ClassLoaderWPMediaImagifyWordPressPlugin::class);
}
@@ -1,9 +1,9 @@
<?php return array(
'root' => array(
'name' => 'wp-media/imagify-plugin',
'pretty_version' => 'v2.1.1',
'version' => '2.1.1.0',
'reference' => '46f9df25cc18fe7a8609d1a94bec039e169282da',
'pretty_version' => 'v2.1.3',
'version' => '2.1.3.0',
'reference' => '58a54d5f7381cc9884874f51021a0c791965fc05',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -29,9 +29,9 @@
'dev_requirement' => false,
),
'wp-media/imagify-plugin' => array(
'pretty_version' => 'v2.1.1',
'version' => '2.1.1.0',
'reference' => '46f9df25cc18fe7a8609d1a94bec039e169282da',
'pretty_version' => 'v2.1.3',
'version' => '2.1.3.0',
'reference' => '58a54d5f7381cc9884874f51021a0c791965fc05',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -0,0 +1,41 @@
<?php
defined( 'ABSPATH' ) || die( 'Cheatin uh?' );
?>
<div class="imagify-admin-bar-quota">
<div class="imagify-abq-row">
<?php if ( $data['plan_with_quota'] ) : ?>
<div class="imagify-meteo-icon"><?php echo $data['quota_icon']; ?></div>
<?php endif; ?>
<div class="imagify-account">
<p class="imagify-meteo-title"><?php esc_html_e( 'Account status', 'imagify' ); ?></p>
<p class="imagify-meteo-subs"><?php esc_html_e( 'Your subscription:', 'imagify' ); ?> &nbsp;<strong class="imagify-user-plan"><?php echo $data['plan_label']; ?></strong></p>
</div>
</div>
<?php if ( $data['plan_with_quota'] ) : ?>
<div class="imagify-abq-row">
<div class="imagify-space-left">
<p><?php
printf(
// translators: %s = percentage.
__( 'You have %s space credit left', 'imagify' ), '<span class="imagify-unconsumed-percent">' . $data['unconsumed_quota'] . '%</span>' );
?></p>
<div class="<?php echo esc_attr( $data['quota_class'] ); ?>">
<div style="width: <?php echo esc_attr( $data['unconsumed_quota'] ); ?>%;" class="imagify-unconsumed-bar imagify-progress"></div>
</div>
</div>
</div>
<?php endif; ?>
<?php if ( $data['plan_with_quota'] && $data['unconsumed_quota'] <= 20 ) : ?>
<div class="imagify-upsell-admin-bar">
<?php if ( $data['unconsumed_quota'] <= 20 ) : ?>
<p><i class="dashicons dashicons-warning" aria-hidden="true"></i><strong><?php esc_html_e( 'Oops, It\'s almost over!', 'imagify' ); ?></strong></p>
<?php elseif ( 0 === $data['unconsumed_quota'] ) : ?>
<p><i class="dashicons dashicons-warning" aria-hidden="true"></i><strong><?php esc_html_e( 'Oops, It\'s Over!', 'imagify' ); ?></strong></p>
<?php endif; ?>
<p><?php echo $data['text']; ?></p>
<p class="center txt-center text-center"><a class="imagify-upsell-admin-bar-button" href="<?php echo esc_url( $data['upgrade_link'] ); ?>" target="_blank"><?php echo $data['button_text']; ?></a></p>
<a href="<?php echo esc_url( get_imagify_admin_url( 'dismiss-notice', 'upsell-admin-bar' ) ); ?>" class="imagify-notice-dismiss imagify-upsell-dismiss" title="<?php esc_attr_e( 'Dismiss this notice', 'imagify' ); ?>"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice', 'imagify' ); ?></span></a>
</div>
<?php endif; ?>
</div>
@@ -1,39 +0,0 @@
<?php
defined( 'ABSPATH' ) || die( 'Cheatin uh?' );
$this->print_template( 'notice-header', array(
'classes' => array( 'imagify-flex-notice-content', 'error' ),
) );
$views = Imagify_Views::get_instance();
?>
<div class="imagify-notice-quota">
<div class="imagify-flex imagify-vcenter">
<span class="imagify-meteo-icon imagify-noshrink"><?php echo $views->get_quota_icon(); ?></span>
<div class="imagify-space-left">
<p>
<?php
printf(
/* translators: %s is a data quota. */
esc_html__( 'You have %s space credit left', 'imagify' ),
'<span class="imagify-unconsumed-percent">' . $views->get_quota_percent() . '%</span>'
);
?>
</p>
<div class="<?php echo $views->get_quota_class(); ?>">
<div class="imagify-unconsumed-bar imagify-progress" style="width: <?php echo $views->get_quota_percent() . '%'; ?>;"></div>
</div>
</div>
</div>
</div>
<p>
<?php esc_html_e( 'You are running out of credit! Dont forget to upgrade your Imagifys account.', 'imagify' ); ?>
</p>
<div class="imagify-notice-quota-btn-container">
<a target="_blank" class="button imagify-button imagify-button-secondary button-mini" href="<?php echo esc_url( imagify_get_external_url( 'subscription' ) ); ?>"><?php esc_html_e( 'See our plans', 'imagify' ); ?></a>
</div>
<?php
$this->print_template( 'notice-footer', array(
'dismissible' => 'almost-over-quota',
) );
@@ -15,7 +15,7 @@ foreach ( $notices as $type => $type_notices ) {
?>
<div class="<?php echo $type; ?> settings-error notice is-dismissible">
<?php foreach ( $type_notices as $details ) { ?>
<p><strong><?php echo $details['message']; ?></strong></p>
<p><strong><?php echo wp_kses( $details['message'], [ 'code' => [] ] ); ?></strong></p>
<?php } ?>
</div>
<?php
@@ -1,4 +1,7 @@
<?php
use Imagify\User\User;
defined( 'ABSPATH' ) || die( 'Cheatin uh?' );
?>
<div class="wrap imagify-settings imagify-bulk">
@@ -85,8 +88,11 @@ defined( 'ABSPATH' ) || die( 'Cheatin uh?' );
<div class="imagify-col imagify-account-info-col">
<?php
if ( ( ! defined( 'IMAGIFY_HIDDEN_ACCOUNT' ) || ! IMAGIFY_HIDDEN_ACCOUNT ) && Imagify_Requirements::is_api_key_valid() ) {
$user = new Imagify_User();
if (
( ! defined( 'IMAGIFY_HIDDEN_ACCOUNT' ) || ! IMAGIFY_HIDDEN_ACCOUNT )
&&
Imagify_Requirements::is_api_key_valid()
) {
?>
<div class="imagify-options-title">
<div class="imagify-th-titles imagify-flex imagify-vcenter">
@@ -97,60 +103,7 @@ defined( 'ABSPATH' ) || die( 'Cheatin uh?' );
</div>
<a href="<?php echo esc_url( imagify_get_external_url( 'subscription' ) ); ?>" target="_blank"><?php _e( 'View your profile', 'imagify' ); ?></a>
</div>
<?php if ( $user && 1 === $user->plan_id ) { ?>
<div class="imagify-col-content">
<div class="imagify-flex imagify-vcenter">
<span class="imagify-meteo-icon imagify-noshrink"><?php echo $this->get_quota_icon(); ?></span>
<div class="imagify-space-left imagify-full-width">
<p>
<?php
printf(
/* translators: %s is a data quota. */
__( 'You have %s space credit left', 'imagify' ),
'<span class="imagify-unconsumed-percent">' . $this->get_quota_percent() . '%</span>'
);
?>
</p>
<div class="<?php echo $this->get_quota_class(); ?>">
<div class="imagify-unconsumed-bar imagify-progress" style="width: <?php echo $this->get_quota_percent() . '%'; ?>;"></div>
</div>
</div>
</div>
<?php
/**
* Filter whether the plan chooser section is displayed.
*
* @param $show_new bool Default to true: display the section.
*/
if ( apply_filters( 'imagify_show_new_to_imagify', true ) ) {
?>
<div class="imagify-block-secondary">
<p class="imagify-section-title imagify-h3-like">
<?php
if ( ! $this->get_quota_percent() ) {
esc_html_e( 'Oops, It\'s Over!', 'imagify' );
} elseif ( $this->get_quota_percent() <= 20 ) {
esc_html_e( 'Oops, It\'s almost over!', 'imagify' );
} else {
esc_html_e( 'You\'re new to Imagify?', 'imagify' );
}
?>
</p>
<p><?php esc_html_e( 'Let us help you by analyzing your existing images and determine the best plan for you.', 'imagify' ); ?></p>
<button id="imagify-get-pricing-modal" data-nonce="<?php echo wp_create_nonce( 'imagify_get_pricing_' . get_current_user_id() ); ?>" data-target="#imagify-pricing-modal" type="button" class="imagify-modal-trigger imagify-button imagify-button-light imagify-button-big imagify-full-width">
<i class="dashicons dashicons-dashboard" aria-hidden="true"></i>
<span class="button-text"><?php _e( 'What plan do I need?', 'imagify' ); ?></span>
</button>
</div>
<?php
}
?>
</div><!-- .imagify-col-content -->
<?php } // End if(). ?>
<?php $this->print_template( 'part-upsell' ); ?>
<?php } // End if(). ?>
</div><!-- .imagify-account-info-col -->
@@ -1,4 +1,7 @@
<?php
use Imagify\User\User;
defined( 'ABSPATH' ) || die( 'Cheatin uh?' );
if ( defined( 'IMAGIFY_HIDDEN_ACCOUNT' ) && IMAGIFY_HIDDEN_ACCOUNT ) {
@@ -12,9 +15,7 @@ if ( defined( 'IMAGIFY_HIDDEN_ACCOUNT' ) && IMAGIFY_HIDDEN_ACCOUNT ) {
}
if ( Imagify_Requirements::is_api_key_valid() ) {
$user = imagify_get_cached_user();
$unconsumed_quota = $user ? $user->get_percent_unconsumed_quota : false;
$hidden_class = '';
$user = imagify_get_cached_user();
if ( ! $user ) {
// Lazyload user.
@@ -23,51 +24,10 @@ if ( Imagify_Requirements::is_api_key_valid() ) {
'_wpnonce' => wp_create_nonce( 'imagify_get_user_data' ),
) );
}
} else {
$hidden_class = ' hidden';
}
?>
<div class="imagify-settings-section">
<?php
$imagify_user = new Imagify_User();
if (
$imagify_user->is_free()
&&
Imagify_Requirements::is_api_key_valid()
) {
?>
<div class="imagify-col-content imagify-block-secondary imagify-mt2">
<?php
/**
* Best plan.
*/
?>
<div class="best-plan<?php echo $hidden_class; ?>">
<h3 class="imagify-user-best-plan-title">
<?php
if ( $user && ! $unconsumed_quota ) {
esc_html_e( 'Oops, It\'s Over!', 'imagify' );
} elseif ( $user && $unconsumed_quota <= 20 ) {
esc_html_e( 'Oops, It\'s almost over!', 'imagify' );
} else {
esc_html_e( 'You\'re new to Imagify?', 'imagify' );
}
?>
</h3>
<p><?php esc_html_e( 'Let us help you by analyzing your existing images and determine the best plan for you.', 'imagify' ); ?></p>
<button id="imagify-get-pricing-modal" data-nonce="<?php echo wp_create_nonce( 'imagify_get_pricing_' . get_current_user_id() ); ?>" data-target="#imagify-pricing-modal" type="button" class="imagify-modal-trigger imagify-button imagify-button-light imagify-full-width">
<i class="dashicons dashicons-dashboard" aria-hidden="true"></i>
<span class="button-text"><?php esc_html_e( 'What plan do I need?', 'imagify' ); ?></span>
</button>
</div>
</div><!-- .imagify-col-content -->
<?php
}
?>
<?php $this->print_template( 'part-upsell' ); ?>
<?php
if ( ! defined( 'IMAGIFY_API_KEY' ) || ! IMAGIFY_API_KEY ) {
@@ -0,0 +1,95 @@
<?php
use Imagify\User\User;
defined( 'ABSPATH' ) || die( 'Cheatin uh?' );
$imagify_user = new User();
$unconsumed_quota = $imagify_user ? $imagify_user->get_percent_unconsumed_quota() : 0;
$infinite = $imagify_user->is_infinite();
$upgrade = '';
$price = '';
$upgrade_link = '';
$user_id = get_current_user_id();
$notices = get_user_meta( $user_id, '_imagify_ignore_notices', true );
$notices = $notices && is_array( $notices ) ? array_flip( $notices ) : [];
$api_key_valid = Imagify_Requirements::is_api_key_valid();
if (
$imagify_user->is_free()
&&
$api_key_valid
&&
$unconsumed_quota > 20
) {
?>
<div class="imagify-col-content imagify-block-secondary imagify-mt2">
<div class="best-plan<?php echo $api_key_valid ? '' : ' hidden'; ?>">
<h3 class="imagify-user-best-plan-title">
<?php esc_html_e( 'You\'re new to Imagify?', 'imagify' ); ?>
</h3>
<p><?php esc_html_e( 'Let us help you by analyzing your existing images and determine the best plan for you.', 'imagify' ); ?></p>
<button id="imagify-get-pricing-modal" data-nonce="<?php echo wp_create_nonce( 'imagify_get_pricing_' . get_current_user_id() ); ?>" data-target="#imagify-pricing-modal" type="button" class="imagify-modal-trigger imagify-button imagify-button-light imagify-full-width">
<i class="dashicons dashicons-dashboard" aria-hidden="true"></i>
<span class="button-text"><?php esc_html_e( 'What plan do I need?', 'imagify' ); ?></span>
</button>
</div>
</div><!-- .imagify-col-content -->
<?php
}
if (
Imagify_Requirements::is_api_key_valid()
&&
! $infinite
&&
! isset( $notices['upsell-banner'] )
&&
$unconsumed_quota <= 20
) {
?>
<div class="imagify-col-content imagify-upsell">
<div class="imagify-flex imagify-vcenter">
<span class="imagify-meteo-icon imagify-noshrink"><?php echo $this->get_quota_icon(); ?></span>
<div class="imagify-space-left imagify-full-width">
<p>
<?php
printf(
/* translators: %s is a data quota. */
__( 'You have %s space credit left', 'imagify' ),
'<span class="imagify-unconsumed-percent">' . $this->get_quota_percent() . '%</span>'
);
?>
</p>
<div class="<?php echo $this->get_quota_class(); ?>">
<div class="imagify-unconsumed-bar imagify-progress" style="width: <?php echo $this->get_quota_percent() . '%'; ?>;"></div>
</div>
</div>
</div>
<?php
if ( $imagify_user->is_free() ) {
$upgrade = esc_html__( 'Upgrade your plan now for more!', 'imagify' );
$price = esc_html__( 'From $4.99/month only, keep going with image optimization!', 'imagify' );
$upgrade_link = IMAGIFY_APP_DOMAIN . '/subscription/?utm_source=plugin&utm_medium=upsell_banner';
} elseif ( $imagify_user->is_growth() ) {
$upgrade = esc_html__( 'Upgrade your plan now to keep optimizing your images.', 'imagify' );
if ( $imagify_user->is_monthly ) {
$price = esc_html__( 'For $9.99/month only, choose unlimited image optimization!', 'imagify' );
$upgrade_link = IMAGIFY_APP_DOMAIN . '/subscription/plan_switch/?label=infinite&payment_plan=1&utm_source=plugin&utm_medium=upsell_banner';
} else {
$price = esc_html__( 'For $99.9/year only, choose unlimited image optimization!', 'imagify' );
$upgrade_link = IMAGIFY_APP_DOMAIN . '/subscription/plan_switch/?label=infinite&payment_plan=2&utm_source=plugin&utm_medium=upsell_banner';
}
}
?>
<p><?php echo $upgrade; ?></p>
<p><?php echo $price; ?></p>
<a href="<?php echo esc_url( $upgrade_link ); ?>" target="_blank" rel="noopener noreferrer" class="imagify-upsell-button"><span class="imagify-upsell-arrow"><?php esc_html_e( 'Upgrade now', 'imagify' ); ?></span></a>
<a href="<?php echo esc_url( get_imagify_admin_url( 'dismiss-notice', 'upsell-banner' ) ); ?>" class="imagify-notice-dismiss imagify-upsell-dismiss" title="<?php esc_attr_e( 'Dismiss this notice', 'imagify' ); ?>"><span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice', 'imagify' ); ?></span></a>
</div><!-- .imagify-col-content -->
<?php
}
?>