0 ) ); WP_CLI::log( 'Starting alt text updates on ' . count( $sites ) . ' sites...' ); foreach ( $sites as $site ) { switch_to_blog( $site->blog_id ); $site_name = get_bloginfo( 'name' ); WP_CLI::log( "Processing site: {$site_name} (ID: {$site->blog_id})" ); $updated_count = $this->run_image_alt_update_on_current_site(); WP_CLI::log( "Finished {$site_name}: {$updated_count} posts/pages updated.\n" ); restore_current_blog(); } WP_CLI::success( 'All sites processed!' ); } /** * Runs the image alt text update on the current site. * * @return int Number of updated posts. */ private function run_image_alt_update_on_current_site() { $args = array( 'post_type' => array( 'post', 'page' ), // Add CPTs if needed. 'post_status' => 'publish', 'posts_per_page' => -1, ); $query = new WP_Query( $args ); $updated_count = 0; foreach ( $query->posts as $post ) { $original_content = $post->post_content; $updated_content = $this->update_image_alts_in_all_blocks( $original_content ); if ( $updated_content !== $original_content ) { wp_update_post( array( 'ID' => $post->ID, 'post_content' => $updated_content, ) ); WP_CLI::log( "Updated post ID {$post->ID} ({$post->post_title})" ); ++$updated_count; } } return $updated_count; } /** * Parses and updates alt text for images in all blocks within post content. * Uses serialize_blocks() to preserve block markup. * * @param string $content The post content. * @return string Updated content. */ private function update_image_alts_in_all_blocks( $content ) { $blocks = parse_blocks( $content ); $updated_blocks = array(); foreach ( $blocks as $block ) { $updated_blocks[] = $this->process_any_block_recursive( $block ); } // Use serialize_blocks() to keep block markup intact. return serialize_blocks( $updated_blocks ); } /** * Recursively process blocks to update image alt text. * * @param array $block * @return array */ private function process_any_block_recursive( $block ) { // === Generic Core Block Handling === if ( ! empty( $block['attrs'] ) && ! empty( $block['attrs']['id'] ) ) { $attachment_id = $block['attrs']['id']; $media_alt = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ); if ( $media_alt ) { if ( empty( $block['attrs']['alt'] ) || $block['attrs']['alt'] !== $media_alt ) { $block['attrs']['alt'] = $media_alt; } } } if ( ! empty( $block['attrs']['images'] ) && is_array( $block['attrs']['images'] ) ) { foreach ( $block['attrs']['images'] as &$image ) { if ( ! empty( $image['id'] ) ) { $attachment_id = $image['id']; $media_alt = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ); if ( $media_alt ) { if ( empty( $image['alt'] ) || $image['alt'] !== $media_alt ) { $image['alt'] = $media_alt; } } } } } // === Custom Kirkwood Block Handling === if ( $block['blockName'] === 'kirkwood/story-section-block' && ! empty( $block['attrs']['sections'] ) ) { foreach ( $block['attrs']['sections'] as $section_key => &$section_data ) { // Main imageID handling if ( isset( $section_data['imageID'] ) && is_numeric( $section_data['imageID'] ) ) { $attachment_id = $section_data['imageID']; $media_alt = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ); if ( $media_alt ) { if ( empty( $section_data['altText'] ) || $section_data['altText'] !== $media_alt ) { $section_data['altText'] = $media_alt; } } } // Optional: Mobile ImageID handling if ( isset( $section_data['mobileImageID'] ) && is_numeric( $section_data['mobileImageID'] ) ) { $attachment_id = $section_data['mobileImageID']; $media_alt = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ); if ( $media_alt ) { if ( empty( $section_data['mobileAltText'] ) || $section_data['mobileAltText'] !== $media_alt ) { $section_data['mobileAltText'] = $media_alt; } } } } } // === Recursively Process Inner Blocks === if ( ! empty( $block['innerBlocks'] ) ) { foreach ( $block['innerBlocks'] as &$inner_block ) { $inner_block = $this->process_any_block_recursive( $inner_block ); } } return $block; } } // Register the WP-CLI command. WP_CLI::add_command( 'network-update-all-image-alts', 'Network_Update_All_Image_Alts_Command' ); }