Last active
August 16, 2018 14:30
-
-
Save pbiron/d72a5d3b63e7077df767735464b2769c to your computer and use it in GitHub Desktop.
func to hook into WP's attachment_url_to_postid filter to try to resolve attachment URLs for intermediate/backup sizes
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 | |
if ( version_compare( get_bloginfo( 'version' ), '4.2', '>=') ) : | |
/* | |
* WP 4.0 introduced attachment_url_to_postid(). However, it fails when the | |
* URL is for an intermediate sized image (e.g., `.../filename-150x150.jpg`). | |
* | |
* WP 4.2.0 introduced the attachment_url_to_postid filter. The filter func | |
* defined below hooks into that filter and attempts remedy that limitation. | |
*/ | |
add_filter( 'attachment_url_to_postid' , 'shc_attachment_url_to_postid_filter', 10, 2 ); | |
/** | |
* Tries to convert an attachment URL (for intermediate/edited sized image) into a post ID. | |
* | |
* @param string $url The URL to resolve. | |
* @return int The found post ID, or 0 on failure. | |
* | |
* @see attachment_url_to_postid() | |
* | |
* @todo produces incorrect results after the following sequence: | |
* 1) set thumbnail site to 150x150; | |
* 2) upload foo-150x150.jpg; | |
* 3) upload foo.jpg; | |
* 4) call attachment_url_to_post_id( 'http://host/wp-content/uploads/foo-150x150.jpg' ) | |
* | |
* this is due to a bug in WP Core, | |
* see @link https://core.trac.wordpress.org/ticket/44095 | |
* | |
* Actually, it is attachment_url_to_postid() that produces the incorrect | |
* results, and we don't try to work around that bug | |
* | |
* @todo produces incorrect results after the following sequence: | |
* 1) set thumbnail site to 150x150; | |
* 2) upload a 300x300 image foo.jpg; | |
* 3) edit foo.jpg and scale to 200x200; | |
* 4) regenerate intermediate sized images (e.g., with https://wordpress.org/plugins/regenerate-thumbnails/) | |
* 5) call attachment_url_to_post_id( 'http://host/wp-content/uploads/foo-150x150.jpg' ) | |
* | |
* this is due to what may/may not be considered a bug in WP core, but the fix/enhancement suggested in | |
* @link https://core.trac.wordpress.org/ticket/44127 would allow a slight mod to this filter | |
* to correctly resolve that case | |
*/ | |
function shc_attachment_url_to_postid_filter( $post_id, $url ) { | |
global $wpdb; | |
if ( $post_id ) { | |
// attachment_url_to_postid() found the attachment, nothing for us to do | |
// however, see the 1st @todo above for one know case where attachment_url_to_postid() | |
// returns a false positive. We could try to work around that bug, but I'd | |
// rather the bug be fixed rather than try to work around it | |
return $post_id; | |
} | |
// start by setting up a few vars the same way attachment_url_to_postid() does | |
$dir = wp_get_upload_dir(); | |
$path = $url; | |
$site_url = parse_url( $dir['url'] ); | |
$image_path = parse_url( $path ); | |
//force the protocols to match if needed | |
if ( isset( $image_path['scheme'] ) && ( $image_path['scheme'] !== $site_url['scheme'] ) ) { | |
$path = str_replace( $image_path['scheme'], $site_url['scheme'], $path ); | |
} | |
if ( 0 === strpos( $path, $dir['baseurl'] . '/' ) ) { | |
$path = substr( $path, strlen( $dir['baseurl'] . '/' ) ); | |
} | |
$basename = wp_basename( $path ); | |
$dirname = dirname( $path ); | |
// note: the "LIKE" we search for is the serialized form of $basename to reduce the | |
// number of false positives we have to deal with | |
$sql = $wpdb->prepare( | |
"SELECT post_id, meta_key, meta_value | |
FROM $wpdb->postmeta | |
WHERE meta_key IN ( '_wp_attachment_metadata', '_wp_attachment_backup_sizes' ) AND meta_value LIKE %s", | |
'%' . serialize( $basename ) . '%' ); | |
$results = $wpdb->get_results( $sql ); | |
foreach ( $results as $row ) { | |
if ( '_wp_attachment_metadata' === $row->meta_key ) { | |
$meta = maybe_unserialize( $row->meta_value ); | |
if ( dirname( $meta['file'] ) === $dirname && in_array( $basename, wp_list_pluck( $meta['sizes'], 'file' ) ) ) { | |
// URL is for a registered intermediate size | |
$post_id = $row->post_id; | |
break; | |
} | |
} | |
else { | |
// see if URL is for a "backup" of an edited image | |
$backup_sizes = maybe_unserialize( $row->meta_value ); | |
if ( in_array( $basename, wp_list_pluck( $backup_sizes, 'file' ) ) ) { | |
// URL is possibly for a "backup" of an edited image | |
// get the meta for the "original" attachment and perform the equivalent | |
// test we did above for '_wp_attachment_metadata' === $row->meta_key | |
$sql = $wpdb->prepare( | |
"SELECT meta_value | |
FROM $wpdb->postmeta | |
WHERE | |
post_id = %d AND meta_key = '_wp_attachment_metadata'", | |
$row->post_id | |
); | |
$meta = maybe_unserialize( $wpdb->get_var( $sql ) ); | |
if ( isset( $meta['file'] ) && dirname( $meta['file'] ) === $dirname ) { | |
// URL is for a "backup" of an edited image | |
$post_id = $row->post_id; | |
break; | |
} | |
} | |
} | |
} | |
return $post_id; | |
} | |
endif; // function_exists( 'attachment_url_to_postid' ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment