Make WordPress Core


Ignore:
Timestamp:
10/02/2015 04:25:40 AM (11 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.