/bp-forums/bbpress/bb-includes/backpress/functions.shortcodes.php

  1. <?php 
  2. // Last sync [WP12206] 
  3.  
  4. /** 
  5. * WordPress API for creating bbcode like tags or what WordPress calls 
  6. * "shortcodes." The tag and attribute parsing or regular expression code is 
  7. * based on the Textpattern tag parser. 
  8. * 
  9. * A few examples are below: 
  10. * 
  11. * [shortcode /] 
  12. * [shortcode foo="bar" baz="bing" /] 
  13. * [shortcode foo="bar"]content[/shortcode] 
  14. * 
  15. * Shortcode tags support attributes and enclosed content, but does not entirely 
  16. * support inline shortcodes in other shortcodes. You will have to call the 
  17. * shortcode parser in your function to account for that. 
  18. * 
  19. * {@internal 
  20. * Please be aware that the above note was made during the beta of WordPress 2.6 
  21. * and in the future may not be accurate. Please update the note when it is no 
  22. * longer the case.}} 
  23. * 
  24. * To apply shortcode tags to content: 
  25. * 
  26. * <code> 
  27. * $out = do_shortcode($content); 
  28. * </code> 
  29. * 
  30. * @link http://codex.wordpress.org/Shortcode_API 
  31. * 
  32. * @package WordPress 
  33. * @subpackage Shortcodes 
  34. * @since 2.5 
  35. */ 
  36.  
  37. /** 
  38. * Container for storing shortcode tags and their hook to call for the shortcode 
  39. * 
  40. * @since 2.5 
  41. * @name $shortcode_tags 
  42. * @var array 
  43. * @global array $shortcode_tags 
  44. */ 
  45. $shortcode_tags = array(); 
  46.  
  47. /** 
  48. * Add hook for shortcode tag. 
  49. * 
  50. * There can only be one hook for each shortcode. Which means that if another 
  51. * plugin has a similar shortcode, it will override yours or yours will override 
  52. * theirs depending on which order the plugins are included and/or ran. 
  53. * 
  54. * Simplest example of a shortcode tag using the API: 
  55. * 
  56. * <code> 
  57. * // [footag foo="bar"] 
  58. * function footag_func($atts) { 
  59. * return "foo = {$atts[foo]}"; 
  60. * } 
  61. * add_shortcode('footag', 'footag_func'); 
  62. * </code> 
  63. * 
  64. * Example with nice attribute defaults: 
  65. * 
  66. * <code> 
  67. * // [bartag foo="bar"] 
  68. * function bartag_func($atts) { 
  69. * extract(shortcode_atts(array( 
  70. * 'foo' => 'no foo',  
  71. * 'baz' => 'default baz',  
  72. * ), $atts)); 
  73. * 
  74. * return "foo = {$foo}"; 
  75. * } 
  76. * add_shortcode('bartag', 'bartag_func'); 
  77. * </code> 
  78. * 
  79. * Example with enclosed content: 
  80. * 
  81. * <code> 
  82. * // [baztag]content[/baztag] 
  83. * function baztag_func($atts, $content='') { 
  84. * return "content = $content"; 
  85. * } 
  86. * add_shortcode('baztag', 'baztag_func'); 
  87. * </code> 
  88. * 
  89. * @since 2.5 
  90. * @uses $shortcode_tags 
  91. * 
  92. * @param string $tag Shortcode tag to be searched in post content. 
  93. * @param callable $func Hook to run when shortcode is found. 
  94. */ 
  95. function add_shortcode($tag, $func) { 
  96. global $shortcode_tags; 
  97.  
  98. if ( is_callable($func) ) 
  99. $shortcode_tags[$tag] = $func; 
  100.  
  101. /** 
  102. * Removes hook for shortcode. 
  103. * 
  104. * @since 2.5 
  105. * @uses $shortcode_tags 
  106. * 
  107. * @param string $tag shortcode tag to remove hook for. 
  108. */ 
  109. function remove_shortcode($tag) { 
  110. global $shortcode_tags; 
  111.  
  112. unset($shortcode_tags[$tag]); 
  113.  
  114. /** 
  115. * Clear all shortcodes. 
  116. * 
  117. * This function is simple, it clears all of the shortcode tags by replacing the 
  118. * shortcodes global by a empty array. This is actually a very efficient method 
  119. * for removing all shortcodes. 
  120. * 
  121. * @since 2.5 
  122. * @uses $shortcode_tags 
  123. */ 
  124. function remove_all_shortcodes() { 
  125. global $shortcode_tags; 
  126.  
  127. $shortcode_tags = array(); 
  128.  
  129. /** 
  130. * Search content for shortcodes and filter shortcodes through their hooks. 
  131. * 
  132. * If there are no shortcode tags defined, then the content will be returned 
  133. * without any filtering. This might cause issues when plugins are disabled but 
  134. * the shortcode will still show up in the post or content. 
  135. * 
  136. * @since 2.5 
  137. * @uses $shortcode_tags 
  138. * @uses get_shortcode_regex() Gets the search pattern for searching shortcodes. 
  139. * 
  140. * @param string $content Content to search for shortcodes 
  141. * @return string Content with shortcodes filtered out. 
  142. */ 
  143. function do_shortcode($content) { 
  144. global $shortcode_tags; 
  145.  
  146. if (empty($shortcode_tags) || !is_array($shortcode_tags)) 
  147. return $content; 
  148.  
  149. $pattern = get_shortcode_regex(); 
  150. return preg_replace_callback('/'.$pattern.'/s', 'do_shortcode_tag', $content); 
  151.  
  152. /** 
  153. * Retrieve the shortcode regular expression for searching. 
  154. * 
  155. * The regular expression combines the shortcode tags in the regular expression 
  156. * in a regex class. 
  157. * 
  158. * The regular expresion contains 6 different sub matches to help with parsing. 
  159. * 
  160. * 1/6 - An extra [ or ] to allow for escaping shortcodes with double [[]] 
  161. * 2 - The shortcode name 
  162. * 3 - The shortcode argument list 
  163. * 4 - The self closing / 
  164. * 5 - The content of a shortcode when it wraps some content. 
  165. * 
  166. * @since 2.5 
  167. * @uses $shortcode_tags 
  168. * 
  169. * @return string The shortcode search regular expression 
  170. */ 
  171. function get_shortcode_regex() { 
  172. global $shortcode_tags; 
  173. $tagnames = array_keys($shortcode_tags); 
  174. $tagregexp = join( '|', array_map('preg_quote', $tagnames) ); 
  175.  
  176. // WARNING! Do not change this regex without changing do_shortcode_tag() and strip_shortcodes() 
  177. return '(.?)\[('.$tagregexp.')\b(.*?)(?:(\/))?\](?:(.+?)\[\/\2\])?(.?)'; 
  178.  
  179. /** 
  180. * Regular Expression callable for do_shortcode() for calling shortcode hook. 
  181. * @see get_shortcode_regex for details of the match array contents. 
  182. * 
  183. * @since 2.5 
  184. * @access private 
  185. * @uses $shortcode_tags 
  186. * 
  187. * @param array $m Regular expression match array 
  188. * @return mixed False on failure. 
  189. */ 
  190. function do_shortcode_tag($m) { 
  191. global $shortcode_tags; 
  192.  
  193. // allow [[foo]] syntax for escaping a tag 
  194. if ($m[1] == '[' && $m[6] == ']') { 
  195. return substr($m[0], 1, -1); 
  196.  
  197. $tag = $m[2]; 
  198. $attr = shortcode_parse_atts($m[3]); 
  199.  
  200. if ( isset($m[5]) ) { 
  201. // enclosing tag - extra parameter 
  202. return $m[1] . call_user_func($shortcode_tags[$tag], $attr, $m[5], $m[2]) . $m[6]; 
  203. } else { 
  204. // self-closing tag 
  205. return $m[1] . call_user_func($shortcode_tags[$tag], $attr, NULL, $m[2]) . $m[6]; 
  206.  
  207. /** 
  208. * Retrieve all attributes from the shortcodes tag. 
  209. * 
  210. * The attributes list has the attribute name as the key and the value of the 
  211. * attribute as the value in the key/value pair. This allows for easier 
  212. * retrieval of the attributes, since all attributes have to be known. 
  213. * 
  214. * @since 2.5 
  215. * 
  216. * @param string $text 
  217. * @return array List of attributes and their value. 
  218. */ 
  219. function shortcode_parse_atts($text) { 
  220. $atts = array(); 
  221. $pattern = '/(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*\'([^\']*)\'(?:\s|$)|(\w+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|(\S+)(?:\s|$)/'; 
  222. $text = preg_replace("/[\x{00a0}\x{200b}]+/u", " ", $text); 
  223. if ( preg_match_all($pattern, $text, $match, PREG_SET_ORDER) ) { 
  224. foreach ($match as $m) { 
  225. if (!empty($m[1])) 
  226. $atts[strtolower($m[1])] = stripcslashes($m[2]); 
  227. elseif (!empty($m[3])) 
  228. $atts[strtolower($m[3])] = stripcslashes($m[4]); 
  229. elseif (!empty($m[5])) 
  230. $atts[strtolower($m[5])] = stripcslashes($m[6]); 
  231. elseif (isset($m[7]) and strlen($m[7])) 
  232. $atts[] = stripcslashes($m[7]); 
  233. elseif (isset($m[8])) 
  234. $atts[] = stripcslashes($m[8]); 
  235. } else { 
  236. $atts = ltrim($text); 
  237. return $atts; 
  238.  
  239. /** 
  240. * Combine user attributes with known attributes and fill in defaults when needed. 
  241. * 
  242. * The pairs should be considered to be all of the attributes which are 
  243. * supported by the caller and given as a list. The returned attributes will 
  244. * only contain the attributes in the $pairs list. 
  245. * 
  246. * If the $atts list has unsupported attributes, then they will be ignored and 
  247. * removed from the final returned list. 
  248. * 
  249. * @since 2.5 
  250. * 
  251. * @param array $pairs Entire list of supported attributes and their defaults. 
  252. * @param array $atts User defined attributes in shortcode tag. 
  253. * @return array Combined and filtered attribute list. 
  254. */ 
  255. function shortcode_atts($pairs, $atts) { 
  256. $atts = (array)$atts; 
  257. $out = array(); 
  258. foreach($pairs as $name => $default) { 
  259. if ( array_key_exists($name, $atts) ) 
  260. $out[$name] = $atts[$name]; 
  261. else 
  262. $out[$name] = $default; 
  263. return $out; 
  264.  
  265. /** 
  266. * Remove all shortcode tags from the given content. 
  267. * 
  268. * @since 2.5 
  269. * @uses $shortcode_tags 
  270. * 
  271. * @param string $content Content to remove shortcode tags. 
  272. * @return string Content without shortcode tags. 
  273. */ 
  274. function strip_shortcodes( $content ) { 
  275. global $shortcode_tags; 
  276.  
  277. if (empty($shortcode_tags) || !is_array($shortcode_tags)) 
  278. return $content; 
  279.  
  280. $pattern = get_shortcode_regex(); 
  281.  
  282. return preg_replace('/'.$pattern.'/s', '$1$6', $content); 
.