Last active
February 15, 2026 01:27
-
-
Save mrfoxtalbot/2148423203a4241fe5364f93a473a7f0 to your computer and use it in GitHub Desktop.
WP Visual Composer (WP Bakery) Migrate Gallery & Image Carousel shortcodes to regular WP shortcodes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Plugin Name: VC Gallery Migrator - NO FATAL ERROR | |
| * Description: SAFE version - replaces [vc_gallery images="20129,20130,20132"...] β [gallery ids="20129,20130,20132"] | |
| * Version: 5.0 - STABLE | |
| */ | |
| if ( ! defined( 'ABSPATH' ) ) exit; | |
| add_action( 'admin_menu', 'vc_gallery_safe_menu' ); | |
| function vc_gallery_safe_menu() { | |
| add_management_page( 'VC Gallery Migrator', 'VC Gallery Migrator', 'manage_options', 'vc-gallery-migrator', 'vc_gallery_safe_page' ); | |
| } | |
| function vc_gallery_safe_page() { | |
| if ( ! current_user_can( 'manage_options' ) ) wp_die( 'No access' ); | |
| $debug_info = $stats = $message = ''; | |
| $dry_run = isset( $_POST['dry_run'] ) ? true : false; | |
| if ( isset( $_POST['run'] ) && wp_verify_nonce( $_POST['nonce'], 'vc_gallery_safe' ) ) { | |
| $result = vc_gallery_safe_migrate( $dry_run ); | |
| $status_class = $dry_run ? 'notice-warning' : 'notice-success'; | |
| $action = $dry_run ? 'PREVIEWED' : 'β REPLACED'; | |
| $stats = sprintf( | |
| '<div class="notice %s"><p><strong>%s:</strong><br> | |
| Found: %d galleries | Replaced: %d | Posts updated: %d</p></div>', | |
| $status_class, $action, $result['found'], $result['replaced'], $result['posts'] | |
| ); | |
| // Simple safe debug table | |
| $debug_info = '<h3>π GALLERIES FOUND:</h3>'; | |
| foreach ( array_slice( $result['details'], 0, 10 ) as $i => $detail ) { | |
| $debug_info .= sprintf( | |
| '<p><strong>Gallery #%d:</strong> <code>%s</code> β <code>[gallery ids="%s"]</code></p>', | |
| $i + 1, | |
| esc_html( $detail['original'] ), | |
| esc_attr( $detail['gallery'] ) | |
| ); | |
| } | |
| $message = $dry_run | |
| ? '<p><strong>β Preview OK! Uncheck "Dry Run" to replace.</strong></p>' | |
| : '<p><strong>π All galleries replaced successfully!</strong></p>'; | |
| } | |
| ?> | |
| <div class="wrap"> | |
| <h1>πΌοΈ VC Gallery Migrator - SAFE</h1> | |
| <?php echo $stats . $debug_info . $message; ?> | |
| <form method="POST"> | |
| <?php wp_nonce_field( 'vc_gallery_safe', 'nonce' ); ?> | |
| <p> | |
| <label> | |
| <input type="checkbox" name="dry_run" <?php checked( $dry_run ); ?>> | |
| Dry Run (Preview - No changes) | |
| </label><br> | |
| <input type="submit" name="run" class="button-primary" | |
| value="<?php echo $dry_run ? 'π Preview Galleries' : 'π Replace All Galleries'; ?>" | |
| onclick="return confirm('<?php echo $dry_run ? 'Preview?' : 'BACKUP FIRST! This replaces ALL VC galleries.'; ?>')"> | |
| </p> | |
| </form> | |
| <h3>π Converts exactly:</h3> | |
| <p><code>[vc_gallery interval="3" images="20129,20130,20132" img_size="medium" onclick="img_link_large"]</code><br> | |
| β<br><code>[gallery ids="20129,20130,20132"]</code></p> | |
| </div> | |
| <?php | |
| } | |
| function vc_gallery_safe_migrate( $dry_run = true ) { | |
| global $wpdb; | |
| $posts = $wpdb->get_results("SELECT ID, post_content FROM {$wpdb->posts} WHERE post_content LIKE '%vc_gallery%' OR post_content LIKE '%vc_images_carousel%' AND post_status != 'trash'"); | |
| $found = $replaced = $posts_changed = 0; | |
| $details = []; | |
| foreach ( $posts as $post ) { | |
| $content = $post->post_content; | |
| $original_content = $content; | |
| // β SAFE REGEX - No complex patterns, no callbacks | |
| if ( preg_match_all( '/\[vc_gallery\s+[^]]*images=["\']([^"\']+)["\'][^\]]*\]/i', $content, $matches, PREG_SET_ORDER ) ) { | |
| foreach ( $matches as $match ) { | |
| $ids_string = $match[1]; // "20129,20130,20132" | |
| $full_shortcode = $match[0]; | |
| $ids = array_map( 'intval', explode( ',', $ids_string ) ); | |
| $ids = array_filter( $ids ); // Remove empty | |
| $gallery_ids = implode( ',', $ids ); | |
| $replacement = '[gallery ids="' . $gallery_ids . '"]'; | |
| $content = str_replace( $full_shortcode, $replacement, $content ); | |
| $details[] = [ | |
| 'original' => $full_shortcode, | |
| 'gallery' => $gallery_ids | |
| ]; | |
| $found++; | |
| $replaced++; | |
| } | |
| } | |
| // Also check vc_images_carousel | |
| if ( preg_match_all( '/\[vc_images_carousel\s+[^]]*images=["\']([^"\']+)["\'][^\]]*\]/i', $content, $matches, PREG_SET_ORDER ) ) { | |
| foreach ( $matches as $match ) { | |
| $ids_string = $match[1]; | |
| $full_shortcode = $match[0]; | |
| $ids = array_map( 'intval', explode( ',', $ids_string ) ); | |
| $ids = array_filter( $ids ); | |
| $gallery_ids = implode( ',', $ids ); | |
| $replacement = '[gallery ids="' . $gallery_ids . '"]'; | |
| $content = str_replace( $full_shortcode, $replacement, $content ); | |
| $details[] = [ | |
| 'original' => $full_shortcode, | |
| 'gallery' => $gallery_ids | |
| ]; | |
| $found++; | |
| $replaced++; | |
| } | |
| } | |
| if ( $content !== $original_content && ! $dry_run ) { | |
| wp_update_post( [ 'ID' => $post->ID, 'post_content' => $content ] ); | |
| $posts_changed++; | |
| } | |
| } | |
| return [ | |
| 'found' => $found, | |
| 'replaced' => $replaced, | |
| 'posts' => $posts_changed, | |
| 'details' => $details | |
| ]; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment