4

If I write a plugin and register a shortcode using this code:

add_shortcode('footag', 'footag_func');

and a user uses this in their post:

[FOOTAG]

Is it supposed to work?

10

Short Answer

Yes, shortcodes are case sensitive

Longer Answer

It's really easy to build a test case for this and see.

<?php
add_shortcode('sOme_ShOrTcOdE', 'wpse102375_shortcode');
function wpse102375_shortcode($args, $content=null)
{
    return 'yep';
}

Longest Answer

Read the source.

The "magic" with shortcodes happens in do_shortcode, so let's take a look at that.

<?php
// wp-includes/shortcode.php
function do_shortcode($content) {
    global $shortcode_tags;

    if (empty($shortcode_tags) || !is_array($shortcode_tags))
        return $content;

    $pattern = get_shortcode_regex();
    return preg_replace_callback( "/$pattern/s", 'do_shortcode_tag', $content );
}

Hmmm, $shortcode_tags -- probably get's set up in add_shortcode:

<?php
// wp-includes/shortcodes.php
function add_shortcode($tag, $func) {
    global $shortcode_tags;

    if ( is_callable($func) )
        $shortcode_tags[$tag] = $func;
}

So that's just a key value part of $shortcode_name => $a_callablle. Makes sense.

Looks like most of the magic of do_shortcode takes place in building the regular expression to match shortcodes themselves. All that happens in get_shortcode_regex, so let's take a look there:

<?php
// wp-includes/shortcode.php
function get_shortcode_regex() {
    global $shortcode_tags;
    $tagnames = array_keys($shortcode_tags);
    $tagregexp = join( '|', array_map('preg_quote', $tagnames) );

    // WARNING! Do not change this regex without changing do_shortcode_tag() and strip_shortcode_tag()
    // Also, see shortcode_unautop() and shortcode.js.
    return
          '\\['                              // Opening bracket
        . '(\\[?)'                           // 1: Optional second opening bracket for escaping shortcodes: [[tag]]
        . "($tagregexp)"                     // 2: Shortcode name
        . '(?![\\w-])'                       // Not followed by word character or hyphen
        . '('                                // 3: Unroll the loop: Inside the opening shortcode tag
        .     '[^\\]\\/]*'                   // Not a closing bracket or forward slash
        .     '(?:'
        .         '\\/(?!\\])'               // A forward slash not followed by a closing bracket
        .         '[^\\]\\/]*'               // Not a closing bracket or forward slash
        .     ')*?'
        . ')'
        . '(?:'
        .     '(\\/)'                        // 4: Self closing tag ...
        .     '\\]'                          // ... and closing bracket
        . '|'
        .     '\\]'                          // Closing bracket
        .     '(?:'
        .         '('                        // 5: Unroll the loop: Optionally, anything between the opening and closing shortcode tags
        .             '[^\\[]*+'             // Not an opening bracket
        .             '(?:'
        .                 '\\[(?!\\/\\2\\])' // An opening bracket not followed by the closing shortcode tag
        .                 '[^\\[]*+'         // Not an opening bracket
        .             ')*+'
        .         ')'
        .         '\\[\\/\\2\\]'             // Closing shortcode tag
        .     ')?'
        . ')'
        . '(\\]?)';                          // 6: Optional second closing brocket for escaping shortcodes: [[tag]]
}

Very well commented in the core, so not much to explain here. The key part is here:

global $shortcode_tags;
$tagnames = array_keys($shortcode_tags);
$tagregexp = join( '|', array_map('preg_quote', $tagnames) );

Which essentially will get used later to explicitly match any of the registered shortcode names. Notice that no text processing is done other than preg_quote, so WP will only try to match the explicit values passed in to add_shortcode as the shortcode name. It's looking like shortcodes are case sensitive so far.

Next we need to take a look at the flags where the regular expression built in get_shortcode_regex is used. The relevant bit of do_shortcode.

"/$pattern/s"

The slashes delimit the regular expression, letters after the closing slash are PRCE flags or modifiers.

If we saw an i there it would be case insensitive. We only have an s (meaning a . matches all characters including the newline).

So, yes, shortcodes are case sensitive.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.