WordPress.org

Make WordPress Core

Changeset 12084


Ignore:
Timestamp:
10/21/2009 09:57:27 PM (9 years ago)
Author:
westi
Message:

Improve wptexturize performance. Fixes #10987 props johanee.

File:
1 edited

Legend:

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

    r12072 r12084  
    2929function wptexturize($text) {
    3030    global $wp_cockneyreplace;
     31    static $static_setup = false, $opening_quote, $closing_quote, $default_no_texturize_tags, $default_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);
    35 
    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');
    40 
    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'));
     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');
     43
     44        $default_no_texturize_tags = array('pre', 'code', 'kbd', 'style', 'script', 'tt');
     45        $default_no_texturize_shortcodes = array('code');
     46
     47        // if a plugin has provided an autocorrect array, use it
     48        if ( isset($wp_cockneyreplace) ) {
     49            $cockney = array_keys($wp_cockneyreplace);
     50            $cockneyreplace = array_values($wp_cockneyreplace);
     51        } else {
     52            $cockney = array("'tain't","'twere","'twas","'tis","'twill","'til","'bout","'nuff","'round","'cause");
     53            $cockneyreplace = array("&#8217;tain&#8217;t","&#8217;twere","&#8217;twas","&#8217;tis","&#8217;twill","&#8217;til","&#8217;bout","&#8217;nuff","&#8217;round","&#8217;cause");
     54        }
     55
     56        $static_characters = array_merge(array('---', ' -- ', '--', ' - ', 'xn&#8211;', '...', '``', '\'s', '\'\'', ' (tm)'), $cockney);
     57        $static_replacements = array_merge(array('&#8212;', ' &#8212; ', '&#8211;', ' &#8211; ', 'xn--', '&#8230;', $opening_quote, '&#8217;s', $closing_quote, ' &#8482;'), $cockneyreplace);
     58
     59        $dynamic_characters = array('/\'(\d\d(?:&#8217;|\')?s)/', '/(\s|\A|[([{<]|")\'/', '/(\d+)"/', '/(\d+)\'/', '/(\S)\'([^\'\s])/', '/(\s|\A|[([{<])"(?!\s)/', '/"(\s|\S|\Z)/', '/\'([\s.]|\Z)/', '/(\d+)x(\d+)/');
     60        $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');
     61
     62        $static_setup = true;
     63    }
     64
     65    // Transform into regexp sub-expression used in _wptexturize_pushpop_element
     66    // Must do this everytime in case plugins use these filters in a context sensitive manner
     67    $no_texturize_tags = '(' . implode('|', apply_filters('no_texturize_tags', $default_no_texturize_tags) ) . ')';
     68    $no_texturize_shortcodes = '(' . implode('|', apply_filters('no_texturize_shortcodes', $default_no_texturize_shortcodes) ) . ')';
     69
    4370    $no_texturize_tags_stack = array();
    4471    $no_texturize_shortcodes_stack = array();
    4572
    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");
    53     }
    54 
    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);
    57 
    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 
    6173    for ( $i = 0; $i < $stop; $i++ ) {
    6274        $curl = $textarr[$i];
    6375
    6476        if ( !empty($curl) && '<' != $curl{0} && '[' != $curl{0}
    65                 && empty($no_texturize_shortcodes_stack) && empty($no_texturize_tags_stack)) { // If it's not a tag
     77                && empty($no_texturize_shortcodes_stack) && empty($no_texturize_tags_stack)) {
     78            // This is not a tag, nor is the texturization disabled
    6679            // static strings
    6780            $curl = str_replace($static_characters, $static_replacements, $curl);
    6881            // regular expressions
    6982            $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, '[', ']');
     83        } elseif (!empty($curl)) {
     84            /*
     85             * Only call _wptexturize_pushpop_element if first char is correct
     86             * tag opening
     87             */
     88            if ('<' == $curl{0})
     89                _wptexturize_pushpop_element($curl, $no_texturize_tags_stack, $no_texturize_tags, '<', '>');
     90            elseif ('[' == $curl{0})
     91                _wptexturize_pushpop_element($curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes, '[', ']');
    7392        }
    7493
     
    8099}
    81100
    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)) {
     101/**
     102 * Search for disabled element tags. Push element to stack on tag open and pop
     103 * on tag close. Assumes first character of $text is tag opening.
     104 *
     105 * @access private
     106 * @since 2.9.0
     107 *
     108 * @param string $text Text to check. First character is assumed to be $opening
     109 * @param array $stack Array used as stack of opened tag elements
     110 * @param string $disabled_elements Tags to match against formatted as regexp sub-expression
     111 * @param string $opening Tag opening character, assumed to be 1 character long
     112 * @param string $opening Tag closing  character
     113 * @return object
     114 */
     115function _wptexturize_pushpop_element($text, &$stack, $disabled_elements, $opening = '<', $closing = '>') {
     116    // Check if it is a closing tag -- otherwise assume opening tag
     117    if (strncmp($opening . '/', $text, 2)) {
     118        // Opening? Check $text+1 against disabled elements
     119        if (preg_match('/^' . $disabled_elements . '\b/', substr($text, 1), $matches)) {
     120            /*
     121             * This disables texturize until we find a closing tag of our type
     122             * (e.g. <pre>) even if there was invalid nesting before that
     123             *
     124             * Example: in the case <pre>sadsadasd</code>"baba"</pre>
     125             *          "baba" won't be texturize
     126             */
     127
     128            array_push($stack, $matches[1]);
     129        }
     130    } else {
     131        // Closing? Check $text+2 against disabled elements
     132        $c = preg_quote($closing, '/');
     133        if (preg_match('/^' . $disabled_elements . $c . '/', substr($text, 2), $matches)) {
    88134            $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);
     135
     136            // Make sure it matches the opening tag
     137            if ($last != $matches[1])
     138                array_push($stack, $last);
    93139        }
    94140    }
Note: See TracChangeset for help on using the changeset viewer.