Il s'agit d'une autre approche que l'autre réponse qui fonctionne lors de l'importation de contenu avec l'importateur et corrige les URL une fois pour toutes. Encore une fois: ce n'est pas testé au combat, mais c'est la solution sur laquelle j'ai opté et cela a fonctionné.
Je préfère cela car cela résout le problème une fois pour toutes et si cela fonctionne, cela fonctionne. Comme vous ne laissez pas de trucs cassés dans la base de données et les réparez à l'écran, vous n'avez pas à vous soucier des trucs qui se brisent plus tard.
/*
Plugin Name: Bugfix Ticket 31581 for WP_Importer
Plugin URI: /wordpress//a/206992/47733
Description: Fixes image references after post WP 4.1 image scaling change in post content when using the WP_Importer (see https://core.trac.wordpress.org/ticket/31581)
Version: 0.0.1
*/
class Bugfix31581WPImporter {
protected $remaps;
/**
* Initialize class, mainly setting up hooks
*/
public function init(){
if (WP_IMPORTING === true){
$this->remaps = array();
//This hook is chosen because it is pretty close to where the actual attachment import is happening.
//TODO: May be reconsidered.
add_filter('wp_update_attachment_metadata', array($this, 'collectRemaps'), 10 , 2);
add_action('import_end', array($this, 'remap'));
add_action('import_end', array($this, 'importEnded'));
}
}
/**
* Cleans up hooks after the import has ended.
*/
public function importEnded(){
remove_filter('wp_update_attachment_metadata', array($this, 'collectRemaps'), 10);
remove_action('import_end', array($this, 'remap'), 10);
remove_action('import_end', array($this, 'importEnded'), 10);
}
/**
* When an attachment is added compare the resulting sizes with the sizes from the legacy algorithm and setup remap.
*
* @param $data
* @param $post_id
*
* @return mixed
*/
public function collectRemaps($data, $post_id ){
$intermediate_sizes = $this->getIntermediateSizes();
if(empty($data) || !array_key_exists('sizes', $data)){
return $data;
}
foreach($data['sizes'] as $key => $size){
$size_new_algorithm = array($size['width'], $size['height']);
$dest_w = $intermediate_sizes[$key]['width'];
$dest_h = $intermediate_sizes[$key]['height'];
$crop = $intermediate_sizes[$key]['crop'];
add_filter('wp_constrain_dimensions', array($this, 'legacy_wp_constrain_dimensions'), 10, 5);
$size_old_algorithm = image_resize_dimensions($data['width'], $data['height'], $dest_w, $dest_h, $crop);
//Bail out in the rare case of `image_resize_dimensions` returning false
if($size_old_algorithm===false){
continue;
}
$size_old_algorithm = array($size_old_algorithm[4], $size_old_algorithm[5]);
remove_filter('wp_constrain_dimensions', array($this, 'legacy_wp_constrain_dimensions'), 10);
// Compare the current size with the calculation of the old algorithm...
$diff = array_diff($size_new_algorithm, $size_old_algorithm);
// ...to detect any mismatches
if(!empty($diff)){
$oldFilename = $this->getOldFilename($size['file'], $size_old_algorithm);
// If getting the old filename didn't work for some reason (probably other filename-structure) bail out.
if($oldFilename===false){
continue;
}
if(!array_key_exists($post_id, $this->remaps)){
$this->remaps[$post_id] = array();
}
$this->remaps[$post_id][$size['file']] = array(
'file' => $oldFilename,
'size' => $key
);
}
}
return $data;
}
/**
* Get resize settings for all image sizes
*
* Taken from wp_generate_attachment_metadata() in includes/image.php
*
* @return array
*/
public function getIntermediateSizes(){
global $_wp_additional_image_sizes;
$sizes = array();
foreach ( get_intermediate_image_sizes() as $s ) {
$sizes[$s] = array( 'width' => '', 'height' => '', 'crop' => false );
if ( isset( $_wp_additional_image_sizes[$s]['width'] ) )
$sizes[$s]['width'] = intval( $_wp_additional_image_sizes[$s]['width'] ); // For theme-added sizes
else
$sizes[$s]['width'] = get_option( "{$s}_size_w" ); // For default sizes set in options
if ( isset( $_wp_additional_image_sizes[$s]['height'] ) )
$sizes[$s]['height'] = intval( $_wp_additional_image_sizes[$s]['height'] ); // For theme-added sizes
else
$sizes[$s]['height'] = get_option( "{$s}_size_h" ); // For default sizes set in options
if ( isset( $_wp_additional_image_sizes[$s]['crop'] ) )
$sizes[$s]['crop'] = $_wp_additional_image_sizes[$s]['crop']; // For theme-added sizes
else
$sizes[$s]['crop'] = get_option( "{$s}_crop" ); // For default sizes set in options
}
return $sizes;
}
/**
* Turn the new filename into the old filename reducing the height by one
*
* @param $newFilename
* @param $size
*
* @return mixed
*/
public function getOldFilename($newFilename, $size){
$dimensions = array();
$filetypes = $this->getAllowedImageExtentions();
// TODO: This pattern can be different. See `image_make_intermediate_size` in image editor implementation.
$matchFiles = '/([0-9]{1,5})x([0-9]{1,5}).(' . $filetypes . ')$/';
// Extract the dimensions
preg_match($matchFiles,$newFilename,$dimensions);
// If the file URL doesn't allow guessing the dimensions bail out.
if(empty($dimensions)){
return $newFilename;
}
$newStub = $dimensions[1] . 'x' . $dimensions[2] . '.' . $dimensions[3];
$oldStub = $size[0] . 'x' . $size[1] . '.' . $dimensions[3];
$oldFilename = str_replace($newStub,$oldStub,$newFilename);
return $oldFilename;
}
/**
* Extract all file extensions that match an image/* mime type
*
* @return string
*/
protected function getAllowedImageExtentions(){
$allowed_filetypes = get_allowed_mime_types();
$allowed_images = array();
foreach($allowed_filetypes as $extensions => $mimetype){
if( substr($mimetype,0,6) == 'image/' ){
$allowed_images[] = $extensions;
}
}
return implode('|',$allowed_images);
}
/**
* This is the heart of this class. Based on the collected remaps from earlier it does a S&R on the DB.
*/
public function remap(){
global $wpdb;
foreach($this->remaps as $attachment_id => $replaces){
foreach($replaces as $new_url => $old_data){
$to_url = wp_get_attachment_image_src($attachment_id,$old_data['size']);
$to_url = $to_url[0];
$from_url = str_replace($new_url, $old_data['file'], $to_url);
// remap urls in post_content
$wpdb->query( $wpdb->prepare("UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", $from_url, $to_url) );
//TODO: This is disabled as enclosures can't be images, right?
// remap enclosure urls
//$result = $wpdb->query( $wpdb->prepare("UPDATE {$wpdb->postmeta} SET meta_value = REPLACE(meta_value, %s, %s) WHERE meta_key='enclosure'", $from_url, $to_url) );
}
}
}
/**
* This is a copy of the legacy pre 4.1 wp_constrain_dimensions()
*
* @param $dimensions
* @param $current_width
* @param $current_height
* @param $max_width
* @param $max_height
*
* @return array
*/
public function legacy_wp_constrain_dimensions($dimensions, $current_width, $current_height, $max_width, $max_height){
if ( !$max_width and !$max_height )
return array( $current_width, $current_height );
$width_ratio = $height_ratio = 1.0;
$did_width = $did_height = false;
if ( $max_width > 0 && $current_width > 0 && $current_width > $max_width ) {
$width_ratio = $max_width / $current_width;
$did_width = true;
}
if ( $max_height > 0 && $current_height > 0 && $current_height > $max_height ) {
$height_ratio = $max_height / $current_height;
$did_height = true;
}
// Calculate the larger/smaller ratios
$smaller_ratio = min( $width_ratio, $height_ratio );
$larger_ratio = max( $width_ratio, $height_ratio );
if ( intval( $current_width * $larger_ratio ) > $max_width || intval( $current_height * $larger_ratio ) > $max_height )
// The larger ratio is too big. It would result in an overflow.
$ratio = $smaller_ratio;
else
// The larger ratio fits, and is likely to be a more "snug" fit.
$ratio = $larger_ratio;
// Very small dimensions may result in 0, 1 should be the minimum.
$w = max ( 1, intval( $current_width * $ratio ) );
$h = max ( 1, intval( $current_height * $ratio ) );
// Sometimes, due to rounding, we'll end up with a result like this: 465x700 in a 177x177 box is 117x176... a pixel short
// We also have issues with recursive calls resulting in an ever-changing result. Constraining to the result of a constraint should yield the original result.
// Thus we look for dimensions that are one pixel shy of the max value and bump them up
if ( $did_width && $w == $max_width - 1 )
$w = $max_width; // Round it up
if ( $did_height && $h == $max_height - 1 )
$h = $max_height; // Round it up
return array( $w, $h );
}
}
add_filter('import_start',array(new Bugfix31581WPImporter(),'init'));
error issue of #13852
dire#18532
? :)