Make WordPress Core

Changeset 30450


Ignore:
Timestamp:
11/20/2014 02:29:03 PM (12 years ago)
Author:
nacin
Message:

Anchor texturize to shortcodes to improve regex efficiency.

For the 4.0 branch; see [30449] for trunk.

props miqrogroove.
see #29557 for segfault issues.

Location:
branches/4.0
Files:
2 edited

Legend:

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

    r29707 r30450  
    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
     212        $comment_regex =
     213                  '!'           // Start of comment, after the <.
     214                . '(?:'         // Unroll the loop: Consume everything until --> is found.
     215                .     '-(?!->)' // Dash not followed by end of comment.
     216                .     '[^\-]*+' // Consume non-dashes.
     217                . ')*+'         // Loop possessively.
     218                . '-->';        // End of comment.
     219
    208220        $regex =  '/('                  // Capture the entire match.
    209221                .       '<'             // Find start of element.
    210222                .       '(?(?=!--)'     // Is this a comment?
    211                 .               '.+?--\s*>'     // Find end of comment
     223                .               $comment_regex  // Find end of comment
    212224                .       '|'
    213225                .               '[^>]+>'        // Find end of element
     
    215227                . '|'
    216228                .       '\['            // Find start of shortcode.
    217                 .       '\[?'           // Shortcodes may begin with [[
     229                .       '[\/\[]?'       // Shortcodes may begin with [/ or [[
     230                .       $tagregexp      // Only match registered shortcodes, because performance.
    218231                .       '(?:'
    219                 .               '[^\[\]<>]'     // Shortcodes do not contain other shortcodes.
     232                .               '[^\[\]<>]+'    // Shortcodes do not contain other shortcodes. Quantifier critical.
    220233                .       '|'
    221                 .               '<[^>]+>'       // HTML elements permitted. Prevents matching ] before >.
    222                 .       ')++'
     234                .               '<[^\[\]>]*>'   // HTML elements permitted. Prevents matching ] before >.
     235                .       ')*+'           // Possessive critical.
    223236                .       '\]'            // Find end of shortcode.
    224237                .       '\]?'           // Shortcodes may end with ]]
     
    242255                        continue;
    243256
    244                 } elseif ( '[' === $first && 1 === preg_match( '/^\[(?:[^\[\]<>]|<[^>]+>)++\]$/', $curl ) ) {
     257                } elseif ( '[' === $first && 1 === preg_match( '/^\[\/?' . $tagregexp . '(?:[^\[\]<>]+|<[^\[\]>]*>)*+\]$/', $curl ) ) {
    245258                        // This is a shortcode delimiter.
    246259
    247260                        _wptexturize_pushpop_element( $curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes );
    248261
    249                 } elseif ( '[' === $first && 1 === preg_match( '/^\[\[?(?:[^\[\]<>]|<[^>]+>)++\]\]?$/', $curl ) ) {
     262                } elseif ( '[' === $first && 1 === preg_match( '/^\[[\/\[]?' . $tagregexp . '(?:[^\[\]<>]+|<[^\[\]>]*>)*+\]\]?$/', $curl ) ) {
    250263                        // This is an escaped shortcode delimiter.
    251264
  • branches/4.0/tests/phpunit/tests/formatting/WPTexturize.php

    r28971 r30450  
    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
     
    11941193                        ),
    11951194                        array(
     1195                                '[is it wise to <a title="allow user content ] here? hmm"> maybe </a> ]',
     1196                                '[is it wise to <a title="allow user content ] here? hmm"> maybe </a> ]',
     1197                        ),
     1198                        array(
     1199                                '[caption - is it wise to <a title="allow user content ] here? hmm"> maybe </a> ]',
     1200                                '[caption &#8211; is it wise to <a title="allow user content ] here? hmm"> maybe </a> ]',
     1201                        ),
     1202                        array(
     1203                                '[caption - is it wise to <a title="allow user content here? hmm"> ] maybe </a> ]',
     1204                                '[caption - is it wise to <a title="allow user content here? hmm"> ] maybe </a> ]',
     1205                        ),
     1206                        array(
     1207                                '[caption - is it wise to <a title="allow user content here? hmm"> maybe </a> ]',
     1208                                '[caption - is it wise to <a title="allow user content here? hmm"> maybe </a> ]',
     1209                        ),
     1210                        array(
     1211                                '[caption compare=">"]',
     1212                                '[caption compare=&#8221;>&#8221;]',
     1213                        ),
     1214                        array(
     1215                                '[caption compare="<>"]',
     1216                                '[caption compare="<>"]',
     1217                        ),
     1218                        array(
     1219                                '[caption compare="<" attr2="value" <!-->/]',
     1220                                '[caption compare="<" attr2="value" <!-->/]',
     1221                        ),
     1222                        array(
     1223                                '[caption compare="<"]',
     1224                                '[caption compare=&#8221;<&#8221;]',
     1225                        ),
     1226                        array(
     1227                                '[caption compare="<"]<br />',
     1228                                '[caption compare=&#8221;<"]<br />',
     1229                        ),
     1230                        array(
    11961231                                '[ photos by <a href="http://example.com/?a[]=1&a[]=2"> this guy </a> ]',
    11971232                                '[ photos by <a href="http://example.com/?a[]=1&#038;a[]=2"> this guy </a> ]',
     
    12111246                        array(
    12121247                                '[/...]', // This would actually be ignored by the shortcode system.  The decision to not texturize it is intentional, if not correct.
    1213                                 '[/...]',
     1248                                '[/&#8230;]',
    12141249                        ),
    12151250                        array(
    12161251                                '[...]...[/...]', // These are potentially usable shortcodes.
    1217                                 '[...]&#8230;[/...]',
     1252                                '[&#8230;]&#8230;[/&#8230;]',
    12181253                        ),
    12191254                        array(
    12201255                                '[[...]]...[[/...]]', // Shortcode parsing will ignore the inner ]...[ part and treat this as a single escaped shortcode.
    1221                                 '[[...]]&#8230;[[/...]]',
     1256                                '[[&#8230;]]&#8230;[[/&#8230;]]',
    12221257                        ),
    12231258                        array(
    12241259                                '[[[...]]]...[[[/...]]]', // Again, shortcode parsing matches, but only the [[...] and [/...]] parts.
    1225                                 '[[[...]]]&#8230;[[[/...]]]',
     1260                                '[[[&#8230;]]]&#8230;[[[/&#8230;]]]',
    12261261                        ),
    12271262                        array(
     
    12311266                        array(
    12321267                                '[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.
     1268                                '[code]&#8230;[/code]]&#8230;', // This test would not pass in 3.9 because the extra brace was always ignored by texturize.
    12341269                        ),
    12351270                        array(
     
    13461381                        ),
    13471382                        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]',
     1383                                '[Let\'s get crazy<input>[caption code="<a href=\'?a[]=100\'>hello</a>"]</input>world]', // caption shortcode is invalid here because it contains [] chars.
     1384                                '[Let&#8217;s get crazy<input>[caption code=&#8221;<a href=\'?a[]=100\'>hello</a>&#8220;]</input>world]',
    13501385                        ),
    13511386                );
     
    17161751                        array(
    17171752                                '<span>hello[code]---</span>',
    1718                                 '<span>hello[code]---</span>',
     1753                                '<span>hello[code]&#8212;</span>',
    17191754                        ),
    17201755                        array(
    17211756                                '[code]hello<span>---</span>',
    1722                                 '[code]hello<span>---</span>',
     1757                                '[code]hello<span>&#8212;</span>',
    17231758                        ),
    17241759                        array(
    17251760                                '[code]hello</span>---</span>',
    1726                                 '[code]hello</span>---</span>',
     1761                                '[code]hello</span>&#8212;</span>',
     1762                        ),
     1763                );
     1764        }
     1765
     1766        /**
     1767         * Test disabling shortcode texturization.
     1768         *
     1769         * @ticket 29557
     1770         * @dataProvider data_unregistered_shortcodes
     1771         */
     1772        function test_unregistered_shortcodes( $input, $output ) {
     1773                add_filter( 'no_texturize_shortcodes', array( $this, 'filter_shortcodes' ), 10, 1 );
     1774       
     1775                $output = $this->assertEquals( $output, wptexturize( $input ) );
     1776       
     1777                remove_filter( 'no_texturize_shortcodes', array( $this, 'filter_shortcodes' ), 10, 1 );
     1778                return $output;
     1779        }
     1780       
     1781        function filter_shortcodes( $disabled ) {
     1782                $disabled[] = 'audio';
     1783                return $disabled;
     1784        }
     1785
     1786        function data_unregistered_shortcodes() {
     1787                return array(
     1788                        array(
     1789                                '[a]a--b[code]---[/code]a--b[/a]', // code is not a registered shortcode.
     1790                                '[a]a&#8211;b[code]&#8212;[/code]a&#8211;b[/a]',
     1791                        ),
     1792                        array(
     1793                                '[a]a--b[audio]---[/audio]a--b[/a]',
     1794                                '[a]a&#8211;b[audio]---[/audio]a&#8211;b[/a]',
     1795                        ),
     1796                        array(
     1797                                '[code ...]...[/code]', // code is not a registered shortcode.
     1798                                '[code &#8230;]&#8230;[/code]',
     1799                        ),
     1800                        array(
     1801                                '[hello ...]...[/hello]', // hello is not a registered shortcode.
     1802                                '[hello &#8230;]&#8230;[/hello]',
     1803                        ),
     1804                        array(
     1805                                '[...]...[/...]', // These are potentially usable shortcodes.
     1806                                '[&#8230;]&#8230;[/&#8230;]',
     1807                        ),
     1808                        array(
     1809                                '[gal>ery ...]',
     1810                                '[gal>ery &#8230;]',
     1811                        ),
     1812                        array(
     1813                                '[randomthing param="test"]',
     1814                                '[randomthing param=&#8221;test&#8221;]',
     1815                        ),
     1816                        array(
     1817                                '[[audio]...[/audio]...', // These are potentially usable shortcodes.  Unfortunately, the meaning of [[audio] is ambiguous unless we run the entire shortcode regexp.
     1818                                '[[audio]&#8230;[/audio]&#8230;',
     1819                        ),
     1820                        array(
     1821                                '[audio]...[/audio]]...', // These are potentially usable shortcodes.  Unfortunately, the meaning of [/audio]] is ambiguous unless we run the entire shortcode regexp.
     1822                                '[audio]...[/audio]]...', // This test would not pass in 3.9 because the extra brace was always ignored by texturize.
     1823                        ),
     1824                        array(
     1825                                '<span>hello[/audio]---</span>',
     1826                                '<span>hello[/audio]&#8212;</span>',
     1827                        ),
     1828                        array(
     1829                                '[/audio]hello<span>---</span>',
     1830                                '[/audio]hello<span>&#8212;</span>',
     1831                        ),
     1832                        array(
     1833                                '[audio]hello[/audio]---</span>',
     1834                                '[audio]hello[/audio]&#8212;</span>',
     1835                        ),
     1836                        array(
     1837                                '<span>hello</span>---[audio]',
     1838                                '<span>hello</span>&#8212;[audio]',
     1839                        ),
     1840                        array(
     1841                                '<span>hello[audio]---</span>',
     1842                                '<span>hello[audio]---</span>',
     1843                        ),
     1844                        array(
     1845                                '[audio]hello<span>---</span>',
     1846                                '[audio]hello<span>---</span>',
     1847                        ),
     1848                        array(
     1849                                '[audio]hello</span>---</span>',
     1850                                '[audio]hello</span>---</span>',
    17271851                        ),
    17281852                );
Note: See TracChangeset for help on using the changeset viewer.