Make WordPress Core

Ticket #33517: 33517.3.patch

File 33517.3.patch, 9.5 KB (added by miqrogroove, 10 years ago)

Shortcode name pattern aligned with #34090

  • src/wp-includes/formatting.php

     
    216216
    217217        // Look for shortcodes and HTML elements.
    218218
    219         $tagnames = array_keys( $shortcode_tags );
    220         $tagregexp = join( '|', array_map( 'preg_quote', $tagnames ) );
    221         $tagregexp = "(?:$tagregexp)(?![\\w-])"; // Excerpt of get_shortcode_regex().
     219        preg_match_all( '@\[/?([^<>&/\[\]\x00-\x20]++)@', $text, $matches );
     220        $tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
     221        $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        }
    222237
    223238        $comment_regex =
    224239                  '!'           // Start of comment, after the <.
     
    228243                . ')*+'         // Loop possessively.
    229244                . '(?:-->)?';   // End of comment. If not found, match all input.
    230245
    231         $shortcode_regex =
    232                   '\['              // Find start of shortcode.
    233                 . '[\/\[]?'         // Shortcodes may begin with [/ or [[
    234                 . $tagregexp        // Only match registered shortcodes, because performance.
    235                 . '(?:'
    236                 .     '[^\[\]<>]+'  // Shortcodes do not contain other shortcodes. Quantifier critical.
     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.
    237250                . '|'
    238                 .     '<[^\[\]>]*>' // HTML elements permitted. Prevents matching ] before >.
    239                 . ')*+'             // Possessive critical.
    240                 . '\]'              // Find end of shortcode.
    241                 . '\]?';            // Shortcodes may end with ]]
     251                .     '[^>]*>?'      // Find end of element. If not found, match all input.
     252                . ')';
    242253
    243         $regex =
    244                   '/('                   // Capture the entire match.
    245                 .     '<'                // Find start of element.
    246                 .     '(?(?=!--)'        // Is this a comment?
    247                 .         $comment_regex // Find end of comment.
    248                 .     '|'
    249                 .         '[^>]*>'       // Find end of element.
    250                 .     ')'
    251                 . '|'
    252                 .     $shortcode_regex   // Find shortcodes.
    253                 . ')/s';
     254        if ( $found_shortcodes ) {
     255                $regex = '/(' . $html_regex . '|' . $shortcode_regex . ')/s';
     256        } else {
     257                $regex = '/(' . $html_regex . ')/s';
     258        }
    254259
    255260        $textarr = preg_split( $regex, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
    256261
     
    257262        foreach ( $textarr as &$curl ) {
    258263                // Only call _wptexturize_pushpop_element if $curl is a delimiter.
    259264                $first = $curl[0];
    260                 if ( '<' === $first && '<!--' === substr( $curl, 0, 4 ) ) {
    261                         // This is an HTML comment delimiter.
     265                if ( '<' === $first ) {
     266                        if ( '<!--' === substr( $curl, 0, 4 ) ) {
     267                                // This is an HTML comment delimeter.
     268                                continue;
     269                        } else {
     270                                // This is an HTML element delimiter.
     271                                _wptexturize_pushpop_element( $curl, $no_texturize_tags_stack, $no_texturize_tags );
     272                        }
    262273
    263                         continue;
    264 
    265                 } elseif ( '<' === $first && '>' === substr( $curl, -1 ) ) {
    266                         // This is an HTML element delimiter.
    267 
    268                         _wptexturize_pushpop_element( $curl, $no_texturize_tags_stack, $no_texturize_tags );
    269 
    270274                } elseif ( '' === trim( $curl ) ) {
    271275                        // This is a newline between delimiters.  Performance improves when we check this.
    272 
    273276                        continue;
    274277
    275                 } elseif ( '[' === $first && 1 === preg_match( '/^' . $shortcode_regex . '$/', $curl ) ) {
     278                } elseif ( '[' === $first && $found_shortcodes && 1 === preg_match( '/^' . $shortcode_regex . '$/', $curl ) ) {
    276279                        // This is a shortcode delimiter.
    277280
    278281                        if ( '[[' !== substr( $curl, 0, 2 ) && ']]' !== substr( $curl, -2 ) ) {
  • src/wp-includes/shortcodes.php

     
    195195        if (empty($shortcode_tags) || !is_array($shortcode_tags))
    196196                return $content;
    197197
    198         $tagnames = array_keys($shortcode_tags);
    199         $tagregexp = join( '|', array_map('preg_quote', $tagnames) );
    200         $pattern = "/\\[($tagregexp)/s";
     198        // Find all registered tag names in $content.
     199        preg_match_all( '@\[([^<>&/\[\]\x00-\x20]++)@', $content, $matches );
     200        $tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
    201201
    202         if ( 1 !== preg_match( $pattern, $content ) ) {
    203                 // Avoids parsing HTML when there are no shortcodes or embeds anyway.
     202        if ( empty( $tagnames ) ) {
    204203                return $content;
    205204        }
    206205
    207         $content = do_shortcodes_in_html_tags( $content, $ignore_html );
     206        $content = do_shortcodes_in_html_tags( $content, $ignore_html, $tagnames );
    208207
    209         $pattern = get_shortcode_regex();
     208        $pattern = get_shortcode_regex( $tagnames );
    210209        $content = preg_replace_callback( "/$pattern/s", 'do_shortcode_tag', $content );
    211210
    212211        // Always restore square braces so we don't break things like <!--[if IE ]>
     
    234233 *
    235234 * @global array $shortcode_tags
    236235 *
     236 * @param array $tagnames List of shortcodes to find. Optional. Defaults to all registered shortcodes.
    237237 * @return string The shortcode search regular expression
    238238 */
    239 function get_shortcode_regex() {
     239function get_shortcode_regex( $tagnames = null ) {
    240240        global $shortcode_tags;
    241         $tagnames = array_keys($shortcode_tags);
     241
     242        if ( empty( $tagnames ) ) {
     243                $tagnames = array_keys( $shortcode_tags );
     244        }
    242245        $tagregexp = join( '|', array_map('preg_quote', $tagnames) );
    243246
    244247        // WARNING! Do not change this regex without changing do_shortcode_tag() and strip_shortcode_tag()
     
    324327 *
    325328 * @param string $content Content to search for shortcodes
    326329 * @param bool $ignore_html When true, all square braces inside elements will be encoded.
     330 * @param array $tagnames List of shortcodes to find.
    327331 * @return string Content with shortcodes filtered out.
    328332 */
    329 function do_shortcodes_in_html_tags( $content, $ignore_html ) {
     333function do_shortcodes_in_html_tags( $content, $ignore_html, $tagnames ) {
    330334        // Normalize entities in unfiltered HTML before adding placeholders.
    331335        $trans = array( '&#91;' => '&#091;', '&#93;' => '&#093;' );
    332336        $content = strtr( $content, $trans );
    333337        $trans = array( '[' => '&#91;', ']' => '&#93;' );
    334338
    335         $pattern = get_shortcode_regex();
     339        $pattern = get_shortcode_regex( $tagnames );
    336340        $textarr = wp_html_split( $content );
    337341
    338342        foreach ( $textarr as &$element ) {
     
    541545        if (empty($shortcode_tags) || !is_array($shortcode_tags))
    542546                return $content;
    543547
    544         $content = do_shortcodes_in_html_tags( $content, true );
     548        // Find all registered tag names in $content.
     549        preg_match_all( '@\[([^<>&/\[\]\x00-\x20]++)@', $content, $matches );
     550        $tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
    545551
    546         $pattern = get_shortcode_regex();
     552        if ( empty( $tagnames ) ) {
     553                return $content;
     554        }
     555
     556        $content = do_shortcodes_in_html_tags( $content, true, $tagnames );
     557
     558        $pattern = get_shortcode_regex( $tagnames );
    547559        $content = preg_replace_callback( "/$pattern/s", 'strip_shortcode_tag', $content );
    548560
    549561        // Always restore square braces so we don't break things like <!--[if IE ]>
  • tests/phpunit/tests/formatting/WPTexturize.php

     
    374374                                "word [&#8216;word word",
    375375                        ),
    376376                        array(
    377                                 "word <'word word", // Invalid HTML input triggers the apos in a word pattern.
    378                                 "word <&#8217;word word",
     377                                "word <'word word", // Invalid HTML
     378                                "word <'word word",
    379379                        ),
    380380                        array(
    381381                                "word &lt;'word word", // Valid HTML input makes curly quotes.
     
    403403                        ),
    404404                        array(
    405405                                "word<'word word",
    406                                 "word<&#8217;word word",
     406                                "word<'word word",
    407407                        ),
    408408                        array(
    409409                                "word&lt;'word word",
     
    431431                        ),
    432432                        array(
    433433                                "word <' word word",
    434                                 "word <&#8217; word word",
     434                                "word <' word word",
    435435                        ),
    436436                        array(
    437437                                "word &lt;' word word",
     
    459459                        ),
    460460                        array(
    461461                                "word<' word word",
    462                                 "word<&#8217; word word",
     462                                "word<' word word",
    463463                        ),
    464464                        array(
    465465                                "word&lt;' word word",
     
    610610                                'word [&#8220;word word',
    611611                        ),
    612612                        array(
    613                                 'word <"word word', // Invalid HTML input triggers the closing quote pattern.
    614                                 'word <&#8221;word word',
     613                                'word <"word word', // Invalid HTML
     614                                'word <"word word',
    615615                        ),
    616616                        array(
    617617                                'word &lt;"word word',
     
    643643                        ),
    644644                        array(
    645645                                'word<"word word',
    646                                 'word<&#8221;word word',
     646                                'word<"word word',
    647647                        ),
    648648                        array(
    649649                                'word&lt;"word word',
     
    13121312                        ),
    13131313                        array(
    13141314                                '<br [gallery ...] ... /',
    1315                                 '<br [gallery ...] &#8230; /',
     1315                                '<br [gallery ...] ... /',
    13161316                        ),
    13171317                        array(
    13181318                                '<br ... />',
     
    13521352                        ),
    13531353                        array(
    13541354                                '<br [[gallery ...]] ... /',
    1355                                 '<br [[gallery ...]] &#8230; /',
     1355                                '<br [[gallery ...]] ... /',
    13561356                        ),
    13571357                        array(
    13581358                                '[[gallery ...]]...[[gallery ...]]',