Last active
February 18, 2017 23:41
-
-
Save mwinckler/54595f2ff0dd9313fcee06c99a64822f to your computer and use it in GitHub Desktop.
This file contains 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 | |
// Populate this array with your shortcode tag names (not including brackets). | |
$shortcodes = array( 'contextbox' ); | |
// Leave this array alone; it's what we'll use to stash shortcode content in until wpautop has safely passed. | |
$shortcode_replacements = array(); | |
// See wp-includes/default-filters.php for core WordPress filter priorities | |
// 9 comes right before wpautop at 10 | |
add_filter('the_content', 'mw_rescue_shortcodes_from_wpautop', 9); | |
// Same level as wp_autop, executed after (because ours is added later) but before do_shortcode at 11 | |
add_filter('the_content', 'mw_restore_shortcodes_after_wpautop', 10); | |
// Returns empty array if no match found, else: | |
// $result[0] == shortcode_tag_found | |
// $result[1] == string index | |
function find_next_shortcode_open_tag( $shortcode, $content, $offset ) { | |
$matches = array(); | |
$result = preg_match( '/\[' . $shortcode . '( [^]]+)?\]/', $content, $matches, PREG_OFFSET_CAPTURE, $offset ); | |
return $result === 1 ? array( $matches[0][0], $matches[0][1] ) : array(); | |
} | |
function find_first_shortcode_pos( $content, $offset ) { | |
global $shortcodes; | |
$earliest_pos = -1; | |
$first_shortcode = null; | |
foreach ( $shortcodes as $shortcode ) { | |
$result = find_next_shortcode_open_tag( $shortcode, $content, $offset ); | |
if ( count( $result ) === 0 ) { | |
continue; | |
} | |
if ( $earliest_pos == -1 || $result[1] < $earliest_pos ) { | |
$earliest_pos = $result[1]; | |
$first_shortcode = $shortcode; | |
} | |
} | |
return array( $earliest_pos, $first_shortcode ); | |
} | |
function mw_rescue_shortcodes_from_wpautop( $content ) { | |
global $shortcode_replacements; | |
$opening_index = 0; | |
while ( $opening_index < strlen( $content ) ) { | |
$result = find_first_shortcode_pos( $content, $opening_index ); | |
$opening_index = $result[0]; | |
$tag_name = $result[1]; | |
if ( $opening_index == -1 ) { | |
break; | |
} | |
// Found an opening tag? Continue searching until we find the matching closing tag. | |
// There is the possibility of nested opening tags before reaching the matching close. | |
$closing_tag = '[/' . $tag_name . ']'; | |
$open_tag_count = 1; | |
$closing_index = $opening_index; | |
while ( $open_tag_count > 0 && $closing_index < strlen( $content )) { | |
$closing_pos = strpos( $content, $closing_tag, $closing_index ); | |
if ( $closing_pos === false ) { | |
// This is a problem; we have no closing tag. Just take the rest of the content. | |
$open_tag_count = 0; | |
$closing_index = strlen( $content ); | |
break; | |
} | |
$open_tag_matches = find_next_shortcode_open_tag ( $tag_name, $content, $closing_index ); | |
$open_tag_found = count( $open_tag_matches ) > 0; | |
if ( $open_tag_found ) { | |
$matched_open_tag = $open_tag_matches[0]; | |
$next_opening_pos = $open_tag_matches[1]; | |
} | |
if ( !$open_tag_found || $closing_pos < $next_opening_pos ) { | |
$closing_index = $closing_pos + strlen( $closing_tag ); | |
$open_tag_count--; | |
} else { | |
$closing_index = $next_opening_pos + strlen( $matched_open_tag ); | |
$open_tag_count++; | |
} | |
} | |
// Replace everything from $opening_index to $closing_index with a placeholder and stash that placeholder. | |
// Don't forget to wrap it in <p> so that wpautop doesn't. :P | |
do { | |
$key = '<p>' . md5(rand()) . '</p>'; | |
} while ( array_key_exists( $key, $shortcode_replacements ) ); | |
$shortcode_replacements[$key] = substr( $content, $opening_index, $closing_index - $opening_index ); | |
$content = substr_replace( $content, $key, $opening_index, $closing_index - $opening_index ); | |
$opening_index = $opening_index + strlen( $key ); | |
} | |
return $content; | |
} | |
function mw_restore_shortcodes_after_wpautop( $content ) { | |
global $shortcode_replacements; | |
foreach ( $shortcode_replacements as $key => $value ) { | |
$content = str_replace( $key, $value, $content ); | |
} | |
return $content; | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment