2

I have a client site that has approx. 2000 posts, most with 2-3 images embedded. Recently we've gone through the media gallery and given all the images proper meta data, clean titles, descriptions, alt tags etc.

However the problem we have now is that in order for this data to show up in post content, we'd have to go through post by post, and re-add each image in order to pull in the new alt tag / title.

How would I go about bulk editing these posts to scrape for image attributes, find the image, and re-embed them with their updated meta info?

2
  • 1
    @ Tanmccuin did you ever find a solution to this? Oct 18, 2023 at 13:53
  • 1
    You should be able to edit the theme or write a function that shows the alt tag from the Media Library for the image in each post. That way you don't need to go in and set them all manually. I'm a little surprised that the theme doesn't do that automatically. have you tried updating a post and seeing if that refreshes the img alt? Try a different theme on a dev environment and see if the img alts are there.
    – keepkalm
    Oct 19, 2023 at 21:51

2 Answers 2

1

The situation

WordPress stores image/media details as an attachment port type within the database. When you edit an image in the media library, all the details are correctly saved in the database. We can take most of these details from the wp_posts table, with the exception of alt text which is stored in the wp_postmeta separately.

Regarding images that have been added previously to a post, the image details are included as an HTML markup (an img tag with arguments) in the post content. It seems like, there is a loose connection/control from the media side to the post content. I presume that WordPress developers attempted to conserve server resources by reducing media functions while authors have full control when they edit a post.

enter image description here

The implementation

So, we need to implement a method to meet your requirements, and I hope the following PHP function will handle most of it. The function has the following parts:

#1. Gather posts

#2. Find attachments that linked to a post. (You can change this logic for your needs.)

#3. Find the appropriate markup by a class name from the content (.wp-image-AttachID)

#4. Replace image details (alt, title, and caption) with regex patterns

#5. Update post content

function image_meta_update_in_post_content($per_page = -1, $paged = 0) {
    // #1. Get posts
    $the_query = new WP_Query(array(
        'posts_per_page' => $per_page,
        'paged' => $paged,
        'post_type' => 'post',
        'post_status' => 'any'
    ));
    $log = '';

    if ($the_query->have_posts()) {
        while ($the_query->have_posts()) {
            $the_query->the_post();

            // #2. Find post attachments | You can change this logic
            $args = array(
                'post_parent' => get_the_ID(),
                'post_type' => 'attachment',
                'post_mime_type' => 'image',
                'posts_per_page' => -1,
            );
            $attachments = get_children($args);

            if ($attachments) {
                $content = get_the_content();
                foreach ($attachments as $key => $attach) {

                    // #3. Find an attachment markup by ID from post content
                    $pattern = "~(<img(.*class=['\"](.*)wp-image-" . $attach->ID . "(.*)['\"].*)*>)+~";

                    if (preg_match($pattern, $content, $matches)) {

                        // Meta details: Alt, Caption and Image title
                        $alt = get_post_meta($attach->ID, '_wp_attachment_image_alt', true);
                        $caption = get_the_excerpt($attach->ID);
                        $title = get_the_title($attach->ID);

                        // #4. Replace meta
                        $patterns = [
                            '~(<img.*? alt=")(.*?)("[^>]*>)~i',
                            '~(<img.*? title=")(.*?)(")~i',
                            // '~\[caption\](.*?)\[\/caption\]~is' // To be updated
                        ];
                        $replacements = [
                            "$1$alt$3",
                            "$1$title$3",
                            // "[caption]$1$caption$3[/caption]" // To be updated
                        ];
                        $new_attachment = preg_replace($patterns, $replacements, $matches[0]);
                        $content = str_replace($matches[0], $new_attachment, $content);
                        $log .= "Has been updated (<b>Post: " . get_the_ID() . "</b>".
                            " | Image: $attach->ID, Title: $title, Alt : $alt, Caption: $caption)<br>";
                    }
                }

                // #5. Update post content
                wp_update_post(array('ID' => get_the_ID(), 'post_content' => $content), true, true);
            }
        }
    }
    wp_reset_postdata();
    echo $log;
}

Note 0: Running through 2,000 posts at once could be challenging, so I've added an option to paginate them.

Note 1: Regex patterns are mostly for the img tags and I hope it will work fine with classic post content or blocks editor. However, it is inevitable to make changes if you are using other content builders.

Note 2: I recommend checking the post and attachment linking, or you may consider changing the logic.

enter image description here

The execution

The function may only need to run once or very infrequent. So it seems like there we don't need to add it to any theme or plugin.

[Completely optional]: If I were you, I would call it as a simple PHP script that could locate in the WP root directory. For instance, wp_root/image-meta-updater.php

Then import the wp-load.php to enable all the WP functionality for the script.

ini_set('memory_limit', '256M');
set_time_limit(600);

require_once("wp-load.php");

image_meta_update_in_post_content(10, 1);

Calling

enter image description here

Note 3: Don't forget to delete the file after a successful run or disallow it from public access.

Precaution

As the function is written roughly (especially regex) and saves modification directly to the database, please be cautious to avoid losing your content and follow the next steps:

  1. Backup your database
  2. Try the script on a Staging or Clone server
  3. Or try to run it as a Dry like disabling wp_update_post part
  4. Run with a few posts (5-10) and make sure
0

You can try this filter hook with regular expression to update image alt tag on wordpress pages/posts

`
add_filter('the_content', 'custom_update_image_alt_tags');

function custom_update_image_alt_tags($content) {
// Define your search and replace patterns
$search = '/<img(.*?)alt="(.*?)"(.*?)>/i';
$replace = '<img$1alt="New Alt Text"$2>';

// Update the alt tags in the content
$content = preg_replace($search, $replace, $content);

return $content;
}
`

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.