Skip to content

Instantly share code, notes, and snippets.

@kovshenin
Created March 6, 2012 06:41
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save kovshenin/1984363 to your computer and use it in GitHub Desktop.
Save kovshenin/1984363 to your computer and use it in GitHub Desktop.
Image shortcode for WordPress
<?php
/**
* Image shortcode callback
*
* Enables the [kovshenin_image] shortcode, pseudo-TimThumb but creates resized and cropped image files
* from existing media library entries. Usage:
* [kovshenin_image src="http://example.org/wp-content/uploads/2012/03/image.png" width="100" height="100"]
*
* @uses image_make_intermediate_size
*/
function kovshenin_image_shortcode( $atts ) {
extract( shortcode_atts( array(
'src' => '',
'width' => '',
'height' => '',
), $atts ) );
global $wpdb;
// Sanitize
$height = absint( $height );
$width = absint( $width );
$src = esc_url( strtolower( $src ) );
$needs_resize = true;
$upload_dir = wp_upload_dir();
$base_url = strtolower( $upload_dir['baseurl'] );
// Let's see if the image belongs to our uploads directory.
if ( substr( $src, 0, strlen( $base_url ) ) != $base_url ) {
return "Error: external images are not supported.";
}
// Look the file up in the database.
$file = str_replace( trailingslashit( $base_url ), '', $src );
$attachment_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wp_attachment_metadata' AND meta_value LIKE %s LIMIT 1;", '%"' . like_escape( $file ) . '"%' ) );
// If an attachment record was not found.
if ( ! $attachment_id ) {
return "Error: attachment not found.";
}
// Look through the attachment meta data for an image that fits our size.
$meta = wp_get_attachment_metadata( $attachment_id );
foreach( $meta['sizes'] as $key => $size ) {
if ( $size['width'] == $width && $size['height'] == $height ) {
$src = str_replace( basename( $src ), $size['file'], $src );
$needs_resize = false;
break;
}
}
// If an image of such size was not found, we can create one.
if ( $needs_resize ) {
$attached_file = get_attached_file( $attachment_id );
$resized = image_make_intermediate_size( $attached_file, $width, $height, true );
if ( ! is_wp_error( $resized ) ) {
// Let metadata know about our new size.
$key = sprintf( 'resized-%dx%d', $width, $height );
$meta['sizes'][$key] = $resized;
$src = str_replace( basename( $src ), $resized['file'], $src );
wp_update_attachment_metadata( $attachment_id, $meta );
// Record in backup sizes so everything's cleaned up when attachment is deleted.
$backup_sizes = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true );
if ( ! is_array( $backup_sizes ) ) $backup_sizes = array();
$backup_sizes[$key] = $resized;
update_post_meta( $attachment_id, '_wp_attachment_backup_sizes', $backup_sizes );
}
}
// Generate the markup and return.
$width = ( $width ) ? 'width="' . absint( $width ) . '"' : '';
$height = ( $height ) ? 'height="' . absint( $height ) . '"' : '';
return sprintf( '<img src="%s" %s %s />', esc_url( $src ), $width, $height );
}
add_shortcode( 'kovshenin_image', 'kovshenin_image_shortcode' );
?>
@rilwis
Copy link

rilwis commented Feb 5, 2013

Do you think strtolower is wrong? Images can have uppercase in its name and that can make the query statement return nothing or incorrect attachment ID.

@benhuson
Copy link

Nice.
It would be great to just hook in this functionality to the 'image_downsize' filter to provide image sizing on the fly for image sizes that haven't been generated
http://core.trac.wordpress.org/browser/tags/3.5.1/wp-includes/media.php#L147

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment