pezy]/i', '', $size);
$size = preg_replace('/[^0-9\.]/', '', $size);
if ( $unit )
return round( $size * pow( 1024, stripos( 'bkmgtpezy', $unit[0] ) ) );
else
round( $size );
}
function get_max_filesize() {
if ( defined ('HHVM_VERSION' ) ) {
$post_max_size = ini_get( 'post_max_size' ) ? (int)$this->parse_ini_size( ini_get( 'post_max_size' ) ) : (int)ini_get( 'hhvm.server.max_post_size' );
$upload_max_filesize = ini_get( 'upload_max_filesize' ) ? (int)$this->parse_ini_size( ini_get( 'upload_max_filesize' ) ) :
(int)ini_get( 'hhvm.server.upload.upload_max_file_size' );
}
else {
$post_max_size = (int)$this->parse_ini_size( ini_get( 'post_max_size' ) );
$upload_max_filesize = (int)$this->parse_ini_size( ini_get( 'upload_max_filesize' ) );
}
$max = min( $post_max_size, $upload_max_filesize );
return $max > 0 ? $max : 66600000;
}
/**
*
* RESPONSIVE IMAGES METHOD
*
*/
function calculate_image_srcset( $srcset, $size, $image_src, $image_meta, $attachment_id ) {
if ( get_option( "wr2x_disable_responsive" ) )
return null;
if ( empty( $srcset ) ) {
return $srcset;
}
$retinized_srcset = $srcset;
$count = 0;
$total = 0;
foreach ( $srcset as $s => $cfg ) {
$total++;
$retinized_srcset[$s]['url'] = $this->cdn_this( $cfg['url'], $attachment_id );
if ( $this->method !== "none" ) {
$retina = $this->cdn_this( $this->get_retina_from_url( $cfg['url'] ), $attachment_id );
if ( !empty( $retina ) ) {
$count++;
$retinized_srcset[(int)$s * 2] = array( 'url' => $retina, 'descriptor' => 'w', 'value' => (int)$s * 2 );
}
}
}
$this->log( "WP's srcset: " . $count . " retina files added out of " . $total . " image sizes" );
return $retinized_srcset;
}
/**
*
* ISSUES CALCULATION AND FUNCTIONS
*
*/
// Compares two images dimensions (resolutions) against each while accepting an margin error
function are_dimensions_ok( $width, $height, $retina_width, $retina_height ) {
$w_margin = $width - $retina_width;
$h_margin = $height - $retina_height;
return ( $w_margin >= -2 && $h_margin >= -2 );
}
// UPDATE THE ISSUE STATUS OF THIS ATTACHMENT
function update_issue_status( $attachmentId, $issues = null, $info = null ) {
if ( $this->is_ignore( $attachmentId ) )
return;
if ( $issues == null )
$issues = $this->get_issues();
if ( $info == null )
$info = $this->retina_info( $attachmentId );
$consideredIssue = in_array( $attachmentId, $issues );
$realIssue = $this->info_has_issues( $info );
if ( $consideredIssue && !$realIssue )
$this->remove_issue( $attachmentId );
else if ( !$consideredIssue && $realIssue )
$this->add_issue( $attachmentId );
return $realIssue;
}
function get_issues() {
$issues = get_transient( 'wr2x_issues' );
if ( !$issues || !is_array( $issues ) ) {
$issues = array();
set_transient( 'wr2x_issues', $issues );
}
return $issues;
}
// CHECK IF THE 'INFO' OBJECT CONTAINS ISSUE (RETURN TRUE OR FALSE)
function info_has_issues( $info ) {
foreach ( $info as $aindex => $aval ) {
if ( is_array( $aval ) || $aval == 'PENDING' )
return true;
}
return false;
}
function calculate_issues() {
global $wpdb;
$postids = $wpdb->get_col( "
SELECT p.ID FROM $wpdb->posts p
WHERE post_status = 'inherit'
AND post_type = 'attachment'" . $this->create_sql_if_wpml_original() . "
AND ( post_mime_type = 'image/jpeg' OR
post_mime_type = 'image/jpg' OR
post_mime_type = 'image/png' OR
post_mime_type = 'image/gif' )
" );
$issues = array();
foreach ( $postids as $id ) {
$info = $this->retina_info( $id );
if ( $this->info_has_issues( $info ) )
array_push( $issues, $id );
}
set_transient( 'wr2x_ignores', array() );
set_transient( 'wr2x_issues', $issues );
}
function add_issue( $attachmentId ) {
if ( $this->is_ignore( $attachmentId ) )
return;
$issues = $this->get_issues();
if ( !in_array( $attachmentId, $issues ) ) {
array_push( $issues, $attachmentId );
set_transient( 'wr2x_issues', $issues );
}
return $issues;
}
function remove_issue( $attachmentId, $onlyIgnore = false ) {
$issues = array_diff( $this->get_issues(), array( $attachmentId ) );
set_transient( 'wr2x_issues', $issues );
if ( !$onlyIgnore )
$this->remove_ignore( $attachmentId );
return $issues;
}
// IGNORE
function get_ignores( $force = false ) {
$ignores = get_transient( 'wr2x_ignores' );
if ( !$ignores || !is_array( $ignores ) ) {
$ignores = array();
set_transient( 'wr2x_ignores', $ignores );
}
return $ignores;
}
function is_ignore( $attachmentId ) {
$ignores = $this->get_ignores();
return in_array( $attachmentId, $ignores );
}
function remove_ignore( $attachmentId ) {
$ignores = $this->get_ignores();
$ignores = array_diff( $ignores, array( $attachmentId ) );
set_transient( 'wr2x_ignores', $ignores );
return $ignores;
}
function add_ignore( $attachmentId ) {
$ignores = $this->get_ignores();
if ( !in_array( $attachmentId, $ignores ) ) {
array_push( $ignores, $attachmentId );
set_transient( 'wr2x_ignores', $ignores );
}
$this->remove_issue( $attachmentId, true );
return $ignores;
}
/**
*
* GET DETAILS / INFO
*
*/
// Get the information about a specific Media (usually for the Retina Dashboard)
function get_media_status_one( $mediaId ) {
$mediaId = (int)$mediaId;
$entry = new stdClass();
$entry->ID = $mediaId;
$entry->post_title = get_the_title( $mediaId );
$entry->metadata = wp_get_attachment_metadata( $mediaId, true );
$entry->info = $this->retina_info( $mediaId, ARRAY_A );
$entry->thumbnail_url = wp_get_attachment_thumb_url( $mediaId );
$attached_file = get_attached_file( $mediaId );
$entry->filesize = $attached_file ? size_format( filesize( $attached_file ), 2 ) : 0;
$version = get_post_meta( $mediaId, '_media_version', true );
$entry->version = (int)$version;
return $entry;
}
function html_get_basic_retina_info_full( $attachmentId, $retina_info ) {
$status = ( isset( $retina_info ) && isset( $retina_info['full-size'] ) ) ? $retina_info['full-size'] : 'IGNORED';
if ( $status == 'EXISTS' ) {
return '
';
}
else if ( is_array( $status ) ) {
return '';
}
else if ( $status == 'IGNORED' ) {
return __( "N/A", "wp-retina-2x" );
}
return $status;
}
function format_title( $i, $size ) {
return $i . ' (' . ( $size['width'] * 2 ) . 'x' . ( $size['height'] * 2 ) . ')';
}
static function size_shortname( $name ) {
if ( $name === 'thumbnail' ) {
return 'T';
}
else if ( $name === 'medium' ) {
return 'M';
}
else if ( $name === 'medium_large' ) {
return 'ML';
}
else if ( $name === 'large' ) {
return 'L';
}
else if ( $name === '1536x1536' ) {
return 'W1';
}
else if ( $name === '2048x2048' ) {
return 'W2';
}
else if ( $name === 'post-thumbnail' ) {
return 'PT';
}
$name = preg_split( '[_-]', $name );
$short = strtoupper( substr( $name[0], 0, 2 ) );
if ( count( $name ) > 1 )
$short .= strtoupper( substr( $name[1], 0, 2 ) );
return $short;
}
// Information for the 'Media Sizes Retina-ized' Column in the Retina Dashboard
function html_get_basic_retina_info( $attachmentId, $retina_info ) {
$sizes = $this->get_active_image_sizes();
$result = '';
foreach ( $sizes as $i => $size ) {
$status = ( isset( $retina_info ) && isset( $retina_info[$i] ) ) ? $retina_info[$i] : null;
if ( is_array( $status ) )
$result .= '- '
. self::size_shortname( $i ) . '
';
else if ( $status == 'EXISTS' )
$result .= '- '
. self::size_shortname( $i ) . '
';
else if ( $status == 'PENDING' )
$result .= '- '
. self::size_shortname( $i ) . '
';
else if ( $status == 'MISSING' )
$result .= '- '
. self::size_shortname( $i ) . '
';
else if ( $status == 'IGNORED' )
$result .= '- '
. self::size_shortname( $i ) . '
';
else {
error_log( "Retina: This status is not recognized: " . $status );
}
}
$result .= '
';
return $result;
}
// Information for Details in the Retina Dashboard
function html_get_details_retina_info( $post, $retina_info ) {
if ( !class_exists( 'MeowPro_WR2X_Core' ) ) {
return __( "PRO VERSION ONLY", 'wp-retina-2x' );
}
$sizes = $this->get_image_sizes();
$total = 0; $possible = 0; $issue = 0; $ignored = 0; $retina = 0;
$postinfo = get_post( $post, OBJECT );
$meta = wp_get_attachment_metadata( $post );
$fullsize_file = get_attached_file( $post );
$pathinfo_system = pathinfo( $fullsize_file );
$pathinfo = pathinfo( $meta['file'] );
$uploads = wp_upload_dir();
$basepath_url = trailingslashit( $uploads['baseurl'] ) . $pathinfo['dirname'];
if ( get_option( "wr2x_full_size" ) ) {
$sizes['full-size']['file'] = $pathinfo['basename'];
$sizes['full-size']['width'] = $meta['width'];
$sizes['full-size']['height'] = $meta['height'];
$meta['sizes']['full-size']['file'] = $pathinfo['basename'];
$meta['sizes']['full-size']['width'] = $meta['width'];
$meta['sizes']['full-size']['height'] = $meta['height'];
}
$result = "This screen displays all the image sizes set-up by your WordPress configuration with the Retina details.
";
$result .= "
";
$result .= "Title:
" . ( $postinfo->post_title ? $postinfo->post_title : 'Untitled' ) . "";
$result .= "Full-size:
" . $meta['width'] . "×" . $meta['height'] . "";
$result .= "Image URL:
" . trailingslashit( $uploads['baseurl'] ) . $meta['file'] . "";
$result .= "Image Path: " . $fullsize_file . "
";
$result .= "
";
$result .= "";
return $result;
}
/**
*
* WP RETINA 2X CORE
*
*/
// Get WordPress upload directory
function get_upload_root() {
$uploads = wp_upload_dir();
return $uploads['basedir'];
}
function get_upload_root_url() {
$uploads = wp_upload_dir();
return $uploads['baseurl'];
}
// Get WordPress directory
function get_wordpress_root() {
return ABSPATH;
}
// Resize the image
function resize( $file_path, $width, $height, $crop, $newfile, $customCrop = false ) {
$crop_params = $crop == '1' ? true : $crop;
$orig_size = getimagesize( $file_path );
$image_src = array ();
$image_src[0] = $file_path;
$image_src[1] = $orig_size[0];
$image_src[2] = $orig_size[1];
$file_info = pathinfo( $file_path );
$newfile_info = pathinfo( $newfile );
$extension = '.' . $newfile_info['extension'];
$no_ext_path = $file_info['dirname'] . '/' . $file_info['filename'];
$cropped_img_path = $no_ext_path . '-' . $width . 'x' . $height . "-tmp" . $extension;
$image = wp_get_image_editor( $file_path );
if ( is_wp_error( $image ) ) {
$this->log( "Resize failure: " . $image->get_error_message() );
error_log( "Resize failure: " . $image->get_error_message() );
return null;
}
// Resize or use Custom Crop
if ( !$customCrop )
$image->resize( $width, $height, $crop_params );
else
$image->crop( $customCrop['x'] * $customCrop['scale'], $customCrop['y'] * $customCrop['scale'], $customCrop['w'] * $customCrop['scale'], $customCrop['h'] * $customCrop['scale'], $width, $height, false );
// Quality
$quality = get_option( 'wr2x_quality', 90 );
$image->set_quality( $quality );
$saved = $image->save( $cropped_img_path );
if ( is_wp_error( $saved ) ) {
$error = $saved->get_error_message();
trigger_error( "Retina: Could not create/resize image " . $file_path . " to " . $newfile . ": " . $error , E_WARNING );
error_log( "Retina: Could not create/resize image " . $file_path . " to " . $newfile . ":" . $error );
return null;
}
if ( rename( $saved['path'], $newfile ) )
$cropped_img_path = $newfile;
else {
trigger_error( "Retina: Could not move " . $saved['path'] . " to " . $newfile . "." , E_WARNING );
error_log( "Retina: Could not move " . $saved['path'] . " to " . $newfile . "." );
return null;
}
$new_img_size = getimagesize( $cropped_img_path );
$new_img = str_replace( basename( $image_src[0] ), basename( $cropped_img_path ), $image_src[0] );
$vt_image = array ( 'url' => $new_img, 'width' => $new_img_size[0], 'height' => $new_img_size[1] );
return $vt_image;
}
// Return the retina file if there is any (system path)
function get_retina( $file ) {
$pathinfo = pathinfo( $file ) ;
if ( empty( $pathinfo ) || !isset( $pathinfo['dirname'] ) ) {
if ( empty( $file ) ) {
$this->log( "An empty filename was given to $this->get_retina()." );
error_log( "An empty filename was given to $this->get_retina()." );
}
else {
$this->log( "Pathinfo is null for " . $file . "." );
error_log( "Pathinfo is null for " . $file . "." );
}
return null;
}
$retina_file = trailingslashit( $pathinfo['dirname'] ) . $pathinfo['filename'] .
$this->retina_extension() . ( isset( $pathinfo['extension'] ) ? $pathinfo['extension'] : "" );
if ( file_exists( $retina_file ) )
return $retina_file;
$this->log( "Retina file at '{$retina_file}' does not exist." );
return null;
}
function get_retina_from_remote_url( $url ) {
$over_http = get_option( 'wr2x_over_http_check', false ) && class_exists( 'MeowPro_WR2X_Core' );
if ( !$over_http )
return null;
$potential_retina_url = $this->rewrite_url_to_retina( $url );
$response = wp_remote_head( $potential_retina_url, array(
'user-agent' => "MeowApps-Retina",
'sslverify' => false,
'timeout' => 10
));
if ( is_array( $response ) && is_array( $response['response'] ) && isset( $response['response']['code'] ) ) {
if ( $response['response']['code'] == 200 ) {
$this->log( "Retina URL: " . $potential_retina_url, true);
return $potential_retina_url;
}
else
$this->log( "Remote head failed with code " . $response['response']['code'] . "." );
}
$this->log( "Retina URL couldn't be found (URL -> Retina URL).", true);
}
// Return retina URL from the image URL
function get_retina_from_url( $url ) {
$this->log( "Standard URL: " . $url, true);
$over_http = get_option( 'wr2x_over_http_check', false ) && class_exists( 'MeowPro_WR2X_Core' );
$filepath = $this->from_url_to_system( $url );
if ( empty ( $filepath ) )
return $this->get_retina_from_remote_url( $url );
$this->log( "Standard PATH: " . $filepath, true);
$system_retina = $this->get_retina( $filepath );
if ( empty ( $system_retina ) )
return $this->get_retina_from_remote_url( $url );
$this->log( "Retina PATH: " . $system_retina, true);
$retina_url = $this->rewrite_url_to_retina( $url );
$this->log( "Retina URL: " . $retina_url, true);
return $retina_url;
}
// Get the filepath from the URL
function from_url_to_system( $url ) {
$img_pathinfo = $this->get_pathinfo_from_image_src( $url );
$filepath = trailingslashit( $this->get_wordpress_root() ) . $img_pathinfo;
if ( file_exists( $filepath ) )
return $filepath;
$filepath = trailingslashit( $this->get_upload_root() ) . $img_pathinfo;
if ( file_exists( $filepath ) )
return $filepath;
$this->log( "Standard PATH couldn't be found (URL -> System).", true);
return null;
}
function rewrite_url_to_retina( $url ) {
$whereisdot = strrpos( $url, '.' );
$url = substr( $url, 0, $whereisdot ) . $this->retina_extension() . substr( $url, $whereisdot + 1 );
return $url;
}
// Clean the PathInfo of the IMG SRC.
// IMPORTANT: This function STRIPS THE UPLOAD FOLDER if it's found
// REASON: The reason is that on some installs the uploads folder is linked to a different "unlogical" physical folder
// http://wordpress.org/support/topic/cant-find-retina-file-with-custom-uploads-constant?replies=3#post-5078892
function get_pathinfo_from_image_src( $image_src ) {
$uploads_url = trailingslashit( $this->get_upload_root_url() );
if ( strpos( $image_src, $uploads_url ) === 0 )
return ltrim( substr( $image_src, strlen( $uploads_url ) ), '/');
else if ( strpos( $image_src, wp_make_link_relative( $uploads_url ) ) === 0 )
return ltrim( substr( $image_src, strlen( wp_make_link_relative( $uploads_url ) ) ), '/');
$img_info = parse_url( $image_src );
return ltrim( $img_info['path'], '/' );
}
// Rename this filename with CDN
function cdn_this( $url, $mediaId = null ) {
$cdn_domain = "";
$cdn_params = array();
$wr2x_easyio_domain = get_option( 'wr2x_easyio_domain', '' );
$wr2x_cdn_domain = get_option( 'wr2x_cdn_domain', '' );
// CDN Domain
if ( !empty( $wr2x_easyio_domain ) ) {
$cdn_domain = "${wr2x_easyio_domain}";
if ( get_option( 'wr2x_easyio_lossless', false ) ) {
$cdn_params['lossy'] = 0;
}
}
else if ( !empty( $wr2x_cdn_domain ) ) {
$cdn_domain = $wr2x_cdn_domain;
}
else {
return $url;
}
// Version
if ( !empty( $mediaId ) ) {
$version = get_post_meta( $mediaId, '_media_version', true );
if ( $version ) {
$cdn_params['version'] = $version;
}
}
$home_url = parse_url( home_url() );
$uploads_url = trailingslashit( $this->get_upload_root_url() );
$uploads_url_cdn = str_replace( $home_url['host'], $cdn_domain, $uploads_url );
// Perform additional CDN check (Issue #1631 by Martin)
if ( strpos( $url, $uploads_url_cdn ) === 0 ) {
$this->log( "URL already has CDN: $url" );
return $url;
}
$this->log( "URL before CDN: $url" );
$queryUrl = !empty( $cdn_params ) ? ( '?' . http_build_query( $cdn_params ) ) : '';
$site_url = preg_replace( '#^https?://#', '', rtrim( get_site_url(), '/' ) );
$new_url = str_replace( $site_url, $cdn_domain, $url ) . $queryUrl;
$this->log( "URL with CDN: $new_url" );
return $new_url;
}
// function admin_menu() {
// add_options_page( 'Retina', 'Retina', 'manage_options', 'wr2x_settings', 'wr2x_settings_page' );
// }
function get_image_sizes( $output_type = OBJECT ) {
$sizes = array();
global $_wp_additional_image_sizes;
foreach ( get_intermediate_image_sizes() as $s ) {
// Get the information
$crop = false;
if ( isset( $_wp_additional_image_sizes[$s] ) ) {
$width = intval( $_wp_additional_image_sizes[$s]['width'] );
$height = intval( $_wp_additional_image_sizes[$s]['height'] );
$crop = $_wp_additional_image_sizes[$s]['crop'];
}
else {
$width = intval( get_option( $s . '_size_w' ) );
$height = intval( get_option( $s . '_size_h' ) );
$crop = intval( get_option( $s . '_crop' ) );
}
// Retina shouldn't be active if the size is disabled
$enabled = !in_array( $s, $this->disabled_sizes );
$retina = in_array( $s, $this->retina_sizes );
if ( !$enabled && $retina ) {
$this->retina_sizes = array_diff( $this->retina_sizes, array( $s ) );
update_option( 'wr2x_retina_sizes', $this->retina_sizes );
$retina = false;
}
$sizes[$s] = array(
'width' => $width,
'height' => $height,
'crop' => $crop,
'enabled' => $enabled,
'retina' => $retina,
'name' => $s,
'shortname' => Meow_WR2X_Core::size_shortname( $s )
);
}
// Let's re-add the disabled sizes
$disabled_to_add = array();
foreach ( $this->disabled_sizes as $size ) {
$retina = in_array( $size, $this->retina_sizes );
if ( $retina ) {
$retina_sizes = array_diff( $this->retina_sizes, array( $size ) );
update_option( 'wr2x_retina_sizes', $retina_sizes );
}
if ( !array_key_exists( $size, $sizes ) ) {
$disabled_to_add[$size] = array(
'enabled' => false,
'retina' => false,
'name' => $size,
'shortname' => Meow_WR2X_Core::size_shortname( $size )
);
}
}
usort( $disabled_to_add, array( $this, 'sizes_sort_func' ) );
$sizes = array_merge( $sizes, $disabled_to_add );
// if ( get_option( 'wr2x_disable_medium_large' ) )
// unset( $sizes['medium_large'] );
if ( $output_type === ARRAY_A ) {
return array_values( $sizes );
}
return $sizes;
}
function sizes_sort_func( $a, $b ) {
return strncmp( $a['shortname'], $b['shortname'], 10 );
}
function get_active_image_sizes() {
$sizes = $this->get_image_sizes();
$active_sizes = array();
// $ignore = get_option( "wr2x_ignore_sizes", array() );
// if ( empty( $ignore ) )
// $ignore = array();
// $ignore = array_keys( $ignore );
foreach ( $sizes as $name => $attr ) {
$validSize = !empty( $attr['width'] ) || !empty( $attr['height'] );
if ( $validSize && $attr['retina'] ) {
$active_sizes[$name] = $attr;
}
}
return $active_sizes;
}
function is_wpml_installed() {
return function_exists( 'icl_object_id' ) && !class_exists( 'Polylang' );
}
// SQL Query if WPML with an AND to check if the p.ID (p is attachment) is indeed an original
// That is to limit the SQL that queries all the attachments
function create_sql_if_wpml_original() {
$whereIsOriginal = "";
if ( $this->is_wpml_installed() ) {
global $wpdb;
global $sitepress;
$tbl_wpml = $wpdb->prefix . "icl_translations";
$language = $sitepress->get_default_language();
$whereIsOriginal = " AND p.ID IN (SELECT element_id FROM $tbl_wpml WHERE element_type = 'post_attachment' AND language_code = '$language') ";
}
return $whereIsOriginal;
}
function increase_media_version( $mediaId ) {
$version = get_post_meta( $mediaId, '_media_version', true );
$version = $version ? intval( $version ) + 1 : 2;
update_post_meta( $mediaId, '_media_version', $version );
return $version;
}
function is_debug() {
static $debug = -1;
if ( $debug == -1 ) {
$debug = get_option( "wr2x_debug" );
}
return !!$debug;
}
function log( $data, $isExtra = false ) {
if ( !$this->is_debug() )
return;
$fh = fopen( trailingslashit( dirname(__FILE__) ) . 'wp-retina-2x.log', 'a' );
$date = date( "Y-m-d H:i:s" );
fwrite( $fh, "$date: {$data}\n" );
fclose( $fh );
}
// Based on http://wordpress.stackexchange.com/questions/6645/turn-a-url-into-an-attachment-post-id
function get_attachment_id( $file ) {
$query = array(
'post_type' => 'attachment',
'meta_query' => array(
array(
'key' => '_wp_attached_file',
'value' => ltrim( $file, '/' )
)
)
);
$posts = get_posts( $query );
foreach( $posts as $post )
return $post->ID;
return false;
}
// Return the retina extension followed by a dot
function retina_extension() {
return '@2x.';
}
function is_image_meta( $meta ) {
if ( !isset( $meta ) )
return false;
if ( !isset( $meta['sizes'] ) )
return false;
if ( !isset( $meta['width'], $meta['height'] ) )
return false;
return true;
}
// Adds the shortname to the metadata
function postprocess_metadata( $metadata ) {
if ( !empty( $metadata['sizes'] ) ) {
foreach ( $metadata['sizes'] as $key => $value ) {
$metadata['sizes'][$key]['shortname'] = self::size_shortname( $key );
}
}
return $metadata;
}
function retina_info( $id, $output_type = OBJECT ) {
$result = array();
$meta = wp_get_attachment_metadata( $id );
if ( !$this->is_image_meta( $meta ) )
return $result;
$original_width = $meta['width'];
$original_height = $meta['height'];
$sizes = $this->get_image_sizes();
$originalfile = get_attached_file( $id );
$pathinfo_fullsize = pathinfo( $originalfile );
$basepath = $pathinfo_fullsize['dirname'];
// Image Sizes
if ( $sizes ) {
foreach ( $sizes as $name => $attr ) {
$validSize = !empty( $attr['width'] ) || !empty( $attr['height'] );
if ( !$validSize || !$attr['retina'] ) {
$result[$name] = 'IGNORED';
continue;
}
// Check if the file related to this size is present
$pathinfo = null;
$retina_file = null;
if ( isset( $meta['sizes'][$name]['width'] ) && isset( $meta['sizes'][$name]['height']) && isset($meta['sizes'][$name]) && isset($meta['sizes'][$name]['file']) && file_exists( trailingslashit( $basepath ) . $meta['sizes'][$name]['file'] ) ) {
$normal_file = trailingslashit( $basepath ) . $meta['sizes'][$name]['file'];
$pathinfo = pathinfo( $normal_file ) ;
$retina_file = trailingslashit( $pathinfo['dirname'] ) . $pathinfo['filename'] . $this->retina_extension() . $pathinfo['extension'];
}
// None of the file exist
else {
$result[$name] = 'MISSING';
continue;
}
// The retina file exists
if ( $retina_file && file_exists( $retina_file ) ) {
$result[$name] = 'EXISTS';
continue;
}
// The size file exists
else if ( $retina_file )
$result[$name] = 'PENDING';
// The retina file exists
$required_width = $meta['sizes'][$name]['width'] * 2;
$required_height = $meta['sizes'][$name]['height'] * 2;
if ( !$this->are_dimensions_ok( $original_width, $original_height, $required_width, $required_height ) ) {
$result[$name] = array( 'width' => $required_width, 'height' => $required_height );
}
}
}
// Full-Size (if required in the settings)
$fullsize_required = get_option( "wr2x_full_size" ) && class_exists( 'MeowPro_WR2X_Core' );
$retina_file = trailingslashit( $pathinfo_fullsize['dirname'] ) . $pathinfo_fullsize['filename'] .
$this->retina_extension() . $pathinfo_fullsize['extension'];
if ( $retina_file && file_exists( $retina_file ) )
$result['full-size'] = 'EXISTS';
else if ( $fullsize_required && $retina_file )
$result['full-size'] = array( 'width' => $original_width * 2, 'height' => $original_height * 2 );
if ( $output_type === ARRAY_A ) {
$new_results = array();
foreach ( $result as $key => $value ) {
array_push( $new_results, array(
'name' => $key,
'shortname' => self::size_shortname( $key ),
'status' => is_array( $value ) ? 'CANNOT' : $value,
'required' => is_array( $value ) ? $value : null
)
);
}
return $new_results;
}
return $result;
}
function delete_attachment( $attach_id, $deleteFullSize = true ) {
$meta = wp_get_attachment_metadata( $attach_id );
$this->delete_images( $meta, $deleteFullSize );
$this->remove_issue( $attach_id );
}
function wp_generate_attachment_metadata( $meta ) {
if ( get_option( "wr2x_auto_generate" ) == true )
if ( $this->is_image_meta( $meta ) )
$this->generate_images( $meta );
return $meta;
}
/**
* @param mixed[] $meta
* int width
* int height
* string file
* mixed[][] sizes
*/
function generate_images( $meta ) {
global $_wp_additional_image_sizes;
$sizes = $this->get_image_sizes();
if ( !isset( $meta['file'] ) ) return;
$uploads = wp_upload_dir();
// Check if the full-size-retina version of the generation source exists.
// If it exists, replace the file path and its dimensions
if ( $retina = $this->get_retina( $uploads['basedir'] . '/' . $meta['file'] ) ) {
$meta['file'] = substr( $retina, strlen( $uploads['basedir'] ) + 1 );
$dim = getimagesize( $retina );
$meta['width'] = $dim[0];
$meta['height'] = $dim[1];
}
$originalfile = $meta['file'];
$pathinfo = pathinfo( $originalfile );
$original_basename = $pathinfo['basename'];
$basepath = trailingslashit( $uploads['basedir'] ) . $pathinfo['dirname'];
// $ignore = get_option( "wr2x_ignore_sizes" );
// if ( empty( $ignore ) )
// $ignore = array();
// $ignore = array_keys( $ignore );
$issue = false;
$id = $this->get_attachment_id( $meta['file'] );
/**
* @param $id ID of the attachment whose retina image is to be generated
*/
do_action( 'wr2x_before_generate_retina', $id );
$this->log("* GENERATE RETINA FOR ATTACHMENT '{$meta['file']}'");
$this->log( "Full-Size is {$original_basename}." );
foreach ( $sizes as $name => $attr ) {
$normal_file = "";
if ( !$attr['retina'] ) {
$this->log( "Retina for {$name} ignored (settings)." );
continue;
}
// Is the file related to this size there?
$pathinfo = null;
$retina_file = null;
if ( isset( $meta['sizes'][$name] ) && isset( $meta['sizes'][$name]['file'] ) ) {
$normal_file = trailingslashit( $basepath ) . $meta['sizes'][$name]['file'];
$pathinfo = pathinfo( $normal_file ) ;
$retina_file = trailingslashit( $pathinfo['dirname'] ) . $pathinfo['filename'] . $this->retina_extension() . $pathinfo['extension'];
}
if ( $retina_file && file_exists( $retina_file ) ) {
$this->log( "Base for {$name} is '{$normal_file }'." );
$this->log( "Retina for {$name} already exists: '$retina_file'." );
continue;
}
if ( $retina_file ) {
$originalfile = trailingslashit( $pathinfo['dirname'] ) . $original_basename;
if ( !file_exists( $originalfile ) ) {
$this->log( "[ERROR] Original file '{$originalfile}' cannot be found." );
return $meta;
}
// Maybe that new image is exactly the size of the original image.
// In that case, let's make a copy of it.
if ( $meta['sizes'][$name]['width'] * 2 == $meta['width'] && $meta['sizes'][$name]['height'] * 2 == $meta['height'] ) {
copy ( $originalfile, $retina_file );
$this->log( "Retina for {$name} created: '{$retina_file}' (as a copy of the full-size)." );
}
// Otherwise let's resize (if the original size is big enough).
else if ( $this->are_dimensions_ok( $meta['width'], $meta['height'], $meta['sizes'][$name]['width'] * 2, $meta['sizes'][$name]['height'] * 2 ) ) {
// Change proposed by Nicscott01, slighlty modified by Jordy (+isset)
// (https://wordpress.org/support/topic/issue-with-crop-position?replies=4#post-6200271)
$crop = isset( $_wp_additional_image_sizes[$name] ) ? $_wp_additional_image_sizes[$name]['crop'] : true;
$customCrop = apply_filters( 'wr2x_custom_crop', null, $id, $name );
// // Support for Manual Image Crop
// // If the size of the image was manually cropped, let's keep it.
// if ( class_exists( 'ManualImageCrop' ) && isset( $meta['micSelectedArea'] ) && isset( $meta['micSelectedArea'][$name] ) && isset( $meta['micSelectedArea'][$name]['scale'] ) ) {
// $customCrop = $meta['micSelectedArea'][$name];
// }
$image = $this->resize( $originalfile, $meta['sizes'][$name]['width'] * 2,
$meta['sizes'][$name]['height'] * 2, $crop, $retina_file, $customCrop );
}
if ( !file_exists( $retina_file ) ) {
$is_ok = apply_filters( "wr2x_last_chance_generate", false, $id, $retina_file,
$meta['sizes'][$name]['width'] * 2, $meta['sizes'][$name]['height'] * 2 );
if ( !$is_ok ) {
$this->log( "[ERROR] Retina for {$name} could not be created. Full-Size is " . $meta['width'] . "x" . $meta['height'] . " but Retina requires a file of at least " . $meta['sizes'][$name]['width'] * 2 . "x" . $meta['sizes'][$name]['height'] * 2 . "." );
$issue = true;
}
}
else {
do_action( 'wr2x_retina_file_added', $id, $retina_file, $name );
$this->log( "Retina for {$name} created: '{$retina_file}'." );
}
} else {
if ( empty( $normal_file ) )
$this->log( "[ERROR] Base file for '{$name}' does not exist." );
else
$this->log( "[ERROR] Base file for '{$name}' cannot be found here: '{$normal_file}'." );
}
}
// Checks attachment ID + issues
if ( !$id )
return $meta;
if ( $issue )
$this->add_issue( $id );
else
$this->remove_issue( $id );
/**
* @param $id ID of the attachment whose retina image has been generated
*/
do_action( 'wr2x_generate_retina', $id );
return $meta;
}
function delete_images( $meta, $deleteFullSize = false ) {
if ( !$this->is_image_meta( $meta ) )
return $meta;
$sizes = $meta['sizes'];
if ( !$sizes || !is_array( $sizes ) )
return $meta;
$this->log("* DELETE RETINA FOR ATTACHMENT '{$meta['file']}'");
$originalfile = $meta['file'];
$id = $this->get_attachment_id( $originalfile );
$pathinfo = pathinfo( $originalfile );
$uploads = wp_upload_dir();
$basepath = trailingslashit( $uploads['basedir'] ) . $pathinfo['dirname'];
foreach ( $sizes as $name => $attr ) {
$pathinfo = pathinfo( $attr['file'] );
$retina_file = $pathinfo['filename'] . $this->retina_extension() . $pathinfo['extension'];
if ( file_exists( trailingslashit( $basepath ) . $retina_file ) ) {
$fullpath = trailingslashit( $basepath ) . $retina_file;
unlink( $fullpath );
do_action( 'wr2x_retina_file_removed', $id, $retina_file );
$this->log("Deleted '$fullpath'.");
}
}
// Remove full-size if there is any
if ( $deleteFullSize ) {
$pathinfo = pathinfo( $originalfile );
$retina_file = $pathinfo[ 'filename' ] . $this->retina_extension() . $pathinfo[ 'extension' ];
if ( file_exists( trailingslashit( $basepath ) . $retina_file ) ) {
$fullpath = trailingslashit( $basepath ) . $retina_file;
unlink( $fullpath );
do_action( 'wr2x_retina_file_removed', $id, $retina_file );
$this->log( "Deleted '$fullpath'." );
}
}
return $meta;
}
// This is called by functions in the REST API
// TODO: However, this function seems to be what delete_images does above,
// so maybe we could optimize and avoid code redundancy.
function delete_retina_fullsize( $mediaId ) {
$originalfile = get_attached_file( $mediaId );
$pathinfo = pathinfo( $originalfile );
$retina_file = trailingslashit( $pathinfo['dirname'] ) . $pathinfo['filename'] . $this->retina_extension() . $pathinfo['extension'];
if ( $retina_file && file_exists( $retina_file ) ) {
return unlink( $retina_file );
}
return false;
}
/**
*
* FILTERS
*
*/
function validate_src( $src ) {
if ( preg_match( "/^data:/i", $src ) )
return null;
return $src;
}
/**
*
* LOAD SCRIPTS IF REQUIRED
*
*/
function wp_enqueue_scripts () {
// Picturefill Debug
if ( $this->method == "Picturefill" && $this->is_debug() ) {
$physical_file = trailingslashit( WR2X_PATH ) . 'app/debug.js';
$cache_buster = file_exists( $physical_file ) ? filemtime( $physical_file ) : WR2X_VERSION;
wp_enqueue_script( 'wr2x-debug-js', trailingslashit( WR2X_URL ) . 'app/debug.js', array(), $cache_buster, false );
}
// No Picturefill Script
if ( $this->method == "Picturefill" && !get_option( "wr2x_picturefill_noscript" ) ) {
$physical_file = trailingslashit( WR2X_PATH ) . 'app/picturefill.min.js';
$cache_buster = file_exists( $physical_file ) ? filemtime( $physical_file ) : WR2X_VERSION;
wp_enqueue_script( 'wr2x-picturefill-js', trailingslashit( WR2X_URL ) . 'app/picturefill.min.js', array(), $cache_buster, false );
}
// Lazysizes
if ( get_option( "wr2x_picturefill_lazysizes" ) && class_exists( 'MeowPro_WR2X_Core' ) ) {
$physical_file = trailingslashit( WR2X_PATH ) . 'app/lazysizes.min.js';
$cache_buster = file_exists( $physical_file ) ? filemtime( $physical_file ) : WR2X_VERSION;
wp_enqueue_script( 'wr2x-picturefill-js', trailingslashit( WR2X_URL ) . 'app/lazysizes.min.js', array(), $cache_buster, false );
}
// Debug + HTML Rewrite = No JS!
if ( $this->is_debug() && $this->method == "HTML Rewrite" ) {
return;
}
// Debug mode, we force the devicePixelRatio to be Retina
if ( $this->is_debug() ) {
$physical_file = trailingslashit( WR2X_PATH ) . 'app/debug.js';
$cache_buster = file_exists( $physical_file ) ? filemtime( $physical_file ) : WR2X_VERSION;
wp_enqueue_script( 'wr2x-debug-js', trailingslashit( WR2X_URL ) . 'app/debug.js', array(), $cache_buster, false );
}
// Retina-Images and HTML Rewrite both need the devicePixelRatio cookie on the server-side
if ( $this->method == "Retina-Images" || $this->method == "HTML Rewrite" ) {
$physical_file = trailingslashit( WR2X_PATH ) . 'app/retina-cookie.js';
$cache_buster = file_exists( $physical_file ) ? filemtime( $physical_file ) : WR2X_VERSION;
wp_enqueue_script( 'wr2x-debug-js', trailingslashit( WR2X_URL ) . 'app/retina-cookie.js', array(), $cache_buster, false );
}
// Retina.js only needs itself
if ( $this->method == "retina.js" ) {
$physical_file = trailingslashit( WR2X_PATH ) . 'app/retina.min.js';
$cache_buster = file_exists( $physical_file ) ? filemtime( $physical_file ) : WR2X_VERSION;
wp_enqueue_script( 'wr2x-retinajs-js', trailingslashit( WR2X_URL ) . 'app/retina.min.js', array(), $cache_buster, false );
}
}
}
// Used by WP Rocket (and maybe by other plugins)
function wr2x_is_registered() {
global $wr2x_core;
return $wr2x_core->admin->is_registered();
}
?>