WordPress.org

Make WordPress Core

Ticket #10987: wptexturize-performance.patch

File wptexturize-performance.patch, 7.7 KB (added by johanee, 5 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}