How do I change the description of the same image which is to be found in multiple instances?

Plugin idea #1

When we insert an image into the editor, the plugin automatically modifies the caption and the alt attribute to:


  <a href="http://example.tld/wp-content/uploads/2015/02/wordpress.jpg">
      <img src="http://example.tld/wp-content/uploads/2015/02/wordpress-300x284.jpg" 
          alt="###ALT###" 
          width="300" 
          height="284" 
          class="size-medium wp-image-729" />
  </a> 
  ###CAPTION###

Then on the front-end the image caption is fetched for the corresponding image attachment, based on the attachment_729 string and replaces the ###ALT### and ###CAPTION### dummy values.

So when we want to modify the captions for all the image copies, we only have to do it once in the Media Manager.

Here’s our Dynamic Image Caption plugin that should support this feature (PHP 5.4+):

<?php
/**
 * Plugin Name:   Dynamic Image Caption #1
 * Description:   We only want to modify the image captions in the Media Manager 
 * Plugin URI:    http://wordpress.stackexchange.com/a/179689/26350
 * Plugin Author: Birgir Erlendsson (birgire)
 * Version:       0.0.1
 */

namespace birgire\wpse;

add_action( 'init', function()
{
    $o = new DynamicImageCaption;
    $o->activate();
});

class DynamicImageCaption
{
    private $caption_dummy = '###CAPTION###';
    private $alt_dummy     = '###ALT###';

    public function activate()
    {
        add_shortcode( 
            'caption', 
             [ $this, 'caption_shortcode' ] 
        );

        add_filter( 
            'image_add_caption_text', 
            [ $this, 'add_caption_text' ], 
            10, 
            2 
        );

        add_filter( 
            'image_send_to_editor',  
            [ $this, 'send_to_editor' ],
            10, 
            8 
        );
    }

    public function caption_shortcode( $attr = [], $content="" )
    {
        if( isset( $attr['id'] ) 
            && ( 
                false !== strpos( $content, $this->caption_dummy ) 
                ||
                false !== strpos( $content, $this->alt_dummy ) 
           )
        )
        {
            $caption = $this->get_caption( 
                $attr['id'], 
                str_replace( 'attachment_', '', $attr['id'] ) 
            );

            $content = str_replace(
                [ $this->caption_dummy, $this->alt_dummy ],
                [ $caption, esc_attr( $caption ) ],
                $content
            );
        }
        return img_caption_shortcode( $attr, $content );
    }

    private function get_caption( $caption, $id )
    {
        $caption = '';

        $attachments = get_posts( 
            [ 
                'p'           =>  $id, 
                'post_type'   => 'attachment', 
                'post_status' => 'inherit' 
            ] 
        );

        if( isset( $attachments[0] ) 
            && $attachments[0] instanceof \WP_Post  
        )
            $caption =  $attachments[0]->post_excerpt;

        return $caption;
    }

    public function send_to_editor( $html, $id, $caption, $title, $align, $url, $size, $alt )
    {
        if( $alt )
        {
            $html = str_replace(
                'alt="' . esc_attr( $alt ),
                'alt="' . $this->alt_dummy,
                $html
            );
        }
        return $html;
    }

} // end class

Copy this into the file:

/wp-content/plugins/dynamic-image-caption/dynamic-image-caption.php

and activate the plugin.

Note that here I use the caption also as the alt attribute for convenience. You should test this further and modify to your needs.

Ps: My first idea was to add extra shortcodes within the shortcode, like:

[dynamic_caption id="729"] 

and

[dynamic_alt id="729"] 

This works, but I wanted to find another way that only fetches the corresponding attachment once, without using these kind of shortcodes.

Plugin idea #2

Here’s another idea to modify the existing image captions and alt attributes. This plugin doesn’t modify the code in the post editor, like the previous plugin did, only it’s output.

<?php
/**
 * Plugin Name:   Dynamic Image Caption And Alt #2
 * Description:   We only want to modify the image caption and alt in the Media Manager. 
 * Plugin URI:    http://wordpress.stackexchange.com/a/179689/26350
 * Plugin Author: Birgir Erlendsson (birgire)
 * Version:       0.0.1
 */

namespace birgire\wpse;

add_action( 'init', function()
{
    $o = new DynamicImageCaptionAlt;
    $o->activate();
});

class DynamicImageCaptionAlt
{
    public function activate()
    {
        add_shortcode( 
            'caption', 
             [ $this, 'caption_shortcode' ] 
        );
    }

    public function caption_shortcode( $attr = [], $content="" )
    {
        if( isset( $attr['id'] ) )
        {
            $id = str_replace( 'attachment_', '', $attr['id'] );

            // Fetch the caption and the alt attribute:
            $caption = $this->get_caption( $id );
            $alt     = esc_attr( $this->get_alt( $id ) );

            // Use caption as alt, if alt is empty:
            if( ! $alt )
                $alt = esc_attr( $caption );

            // Modify the caption:
            $content .= '###END###';
            $content = str_replace( 
                strip_tags( $content ), 
                $caption, 
                $content 
            );

            // Modify the alt attribute:
            $content = preg_replace( 
                '#alt="[^"]*"#', 
                sprintf( 'alt="%s"', $alt ), 
                $content 
            );
        }
        return img_caption_shortcode( $attr, $content );
    }

    private function get_caption( $id )
    {
        global $wpdb;
        $sql = $wpdb->prepare( 
            "SELECT post_excerpt 
             FROM {$wpdb->posts} 
             WHERE ID = %d AND post_type="attachment" ", 
            $id 
        );
        return $wpdb->get_var( $sql );
    }

    private function get_alt( $id )
    {
       return get_post_meta( $id, '_wp_attachment_image_alt', true );
    }

} // end class

Note that this will add extra database queries to your site, as expected.

Leave a Comment