Make WordPress Core


Ignore:
Timestamp:
10/02/2015 04:25:40 AM (9 years ago)
Author:
wonderboymusic
Message:

Shortcodes/Formatting: Add PCRE Performance Testing

  • Move pattern from wptexturize() into a separate function.
  • Move pattern from wp_html_split() into a separate function.
  • Beautify code for wp_html_split().
  • Remove unnecessary instances of /s modifier in patterns that don't use dots.
  • Add tests/phpunit/data/formatting/whole-posts.php for testing larger strings.
  • Add function benchmark_pcre_backtracking().
  • Add tests for wp_html_split().
  • Add tests for wptexturize().
  • Add tests for get_shortcode_regex().

Props miqrogroove.
Fixes #34121.

File:
1 edited

Legend:

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

    r34747 r34761  
    220220    $tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
    221221    $found_shortcodes = ! empty( $tagnames );
    222     if ( $found_shortcodes ) {
    223         $tagregexp = join( '|', array_map( 'preg_quote', $tagnames ) );
    224         $tagregexp = "(?:$tagregexp)(?![\\w-])"; // Excerpt of get_shortcode_regex().
    225         $shortcode_regex =
    226               '\['              // Find start of shortcode.
    227             . '[\/\[]?'         // Shortcodes may begin with [/ or [[
    228             . $tagregexp        // Only match registered shortcodes, because performance.
    229             . '(?:'
    230             .     '[^\[\]<>]+'  // Shortcodes do not contain other shortcodes. Quantifier critical.
    231             . '|'
    232             .     '<[^\[\]>]*>' // HTML elements permitted. Prevents matching ] before >.
    233             . ')*+'             // Possessive critical.
    234             . '\]'              // Find end of shortcode.
    235             . '\]?';            // Shortcodes may end with ]]
    236     }
    237 
    238     $comment_regex =
    239           '!'           // Start of comment, after the <.
    240         . '(?:'         // Unroll the loop: Consume everything until --> is found.
    241         .     '-(?!->)' // Dash not followed by end of comment.
    242         .     '[^\-]*+' // Consume non-dashes.
    243         . ')*+'         // Loop possessively.
    244         . '(?:-->)?';   // End of comment. If not found, match all input.
    245 
    246     $html_regex =            // Needs replaced with wp_html_split() per Shortcode API Roadmap.
    247           '<'                // Find start of element.
    248         . '(?(?=!--)'        // Is this a comment?
    249         .     $comment_regex // Find end of comment.
    250         . '|'
    251         .     '[^>]*>?'      // Find end of element. If not found, match all input.
    252         . ')';
    253 
    254     if ( $found_shortcodes ) {
    255         $regex = '/(' . $html_regex . '|' . $shortcode_regex . ')/s';
    256     } else {
    257         $regex = '/(' . $html_regex . ')/s';
    258     }
     222    $shortcode_regex = $found_shortcodes ? _get_wptexturize_shortcode_regex( $tagnames ) : '';
     223    $regex = _get_wptexturize_split_regex( $shortcode_regex );
    259224
    260225    $textarr = preg_split( $regex, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
     
    265230        if ( '<' === $first ) {
    266231            if ( '<!--' === substr( $curl, 0, 4 ) ) {
    267                 // This is an HTML comment delimeter.
     232                // This is an HTML comment delimiter.
    268233                continue;
    269234            } else {
     
    616581 */
    617582function wp_html_split( $input ) {
     583    return preg_split( get_html_split_regex(), $input, -1, PREG_SPLIT_DELIM_CAPTURE );
     584}
     585
     586/**
     587 * Retrieve the regular expression for an HTML element.
     588 *
     589 * @since 4.4.0
     590 *
     591 * @return string The regular expression
     592 */
     593function get_html_split_regex() {
    618594    static $regex;
    619595
     
    636612            . '(?:]]>)?';   // End of comment. If not found, match all input.
    637613
     614        $escaped =
     615              '(?='           // Is the element escaped?
     616            .    '!--'
     617            . '|'
     618            .    '!\[CDATA\['
     619            . ')'
     620            . '(?(?=!-)'      // If yes, which type?
     621            .     $comments
     622            . '|'
     623            .     $cdata
     624            . ')';
     625
    638626        $regex =
    639627              '/('              // Capture the entire match.
    640628            .     '<'           // Find start of element.
    641             .     '(?(?=!--)'   // Is this a comment?
    642             .         $comments // Find end of comment.
    643             .     '|'
    644             .         '(?(?=!\[CDATA\[)' // Is this a comment?
    645             .             $cdata // Find end of comment.
    646             .         '|'
    647             .             '[^>]*>?' // Find end of element. If not found, match all input.
    648             .         ')'
     629            .     '(?'          // Conditional expression follows.
     630            .         $escaped  // Find end of escaped element.
     631            .     '|'           // ... else ...
     632            .         '[^>]*>?' // Find end of normal element.
    649633            .     ')'
    650             . ')/s';
    651     }
    652 
    653     return preg_split( $regex, $input, -1, PREG_SPLIT_DELIM_CAPTURE );
     634            . ')/';
     635    }
     636
     637    return $regex;
     638}
     639
     640/**
     641 * Retrieve the combined regular expression for HTML and shortcodes.
     642 *
     643 * @access private
     644 * @ignore
     645 * @internal This function will be removed in 4.5.0 per Shortcode API Roadmap.
     646 * @since 4.4.0
     647 *
     648 * @param string $shortcode_regex The result from _get_wptexturize_shortcode_regex().  Optional.
     649 * @return string The regular expression
     650 */
     651function _get_wptexturize_split_regex( $shortcode_regex = '' ) {
     652    static $html_regex;
     653
     654    if ( ! isset( $html_regex ) ) {
     655        $comment_regex =
     656              '!'           // Start of comment, after the <.
     657            . '(?:'         // Unroll the loop: Consume everything until --> is found.
     658            .     '-(?!->)' // Dash not followed by end of comment.
     659            .     '[^\-]*+' // Consume non-dashes.
     660            . ')*+'         // Loop possessively.
     661            . '(?:-->)?';   // End of comment. If not found, match all input.
     662
     663        $html_regex =            // Needs replaced with wp_html_split() per Shortcode API Roadmap.
     664              '<'                // Find start of element.
     665            . '(?(?=!--)'        // Is this a comment?
     666            .     $comment_regex // Find end of comment.
     667            . '|'
     668            .     '[^>]*>?'      // Find end of element. If not found, match all input.
     669            . ')';
     670    }
     671
     672    if ( empty( $shortcode_regex ) ) {
     673        $regex = '/(' . $html_regex . ')/';
     674    } else {
     675        $regex = '/(' . $html_regex . '|' . $shortcode_regex . ')/';
     676    }
     677
     678    return $regex;
     679}
     680
     681/**
     682 * Retrieve the regular expression for shortcodes.
     683 *
     684 * @access private
     685 * @ignore
     686 * @internal This function will be removed in 4.5.0 per Shortcode API Roadmap.
     687 * @since 4.4.0
     688 *
     689 * @param array $tagnames List of shortcodes to find.
     690 * @return string The regular expression
     691 */
     692function _get_wptexturize_shortcode_regex( $tagnames ) {
     693    $tagregexp = join( '|', array_map( 'preg_quote', $tagnames ) );
     694    $tagregexp = "(?:$tagregexp)(?=[\\s\\]\\/])"; // Excerpt of get_shortcode_regex().
     695    $regex =
     696          '\['              // Find start of shortcode.
     697        . '[\/\[]?'         // Shortcodes may begin with [/ or [[
     698        . $tagregexp        // Only match registered shortcodes, because performance.
     699        . '(?:'
     700        .     '[^\[\]<>]+'  // Shortcodes do not contain other shortcodes. Quantifier critical.
     701        . '|'
     702        .     '<[^\[\]>]*>' // HTML elements permitted. Prevents matching ] before >.
     703        . ')*+'             // Possessive critical.
     704        . '\]'              // Find end of shortcode.
     705        . '\]?';            // Shortcodes may end with ]]
     706
     707    return $regex;
    654708}
    655709
     
    769823        . '(?:' . $spaces . ')*+'            // optional trailing whitespace
    770824        . '<\\/p>'                           // closing paragraph
    771         . '/s';
     825        . '/';
    772826
    773827    return preg_replace( $pattern, '$1', $pee );
Note: See TracChangeset for help on using the changeset viewer.