Created
November 13, 2010 16:05
-
-
Save janfabry/675439 to your computer and use it in GitHub Desktop.
WordPress Virtual intermediate images plugin (first public attempt)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Plugin Name: Virtual intermediate images | |
Plugin URI: http://www.monkeyman.be | |
Description: Prevent creation of actual intermediate image sizes | |
Version: 0.1 | |
Author: Jan Fabry | |
This plugin prevents the creation of actual intermediate image sizes. It does, however, fill in all metadata attributes as if the intermediate sizes exist. It is designed to work together with a plugin that can create these images on the fly, like monkeyman-on-demand-resizer. | |
The intermediate images are created by image_make_intermediate_size(). Because this function has no hook to prevent it from actually creating the file, we need to go one step back. | |
This function is called in two places (by core WordPress files): wp_generate_attachment_metadata() for the normal flow of uploading a new image, and by the image editor. | |
wp_generate_attachment_metadata() is intercepted by hooking into the `intermediate_image_sizes_advanced`. We save the passed sizes for later and return an empty array, preventing any actual intermediate sizes from being created. The output of this function is then filtered through `wp_generate_attachment_metadata`, so we use that to add the sizes back to the metadata as if nothing happened. | |
The URLs are constructed almost like normal size URLs, with one exception: crop information is added, by prepending a 'c'. We calculate the intermediate image sizes by using the same functions WordPress uses, but this requires we first read the original image size. Because we only get the final part of the upload path, we hook into the (seemingly unrelated) `_wp_relative_upload_path` filter to map the trimmed to the full paths. | |
The image editor is trickier because it modifies the images and the metadata on its own. I'm still finding out with hooks to use there. We already hook into `load_image_to_edit_path` to make sure it returns a existing and not a virtual file path. But probably the whole editor needs to be re-written for this to work. | |
If you think the variables have weird names ($idPost instead of $post_id), it's because I am trying to use "Apps Hungrarian" notation [ http://www.joelonsoftware.com/articles/Wrong.html ] to indicate the type of the value stored there. But I'm not consistent enough (and it clashes with WordPress coding standard), and maybe should rethink it. | |
*/ | |
class Monkeyman_VirtualIntermediateImages | |
{ | |
protected $trimmedPaths = array(); | |
protected $intermediateSizes = null; | |
public function __construct() | |
{ | |
// Save full paths for later | |
add_filter('_wp_relative_upload_path', array(&$this, 'storeTrimmedPath'), 10, 2); | |
// Save intermediate sizes for later (and return none) | |
add_filter('intermediate_image_sizes_advanced', array(&$this, 'storeIntermediateSizes'), 900); | |
// Generate "fake" metadata | |
add_filter('wp_generate_attachment_metadata', array(&$this, 'generateAttachmentMetadata'), 10, 2); | |
// Get an image for the editor | |
add_filter('load_image_to_edit_path', array(&$this, 'getEditorImage'), 10, 3); | |
} | |
public function storeTrimmedPath($trimmedPath, $origPath) | |
{ | |
$this->trimmedPaths[$trimmedPath] = $origPath; | |
return $trimmedPath; | |
} | |
public function storeIntermediateSizes($intermediateSizes) | |
{ | |
$this->intermediateSizes = $intermediateSizes; | |
return array(); | |
} | |
public function generateAttachmentMetadata($metadata, $idAttachment) | |
{ | |
$rootedImagePath = $this->trimmedPaths[$metadata['file']]; | |
$fullImageSize = @getimagesize($rootedImagePath); | |
if (!$fullImageSize) { | |
return new WP_Error('invalid_image', __('Could not read image size'), $rootedImagePath); | |
} | |
$imagePathInfo = pathinfo($metadata['file']); | |
$metadata['sizes'] = array(); | |
foreach ($this->intermediateSizes as $sizeName => $sizeInfo) { | |
$dims = image_resize_dimensions($fullImageSize[0], $fullImageSize[1], $sizeInfo['width'], $sizeInfo['height'], $sizeInfo['crop']); | |
if (!$dims) { | |
// The source image is probably smaller than the destination size, just skip it | |
continue; | |
} | |
list($dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = $dims; | |
$suffix = '-'; | |
if ($sizeInfo['crop']) { | |
$suffix .= 'c'; | |
} | |
$suffix .= $dst_w . 'x' . $dst_h; | |
$metadata['sizes'][$sizeName] = array( | |
'file' => $imagePathInfo['filename'] . $suffix . '.' . $imagePathInfo['extension'], | |
'width' => $dst_w, | |
'height' => $dst_h, | |
); | |
} | |
return $metadata; | |
} | |
public function getEditorImage($filepath, $idPost, $size) | |
{ | |
if (file_exists($filepath)) { | |
return $filepath; | |
} | |
$finalImagePath = get_post_meta($idPost, '_wp_attached_file', true); | |
$uploadInfo = wp_upload_dir(); | |
// TODO: All kinds of backwards-compatible stuff | |
// See wp_get_attachment_url() | |
$filepath = $uploadInfo['basedir'] . '/' . $finalImagePath; | |
return $filepath; | |
} | |
} | |
$monkeyman_VirtualIntermediateImages_instance = new Monkeyman_VirtualIntermediateImages(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment