WordPress.org

Make WordPress Core

Changeset 30450


Ignore:
Timestamp:
11/20/2014 02:29:03 PM (5 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.