Fixing WordPress 4.4 Responsive Images In Azure Scalable WordPress Installs

Update, 9 February 2016: Looks like Microsoft has corrected this error in its Azure storage plugin, which is mandatory for Scalable WordPress installs.

However, if you installed this fix in your functions.php file or in a plugin, you may see your site lock up with this error:

Fatal error: Cannot redeclare windows_azure_storage_wp_calculate_image_srcset() (previously declared in {some path}) in {another path}\windows-azure-storage.php on line 721

In short, if you see that error, you need to FTP into your site, fish out the plugin or functions.php file, remove this fix and then re-upload. That should un-trash your site.

Update, 5 January 2016: Microsoft reports it has put in a ticket for this issue.

In the meantime, there’s a fix over at Project Nami (a SQL Server-based port of WordPress) that hacks the storage plugin for a fix. It uses the wp_calculate_image_srcset as well and does so by leveraging the metadata attached to each image by Azure.

A quick look at their code shows that it’s a better solution than the one I originally posted, but it’s not written to WordPress coding standards. I adapted it to follow WordPress style and posted that code as a Gist.

I’ve also amended this post to use the amended code from Project Nami.

If you have a Scalable WordPress install running on Microsoft Azure, recently upgraded to WordPress 4.4, and found that the image links in your responsive template have suddenly gone bad, I have the fix.

WordPress 4.4 introduced automatic responsive image handling via the srcset attribute of the img element.

In short, this attribute allows your responsive theme to load one of the three alternate sizes of your images, created whenever you upload media through the Dashboard, if that alternate size is a better fit for the current screen size.

It works great when it works as advertised. For example, the featured image on this post is 1920 px wide, but you’ll proably load a much smaller size if you’re viewing this on a tablet or phone:

The Windows Azure Storage for WordPress plugin in Scalable WordPress doesn't properly build responsive images in WordPress 4.4. Photo via Pixabay, in the public domain.
The Windows Azure Storage for WordPress plugin in Scalable WordPress doesn’t properly build responsive images in WordPress 4.4. Photo via Pixabay, in the public domain.

Microsoft’s Windows Azure Storage for WordPress plugin, saves certain files — including uploaded media — to an Azure Storage account, allowing your WordPress site to be “scalable”.

Unfortunately, the Windows Azure Storage for WordPress plugin has not been updated to handle the addition of responsive images.

Therefore, all the URLs in the srcset attribute, pointing to the thumbnail, medium and large sizes of your image, will be broken; and if your site is responsive, you’ll see broken images.

If you look at the HTML rendered by WordPress, you can see why:

<img 
	width="900" 
	height="604" 
	src="http://mystorage.blob.core.windows.net/wp-media/2016/01/photo.jpg" 
	class="attachment-large size-large wp-post-image" alt="Former President Bill Clinton waves to a cheering crowd as he arrives during a campaign stop for his wife, Democratic presidential candidate Hillary Clinton, Monday in Nashua, N.H." 
	srcset="http://mywebsite.azurewebsites.net/wp-content/uploads/D:homesitewwwroot/wp-content/uploads/2016/01/photo.jpg 450w, 
	http://mywebsite.azurewebsites.net/wp-content/uploads/D:homesitewwwroot/wp-content/uploads/2016/01/photo.jpg 900w, 
	http://mywebsite.azurewebsites.net/wp-content/uploads/D:homesitewwwroot/wp-content/uploads/2016/01/photo.jpg 999w" sizes="(max-width: 900px) 100vw, 900px"
>

At Line 4, you’ll see that the src for the image correctly calls to the Azure Storage blob that holds the original photo you uploaded.

But the srcset, at lines 6-8, are all pointing to the website itself; not blob storage. And the path is also wrong; it’s a combination of the wp-content folder and the physical file path to the wp-content folder.

That’s because of the way that WordPress figures out the URL to the alternate image sizes, via the wp_calculate_image_srcset function.

Fortunately, we can fix this with a filter, called on the wp_calculate_image_srcset event. This event is fired immediately before the srcset attribute’s value is created by WordPress, so we can be sure any change to an image path we create via a filter will be made in time for proper rendering.

Here’s the code I am using in my functions.php file:

