WordPress.org

Make WordPress Core

Ticket #10987: wptexturize-performance.patch

File wptexturize-performance.patch, 7.7 KB (added by johanee, 9 years ago)

Improve wptexturize performance

  • wp-includes/formatting.php

     
    2828 */
    2929function wptexturize($text) {
    3030        global $wp_cockneyreplace;
     31        static $static_setup = false, $opening_quote, $closing_quote, $no_texturize_tags, $no_texturize_shortcodes, $static_characters, $static_replacements, $dynamic_characters, $dynamic_replacements;
    3132        $output = '';
    3233        $curl = '';
    3334        $textarr = preg_split('/(<.*>|\[.*\])/Us', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
    3435        $stop = count($textarr);
     36       
     37        // No need to setup these variables more than once
     38        if (!$static_setup) {
     39                /* translators: opening curly quote */
     40                $opening_quote = _x('&#8220;', 'opening curly quote');
     41                /* translators: closing curly quote */
     42                $closing_quote = _x('&#8221;', 'closing curly quote');
    3543
    36         /* translators: opening curly quote */
    37         $opening_quote = _x('&#8220;', 'opening curly quote');
    38         /* translators: closing curly quote */
    39         $closing_quote = _x('&#8221;', 'closing curly quote');
     44                $no_texturize_tags = apply_filters('no_texturize_tags', array('pre', 'code', 'kbd', 'style', 'script', 'tt'));
     45                $no_texturize_shortcodes = apply_filters('no_texturize_shortcodes', array('code'));
    4046
    41         $no_texturize_tags = apply_filters('no_texturize_tags', array('pre', 'code', 'kbd', 'style', 'script', 'tt'));
    42         $no_texturize_shortcodes = apply_filters('no_texturize_shortcodes', array('code'));
    43         $no_texturize_tags_stack = array();
    44         $no_texturize_shortcodes_stack = array();
     47                // Transform into regexp sub-expression used in _wptexturize_pushpop_element
     48                $no_texturize_tags = '(' . implode('|', $no_texturize_tags) . ')';
     49                $no_texturize_shortcodes = '(' . implode('|', $no_texturize_shortcodes) . ')';
    4550
    46         // if a plugin has provided an autocorrect array, use it
    47         if ( isset($wp_cockneyreplace) ) {
    48                 $cockney = array_keys($wp_cockneyreplace);
    49                 $cockneyreplace = array_values($wp_cockneyreplace);
    50         } else {
    51                 $cockney = array("'tain't","'twere","'twas","'tis","'twill","'til","'bout","'nuff","'round","'cause");
    52                 $cockneyreplace = array("&#8217;tain&#8217;t","&#8217;twere","&#8217;twas","&#8217;tis","&#8217;twill","&#8217;til","&#8217;bout","&#8217;nuff","&#8217;round","&#8217;cause");
     51                // if a plugin has provided an autocorrect array, use it
     52                if ( isset($wp_cockneyreplace) ) {
     53                        $cockney = array_keys($wp_cockneyreplace);
     54                        $cockneyreplace = array_values($wp_cockneyreplace);
     55                } else {
     56                        $cockney = array("'tain't","'twere","'twas","'tis","'twill","'til","'bout","'nuff","'round","'cause");
     57                        $cockneyreplace = array("&#8217;tain&#8217;t","&#8217;twere","&#8217;twas","&#8217;tis","&#8217;twill","&#8217;til","&#8217;bout","&#8217;nuff","&#8217;round","&#8217;cause");
     58                }
     59
     60                $static_characters = array_merge(array('---', ' -- ', '--', ' - ', 'xn&#8211;', '...', '``', '\'s', '\'\'', ' (tm)'), $cockney);
     61                $static_replacements = array_merge(array('&#8212;', ' &#8212; ', '&#8211;', ' &#8211; ', 'xn--', '&#8230;', $opening_quote, '&#8217;s', $closing_quote, ' &#8482;'), $cockneyreplace);
     62
     63                $dynamic_characters = array('/\'(\d\d(?:&#8217;|\')?s)/', '/(\s|\A|[([{<]|")\'/', '/(\d+)"/', '/(\d+)\'/', '/(\S)\'([^\'\s])/', '/(\s|\A|[([{<])"(?!\s)/', '/"(\s|\S|\Z)/', '/\'([\s.]|\Z)/', '/(\d+)x(\d+)/');
     64                $dynamic_replacements = array('&#8217;$1','$1&#8216;', '$1&#8243;', '$1&#8242;', '$1&#8217;$2', '$1' . $opening_quote . '$2', $closing_quote . '$1', '&#8217;$1', '$1&#215;$2');
     65
     66                $static_setup = true;
    5367        }
    5468
    55         $static_characters = array_merge(array('---', ' -- ', '--', ' - ', 'xn&#8211;', '...', '``', '\'s', '\'\'', ' (tm)'), $cockney);
    56         $static_replacements = array_merge(array('&#8212;', ' &#8212; ', '&#8211;', ' &#8211; ', 'xn--', '&#8230;', $opening_quote, '&#8217;s', $closing_quote, ' &#8482;'), $cockneyreplace);
     69        $no_texturize_tags_stack = array();
     70        $no_texturize_shortcodes_stack = array();
    5771
    58         $dynamic_characters = array('/\'(\d\d(?:&#8217;|\')?s)/', '/(\s|\A|[([{<]|")\'/', '/(\d+)"/', '/(\d+)\'/', '/(\S)\'([^\'\s])/', '/(\s|\A|[([{<])"(?!\s)/', '/"(\s|\S|\Z)/', '/\'([\s.]|\Z)/', '/(\d+)x(\d+)/');
    59         $dynamic_replacements = array('&#8217;$1','$1&#8216;', '$1&#8243;', '$1&#8242;', '$1&#8217;$2', '$1' . $opening_quote . '$2', $closing_quote . '$1', '&#8217;$1', '$1&#215;$2');
    60 
    6172        for ( $i = 0; $i < $stop; $i++ ) {
    6273                $curl = $textarr[$i];
    6374
    6475                if ( !empty($curl) && '<' != $curl{0} && '[' != $curl{0}
    65                                 && empty($no_texturize_shortcodes_stack) && empty($no_texturize_tags_stack)) { // If it's not a tag
     76                                && empty($no_texturize_shortcodes_stack) && empty($no_texturize_tags_stack)) {
     77                        // This is not a tag, nor is the texturization disabled
    6678                        // static strings
    6779                        $curl = str_replace($static_characters, $static_replacements, $curl);
    6880                        // regular expressions
    6981                        $curl = preg_replace($dynamic_characters, $dynamic_replacements, $curl);
    70                 } else {
    71                         wptexturize_pushpop_element($curl, $no_texturize_tags_stack, $no_texturize_tags, '<', '>');
    72                         wptexturize_pushpop_element($curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes, '[', ']');
     82                } elseif (!empty($curl)) {
     83                        /*
     84                         * Only call _wptexturize_pushpop_element if first char is correct
     85                         * tag opening
     86                         */
     87                        if ('<' == $curl{0})
     88                                _wptexturize_pushpop_element($curl, $no_texturize_tags_stack, $no_texturize_tags, '<', '>');
     89                        elseif ('[' == $curl{0})
     90                                _wptexturize_pushpop_element($curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes, '[', ']');
    7391                }
    7492
    7593                $curl = preg_replace('/&([^#])(?![a-zA-Z1-4]{1,8};)/', '&#038;$1', $curl);
     
    7997        return $output;
    8098}
    8199
    82 function wptexturize_pushpop_element($text, &$stack, $disabled_elements, $opening = '<', $closing = '>') {
    83         $o = preg_quote($opening, '/');
    84         $c = preg_quote($closing, '/');
    85         foreach($disabled_elements as $element) {
    86                 if (preg_match('/^'.$o.$element.'\b/', $text)) array_push($stack, $element);
    87                 if (preg_match('/^'.$o.'\/'.$element.$c.'/', $text)) {
     100/**
     101 * Search for disabled element tags. Push element to stack on tag open and pop
     102 * on tag close. Assumes first character of $text is tag opening.
     103 *
     104 * @access private
     105 * @since 2.9.0
     106 *
     107 * @param string $text Text to check. First character is assumed to be $opening
     108 * @param array $stack Array used as stack of opened tag elements
     109 * @param string $disabled_elements Tags to match against formatted as regexp sub-expression
     110 * @param string $opening Tag opening character, assumed to be 1 character long
     111 * @param string $opening Tag closing  character
     112 * @return object
     113 */
     114function _wptexturize_pushpop_element($text, &$stack, $disabled_elements, $opening = '<', $closing = '>') {
     115        // Check if it is a closing tag -- otherwise assume opening tag
     116        if (strncmp($opening . '/', $text, 2)) {
     117                // Opening? Check $text+1 against disabled elements
     118                if (preg_match('/^' . $disabled_elements . '\b/', substr($text, 1), $matches)) {
     119                        /*
     120                         * This disables texturize until we find a closing tag of our type
     121                         * (e.g. <pre>) even if there was invalid nesting before that
     122                         *
     123                         * Example: in the case <pre>sadsadasd</code>"baba"</pre>
     124                         *          "baba" won't be texturize
     125                         */
     126
     127                        array_push($stack, $matches[1]);
     128                }
     129        } else {
     130                // Closing? Check $text+2 against disabled elements
     131                $c = preg_quote($closing, '/');
     132                if (preg_match('/^' . $disabled_elements . $c . '/', substr($text, 2), $matches)) {
    88133                        $last = array_pop($stack);
    89                         // disable texturize until we find a closing tag of our type (e.g. <pre>)
    90                         // even if there was invalid nesting before that
    91                         // Example: in the case <pre>sadsadasd</code>"baba"</pre> "baba" won't be texturized
    92                         if ($last != $element) array_push($stack, $last);
     134
     135                        // Make sure it matches the opening tag
     136                        if ($last != $matches[1])
     137                                array_push($stack, $last);
    93138                }
    94139        }
    95140}