Understanding and altering the structure of posted images

Lets start with your first code.
If you add texts, captions etc. a shortcode will be generated:
The function img_caption_shortcode() in wp-content/media.php is responsible to execute the shortcode. But this shortcode is only produced, when you use captions. Otherwise, it will be simply inserted the <a>– and <img>-Tag.

who decides, what gets inserted?

There is an interesting ajax request taking place, once you add a media file: send-attachment-to-editor. It sends all the data like ‘image-size’, ‘url’, ‘html’…

The function wp_ajax_send_attachment_to_editor() which can be found in wp-admin/includes/ajax-actions.php is called by this ajax request. This functions attaches the image for example to the post. More interesting for us: This function creates the HTML, which will be posted in the editor. So, here it is decided, whether the shortcode or a simple <img>-Tag will be used.

The filter media_send_to_editor

Good for us since wp_ajax_send_attachment_to_editor() uses the filter media_send_to_editor to give us the chance to alter this code. Three parameters are given:
– the current HTML output
– the Attachment ID
– the information, how big the image is, the align…

Just as an example:

 add_filter( 'media_send_to_editor', 'test_media', 10, 3 );
 function test_media( $html, $id, $attachment ){
    return '<a href="http://example.com">TEST</a>';
 }

This would always print the Link http://example.com/

I hope this helps you as a start.

A “better” shortcode

To receive now the output, you want, I would suggest the following:

<?php
  add_filter( 'media_send_to_editor', 'use_always_caption', 10, 3 );
     function use_always_caption( $html, $id, $attachment ){
        $post = get_post( $id );
        //Return if its not an image
        if ( 'image' != substr( $post->post_mime_type, 0, 5 ) )
            return $html;
        $rel="";
        $url =  isset( $attachment['url'] ) ? $attachment['url'] : '';

        if ( strpos( $url, 'attachment_id') || get_attachment_link( $id ) == $url )
            $rel=" rel="attachment"";

        $align = isset( $attachment['align'] ) ? $attachment['align'] : 'none';
        $size = isset( $attachment['image-size'] ) ? $attachment['image-size'] : 'medium';
        $alt = isset( $attachment['image_alt'] ) ? $attachment['image_alt'] : '';
        $caption = ' ';
        if( isset( $attachment['post_excerpt'] ) && ! empty( $attachment['post_excerpt'] ) )
            $caption = $attachment['post_excerpt'];
        $title=""; // We no longer insert title tags into <img> tags, as they are redundant.
        add_filter( 'get_image_tag', 'remove_id_from_class_and_hw', 10, 6 );
        $html = get_image_send_to_editor( $id, $caption, $title, $align, $url, (bool) $rel, $size, $alt );
        remove_filter( 'get_image_tag', 'remove_id_from_class_and_hw', 10, 6 );
        $html = preg_replace( '^toremove--width="(.*)"--toremove^', '', $html );
        return $html;
     }

     function remove_id_from_class_and_hw( $html, $id, $alt, $title, $align, $size ){
         list( $img_src, $width, $height ) = image_downsize( $id, $size );
         $class="align" . esc_attr( $align ) .' size-' . esc_attr( $size );
         return '<img src="' . esc_attr( $img_src ) . '" alt="' . esc_attr( $alt ) . '" ' . $title . ' class="' . $class . '" toremove--width="' . $width . '" height="' . $height . '"--toremove />';
     }

     remove_shortcode( 'caption' );
     add_shortcode( 'caption', 'better_img_caption_shortcode' );
     function better_img_caption_shortcode( $attr, $content = null ){
        if ( ! isset( $attr['caption'] ) ) {
            if ( preg_match( '#((?:<a [^>]+>\s*)?<img [^>]+>(?:\s*</a>)?)(.*)#is', $content, $matches ) ) {
                $content = $matches[1];
                $attr['caption'] = trim( $matches[2] );
            }
        }

        $output = apply_filters( 'img_caption_shortcode', '', $attr, $content );
        if ( $output != '' )
            return $output;

        $atts = shortcode_atts( array(
            'id'      => '',
            'align'   => 'alignnone',
            'width'   => '',
            'caption' => '',
            'class'   => '',
        ), $attr, 'caption' );

        $atts['width'] = (int) $atts['width'];
        if ( $atts['width'] < 1 )
            return $content;

        $class = trim( 'wp-caption ' . $atts['align'] . ' ' . $atts['class'] );

        $figcaption = '';
        if( ! empty( $atts['caption'] ) )
            $figcaption = '<figcaption class="wp-caption-text">' . $atts['caption'] . '</figcaption>';
        return '<figure class="' . esc_attr( $class ) . '">'
            . do_shortcode( $content ) . $figcaption . '</figure>';

     }
?>

I’ve copy-pasted a bit 🙂

So, what I do: With the filter media_send_to_editor I force WordPress to always use the -Shortcode. We alter a bit the image output by using the filter get_image_tag which is used by the function get_image_tag() to create the <img>-Tag. This function can be found in wp-include/media.php. Since I didn’t wanted to create the whole shortcode and leave WordPress to do it, I needed to leave the width and height (you should leave it anyway, i think) because the caption creation done by image_add_caption() ( to be found in wp-admin/includes/media.php) needs these values from the string. I added an ugly toremove-- and remove it later on.

In a second step, I remove the existing -Shortcode and overwrite it with my own. My own is basically the same, but I removed the ID- and the Style-Attribute. I stick to the -Shortcode, so once the user disables the plugin, the pictures would still show up in a reasonable way.

Docs: