image = array();
$speedycache->image['upload_dir'] = wp_upload_dir();
$speedycache->image['id'] = false;
$speedycache->image['metadata'] = array();
$speedycache->image['name'] = '';
$speedycache->image['path'] = '';
$speedycache->image['url'] = '';
$speedycache->image['images'] = array();
$speedycache->image['images_clone'] = array();
$speedycache->image['disabled_method'] = 0;
// Default settings for img optimization
$speedycache->image['settings'] = array(
'on_upload' => false,
'automatic_optm' => false,
'url_rewrite' => false,
'compression_method' => 'gd',
'compression_quality' => '70'
);
$speedycache_optm_method = array(
'gd' => array(
'title' => 'GD',
'desc' => 'Compress using PHP\'s native Extension for compression and conversion.'
),
'imagick' => array(
'title' => 'Imagick',
'desc' => 'Imagick outputs better image quality after compression at the cost of a little bigger file size compared to GD.'
),
'cwebp' => array(
'title' => 'cWebP',
'desc' => 'cwebp is a utility which can be downloaded on your server and its fast and light on you server.'
)
);
// Binaries for cwebp
$speedycache->image['binaries'] = array(
'WINNT' => ['cwebp-122-windows-x64.exe', 'gif2webp-122-windows-x64.exe'],
'Linux' => ['cwebp-122-linux-x86-64', 'gif2webp-122-linux-x86-64']
);
if(array_key_exists(PHP_OS, $speedycache->image['binaries'])){
$speedycache->image['cwebp_binary'] = $speedycache->image['binaries'][PHP_OS][0];
$speedycache->image['cwebp_gif'] = $speedycache->image['binaries'][PHP_OS][1];
}
if($img_settings = get_option('speedycache_img')){
$speedycache->image['settings'] = array_merge($speedycache->image['settings'], $img_settings);
self::compression_method_checks();
return;
}
self::compression_method_checks();
update_option('speedycache_img', $speedycache->image['settings']);
}
static function total_reduction(){
global $wpdb;
$query = "SELECT sum(`meta_value`) as total FROM `".$wpdb->prefix."postmeta` WHERE `meta_key`= 'speedycache_optimisation_reduction'";
$result = $wpdb->get_row( $query );
if(!empty($result->total)){
$reduced = ($result->total && $result->total > 0) ? $result->total : 0;
return $reduced > 10000 ? $reduced/1000 : $reduced;
}
return 0;
}
static function optimized_file_count(){
global $wpdb;
$query = "SELECT count(`meta_value`) as optimized FROM `".$wpdb->prefix."postmeta` WHERE `meta_key`= 'speedycache_optimisation'";
$result = $wpdb->get_row($query);
if($result->optimized && $result->optimized > 0){
return $result->optimized;
}
return 0;
}
static function optm_img_count(){
return self::count_query(array(
'post_type' => 'attachment',
'post_mime_type' => array('image/jpeg', 'image/png', 'image/gif'),
'post_status' => 'inherit',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'speedycache_optimisation',
'compare' => 'EXISTS'
),
array(
'key' => 'speedycache_optimisation',
'value' => base64_encode('"destination_path"'),
'compare' => 'LIKE'
)
)
));
}
static function error_count(){
return self::count_query(array(
'post_type' => 'attachment',
'post_mime_type' => array('image/jpeg', 'image/png', 'image/gif'),
'post_status' => 'inherit',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'speedycache_optimisation',
'compare' => 'EXISTS'
),
array(
'key' => 'speedycache_optimisation',
'value' => base64_encode('"error_code"'),
'compare' => 'LIKE'
)
)
));
}
static function null_posts_groupby(){
return '';
}
static function count_posts_fields(){
return 'COUNT(*) as post_count_speedycache';
}
static function count_query($query_images_args){
add_filter('posts_fields', '\SpeedyCache\Image::count_posts_fields');
add_filter('posts_groupby', '\SpeedyCache\Image::null_posts_groupby');
unset($query_images_args['offset']);
unset($query_images_args['order']);
unset($query_images_args['orderby']);
$query_images_args['posts_per_page'] = -1;
$query_image = new \WP_Query( $query_images_args );
return $query_image->posts[0]->post_count_speedycache;
}
static function image_count(){
return self::count_query(array(
'post_type' => 'attachment',
'post_mime_type' => array('image/jpeg', 'image/png', 'image/gif'),
'post_status' => 'inherit',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => '_wp_attachment_metadata',
'compare' => 'EXISTS'
)
)
));
}
static function uncompressed_count(){
return self::count_query(array(
'post_type' => 'attachment',
'post_mime_type' => array('image/jpeg', 'image/png', 'image/gif'),
'post_status' => 'inherit',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'speedycache_optimisation',
'compare' => 'NOT EXISTS'
)
)
));
}
static function unoptimized(){
global $speedycache;
$tmp_image = array();
$optimization_data = get_post_meta($speedycache->image['id'], 'speedycache_optimisation', true);
$optm_json = base64_decode($optimization_data);
if(empty($optm_json)){
$percentage = 100 / count($speedycache->image['images']);
return array('meta_optimized' => array(), 'images' => $speedycache->image['images'], 'total_reduction' => 0, 'percentage' => $percentage);
}
$optm_json = json_decode($optm_json, true);
$meta_optimized = self::object_to_array($optm_json);
$percentage = count($meta_optimized) * 100/count($speedycache->image['images']);
foreach($speedycache->image['images'] as $key => $value){
$exist = false;
foreach($meta_optimized as $meta_key => $meta_value){
if($value['file'] == $meta_value['file']){
$exist = true;
//break;
}
}
if(empty($exist)){
array_push($tmp_image, $value);
}
}
//START: total reduction
$total_reduction = 0;
foreach($meta_optimized as $m_key => $m_value){
$m_value['reduction'] = isset($m_value['reduction']) ? $m_value['reduction'] : 0;
if($m_key == 0){
$reduction = $m_value['reduction'];
}
$total_reduction += $m_value['reduction'];
}
//END: total reduction
if(count($tmp_image) <= 0){
return array('meta_optimized' => array(), 'images' => array(), 'total_reduction' => 0);
}
$last = speedycache_optget('last');
if(!empty($last)){
if(preg_match('/last-(\d+)/', $last, $last_number)){
if(count($tmp_image) > 5){
$tmp_image = array_slice($tmp_image, $last_number[1]*-1, 1);
}
}
}
return array('meta_optimized' => $meta_optimized, 'images' => array_slice($tmp_image, 0, 1), 'total_reduction' => $total_reduction, 'percentage' => $percentage);
}
static function object_to_array($obj){
if(is_object($obj)){
$obj = (array) $obj;
}
if(!is_array($obj)){
$new = $obj;
return $new;
}
$new = array();
foreach($obj as $key => $val){
$new[$key] = self::object_to_array($val);
}
return $new;
}
static function reorder_by_dimensions(){
global $speedycache;
$tmp = $speedycache->image['images'];
foreach($tmp as $key => $value){
$width_list[$key] = $value['width'];
}
array_multisort($width_list, SORT_DESC, $tmp);
return $tmp;
}
static function optimize_single($id = null){
global $speedycache;
if(!empty($id)){
self::init();
}
self::set_id($id);
self::set_meta_data();
if(wp_next_scheduled('speedycache_auto_optm', array($speedycache->image['id']))){
wp_clear_scheduled_hook('speedycache_auto_optm' , array($speedycache->image['id']));
}
if(empty($speedycache->image['id'])){
return array('finish', 'success');
}
if(!isset($speedycache->image['metadata']['file']) && !empty($speedycache->image['id'])){
$meta_optimized = array();
$meta_optimized[0]['time'] = time();
$meta_optimized[0]['id'] = $speedycache->image['id'];
$meta_optimized[0]['error_code'] = 17;
update_post_meta($speedycache->image['id'], 'speedycache_optimisation_reduction', 0);
update_post_meta($speedycache->image['id'], 'speedycache_optimisation', base64_encode(json_encode($meta_optimized)));
return array('Image has been optimized', 'success', $speedycache->image['id'], 100);
}
self::set_name();
self::set_path();
self::set_url();
self::set_images();
if(!empty($speedycache->image['id']) && count($speedycache->image['images']) == 0){
$meta_optimized = array();
$meta_optimized[0]['time'] = time();
$meta_optimized[0]['id'] = $speedycache->image['id'];
$meta_optimized[0]['error_code'] = 18;
update_post_meta($speedycache->image['id'], 'speedycache_optimisation_reduction', 0);
update_post_meta($speedycache->image['id'], 'speedycache_optimisation', base64_encode(json_encode($meta_optimized)));
return array('Image has been optimized', 'success', $speedycache->image['id'], 100);
}
$error_exist = false;
$meta_optimized = array();
$total_reduction = 0;
$speedycache->image['images'] = self::unique_array($speedycache->image['images']);
$speedycache->image['images'] = self::reorder_by_dimensions();
$speedycache->image['images_clone'] = $speedycache->image['images'];
$unoptimized = self::unoptimized();
$speedycache->image['images'] = $unoptimized['images'];
$meta_optimized = $unoptimized['meta_optimized'];
$total_reduction = $unoptimized['total_reduction'];
$percentage = isset($unoptimized['percentage']) && $unoptimized['percentage'] ? $unoptimized['percentage'] : 0;
if(count($speedycache->image['images']) == 0){
return array('Image has been optimized', 'success', '', 100);
}
foreach($speedycache->image['images'] as $key => $value){
$res = self::compress($value);
if(!empty($res['success'])){
$value['destination_path'] = $res['destination_path'];
$value['reduction'] = $res['reduction'];
$total_reduction += $value['reduction'];
$value['time'] = time();
$value['id'] = $speedycache->image['id'];
array_push($meta_optimized, $value);
}else{
if(!isset($res['error_code']) && isset($res['error_message'])){
return array($res['error_message'], 'error');
break;
}
if(in_array($res['error_code'] , array(2, 6, 7, 11, 19, 20, 22, 23))){
return array($res['error_message'], 'error');
break;
}
$value['error_code'] = $res['error_code'];
$error_exist = true;
}
$value['time'] = time();
$value['id'] = $speedycache->image['id'];
if(!empty($value['error_code'])){
if($value['error_code'] != 8 || ($value['error_code'] == 8 && $key === 0)){
array_push($meta_optimized, $value);
}
}
}
$percentage = self::update_meta($total_reduction, $meta_optimized);
return array('Image has been optimized', 'success', $speedycache->image['id'], $percentage, $total_reduction);
}
static function update_meta($total_reduction, $meta_optimized){
global $speedycache;
if(isset($meta_optimized[0]) && isset($meta_optimized[0]['error_code']) && $meta_optimized[0]['error_code']){
update_post_meta($speedycache->image['id'], 'speedycache_optimisation', base64_encode(json_encode($meta_optimized)));
update_post_meta($speedycache->image['id'], 'speedycache_optimisation_reduction', 0);
return 100;
}
$percentage = 0;
$meta_temp = array();
foreach($speedycache->image['images_clone'] as $key => $value){
$backup_file = $value['file'];
$value['file'] = preg_replace('/.(jpg|jpeg|png|gif)$/', '.webp', $value['file']);
if(!file_exists($value['file']) || !file_exists($backup_file)){
continue;
}
$diff = filesize($backup_file) - filesize($value['file']);
$diff = $diff > 0 ? $diff : 0;
$value['destination_path'] = $backup_file;
$value['reduction'] = $diff;
$value['time'] = time();
$value['id'] = $speedycache->image['id'];
array_push($meta_temp, $value);
}
foreach($meta_optimized as $m_key => $m_value){
if(empty($m_value['error_code'])){
continue;
}
$exist = false;
for($i=0; $i < count($meta_temp); $i++){
if($meta_temp['file'] == $m_value['file']){
$exist = true;
}
}
if(empty($exist)){
$m_value['destination_path'] = '';
$m_value['reduction'] = 0;
$m_value['time'] = time();
$m_value['id'] = $speedycache->image['id'];
array_push($meta_temp, $m_value);
}
}
if(count($meta_temp) > 0){
$percentage = count($meta_temp)*100/count($speedycache->image['images_clone']);
}else{
$percentage = 0;
}
update_post_meta($speedycache->image['id'], 'speedycache_optimisation_reduction', $total_reduction);
update_post_meta($speedycache->image['id'], 'speedycache_optimisation', base64_encode(json_encode($meta_temp)));
return $percentage;
}
static function compress($source_image){
global $speedycache;
/*
Error Codes
2 = in backup folder parent folder not writable
3 = no need to optimize
4 = source is not writable
5 = destination is not writable
6 = ImageMagick library is not avaliable
7 = Error via api
8 = Source file does not exist
9 = Image size exceed 5mb limit while processing
11 = Empty Name
12 = Forbidden
13 = CloudFlare to restrict access
14 = No Extension
15 = Image size is 0Kb
16 = Corrupted Image
17 = Empty Metadata
18 = No Image
19 = webp is not saved
20 = file size of destination_move_source_path is zero
21 = Unacceptable file type
22 = Unable to Convert Image using cwebp.
23 = The URL of the image has webp extension.
*/
// if the url starts with /wp-content
if(preg_match('/^\/' . SPEEDYCACHE_WP_CONTENT_DIR . '/i', $source_image['url'])){
$source_image['url'] = home_url().$source_image['url'];
}
$source_path = $source_image['file'];
$res_backup = array('success' => true, 'error_message' => '');
$webp_path = preg_replace('/.(jpe?g|png|gif)$/', '.webp', $source_path);
if(strlen($speedycache->image['name']) === 0){
return array('success' => false, 'error_code' => 11);
}
if(!file_exists($source_path)){
return array('success' => false, 'error_code' => 8);
}
if(!pathinfo($source_image['url'], PATHINFO_EXTENSION)){
return array('success' => false, 'error_code' => 14);
}
// If the URL of the image is a webp
if(pathinfo($source_image['url'], PATHINFO_EXTENSION) == 'webp' && file_exists($webp_path)){
return array('success' => false, 'error_code' => 23);
}
if(@filesize($source_path) > 5000000){
return array("success" => false, 'error_code' => 9);
}
if(!self::allowed_mime($source_path)){
return array('success' => false, 'error_code' => 21);
}
if(!self::path_is_image($source_path)){
return array('success' => false, 'error_code' => 16);
}
if(filesize($source_path) == 0){
return array('success' => false, 'error_code' => 15);
}
if(@rename($source_path, $source_path.'_writabletest')){
rename($source_path.'_writabletest', $source_path);
}else{
return array('success' => false, 'error_message' => $source_path . ' is not writable', 'error_code' => 4);
}
$optm_result = self::start_optimization($source_path); // here we need to plugin compression static function
if(empty($optm_result['success'])){
//NOTE:Place some error Message here.
return $optm_result;
}
if(!file_exists($webp_path)){
return array('success' => false, 'error_code' => 19, 'error_message' => $webp_path . ' destination_path is not saved');
}
if(filesize($webp_path) <= 0){
return array('success' => false, 'error_code' => 20, 'error_message' => $webp_path . ' file size of destination_path is zero');
}
$diff = self::compare_sizes($source_path, $webp_path);
return array('success' => true, 'destination_path' => $webp_path, 'reduction' => $diff);
}
static function start_optimization($img){
global $speedycache;
switch($speedycache->image['settings']['compression_method']){
case 'gd':
return self::gd_webp($img);
case 'imagick':
return self::imagick_webp($img);
case 'cwebp':
if(defined('SPEEDYCACHE_PRO')){
return \SpeedyCache\Image::cwebp_convert($img);
}
return array('success' => false, 'error_message' => 'SpeedyCache cwebp is a Pro feature');
default:
return array('success' => false, 'error_message' => 'The provided conversion method is not valid');
}
}
static function path_is_image($source_path){
$size = getimagesize($source_path);
if(empty($size)){
return false;
}
return true;
}
static function get_quality($img){
$dimensions = $img->getImageGeometry();
if($dimensions['width'] < 200 && $dimensions['height'] < 200){
return 85;
}
return 90;
}
static function compare_sizes($source_path, $destination_path){
$diff = filesize($source_path) - filesize($destination_path);
return ($diff > 0) ? $diff : 1;
}
//TODO:: Will need it when we will add non webp compression
static function create_backup_folder($destination_path){
global $speedycache;
$destination_path = str_replace($speedycache->image['upload_dir']['basedir'], '', $destination_path);
$path_arr = explode('/', $destination_path);
$path = $speedycache->image['upload_dir']['basedir'];
for ($i=1; $i < count($path_arr) - 1; $i++){
$parent_path = $path;
$path = $path.'/'.$path_arr[$i];
if(is_dir($path)){
continue;
}
if(@mkdir($path, 0755, true)){
//
}else{
//warning
if($path_arr[$i] == 'speedycache-backup'){
//toDO: to stop cron job and warn the user
}
return array('success' => false, 'error_message' => $parent_path.' is not writable', 'error_code' => 2);
}
}
return array('success' => true, 'error_message' => '');
}
static function set_id($id = null){
global $speedycache;
$get_id = speedycache_optget('id');
if(!empty($get_id)){
$speedycache->image['id'] = intval($get_id);
}elseif(!empty($id)){
$speedycache->image['id'] = intval($id);
}else{
$speedycache->image['id'] = self::get_first_id();
}
}
static function set_images(){
global $speedycache;
if(empty($speedycache->image['metadata']['file'])){
return;
}
$arr = array(
'file' => $speedycache->image['upload_dir']['basedir'].'/'.$speedycache->image['metadata']['file'],
'url' => $speedycache->image['upload_dir']['baseurl'].'/'.$speedycache->image['metadata']['file'],
'width' => $speedycache->image['metadata']['width'],
'height' => $speedycache->image['metadata']['height'],
'mime_type' => ''
);
array_push($speedycache->image['images'], $arr);
$i = 0;
$image_error = false;
if(!is_array($speedycache->image['metadata']['sizes'])){
if(empty($image_error)){
self::not_in_metadata();
}
}
foreach((array)$speedycache->image['metadata']['sizes'] as $key => $value){
$value['url'] = $speedycache->image['url'].$value['file'];
$value['file'] = $speedycache->image['path'].$value['file'];
$value['mime_type'] = isset($value['mime-type']) ? $value['mime-type'] : '';
unset($value['mime-type']);
if($i == 0){
if(self::not_found(self::get_correct_url($speedycache->image['upload_dir']['baseurl'].'/'.$speedycache->image['metadata']['file']))){
$image_error = true;
break;
}
}
if(!self::not_found(self::get_correct_url($value['url'])) && self::allowed_mime($value['file'])){
array_push($speedycache->image['images'], $value);
}
$i++;
}
if(empty($image_error)){
self::not_in_metadata();
}
}
static function get_correct_url($path){
if(preg_match('/^\/'.SPEEDYCACHE_WP_CONTENT_DIR.'/i', $path)){
// content_url() must return HTTP but it return /wp-content so we need to check
if(content_url() == '/'.SPEEDYCACHE_WP_CONTENT_DIR && home_url() == site_url()){
$path = home_url().$path;
}
}
return $path;
}
static function not_in_metadata(){
global $speedycache;
$paths = array();
foreach($speedycache->image['images'] as $key => $value){
array_push($paths, $value['file']);
}
$files = glob($speedycache->image['path'].$speedycache->image['name'].'-'.'*');
foreach((array)$files as $file){
if(@filesize($file) > 1000000){
continue;
}
if(!preg_match('/\.(jpg|jpeg|jpe|png|gif)$/i', $file)){
continue;
}
$exp_dos = explode('/',$file);
$basename = end($exp_dos);
if(in_array($file, $paths)){
continue;
}
if(!preg_match('/'.preg_quote($speedycache->image['name'], '/').'-(\d+)x(\d+)\..+/', $basename, $dimensions)){
continue;
}
$value = array(
'url' => $speedycache->image['url'].$basename,
'file' => $file,
'width' => $dimensions[1],
'height' => $dimensions[2],
);
if(!self::not_found($value['url'])){
array_push($speedycache->image['images'], $value);
}
}
}
static function set_path(){
global $speedycache;
$speedycache->image['path'] = $speedycache->image['upload_dir']['basedir'].'/'.preg_replace('/'.preg_quote($speedycache->image['name'], '/').'.+/', '', $speedycache->image['metadata']['file']);
}
static function set_url(){
global $speedycache;
$speedycache->image['url'] = $speedycache->image['upload_dir']['baseurl'].'/'.preg_replace('/'.preg_quote($speedycache->image['name'], '/').'.+/', '', $speedycache->image['metadata']['file']);
}
static function set_name(){
global $speedycache;
if(empty($speedycache->image['metadata'])){
return;
}
if(isset($speedycache->image['metadata']['sizes']) && count($speedycache->image['metadata']['sizes']) > 0){
$array_values = array_values($speedycache->image['metadata']['sizes']);
$speedycache->image['name'] = preg_replace('/-'.$array_values[0]['width'].'x'.$array_values[0]['height'].'.+/', '', $array_values[0]['file']);
if(!$speedycache->image['name']){
$speedycache->image['name'] = substr($speedycache->image['metadata']['file'], strrpos($speedycache->image['metadata']['file'], '/') + 1);
}
return;
}
$info = pathinfo($speedycache->image['metadata']['file']);
$speedycache->image['name'] = basename($speedycache->image['metadata']['file'],'.'.$info['extension']);
//$this->name = substr($this->metadata['file'], strrpos($this->metadata['file'], '/') + 1);
}
static function set_meta_data(){
global $speedycache;
$speedycache->image['metadata'] = wp_get_attachment_metadata($speedycache->image['id']);
}
//to get last image which is not optimized
static function get_first_id(){
$query_image = new \WP_Query(array(
'order' => 'DESC',
'orderby' => 'ID',
'post_type' => 'attachment',
'post_mime_type' => 'image/jpeg, image/png, image/gif',
'post_status' => 'inherit',
'posts_per_page' => 1,
'meta_query' => array(
array(
'key' => 'speedycache_optimisation',
'compare' => 'NOT EXISTS'
),
array(
'key' => '_wp_attachment_metadata',
'compare' => 'EXISTS'
)
)
));
return count($query_image->posts) == 1 ? $query_image->posts[0]->ID : false;
}
static function statics_data(){
$res = array(
'total_image_number' => self::image_count(),
'error' => self::error_count(),
'optimized' => self::optimized_file_count(),
'uncompressed' => self::uncompressed_count(),
'reduction' => self::total_reduction(),
'percent' => 0,
);
if($res['optimized'] > 0){
$res['percent'] = ($res['optimized'] - $res['error']) * 100/$res['optimized'];
}else{
$res['percent'] = 0;
}
$res['percent'] = number_format($res['percent'], 2);
$res['reduction'] = $res['reduction'];
return $res;
}
static function revert_all(){
global $speedycache;
if(!current_user_can('manage_options')){
wp_die('Must Be admin');
}
$images = new \WP_Query(array(
'order' => 'DESC',
'orderby' => 'ID',
'post_type' => 'attachment',
'post_mime_type' => array('image/jpeg', 'image/png', 'image/gif'),
'post_status' => 'inherit',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'speedycache_optimisation',
'compare' => 'EXISTS'
)
)
));
$failed = true;
if(count($images->posts) <= 100){
if($images->posts && count($images->posts) > 0){
foreach($images->posts as $key => $post){
$speedycache->image['id'] = $post->ID;
$result = self::revert();
if($result['success'] === true){
$failed = false;
}
}
}
if(!empty($failed)){
wp_send_json(array('success' => false, 'message' => __('Files can\'t be reverted', 'speedycache')));
}
wp_send_json(array('success' => true));
}
$schedule_posts = [];
foreach($images->posts as $key => $post){
if(100 === count($schedule_posts) || !empty($erase)){
$schedule_posts = [];
}
$erase = false; // Flag to unset the $scheduled_posts
$schedule_posts[] = $post->ID;
// Check if we have reached 99 and make sure its not the last index
if(count($schedule_posts) <= 99 && $key !== (count($images->posts) - 1)){
continue;
}
// Skip if alredy on schedule list.
if(wp_next_scheduled('speedycache_img_delete', array($schedule_posts))){
$erase = true;
continue;
}
$scheduled = self::get_optimization_schedule(array('speedycache_img_delete'));
$time = time();
if(!empty($scheduled) && isset(end($scheduled)['time'])){
// getting the last index to get the last scheduled event
$time = end($scheduled)['time'];
}
$final_schd_time = $time + 10;
if(!wp_next_scheduled('speedycache_img_delete', array($schedule_posts))){
wp_schedule_single_event($final_schd_time, 'speedycache_img_delete', array($schedule_posts));
continue;
}
}
wp_send_json(array('success' => true));
}
// Schedule deletion of image to reduce load on the server at a single time.
static function scheduled_delete($img_id){
global $speedycache;
if(empty($img_id)){
return;
}
if(is_scalar($img_id)){
$speedycache->image['id'] = $img_id;
self::revert();
return;
}
foreach($img_id as $id){
$speedycache->image['id'] = $id;
self::revert();
}
}
// Reverts a single image
static function revert(){
global $speedycache;
if(empty($speedycache->image['id'])){
return array('success' => false);
}
$optimization_data = get_post_meta($speedycache->image['id'], 'speedycache_optimisation', true);
// optm = optimization
$optm_json = base64_decode($optimization_data);
$optm_json = json_decode($optm_json, true);
if(empty($optm_json)){
return array('success' => false);
}
if(!empty($optm_json) && is_array($optm_json) && count($optm_json) == 1 && !empty($optm_json[0])){
if(!empty($optm_json[0]['error_code']) && $optm_json[0]['error_code'] == 18){
delete_post_meta($speedycache->image['id'], 'speedycache_optimisation');
delete_post_meta($speedycache->image['id'], 'speedycache_optimisation_reduction');
return array('success' => true);
}
}
$result = false;
$optm_json = array_reverse($optm_json);
$error_numbers = 0;
foreach($optm_json as $key => $image){
if(@!is_writable($image['file'])){
if(isset($speedycache->image['metadata']['file']) && preg_match('/'.preg_quote($speedycache->image['metadata']['file'], '/').'/', $image['url'])){
if(file_exists($image['file'])){
$result = array('success' => true, 'message' => $image['file'].' is not writable');
break;
}
delete_post_meta($speedycache->image['id'], 'speedycache_optimisation');
delete_post_meta($speedycache->image['id'], 'speedycache_optimisation_reduction');
}
}
if(
!empty($image['url']) &&
!preg_match('/\.webp$/', $image['url']) &&
isset($image['destination_path']) &&
file_exists($image['destination_path']) &&
(pathinfo($image['destination_path'], PATHINFO_EXTENSION) == 'webp')
){
@unlink($image['file']);
delete_post_meta($speedycache->image['id'], 'speedycache_optimisation');
delete_post_meta($speedycache->image['id'], 'speedycache_optimisation_reduction');
$result = array('success' => true);
continue;
}
if(!empty($image['error_code'])){
if(isset($speedycache->image['metadata']['file']) && preg_match('/'.preg_quote($speedycache->image['metadata']['file'], '/').'/', $image['url'])){
delete_post_meta($speedycache->image['id'], 'speedycache_optimisation');
delete_post_meta($speedycache->image['id'], 'speedycache_optimisation_reduction');
$result = array('success' => true);
}else{
$error_numbers++;
if($error_numbers == count($optm_json)){
delete_post_meta($speedycache->image['id'], 'speedycache_optimisation');
delete_post_meta($speedycache->image['id'], 'speedycache_optimisation_reduction');
$result = array('success' => true);
}
}
continue;
}
if(preg_match('/'.preg_quote($speedycache->image['metadata']['file'], '/').'/', $image['url'])){
delete_post_meta($speedycache->image['id'], 'speedycache_optimisation');
delete_post_meta($speedycache->image['id'], 'speedycache_optimisation_reduction');
$result = array('success' => true);
}
}
return $result;
}
static function revert_on_delete($id){
global $speedycache;
if(!wp_attachment_is_image($id)){
return;
}
$speedycache->image['id'] = $id;
self::revert();
}
static function get_error_text($id){
//Error Codes
$errors = array(
2 => __('In backup folder parent folder not writable', 'speedycache'),
3 => __('No need to optimize', 'speedycache'),
4 => __('Source is not writable', 'speedycache'),
5 => __('Destination is not writable', 'speedycache'),
6 => __('ImageMagick library is not avaliable', 'speedycache'),
7 => __('Error via api', 'speedycache'),
8 => __('Source file does not exist', 'speedycache'),
9 => __('Image size exceed 20mb limit while processing', 'speedycache'),
11 => __('Empty Name', 'speedycache'),
12 => __('Forbidden', 'speedycache'),
13 => __('CloudFlare to restrict access', 'speedycache'),
14 => __('No Extension', 'speedycache'),
15 => __('Image size is 0Kb', 'speedycache'),
16 => __('Corrupted Image', 'speedycache'),
17 => __('Empty metadata', 'speedycache'),
18 => __('No Image', 'speedycache'),
19 => __('destination_move_source_path is not saved', 'speedycache'),
20 => __('file size of destination_move_source_path is zero', 'speedycache'),
21 => __('Unacceptable file type', 'speedycache'),
23 => __('WEBP create by other tool', 'speedycache'),
);
return isset($errors[$id]) ? $errors[$id] : 'Unkown error code';
}
// TODO:: Will use it when we will do non-webp compression
static function backup_folder_exist(){
global $speedycache;
$backup_folder_path = $speedycache->image['upload_dir']['basedir'].'/speedycache-backup';
if(is_dir($backup_folder_path)){
return true;
}
if(@mkdir($backup_folder_path, 0755, true)){
return true;
}
return false;
}
static function push_main_image($arr){
if(!isset($arr[0]) || isset($arr[0]->error_code)){
return $arr;
}
$main = clone $arr[0];
$total_reduction = 0;
foreach($arr as $std_key => $std_value){
if(!isset($std_value->error_code)){
if(isset($std_value->reduction) && $std_value->reduction){
$total_reduction = $total_reduction + $std_value->reduction;
}
}
}
$main->reduction = $total_reduction;
array_unshift($arr, $main);
return $arr;
}
static function list_content($query_images_args = array()){
global $speedycache;
remove_filter('posts_fields', '\SpeedyCache\Image::count_posts_fields'); //was causing bug
$query_image = new \WP_Query( $query_images_args );
$return_output = '';
if(empty($query_image->posts) || count($query_image->posts) <= 0){
return self::get_empty_row();
}
$count = 0;
foreach($query_image->posts as $key => $post){
$count++;
$value_json = get_post_meta($post->ID, 'speedycache_optimisation', true);
$tmpvalue_json = base64_decode($value_json);
$std = json_decode($tmpvalue_json);
$revert = true;
$std = self::push_main_image($std);
foreach($std as $std_key => $std_value){
$content = ($std_key === 0) ? self::get_row() : self::get_child_row();
if(empty($content)){
continue;
}
$std_value->destination_path = isset($std_value->destination_path) ? $std_value->destination_path : '';
$std_value->reduction = isset($std_value->reduction) ? $std_value->reduction : 0;
if($std_key === 0 && $revert){
$revert_button = '';
}else{
$revert_button = 'display:none;';
}
if(isset($std_value->error_code) && $std_value->error_code == 8){
$revert_button = 'display:none;';
}
if(file_exists($std_value->destination_path)){
$backup_url = $std_value->url.'?v='.time();
$backup_title = 'Original Image';
$backup_error_style = '';
}else{
if(isset($std_value->error_code) && $std_value->error_code){
$backup_url = get_edit_post_link($std_value->id);
$backup_title = self::get_error_text($std_value->error_code);
$backup_error_style = 'color: #FF0000;cursor:pointer;font-weight:bold;';
}else{
$backup_url = '#';
$backup_title = '';
$backup_error_style = '';
}
}
$std_value->file = preg_replace('/.(jpg|jpeg|png|gif)$/','.webp', $std_value->file);
if(file_exists($std_value->file)){
$std_value->url = preg_replace('/.(jpg|jpeg|png|gif)$/','.webp', $std_value->url).'?v='.time();
}else{
$std_value->url = SPEEDYCACHE_PRO_URL.'/assets/images/no-image.png';
}
$short_code = array(
'{{post_id}}',
'{{attachment}}',
'{{post_title}}',
'{{url}}',
'{{width}}',
'{{height}}',
'{{reduction}}',
'{{date}}',
'{{revert_button}}',
'{{backup_url}}',
'{{backup_title}}',
'{{backup_error_style}}'
);
$datas = array(
$std_value->id,
$std_value->url,
$post->post_title,
$std_value->url,
$std_value->width,
$std_value->height,
$std_value->reduction/1000,
date('d-m-Y
H:i:s', $std_value->time),
$revert_button,
$backup_url,
$backup_title,
$backup_error_style
);
$return_output .= str_replace($short_code, $datas, $content);
}
}
return $return_output;
}
static function allowed_mime($filename){
global $speedycache;
$mimetype = false;
if(!file_exists($filename)){
return false;
}
if(function_exists('finfo_open')){
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $filename);
finfo_close($finfo);
}else if(function_exists('getimagesize')){
$img = getimagesize($filename);
$mimetype = $img['mime'];
}else{
echo 'not found mime_content_type';
exit;
}
if($speedycache->image['settings']['compression_method'] === 'cwebp' && self::gif2webp_exists()){
if(preg_match('/(jpg|jpeg|jpe|png|gif)/i', $mimetype)){
return true;
}
return false;
}
if(preg_match('/(jpg|jpeg|jpe|png)/i', $mimetype)){
return true;
}
return false;
}
// Check if the image is available, the response code should be 200
static function not_found($url){
return false;
$res = wp_remote_head($url, array('timeout' => 3 ));
if(is_wp_error($res)){
$url_header = @get_headers($url);
if(preg_match('/200\s+OK/i', $url_header[0])){
return false;
}
return true;
}
if($res['response']['code'] == 200){
return false;
}
return true;
}
//Checks if the image is Unique
static function unique_array($images){
if(count($images) <= 1){
return $images;
}
$arr = array();
$images_tmp = array();
foreach($images as $key => $value){
if(!in_array($value['file'], $arr)){
array_push($arr, $value['file']);
array_push($images_tmp, $value);
}
}
return $images_tmp;
}
//Template static functions Starts Here
//Table row for the converted Image
static function get_row(){
return '