Here is the script I came up with. It loops through all the posts in a WordPress instance and splits it up into three sections:
- The HTML/content before the row of shortcodes
- The row of shortcodes
- The HTML/content after the row of shortcodes
I decided to use substr()
to split up the content. I then re-assemble everything together towards the end and include the “wrapping” shortcode around the middle piece.
$args = array( 'numberposts' => -1, 'post_status' => 'publish|draft|trash' )
$posts = get_posts( $args );
if( !empty( $posts ) ){
foreach( $posts as $post ){
$content = $post->post_content;
if( !has_shortcode( $content, 'components') ){
$pattern = '/\[component id=\"[0-9]+\"\]/';
preg_match_all( $pattern, $content, $matches, PREG_OFFSET_CAPTURE);
$first_match = $matches[0][0];
$first_match_start = $first_match[1]; // Start position of the first match
$last_match = $matches[0][ count($matches[0]) - 1 ];
$last_match_start = $last_match[1];
$last_match_end = $last_match_start + strlen($last_match[0]);
$before_html = substr($content, 0, $first_match_start); // Get all the content before the first match of [component id="XYZ"]
$component_shortcodes = substr($content, $first_match_start, $last_match_end - $first_match_start ); // Get everything in between the first [component id="XYZ"] and the last
$after_html = substr($content, $last_match_end ); // Get everything after the last [component id="XYZ"] match
// Perform the actual wrapping here
$new_content = $before_html . '[components]' . $component_shortcodes . '[/components]' . $after_html;
$post->post_content = $new_content;
wp_update_post( $post );
}
}
}