web/wp-includes/shortcodes.php
changeset 194 32102edaa81b
parent 136 bde1974c263b
child 204 09a1c134465b
equal deleted inserted replaced
193:2f6f6f7551ca 194:32102edaa81b
   146 
   146 
   147 	if (empty($shortcode_tags) || !is_array($shortcode_tags))
   147 	if (empty($shortcode_tags) || !is_array($shortcode_tags))
   148 		return $content;
   148 		return $content;
   149 
   149 
   150 	$pattern = get_shortcode_regex();
   150 	$pattern = get_shortcode_regex();
   151 	return preg_replace_callback('/'.$pattern.'/s', 'do_shortcode_tag', $content);
   151 	return preg_replace_callback( "/$pattern/s", 'do_shortcode_tag', $content );
   152 }
   152 }
   153 
   153 
   154 /**
   154 /**
   155  * Retrieve the shortcode regular expression for searching.
   155  * Retrieve the shortcode regular expression for searching.
   156  *
   156  *
   157  * The regular expression combines the shortcode tags in the regular expression
   157  * The regular expression combines the shortcode tags in the regular expression
   158  * in a regex class.
   158  * in a regex class.
   159  *
   159  *
   160  * The regular expresion contains 6 different sub matches to help with parsing.
   160  * The regular expression contains 6 different sub matches to help with parsing.
   161  *
   161  *
   162  * 1/6 - An extra [ or ] to allow for escaping shortcodes with double [[]]
   162  * 1 - An extra [ to allow for escaping shortcodes with double [[]]
   163  * 2 - The shortcode name
   163  * 2 - The shortcode name
   164  * 3 - The shortcode argument list
   164  * 3 - The shortcode argument list
   165  * 4 - The self closing /
   165  * 4 - The self closing /
   166  * 5 - The content of a shortcode when it wraps some content.
   166  * 5 - The content of a shortcode when it wraps some content.
       
   167  * 6 - An extra ] to allow for escaping shortcodes with double [[]]
   167  *
   168  *
   168  * @since 2.5
   169  * @since 2.5
   169  * @uses $shortcode_tags
   170  * @uses $shortcode_tags
   170  *
   171  *
   171  * @return string The shortcode search regular expression
   172  * @return string The shortcode search regular expression
   173 function get_shortcode_regex() {
   174 function get_shortcode_regex() {
   174 	global $shortcode_tags;
   175 	global $shortcode_tags;
   175 	$tagnames = array_keys($shortcode_tags);
   176 	$tagnames = array_keys($shortcode_tags);
   176 	$tagregexp = join( '|', array_map('preg_quote', $tagnames) );
   177 	$tagregexp = join( '|', array_map('preg_quote', $tagnames) );
   177 
   178 
   178 	// WARNING! Do not change this regex without changing do_shortcode_tag() and strip_shortcodes()
   179 	// WARNING! Do not change this regex without changing do_shortcode_tag() and strip_shortcode_tag()
   179 	return '(.?)\[('.$tagregexp.')\b(.*?)(?:(\/))?\](?:(.+?)\[\/\2\])?(.?)';
   180 	return
       
   181 		  '\\['                              // Opening bracket
       
   182 		. '(\\[?)'                           // 1: Optional second opening bracket for escaping shortcodes: [[tag]]
       
   183 		. "($tagregexp)"                     // 2: Shortcode name
       
   184 		. '\\b'                              // Word boundary
       
   185 		. '('                                // 3: Unroll the loop: Inside the opening shortcode tag
       
   186 		.     '[^\\]\\/]*'                   // Not a closing bracket or forward slash
       
   187 		.     '(?:'
       
   188 		.         '\\/(?!\\])'               // A forward slash not followed by a closing bracket
       
   189 		.         '[^\\]\\/]*'               // Not a closing bracket or forward slash
       
   190 		.     ')*?'
       
   191 		. ')'
       
   192 		. '(?:'
       
   193 		.     '(\\/)'                        // 4: Self closing tag ...
       
   194 		.     '\\]'                          // ... and closing bracket
       
   195 		. '|'
       
   196 		.     '\\]'                          // Closing bracket
       
   197 		.     '(?:'
       
   198 		.         '('                        // 5: Unroll the loop: Optionally, anything between the opening and closing shortcode tags
       
   199 		.             '[^\\[]*+'             // Not an opening bracket
       
   200 		.             '(?:'
       
   201 		.                 '\\[(?!\\/\\2\\])' // An opening bracket not followed by the closing shortcode tag
       
   202 		.                 '[^\\[]*+'         // Not an opening bracket
       
   203 		.             ')*+'
       
   204 		.         ')'
       
   205 		.         '\\[\\/\\2\\]'             // Closing shortcode tag
       
   206 		.     ')?'
       
   207 		. ')'
       
   208 		. '(\\]?)';                          // 6: Optional second closing brocket for escaping shortcodes: [[tag]]
   180 }
   209 }
   181 
   210 
   182 /**
   211 /**
   183  * Regular Expression callable for do_shortcode() for calling shortcode hook.
   212  * Regular Expression callable for do_shortcode() for calling shortcode hook.
   184  * @see get_shortcode_regex for details of the match array contents.
   213  * @see get_shortcode_regex for details of the match array contents.
   188  * @uses $shortcode_tags
   217  * @uses $shortcode_tags
   189  *
   218  *
   190  * @param array $m Regular expression match array
   219  * @param array $m Regular expression match array
   191  * @return mixed False on failure.
   220  * @return mixed False on failure.
   192  */
   221  */
   193 function do_shortcode_tag($m) {
   222 function do_shortcode_tag( $m ) {
   194 	global $shortcode_tags;
   223 	global $shortcode_tags;
   195 
   224 
   196 	// allow [[foo]] syntax for escaping a tag
   225 	// allow [[foo]] syntax for escaping a tag
   197 	if ($m[1] == '[' && $m[6] == ']') {
   226 	if ( $m[1] == '[' && $m[6] == ']' ) {
   198 		return substr($m[0], 1, -1);
   227 		return substr($m[0], 1, -1);
   199 	}
   228 	}
   200 
   229 
   201 	$tag = $m[2];
   230 	$tag = $m[2];
   202 	$attr = shortcode_parse_atts($m[3]);
   231 	$attr = shortcode_parse_atts( $m[3] );
   203 
   232 
   204 	if ( isset($m[5]) ) {
   233 	if ( isset( $m[5] ) ) {
   205 		// enclosing tag - extra parameter
   234 		// enclosing tag - extra parameter
   206 		return $m[1] . call_user_func($shortcode_tags[$tag], $attr, $m[5], $m[2]) . $m[6];
   235 		return $m[1] . call_user_func( $shortcode_tags[$tag], $attr, $m[5], $tag ) . $m[6];
   207 	} else {
   236 	} else {
   208 		// self-closing tag
   237 		// self-closing tag
   209 		return $m[1] . call_user_func($shortcode_tags[$tag], $attr, NULL, $m[2]) . $m[6];
   238 		return $m[1] . call_user_func( $shortcode_tags[$tag], $attr, null,  $tag ) . $m[6];
   210 	}
   239 	}
   211 }
   240 }
   212 
   241 
   213 /**
   242 /**
   214  * Retrieve all attributes from the shortcodes tag.
   243  * Retrieve all attributes from the shortcodes tag.
   288 	if (empty($shortcode_tags) || !is_array($shortcode_tags))
   317 	if (empty($shortcode_tags) || !is_array($shortcode_tags))
   289 		return $content;
   318 		return $content;
   290 
   319 
   291 	$pattern = get_shortcode_regex();
   320 	$pattern = get_shortcode_regex();
   292 
   321 
   293 	return preg_replace('/'.$pattern.'/s', '$1$6', $content);
   322 	return preg_replace_callback( "/$pattern/s", 'strip_shortcode_tag', $content );
       
   323 }
       
   324 
       
   325 function strip_shortcode_tag( $m ) {
       
   326 	// allow [[foo]] syntax for escaping a tag
       
   327 	if ( $m[1] == '[' && $m[6] == ']' ) {
       
   328 		return substr($m[0], 1, -1);
       
   329 	}
       
   330 
       
   331 	return $m[1] . $m[6];
   294 }
   332 }
   295 
   333 
   296 add_filter('the_content', 'do_shortcode', 11); // AFTER wpautop()
   334 add_filter('the_content', 'do_shortcode', 11); // AFTER wpautop()
   297 
       
   298 ?>