PLUGIN – Enable SRCSET generation on Divi Generated Images.

TL;DR – jump to the plug-in code (alpha version).

The problem:

In short, WordPress added a feature to automatically insert srcset tags into images. Responsiveness!

However, for this to work the image tag must have the right “wp-image-xxxxx” class tag (where xxxxx is the image’s attachment ID).

The DIVI Page Builder (https://www.elegantthemes.com/gallery/divi/) doesn’t add this class tag, so WordPress doesn’t add srcset (even when there are plenty of resized version sof the image in question, generated either by WordPress or plugins like EWWW, TinyPNG and so on).

The pronlem is described in more detail by Sky Shabatura here: https://www.facebook.com/divisiontheme/posts/682555988588984:0?hc_location=ufi

The theoretical solution:

The magic that does the srcset insertion is the WordPress function wp_make_content_images_responsive. This function is called by a standard priority add_filter (executed in default-filters.php (#140)).

So, make our plugin work, we have to jiggle priorities around a bit:-

  1. Implement our own filter that’s called after all shortcodes have been executed (allowing Divi to generate the tags), so that our filter can then insert a “class=”wp-image-xxxxx” attribute into the tag.
  2. Reprioritise WordPress’s filter so that it’s called AFTER our filter.

At the start of our plugin) execute the following:-
remove_filter( ‘the_content’, ‘wp_make_content_images_responsive’ );
add_filter (“the_content”, “our_filter_that_inserts_wp-image_class”, 9998);
add_filter( ‘the_content’, ‘wp_make_content_images_responsive’, 9999 );

… now, our filter will be responsible for looking at all tags, looking up the ID from the posts table (post_type=”image”) using the image’s src attribute as a reference. If found, we’ll insert ‘class=”wp-image-xxxxx”.

Shortly after, wordpress’s filter will be called and srcset will be inserted.

The solution in plugin form (alpha!)

Firstly, this proof-of-concept is a slight sledge-hammer approach. It isn’t elegant yet.

Sending Feedback.

If you’ve been invited to test this plugin (or someone’s forwarded it to you) please use the comments section below for feedback (baring in mind that if you’re going to write “This is a load of shit, it doesn’t work, waste of my time, I’m so angry” then you’re clearly in the wrong place, with the wrong expectations, and the wrong mindset. Try going here instead).

Stuff the plug-in don’t do (yet).

  1. The plugin processes ALL img tags (not just the ones generated by Divi). This shouldn’t be a bad thing, really.
  2. The plugin only inserts a class tag into the <img> tags that don’t already have one. So, it’ll ignore an image that already has a class=”…” tag (not so bad, as currently all DIVI images don’t create a class on the image tag. Divi DOES allow you to add classes (and IDs) to modules, but the class/ID is applied to a containing DIV rather than the IMG itself).

It shouldn’t be too difficult to code a beta version that takes care of these things (plus any other feedback & suggestions) – but it’s Easter bank holiday in England and I need to dry my washing… and eat!

Installation Instructions.

Yeah, there are easier ways to install a plugin, but right now this is just a quick and dirty proof-of-concept plugin.

  1. In your plugins directory, create a folder calls CS_diviimagesrcset
  2. Within this directory create a file called CS_diviimagesrcset.php
  3. Copy and paste the following code into CS_diviimagesrcset.php (everything including-and-from <?php up-to-and-including the closing ?> – make sure there’s no spaces before the <?php tag, and no spaces after the closing ?> tag or WordPress might moan at you.
  4. Go to your site’s plugin page and activate this plugin.
  5. (Clear any caches etc or you might not see the benefits for a while).
  6. Go load a page with images that you know should have srcset attributes, and check that they do now (your browser should have a debugger – if you don’t know what that is you probably shouldn’t be playing with this plugin at this early stage!).
  7. Any problems – message me if I asked you to test this out, Otherwise, don’t call on me; who are you anyway?

 

<?php
   /*
   Plugin Name: DIVI Image SRCSET Enabler
   Plugin URI: http://deanrichardson.co.uk/
   Description: PROOF OF CONCEPT (alpha version). Plugin that inserts the correct image ID class into <img> tags so that WordPress will auto-insert SRCSET tags. Problem: DIVI modules that insert images into the HTML do not (yet) include the correct image class (eg class="wp-image-9999"). Because of this, WordPress does not auto-insert srcset tags (taking advantage of automatic image resizing done by WordPress itself or other plugins, thereby making the image responsive). This plugin attempts to lookup the correct ID for each image found in the source HTML code, and inserts it into a class tag. NB this version is dirty - it processes ALL image tags (not just the ones created by DIVI) and only attempts to create a class tag for images that have no class tag. The next version should be a little more intelligent!
   Author: Dean Richardson
   Version: 0.1alpha
   Author URI: http://deanrichardson.co.uk
 */

 
 // Timing! We have to make sure that DIVI does it's thing (converting shortcodes into HTML) followed by OUR function to insert class tags, followed only then by WordPress's wp_make_content_images_responsive function.
 // So, change the default priority of the wp_make_content_images_responsive filter to make it run after our filter inserts wp-image-xxx class
 remove_filter( 'the_content', 'wp_make_content_images_responsive' );
 add_filter ("the_content", "CS_DiviImageSrcset::divifilter_enablesrcset", 9998);
 add_filter( 'the_content', 'wp_make_content_images_responsive', 9999 ); 
 
 
class CS_DiviImageSrcset {
   static function divifilter_enablesrcset($content) {
   // Get an array of all images (TODO: only images that fall within DIVI's et_pb_image class)
   if ( ! preg_match_all( '/<img [^>]+>/', $content, $matches) ) {
      return $content;
   }

   $selected_images = array();
   foreach( $matches[0] as $image ) {
      // Mustn't have a "class" set - TODO: insert into an existing class tag.
      if (preg_match("/\\bclass\\b/", $image)) {
         continue;
      }
      if (preg_match('/src\s*=\s*"([^"]+)"/', $image, $srcmatch)) { 
         $attachment_id = self::get_attachment_id_from_url( $srcmatch[1] ); 
         if ($attachment_id) {
            $selected_images[ $image ] = $attachment_id;
         }
      }
   } 

// We now have an array of images where we've found an attachment_id. Amend all these images to add the class.
   foreach ( $selected_images as $image => $attachment_id ) {
      $newimagetag = str_replace("<img ", "<img class='wp-image-{$attachment_id}' ", $image);
      $content = str_replace( $image, $newimagetag, $content );
   }
 
   return $content;
} 

 /**
 * Get an attachment ID given a URL.
 * 
 * Original: https://wpscholar.com/blog/get-attachment-id-from-wp-image-url/
 * 
 * @param string $url
 *
 * @return int Attachment ID on success, 0 on failure
 */
 static function get_attachment_id_from_url( $url ) {
   $attachment_id = 0;
   $dir = wp_upload_dir();
   //if ( false !== strpos( $url, $dir['baseurl'] . '/' ) ) { // Is URL in uploads directory?
   $file = basename( $url );
   $query_args = array(
      'post_type' => 'attachment',
      'post_status' => 'inherit',
      'fields' => 'ids',
      'meta_query' => array(
         array(
            'value' => $file,
            'compare' => 'LIKE',
            'key' => '_wp_attachment_metadata',
         ),
      )
   );
   $query = new WP_Query( $query_args );
   if ( $query->have_posts() ) {
      foreach ( $query->posts as $post_id ) {
         $meta = wp_get_attachment_metadata( $post_id );
         $original_file = basename( $meta['file'] );
         $cropped_image_files = wp_list_pluck( $meta['sizes'], 'file' );
         if ( $original_file === $file || in_array( $file, $cropped_image_files ) ) {
            $attachment_id = $post_id;
            break;
         }
      }
   }
 //}
 return $attachment_id;
 }
}
?>