Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save davidwolfpaw/fbe020cd282c4f6ad7ed805f5ad72a85 to your computer and use it in GitHub Desktop.
Save davidwolfpaw/fbe020cd282c4f6ad7ed805f5ad72a85 to your computer and use it in GitHub Desktop.
Sync attachment titles and alt text across WordPress multisite sites
<?php
/**
* Plugin Name: Sync Attachment Meta
* Description: Sync attachment titles and alt text across multisite sites. Choose a source site to pull titles and alt text from, and have matching attachments updated on all other sites.
* Version: 1.0.0
*/
// Confirm that WP-CLI is available.
if ( defined( 'WP_CLI' ) && WP_CLI ) {
/**
* Sync attachment titles and alt text across multisite sites.
*/
class Sync_Attachment_Meta_Command {
/**
* Sync titles and alt text based on post_title or filename match.
*
* <source_site_id> The ID of the source site to pull titles/alt text from.
*
* Example Command: wp sync-attachment-meta 1
*/
public function __invoke( $args ) {
list( $source_site_id ) = $args;
if ( ! is_multisite() ) {
WP_CLI::error( 'This script only works on multisite installs.' );
}
$sites = get_sites();
// Switch to the source site and get attachments.
switch_to_blog( $source_site_id );
WP_CLI::log( "Switched to source site: {$source_site_id}" );
// Get all attachments on the source site.
// Note: This will only get attachments that are in the media library.
$attachments = get_posts(
array(
'post_type' => 'attachment',
'post_status' => 'inherit',
'posts_per_page' => -1,
)
);
// Display count of attachments found.
WP_CLI::log( 'Found ' . count( $attachments ) . ' attachments on source site.' );
// Collect source site attachment data indexed by both title and filename.
$attachment_data = array();
foreach ( $attachments as $attachment ) {
$alt_text = get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true );
$file_path = get_post_meta( $attachment->ID, '_wp_attached_file', true );
$file_name = basename( $file_path );
// Add both title and filename as keys for quick lookup.
$attachment_data[ $attachment->post_title ] = array(
'title' => $attachment->post_title,
'caption' => $attachment->post_excerpt,
'alt' => $alt_text,
'file' => $file_name,
);
$attachment_data[ $file_name ] = array(
'title' => $attachment->post_title,
'caption' => $attachment->post_excerpt,
'alt' => $alt_text,
'file' => $file_name,
);
}
restore_current_blog();
// Loop through all sites and update matching attachments.
foreach ( $sites as $site ) {
$site_id = (int) $site->blog_id;
// Skip the source site.
if ( $site_id === (int) $source_site_id ) {
continue;
}
// Display site ID being processed.
WP_CLI::log( "Processing site ID: {$site_id}" );
switch_to_blog( $site_id );
$site_attachments = get_posts(
array(
'post_type' => 'attachment',
'post_status' => 'inherit',
'posts_per_page' => -1,
)
);
$updated_count = 0;
foreach ( $site_attachments as $site_attachment ) {
$site_file_path = get_post_meta( $site_attachment->ID, '_wp_attached_file', true );
$site_file_name = basename( $site_file_path );
$site_title = $site_attachment->post_title;
$matched_data = null;
// Check if there's a match by post_title or file_name.
if ( isset( $attachment_data[ $site_title ] ) ) {
$matched_data = $attachment_data[ $site_title ];
} elseif ( isset( $attachment_data[ $site_file_name ] ) ) {
$matched_data = $attachment_data[ $site_file_name ];
}
if ( $matched_data ) {
// Update post title and caption.
wp_update_post(
array(
'ID' => $site_attachment->ID,
'post_title' => $matched_data['title'],
'post_excerpt' => $matched_data['caption'],
)
);
// Check if alt text already exists on this attachment.
$existing_alt_text = get_post_meta( $site_attachment->ID, '_wp_attachment_image_alt', true );
if ( empty( $existing_alt_text ) ) {
// If there is no alt text, add it.
update_post_meta( $site_attachment->ID, '_wp_attachment_image_alt', $matched_data['alt'] );
WP_CLI::log( "Updated attachment ID {$site_attachment->ID} on site {$site_id} (matched by title or filename: {$matched_data['file']}, alt text added)" );
} else {
// Alt text already exists, skip updating
WP_CLI::log( "Skipped alt text for attachment ID {$site_attachment->ID} on site {$site_id} (alt text already present)" );
}
++$updated_count;
}
}
WP_CLI::log( "Site {$site_id} complete. Updated {$updated_count} attachments." );
restore_current_blog();
}
WP_CLI::success( 'Attachment meta sync complete!' );
}
}
WP_CLI::add_command( 'sync-attachment-meta', 'Sync_Attachment_Meta_Command' );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment