WordPress.org

Make WordPress Core


Ignore:
Timestamp:
07/22/2015 05:14:50 AM (5 years ago)
Author:
pento
Message:

Shortcodes: Improve the reliablity of shortcodes inside HTML tags.

Props miqrogroove.

See #15694.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/formatting.php

    r33271 r33359  
    505505    $pee = str_replace(array("\r\n", "\r"), "\n", $pee);
    506506
     507    // Strip newlines from all elements.
     508    $pee = wp_replace_in_html_tags( $pee, array( "\n" => " " ) );
     509
    507510    // Collapse line breaks before and after <option> elements so they don't get autop'd.
    508511    if ( strpos( $pee, '<option' ) !== false ) {
     
    591594
    592595    return $pee;
     596}
     597
     598/**
     599 * Replace characters or phrases within HTML elements only.
     600 *
     601 * @since 4.2.3
     602 *
     603 * @param string $haystack The text which has to be formatted.
     604 * @param array $replace_pairs In the form array('from' => 'to', ...).
     605 * @return string The formatted text.
     606 */
     607function wp_replace_in_html_tags( $haystack, $replace_pairs ) {
     608    // Find all elements.
     609    $comments =
     610          '!'           // Start of comment, after the <.
     611        . '(?:'         // Unroll the loop: Consume everything until --> is found.
     612        .     '-(?!->)' // Dash not followed by end of comment.
     613        .     '[^\-]*+' // Consume non-dashes.
     614        . ')*+'         // Loop possessively.
     615        . '(?:-->)?';   // End of comment. If not found, match all input.
     616
     617    $regex =
     618          '/('              // Capture the entire match.
     619        .     '<'           // Find start of element.
     620        .     '(?(?=!--)'   // Is this a comment?
     621        .         $comments // Find end of comment.
     622        .     '|'
     623        .         '[^>]*>?' // Find end of element. If not found, match all input.
     624        .     ')'
     625        . ')/s';
     626
     627    $textarr = preg_split( $regex, $haystack, -1, PREG_SPLIT_DELIM_CAPTURE );
     628    $changed = false;
     629
     630    // Optimize when searching for one item.
     631    if ( 1 === count( $replace_pairs ) ) {
     632        // Extract $needle and $replace.
     633        foreach ( $replace_pairs as $needle => $replace );
     634
     635        // Loop through delimeters (elements) only.
     636        for ( $i = 1, $c = count( $textarr ); $i < $c; $i += 2 ) {
     637            if ( false !== strpos( $textarr[$i], $needle ) ) {
     638                $textarr[$i] = str_replace( $needle, $replace, $textarr[$i] );
     639                $changed = true;
     640            }
     641        }
     642    } else {
     643        // Extract all $needles.
     644        $needles = array_keys( $replace_pairs );
     645
     646        // Loop through delimeters (elements) only.
     647        for ( $i = 1, $c = count( $textarr ); $i < $c; $i += 2 ) {
     648            foreach ( $needles as $needle ) {
     649                if ( false !== strpos( $textarr[$i], $needle ) ) {
     650                    $textarr[$i] = strtr( $textarr[$i], $replace_pairs );
     651                    $changed = true;
     652                    // After one strtr() break out of the foreach loop and look at next element.
     653                    break;
     654                }
     655            }
     656        }
     657    }
     658
     659    if ( $changed ) {
     660        $haystack = implode( $textarr );
     661    }
     662
     663    return $haystack;
    593664}
    594665
Note: See TracChangeset for help on using the changeset viewer.