Update, 5 January 2016: This code has been amended to reflect the fix provided at Project Nami.
function azure_fix_invalid_srcset_path( $sources, $size_array, $image_src, $image_meta, $attachment_id ) {
	$media_info = get_post_meta( $attachment_id, 'windows_azure_storage_info', true );

	if ( !empty( $media_info ) ) {
		foreach ( $sources as &$source ) {
			$img_file_name = substr( $source['url'], strrpos( $source['url'], '/' ) + 1 );

			if ( $img_file_name == substr( $media_info['blob'], strrpos( $media_info['blob'], '/' ) + 1 ) ) {
				$source['url'] = "https://" . get_option( 'azure_storage_account_name' ) . ".blob.core.windows.net/" . $media_info['container'] . "/" . $media_info['blob'];
			} else {
				foreach ( $media_info['thumbnails'] as $thumbnail ) {
					if ( $img_file_name == substr( $thumbnail, strrpos( $thumbnail, '/' ) + 1 ) ) {
						$source['url'] = "https://" . get_option( 'azure_storage_account_name' ) . ".blob.core.windows.net/" . $media_info['container'] . "/" . $thumbnail;
						break;
					}
				}
			}
		}
	}

	return $sources;
}

add_filter( 'wp_calculate_image_srcset', 'azure_fix_invalid_srcset_path', 10, 5 );
You can write this as a plugin if you prefer; it doesn’t need to be in functions.php.

This code as a Github Gist: https://gist.github.com/dougvdotcom/97f049b5d5d345e43174

Let’s look at how this filter works.

We need to correct two problems with the URLs wrongly created by Scalable WordPress: Links that point to images on the web host, rather than the storage host; and bad paths.

  • At Line 2, we get some metadata that Azure attaches to each image, which includes the name of the image file (blob).
  • At Line 5, we read by reference each array that will be used to build the srcset, so that we can reset the values passed in to the function.
  • Lines 8-9 evaluates where the blob at Line 2 is part of the current URL being iterated. If so, the URL to that blob is corrected to be at the storage account URL and container for your Scalable WordPress install.
  • Lines 10-15 replace bad file paths to the thumbnails / alternate image sizes with the correct storage account host and container name.

For what it’s worth, I posted this issue to the MSDN forums prior to creating this post, and hopefully Microsoft will create a permanent fix soon.

4 Comments

  1. Thanks for the post. I noticed that the srcset for my images is being incorrectly calculated. The images are uploaded to the root of my Azure container, but the srcset paths references the url to the container + /wp-content/uploads. Is there a way to change how this is calculated or would it make more sense to just move everything in my container into a wp-content/uploads folder?

    Thanks!

  2. @James: Sorry for delay in responding, for reasons unknown the blog did not email me about your comments.

    To the best of my knowledge the Windows Azure Storage for WordPress plugin, version 3.0.1, is correctly configuring srcset attributes using a workaround similar to the one mentioned here. At least, it works on this site. Since it works here, there’s something clearly amiss in your install, especially if you are, indeed, running the Windows Azure Storage for WordPress plugin, version 3.0.1.

    If so, it is possible, bordering on probable, that your issue is related to another plugin or theme function which is overriding the correct calculation of your srcset variables. The easiest way to test that is to spin up a new Scalable WordPress install, use the Twenty Sixteen theme, create a post with some media, save it and see whether the srcset is correctly calculated. If it is, then almost certainly your problem is a plugin you are running, or possibly your theme is at issue.

    Add your theme to your test install and see if srcsets are calculated correctly. Then keep adding plugins, checking the rendered markup until it’s broken. The last plugin you installed is your culprit.

    It is also possible, but unlikely, your wp_options table is corrupted. To fix the relevant entries, you can visit Settings > Media, make sure the image sizes there are all set to appropriate integers, then save; if wp_options is the issue, that should fix it.

  3. Hi Doug. No worries!

    I did some investigating and was able to fix the problem by modifying the database. Specifically, for the images where srcset wasn’t properly calculated, I was able to fix it by modifying the _wp_attachment_metadata in the wp_postmeta table. For example, for one of the images, I was seeing the following in that column:

    a:7:{s:5:"width";i:872;s:6:"height";i:292;s:4:"file";s:54:"/usr/share/nginx/www/wp-content/uploads/scout-logo.png";s:5:"sizes"; ...

    Editor’s note: Lots of extra code snipped

    By changing that first path from /usr/share/nginx/www/wp-content/uploads/scout-logo.png to /usr/share/nginx/www/scout-logo.png, the srcset no longer appends /wp-content/uploads to the Azure Storage url.

    I’m not sure if this is going to affect any future uploads or if this is just a result of a breaking change. Any thoughts?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  • Check out the Commenting Guidelines before commenting, please!
  • Want to share code? Please put it into a GitHub Gist, CodePen or pastebin and link to that in your comment.
  • Just have a line or two of markup? Wrap them in an appropriate SyntaxHighlighter Evolved shortcode for your programming language, please!