Make WordPress Core

Changeset 29748


Ignore:
Timestamp:
09/17/2014 03:13:24 PM (12 years ago)
Author:
wonderboymusic
Message:

wptexturize() improvements:

  • Expand the wptexturize() RegEx to include the list of registered shortcodes.
  • Avoid backtracking after [ chars by not filtering params in registered shortcodes. This will cause escaped shortcodes and their params to become texturized if not registered.
  • Registered shortcode params will never be texturized, even when escaped.
  • Move all tests involving unregistered shortcodes to a new and improved unit.
  • Update one test involving HTML within shortcode params.

Props miqrogroove.
See #29557.

Location:
trunk
Files:
3 edited

Legend:

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

    r29715 r29748  
    2929 */
    3030function wptexturize($text, $reset = false) {
    31         global $wp_cockneyreplace;
     31        global $wp_cockneyreplace, $shortcode_tags;
    3232        static $static_characters, $static_replacements, $dynamic_characters, $dynamic_replacements,
    3333                $default_no_texturize_tags, $default_no_texturize_shortcodes, $run_texturize = true;
    … …  
    206206        // Look for shortcodes and HTML elements.
    207207
     208        $tagnames = array_keys( $shortcode_tags );
     209        $tagregexp = join( '|', array_map( 'preg_quote', $tagnames ) );
     210        $tagregexp = "(?:$tagregexp)(?![\\w-])"; // Excerpt of get_shortcode_regex().
     211       
    208212        $regex =  '/('                  // Capture the entire match.
    209213                .       '<'             // Find start of element.
    … …  
    216220                .       '\['            // Find start of shortcode.
    217221                .       '\[?'           // Shortcodes may begin with [[
    218                 .       '(?:'
    219                 .               '[^\[\]<>]'     // Shortcodes do not contain other shortcodes.
    220                 .       '|'
    221                 .               '<[^>]+>'       // HTML elements permitted. Prevents matching ] before >.
    222                 .       ')++'
     222                .       '\/?'           // Closing slash may precede name.
     223                .       $tagregexp      // Only match registered shortcodes, because performance.
     224                .       '[^\[\]]*'      // Shortcodes do not contain other shortcodes.
    223225                .       '\]'            // Find end of shortcode.
    224226                .       '\]?'           // Shortcodes may end with ]]
    … …  
    242244                        continue;
    243245
    244                 } elseif ( '[' === $first && 1 === preg_match( '/^\[(?:[^\[\]<>]|<[^>]+>)++\]$/', $curl ) ) {
     246                } elseif ( '[' === $first && 1 === preg_match( '/^\[\[?\/?' . $tagregexp . '[^\[\]]*\]\]?$/', $curl ) ) {
    245247                        // This is a shortcode delimiter.
    246248
    247                         _wptexturize_pushpop_element( $curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes );
    248 
    249                 } elseif ( '[' === $first && 1 === preg_match( '/^\[\[?(?:[^\[\]<>]|<[^>]+>)++\]\]?$/', $curl ) ) {
    250                         // This is an escaped shortcode delimiter.
    251 
    252                         // Do not texturize.
    253                         // Do not push to the shortcodes stack.
    254 
    255                         continue;
     249                        if ( '[[' !== substr( $curl, 0, 2 ) && ']]' !== substr( $curl, -2 ) ) {
     250                                // Looks like a normal shortcode.
     251                                _wptexturize_pushpop_element( $curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes );
     252                        } else {
     253                                // Looks like an escaped shortcode.
     254                                // Do not texturize.
     255                                // Do not push to the shortcodes stack.
     256                                continue;
     257                        }
    256258
    257259                } elseif ( empty( $no_texturize_shortcodes_stack ) && empty( $no_texturize_tags_stack ) ) {
    … …  
    314316        // Parse out the tag name.
    315317        $space = strpos( $text, ' ' );
    316         if ( FALSE === $space ) {
     318        if ( false === $space ) {
    317319                $space = -1;
    318320        } else {
  • trunk/src/wp-includes/shortcodes.php

    r29207 r29748  
    232232
    233233        // WARNING! Do not change this regex without changing do_shortcode_tag() and strip_shortcode_tag()
    234         // Also, see shortcode_unautop() and shortcode.js.
     234        // Also, see shortcode_unautop() and shortcode.js and wptexturize().
    235235        return
    236236                  '\\['                              // Opening bracket
  • trunk/tests/phpunit/tests/formatting/WPTexturize.php

    r28971 r29748  
    1212        function test_disable() {
    1313                $this->assertEquals('<pre>---</pre>', wptexturize('<pre>---</pre>'));
    14                 $this->assertEquals('[a]a&#8211;b[code]---[/code]a&#8211;b[/a]', wptexturize('[a]a--b[code]---[/code]a--b[/a]'));
    1514                $this->assertEquals('<pre><code></code>--</pre>', wptexturize('<pre><code></code>--</pre>'));
    1615
    … …  
    12101209                        ),
    12111210                        array(
    1212                                 '[/...]', // This would actually be ignored by the shortcode system.  The decision to not texturize it is intentional, if not correct.
    1213                                 '[/...]',
     1211                                '[/gallery ...]', // This would actually be ignored by the shortcode system.  The decision to not texturize it is intentional, if not correct.
     1212                                '[/gallery ...]',
    12141213                        ),
    12151214                        array(
    12161215                                '[...]...[/...]', // These are potentially usable shortcodes.
    1217                                 '[...]&#8230;[/...]',
    1218                         ),
    1219                         array(
    1220                                 '[[...]]...[[/...]]', // Shortcode parsing will ignore the inner ]...[ part and treat this as a single escaped shortcode.
    1221                                 '[[...]]&#8230;[[/...]]',
    1222                         ),
    1223                         array(
    1224                                 '[[[...]]]...[[[/...]]]', // Again, shortcode parsing matches, but only the [[...] and [/...]] parts.
    1225                                 '[[[...]]]&#8230;[[[/...]]]',
    1226                         ),
    1227                         array(
    1228                                 '[[code]...[/code]...', // These are potentially usable shortcodes.  Unfortunately, the meaning of [[code] is ambiguous unless we run the entire shortcode regexp.
    1229                                 '[[code]&#8230;[/code]&#8230;',
    1230                         ),
    1231                         array(
    1232                                 '[code]...[/code]]...', // These are potentially usable shortcodes.  Unfortunately, the meaning of [/code]] is ambiguous unless we run the entire shortcode regexp.
    1233                                 '[code]...[/code]]...', // This test would not pass in 3.9 because the extra brace was always ignored by texturize.
     1216                                '[&#8230;]&#8230;[/&#8230;]',
     1217                        ),
     1218                        array(
     1219                                '[[gallery]]...[[/gallery]]', // Shortcode parsing will ignore the inner ]...[ part and treat this as a single escaped shortcode.
     1220                                '[[gallery]]&#8230;[[/gallery]]',
     1221                        ),
     1222                        array(
     1223                                '[[[gallery]]]...[[[/gallery]]]', // Again, shortcode parsing matches, but only the [[gallery] and [/gallery]] parts.
     1224                                '[[[gallery]]]&#8230;[[[/gallery]]]',
    12341225                        ),
    12351226                        array(
    … …  
    13461337                        ),
    13471338                        array(
    1348                                 '[Let\'s get crazy<input>[plugin code="<a href=\'?a[]=100\'>hello</a>"]</input>world]',
    1349                                 '[Let&#8217;s get crazy<input>[plugin code="<a href=\'?a[]=100\'>hello</a>"]</input>world]',
     1339                                '[Let\'s get crazy<input>[caption code="<a href=\'?a[]=100\'>hello</a>"]</input>world]', // caption shortcode is invalid here because it contains [] chars.
     1340                                '[Let&#8217;s get crazy<input>[caption code=&#8221;<a href=\'?a[]=100\'>hello</a>&#8220;]</input>world]',
    13501341                        ),
    13511342                );
    … …  
    16991690                        ),
    17001691                        array(
    1701                                 '<span>hello[/code]---</span>',
    1702                                 '<span>hello[/code]&#8212;</span>',
    1703                         ),
    1704                         array(
    1705                                 '[/code]hello<span>---</span>',
    1706                                 '[/code]hello<span>&#8212;</span>',
    1707                         ),
    1708                         array(
    1709                                 '[code]hello[/code]---</span>',
    1710                                 '[code]hello[/code]&#8212;</span>',
    1711                         ),
    1712                         array(
    1713                                 '<span>hello</span>---[code]',
    1714                                 '<span>hello</span>&#8212;[code]',
    1715                         ),
    1716                         array(
    1717                                 '<span>hello[code]---</span>',
    1718                                 '<span>hello[code]---</span>',
    1719                         ),
    1720                         array(
    1721                                 '[code]hello<span>---</span>',
    1722                                 '[code]hello<span>---</span>',
    1723                         ),
    1724                         array(
    1725                                 '[code]hello</span>---</span>',
    1726                                 '[code]hello</span>---</span>',
     1692                                '<span><code>hello</code>---</span>',
     1693                                '<span><code>hello</code>&#8212;</span>',
     1694                        ),
     1695                        array(
     1696                                '<code>hello</code>world<span>---</span>',
     1697                                '<code>hello</code>world<span>&#8212;</span>',
     1698                        ),
     1699                );
     1700        }
     1701
     1702        /**
     1703         * Test disabling shortcode texturization.
     1704         *
     1705         * @ticket 29557
     1706         * @dataProvider data_unregistered_shortcodes
     1707         */
     1708        function test_unregistered_shortcodes( $input, $output ) {
     1709                add_filter( 'no_texturize_shortcodes', array( $this, 'filter_shortcodes' ), 10, 1 );
     1710       
     1711                $output = $this->assertEquals( $output, wptexturize( $input ) );
     1712       
     1713                remove_filter( 'no_texturize_shortcodes', array( $this, 'filter_shortcodes' ), 10, 1 );
     1714                return $output;
     1715        }
     1716       
     1717        function filter_shortcodes( $disabled ) {
     1718                $disabled[] = 'audio';
     1719                return $disabled;
     1720        }
     1721
     1722        function data_unregistered_shortcodes() {
     1723                return array(
     1724                        array(
     1725                                '[a]a--b[audio]---[/audio]a--b[/a]',
     1726                                '[a]a&#8211;b[audio]---[/audio]a&#8211;b[/a]',
     1727                        ),
     1728                        array(
     1729                                '[code ...]...[/code]', // code is not a registered shortcode.
     1730                                '[code &#8230;]&#8230;[/code]',
     1731                        ),
     1732                        array(
     1733                                '[hello ...]...[/hello]', // hello is not a registered shortcode.
     1734                                '[hello &#8230;]&#8230;[/hello]',
     1735                        ),
     1736                        array(
     1737                                '[[audio]...[/audio]...', // These are potentially usable shortcodes.  Unfortunately, the meaning of [[audio] is ambiguous unless we run the entire shortcode regexp.
     1738                                '[[audio]&#8230;[/audio]&#8230;',
     1739                        ),
     1740                        array(
     1741                                '[audio]...[/audio]]...', // These are potentially usable shortcodes.  Unfortunately, the meaning of [/audio]] is ambiguous unless we run the entire shortcode regexp.
     1742                                '[audio]...[/audio]]...', // This test would not pass in 3.9 because the extra brace was always ignored by texturize.
     1743                        ),
     1744                        array(
     1745                                '<span>hello[/audio]---</span>',
     1746                                '<span>hello[/audio]&#8212;</span>',
     1747                        ),
     1748                        array(
     1749                                '[/audio]hello<span>---</span>',
     1750                                '[/audio]hello<span>&#8212;</span>',
     1751                        ),
     1752                        array(
     1753                                '[audio]hello[/audio]---</span>',
     1754                                '[audio]hello[/audio]&#8212;</span>',
     1755                        ),
     1756                        array(
     1757                                '<span>hello</span>---[audio]',
     1758                                '<span>hello</span>&#8212;[audio]',
     1759                        ),
     1760                        array(
     1761                                '<span>hello[audio]---</span>',
     1762                                '<span>hello[audio]---</span>',
     1763                        ),
     1764                        array(
     1765                                '[audio]hello<span>---</span>',
     1766                                '[audio]hello<span>---</span>',
     1767                        ),
     1768                        array(
     1769                                '[audio]hello</span>---</span>',
     1770                                '[audio]hello</span>---</span>',
    17271771                        ),
    17281772                );
Note: See TracChangeset for help on using the changeset viewer.