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?
Yes, shortcodes are case sensitive
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';
}
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.