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