[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
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 * $out = do_shortcode( $content ); 25 * 26 * @link https://developer.wordpress.org/plugins/shortcodes/ 27 * 28 * @package WordPress 29 * @subpackage Shortcodes 30 * @since 2.5.0 31 */ 32 33 /** 34 * Container for storing shortcode tags and their hook to call for the shortcode. 35 * 36 * @since 2.5.0 37 * 38 * @name $shortcode_tags 39 * @var array 40 * @global array $shortcode_tags 41 */ 42 $shortcode_tags = array(); 43 44 /** 45 * Adds a new shortcode. 46 * 47 * Care should be taken through prefixing or other means to ensure that the 48 * shortcode tag being added is unique and will not conflict with other, 49 * already-added shortcode tags. In the event of a duplicated tag, the tag 50 * loaded last will take precedence. 51 * 52 * @since 2.5.0 53 * 54 * @global array $shortcode_tags 55 * 56 * @param string $tag Shortcode tag to be searched in post content. 57 * @param callable $callback The callback function to run when the shortcode is found. 58 * Every shortcode callback is passed three parameters by default, 59 * including an array of attributes (`$atts`), the shortcode content 60 * or null if not set (`$content`), and finally the shortcode tag 61 * itself (`$shortcode_tag`), in that order. 62 */ 63 function add_shortcode( $tag, $callback ) { 64 global $shortcode_tags; 65 66 if ( '' === trim( $tag ) ) { 67 _doing_it_wrong( 68 __FUNCTION__, 69 __( 'Invalid shortcode name: Empty name given.' ), 70 '4.4.0' 71 ); 72 return; 73 } 74 75 if ( 0 !== preg_match( '@[<>&/\[\]\x00-\x20=]@', $tag ) ) { 76 _doing_it_wrong( 77 __FUNCTION__, 78 sprintf( 79 /* translators: 1: Shortcode name, 2: Space-separated list of reserved characters. */ 80 __( 'Invalid shortcode name: %1$s. Do not use spaces or reserved characters: %2$s' ), 81 $tag, 82 '& / < > [ ] =' 83 ), 84 '4.4.0' 85 ); 86 return; 87 } 88 89 $shortcode_tags[ $tag ] = $callback; 90 } 91 92 /** 93 * Removes hook for shortcode. 94 * 95 * @since 2.5.0 96 * 97 * @global array $shortcode_tags 98 * 99 * @param string $tag Shortcode tag to remove hook for. 100 */ 101 function remove_shortcode( $tag ) { 102 global $shortcode_tags; 103 104 unset( $shortcode_tags[ $tag ] ); 105 } 106 107 /** 108 * Clears all shortcodes. 109 * 110 * This function clears all of the shortcode tags by replacing the shortcodes global with 111 * an empty array. This is actually an efficient method for removing all shortcodes. 112 * 113 * @since 2.5.0 114 * 115 * @global array $shortcode_tags 116 */ 117 function remove_all_shortcodes() { 118 global $shortcode_tags; 119 120 $shortcode_tags = array(); 121 } 122 123 /** 124 * Determines whether a registered shortcode exists named $tag. 125 * 126 * @since 3.6.0 127 * 128 * @global array $shortcode_tags List of shortcode tags and their callback hooks. 129 * 130 * @param string $tag Shortcode tag to check. 131 * @return bool Whether the given shortcode exists. 132 */ 133 function shortcode_exists( $tag ) { 134 global $shortcode_tags; 135 return array_key_exists( $tag, $shortcode_tags ); 136 } 137 138 /** 139 * Determines whether the passed content contains the specified shortcode. 140 * 141 * @since 3.6.0 142 * 143 * @global array $shortcode_tags 144 * 145 * @param string $content Content to search for shortcodes. 146 * @param string $tag Shortcode tag to check. 147 * @return bool Whether the passed content contains the given shortcode. 148 */ 149 function has_shortcode( $content, $tag ) { 150 if ( ! str_contains( $content, '[' ) ) { 151 return false; 152 } 153 154 if ( shortcode_exists( $tag ) ) { 155 preg_match_all( '/' . get_shortcode_regex() . '/', $content, $matches, PREG_SET_ORDER ); 156 if ( empty( $matches ) ) { 157 return false; 158 } 159 160 foreach ( $matches as $shortcode ) { 161 if ( $tag === $shortcode[2] ) { 162 return true; 163 } elseif ( ! empty( $shortcode[5] ) && has_shortcode( $shortcode[5], $tag ) ) { 164 return true; 165 } 166 } 167 } 168 return false; 169 } 170 171 /** 172 * Returns a list of registered shortcode names found in the given content. 173 * 174 * Example usage: 175 * 176 * get_shortcode_tags_in_content( '[audio src="file.mp3"][/audio] [foo] [gallery ids="1,2,3"]' ); 177 * // array( 'audio', 'gallery' ) 178 * 179 * @since 6.3.2 180 * 181 * @param string $content The content to check. 182 * @return string[] An array of registered shortcode names found in the content. 183 */ 184 function get_shortcode_tags_in_content( $content ) { 185 if ( false === strpos( $content, '[' ) ) { 186 return array(); 187 } 188 189 preg_match_all( '/' . get_shortcode_regex() . '/', $content, $matches, PREG_SET_ORDER ); 190 if ( empty( $matches ) ) { 191 return array(); 192 } 193 194 $tags = array(); 195 foreach ( $matches as $shortcode ) { 196 $tags[] = $shortcode[2]; 197 198 if ( ! empty( $shortcode[5] ) ) { 199 $deep_tags = get_shortcode_tags_in_content( $shortcode[5] ); 200 if ( ! empty( $deep_tags ) ) { 201 $tags = array_merge( $tags, $deep_tags ); 202 } 203 } 204 } 205 206 return $tags; 207 } 208 209 /** 210 * Searches content for shortcodes and filter shortcodes through their hooks. 211 * 212 * This function is an alias for do_shortcode(). 213 * 214 * @since 5.4.0 215 * 216 * @see do_shortcode() 217 * 218 * @param string $content Content to search for shortcodes. 219 * @param bool $ignore_html When true, shortcodes inside HTML elements will be skipped. 220 * Default false. 221 * @return string Content with shortcodes filtered out. 222 */ 223 function apply_shortcodes( $content, $ignore_html = false ) { 224 return do_shortcode( $content, $ignore_html ); 225 } 226 227 /** 228 * Searches content for shortcodes and filter shortcodes through their hooks. 229 * 230 * If there are no shortcode tags defined, then the content will be returned 231 * without any filtering. This might cause issues when plugins are disabled but 232 * the shortcode will still show up in the post or content. 233 * 234 * @since 2.5.0 235 * 236 * @global array $shortcode_tags List of shortcode tags and their callback hooks. 237 * 238 * @param string $content Content to search for shortcodes. 239 * @param bool $ignore_html When true, shortcodes inside HTML elements will be skipped. 240 * Default false. 241 * @return string Content with shortcodes filtered out. 242 */ 243 function do_shortcode( $content, $ignore_html = false ) { 244 global $shortcode_tags; 245 246 if ( ! str_contains( $content, '[' ) ) { 247 return $content; 248 } 249 250 if ( empty( $shortcode_tags ) || ! is_array( $shortcode_tags ) ) { 251 return $content; 252 } 253 254 // Find all registered tag names in $content. 255 preg_match_all( '@\[([^<>&/\[\]\x00-\x20=]++)@', $content, $matches ); 256 $tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] ); 257 258 if ( empty( $tagnames ) ) { 259 return $content; 260 } 261 262 // Ensure this context is only added once if shortcodes are nested. 263 $has_filter = has_filter( 'wp_get_attachment_image_context', '_filter_do_shortcode_context' ); 264 $filter_added = false; 265 266 if ( ! $has_filter ) { 267 $filter_added = add_filter( 'wp_get_attachment_image_context', '_filter_do_shortcode_context' ); 268 } 269 270 $content = do_shortcodes_in_html_tags( $content, $ignore_html, $tagnames ); 271 272 $pattern = get_shortcode_regex( $tagnames ); 273 $content = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $content ); 274 275 // Always restore square braces so we don't break things like <!--[if IE ]>. 276 $content = unescape_invalid_shortcodes( $content ); 277 278 // Only remove the filter if it was added in this scope. 279 if ( $filter_added ) { 280 remove_filter( 'wp_get_attachment_image_context', '_filter_do_shortcode_context' ); 281 } 282 283 return $content; 284 } 285 286 /** 287 * Filter the `wp_get_attachment_image_context` hook during shortcode rendering. 288 * 289 * When wp_get_attachment_image() is called during shortcode rendering, we need to make clear 290 * that the context is a shortcode and not part of the theme's template rendering logic. 291 * 292 * @since 6.3.0 293 * @access private 294 * 295 * @return string The filtered context value for wp_get_attachment_images when doing shortcodes. 296 */ 297 function _filter_do_shortcode_context() { 298 return 'do_shortcode'; 299 } 300 301 /** 302 * Retrieves the shortcode regular expression for searching. 303 * 304 * The regular expression combines the shortcode tags in the regular expression 305 * in a regex class. 306 * 307 * The regular expression contains 6 different sub matches to help with parsing. 308 * 309 * 1 - An extra [ to allow for escaping shortcodes with double [[]] 310 * 2 - The shortcode name 311 * 3 - The shortcode argument list 312 * 4 - The self closing / 313 * 5 - The content of a shortcode when it wraps some content. 314 * 6 - An extra ] to allow for escaping shortcodes with double [[]] 315 * 316 * @since 2.5.0 317 * @since 4.4.0 Added the `$tagnames` parameter. 318 * 319 * @global array $shortcode_tags 320 * 321 * @param array $tagnames Optional. List of shortcodes to find. Defaults to all registered shortcodes. 322 * @return string The shortcode search regular expression 323 */ 324 function get_shortcode_regex( $tagnames = null ) { 325 global $shortcode_tags; 326 327 if ( empty( $tagnames ) ) { 328 $tagnames = array_keys( $shortcode_tags ); 329 } 330 $tagregexp = implode( '|', array_map( 'preg_quote', $tagnames ) ); 331 332 /* 333 * WARNING! Do not change this regex without changing do_shortcode_tag() and strip_shortcode_tag(). 334 * Also, see shortcode_unautop() and shortcode.js. 335 */ 336 337 // phpcs:disable Squiz.Strings.ConcatenationSpacing.PaddingFound -- don't remove regex indentation 338 return '\\[' // Opening bracket. 339 . '(\\[?)' // 1: Optional second opening bracket for escaping shortcodes: [[tag]]. 340 . "($tagregexp)" // 2: Shortcode name. 341 . '(?![\\w-])' // Not followed by word character or hyphen. 342 . '(' // 3: Unroll the loop: Inside the opening shortcode tag. 343 . '[^\\]\\/]*' // Not a closing bracket or forward slash. 344 . '(?:' 345 . '\\/(?!\\])' // A forward slash not followed by a closing bracket. 346 . '[^\\]\\/]*' // Not a closing bracket or forward slash. 347 . ')*?' 348 . ')' 349 . '(?:' 350 . '(\\/)' // 4: Self closing tag... 351 . '\\]' // ...and closing bracket. 352 . '|' 353 . '\\]' // Closing bracket. 354 . '(?:' 355 . '(' // 5: Unroll the loop: Optionally, anything between the opening and closing shortcode tags. 356 . '[^\\[]*+' // Not an opening bracket. 357 . '(?:' 358 . '\\[(?!\\/\\2\\])' // An opening bracket not followed by the closing shortcode tag. 359 . '[^\\[]*+' // Not an opening bracket. 360 . ')*+' 361 . ')' 362 . '\\[\\/\\2\\]' // Closing shortcode tag. 363 . ')?' 364 . ')' 365 . '(\\]?)'; // 6: Optional second closing bracket for escaping shortcodes: [[tag]]. 366 // phpcs:enable 367 } 368 369 /** 370 * Regular Expression callable for do_shortcode() for calling shortcode hook. 371 * 372 * @see get_shortcode_regex() for details of the match array contents. 373 * 374 * @since 2.5.0 375 * @access private 376 * 377 * @global array $shortcode_tags 378 * 379 * @param array $m { 380 * Regular expression match array. 381 * 382 * @type string $0 Entire matched shortcode text. 383 * @type string $1 Optional second opening bracket for escaping shortcodes. 384 * @type string $2 Shortcode name. 385 * @type string $3 Shortcode arguments list. 386 * @type string $4 Optional self closing slash. 387 * @type string $5 Content of a shortcode when it wraps some content. 388 * @type string $6 Optional second closing bracket for escaping shortcodes. 389 * } 390 * @return string Shortcode output. 391 */ 392 function do_shortcode_tag( $m ) { 393 global $shortcode_tags; 394 395 // Allow [[foo]] syntax for escaping a tag. 396 if ( '[' === $m[1] && ']' === $m[6] ) { 397 return substr( $m[0], 1, -1 ); 398 } 399 400 $tag = $m[2]; 401 $attr = shortcode_parse_atts( $m[3] ); 402 403 if ( ! is_callable( $shortcode_tags[ $tag ] ) ) { 404 _doing_it_wrong( 405 __FUNCTION__, 406 /* translators: %s: Shortcode tag. */ 407 sprintf( __( 'Attempting to parse a shortcode without a valid callback: %s' ), $tag ), 408 '4.3.0' 409 ); 410 return $m[0]; 411 } 412 413 /** 414 * Filters whether to call a shortcode callback. 415 * 416 * Returning a non-false value from filter will short-circuit the 417 * shortcode generation process, returning that value instead. 418 * 419 * @since 4.7.0 420 * 421 * @param false|string $output Short-circuit return value. Either false or the value to replace the shortcode with. 422 * @param string $tag Shortcode name. 423 * @param array|string $attr Shortcode attributes array or the original arguments string if it cannot be parsed. 424 * @param array $m Regular expression match array. 425 */ 426 $return = apply_filters( 'pre_do_shortcode_tag', false, $tag, $attr, $m ); 427 if ( false !== $return ) { 428 return $return; 429 } 430 431 $content = isset( $m[5] ) ? $m[5] : null; 432 433 $output = $m[1] . call_user_func( $shortcode_tags[ $tag ], $attr, $content, $tag ) . $m[6]; 434 435 /** 436 * Filters the output created by a shortcode callback. 437 * 438 * @since 4.7.0 439 * 440 * @param string $output Shortcode output. 441 * @param string $tag Shortcode name. 442 * @param array|string $attr Shortcode attributes array or the original arguments string if it cannot be parsed. 443 * @param array $m Regular expression match array. 444 */ 445 return apply_filters( 'do_shortcode_tag', $output, $tag, $attr, $m ); 446 } 447 448 /** 449 * Searches only inside HTML elements for shortcodes and process them. 450 * 451 * Any [ or ] characters remaining inside elements will be HTML encoded 452 * to prevent interference with shortcodes that are outside the elements. 453 * Assumes $content processed by KSES already. Users with unfiltered_html 454 * capability may get unexpected output if angle braces are nested in tags. 455 * 456 * @since 4.2.3 457 * 458 * @param string $content Content to search for shortcodes. 459 * @param bool $ignore_html When true, all square braces inside elements will be encoded. 460 * @param array $tagnames List of shortcodes to find. 461 * @return string Content with shortcodes filtered out. 462 */ 463 function do_shortcodes_in_html_tags( $content, $ignore_html, $tagnames ) { 464 // Normalize entities in unfiltered HTML before adding placeholders. 465 $trans = array( 466 '[' => '[', 467 ']' => ']', 468 ); 469 $content = strtr( $content, $trans ); 470 $trans = array( 471 '[' => '[', 472 ']' => ']', 473 ); 474 475 $pattern = get_shortcode_regex( $tagnames ); 476 $textarr = wp_html_split( $content ); 477 478 foreach ( $textarr as &$element ) { 479 if ( '' === $element || '<' !== $element[0] ) { 480 continue; 481 } 482 483 $noopen = ! str_contains( $element, '[' ); 484 $noclose = ! str_contains( $element, ']' ); 485 if ( $noopen || $noclose ) { 486 // This element does not contain shortcodes. 487 if ( $noopen xor $noclose ) { 488 // Need to encode stray '[' or ']' chars. 489 $element = strtr( $element, $trans ); 490 } 491 continue; 492 } 493 494 if ( $ignore_html || str_starts_with( $element, '<!--' ) || str_starts_with( $element, '<![CDATA[' ) ) { 495 // Encode all '[' and ']' chars. 496 $element = strtr( $element, $trans ); 497 continue; 498 } 499 500 $attributes = wp_kses_attr_parse( $element ); 501 if ( false === $attributes ) { 502 // Some plugins are doing things like [name] <[email]>. 503 if ( 1 === preg_match( '%^<\s*\[\[?[^\[\]]+\]%', $element ) ) { 504 $element = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $element ); 505 } 506 507 // Looks like we found some unexpected unfiltered HTML. Skipping it for confidence. 508 $element = strtr( $element, $trans ); 509 continue; 510 } 511 512 // Get element name. 513 $front = array_shift( $attributes ); 514 $back = array_pop( $attributes ); 515 $matches = array(); 516 preg_match( '%[a-zA-Z0-9]+%', $front, $matches ); 517 $elname = $matches[0]; 518 519 // Look for shortcodes in each attribute separately. 520 foreach ( $attributes as &$attr ) { 521 $open = strpos( $attr, '[' ); 522 $close = strpos( $attr, ']' ); 523 if ( false === $open || false === $close ) { 524 continue; // Go to next attribute. Square braces will be escaped at end of loop. 525 } 526 $double = strpos( $attr, '"' ); 527 $single = strpos( $attr, "'" ); 528 if ( ( false === $single || $open < $single ) && ( false === $double || $open < $double ) ) { 529 /* 530 * $attr like '[shortcode]' or 'name = [shortcode]' implies unfiltered_html. 531 * In this specific situation we assume KSES did not run because the input 532 * was written by an administrator, so we should avoid changing the output 533 * and we do not need to run KSES here. 534 */ 535 $attr = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $attr ); 536 } else { 537 /* 538 * $attr like 'name = "[shortcode]"' or "name = '[shortcode]'". 539 * We do not know if $content was unfiltered. Assume KSES ran before shortcodes. 540 */ 541 $count = 0; 542 $new_attr = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $attr, -1, $count ); 543 if ( $count > 0 ) { 544 // Sanitize the shortcode output using KSES. 545 $new_attr = wp_kses_one_attr( $new_attr, $elname ); 546 if ( '' !== trim( $new_attr ) ) { 547 // The shortcode is safe to use now. 548 $attr = $new_attr; 549 } 550 } 551 } 552 } 553 $element = $front . implode( '', $attributes ) . $back; 554 555 // Now encode any remaining '[' or ']' chars. 556 $element = strtr( $element, $trans ); 557 } 558 559 $content = implode( '', $textarr ); 560 561 return $content; 562 } 563 564 /** 565 * Removes placeholders added by do_shortcodes_in_html_tags(). 566 * 567 * @since 4.2.3 568 * 569 * @param string $content Content to search for placeholders. 570 * @return string Content with placeholders removed. 571 */ 572 function unescape_invalid_shortcodes( $content ) { 573 // Clean up entire string, avoids re-parsing HTML. 574 $trans = array( 575 '[' => '[', 576 ']' => ']', 577 ); 578 579 $content = strtr( $content, $trans ); 580 581 return $content; 582 } 583 584 /** 585 * Retrieves the shortcode attributes regex. 586 * 587 * @since 4.4.0 588 * 589 * @return string The shortcode attribute regular expression. 590 */ 591 function get_shortcode_atts_regex() { 592 return '/([\w-]+)\s*=\s*"([^"]*)"(?:\s|$)|([\w-]+)\s*=\s*\'([^\']*)\'(?:\s|$)|([\w-]+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|\'([^\']*)\'(?:\s|$)|(\S+)(?:\s|$)/'; 593 } 594 595 /** 596 * Retrieves all attributes from the shortcodes tag. 597 * 598 * The attributes list has the attribute name as the key and the value of the 599 * attribute as the value in the key/value pair. This allows for easier 600 * retrieval of the attributes, since all attributes have to be known. 601 * 602 * @since 2.5.0 603 * @since 6.5.0 The function now always returns an empty array, 604 * even if the original arguments string cannot be parsed or is empty. 605 * 606 * @param string $text Shortcode arguments list. 607 * @return array Array of attribute values keyed by attribute name. 608 * Returns empty array if there are no attributes 609 * or if the original arguments string cannot be parsed. 610 */ 611 function shortcode_parse_atts( $text ) { 612 $atts = array(); 613 $pattern = get_shortcode_atts_regex(); 614 $text = preg_replace( "/[\x{00a0}\x{200b}]+/u", ' ', $text ); 615 if ( preg_match_all( $pattern, $text, $match, PREG_SET_ORDER ) ) { 616 foreach ( $match as $m ) { 617 if ( ! empty( $m[1] ) ) { 618 $atts[ strtolower( $m[1] ) ] = stripcslashes( $m[2] ); 619 } elseif ( ! empty( $m[3] ) ) { 620 $atts[ strtolower( $m[3] ) ] = stripcslashes( $m[4] ); 621 } elseif ( ! empty( $m[5] ) ) { 622 $atts[ strtolower( $m[5] ) ] = stripcslashes( $m[6] ); 623 } elseif ( isset( $m[7] ) && strlen( $m[7] ) ) { 624 $atts[] = stripcslashes( $m[7] ); 625 } elseif ( isset( $m[8] ) && strlen( $m[8] ) ) { 626 $atts[] = stripcslashes( $m[8] ); 627 } elseif ( isset( $m[9] ) ) { 628 $atts[] = stripcslashes( $m[9] ); 629 } 630 } 631 632 // Reject any unclosed HTML elements. 633 foreach ( $atts as &$value ) { 634 if ( str_contains( $value, '<' ) ) { 635 if ( 1 !== preg_match( '/^[^<]*+(?:<[^>]*+>[^<]*+)*+$/', $value ) ) { 636 $value = ''; 637 } 638 } 639 } 640 } 641 642 return $atts; 643 } 644 645 /** 646 * Combines user attributes with known attributes and fill in defaults when needed. 647 * 648 * The pairs should be considered to be all of the attributes which are 649 * supported by the caller and given as a list. The returned attributes will 650 * only contain the attributes in the $pairs list. 651 * 652 * If the $atts list has unsupported attributes, then they will be ignored and 653 * removed from the final returned list. 654 * 655 * @since 2.5.0 656 * 657 * @param array $pairs Entire list of supported attributes and their defaults. 658 * @param array $atts User defined attributes in shortcode tag. 659 * @param string $shortcode Optional. The name of the shortcode, provided for context to enable filtering 660 * @return array Combined and filtered attribute list. 661 */ 662 function shortcode_atts( $pairs, $atts, $shortcode = '' ) { 663 $atts = (array) $atts; 664 $out = array(); 665 foreach ( $pairs as $name => $default ) { 666 if ( array_key_exists( $name, $atts ) ) { 667 $out[ $name ] = $atts[ $name ]; 668 } else { 669 $out[ $name ] = $default; 670 } 671 } 672 673 if ( $shortcode ) { 674 /** 675 * Filters shortcode attributes. 676 * 677 * If the third parameter of the shortcode_atts() function is present then this filter is available. 678 * The third parameter, $shortcode, is the name of the shortcode. 679 * 680 * @since 3.6.0 681 * @since 4.4.0 Added the `$shortcode` parameter. 682 * 683 * @param array $out The output array of shortcode attributes. 684 * @param array $pairs The supported attributes and their defaults. 685 * @param array $atts The user defined shortcode attributes. 686 * @param string $shortcode The shortcode name. 687 */ 688 $out = apply_filters( "shortcode_atts_{$shortcode}", $out, $pairs, $atts, $shortcode ); 689 } 690 691 return $out; 692 } 693 694 /** 695 * Removes all shortcode tags from the given content. 696 * 697 * @since 2.5.0 698 * 699 * @global array $shortcode_tags 700 * 701 * @param string $content Content to remove shortcode tags. 702 * @return string Content without shortcode tags. 703 */ 704 function strip_shortcodes( $content ) { 705 global $shortcode_tags; 706 707 if ( ! str_contains( $content, '[' ) ) { 708 return $content; 709 } 710 711 if ( empty( $shortcode_tags ) || ! is_array( $shortcode_tags ) ) { 712 return $content; 713 } 714 715 // Find all registered tag names in $content. 716 preg_match_all( '@\[([^<>&/\[\]\x00-\x20=]++)@', $content, $matches ); 717 718 $tags_to_remove = array_keys( $shortcode_tags ); 719 720 /** 721 * Filters the list of shortcode tags to remove from the content. 722 * 723 * @since 4.7.0 724 * 725 * @param array $tags_to_remove Array of shortcode tags to remove. 726 * @param string $content Content shortcodes are being removed from. 727 */ 728 $tags_to_remove = apply_filters( 'strip_shortcodes_tagnames', $tags_to_remove, $content ); 729 730 $tagnames = array_intersect( $tags_to_remove, $matches[1] ); 731 732 if ( empty( $tagnames ) ) { 733 return $content; 734 } 735 736 $content = do_shortcodes_in_html_tags( $content, true, $tagnames ); 737 738 $pattern = get_shortcode_regex( $tagnames ); 739 $content = preg_replace_callback( "/$pattern/", 'strip_shortcode_tag', $content ); 740 741 // Always restore square braces so we don't break things like <!--[if IE ]>. 742 $content = unescape_invalid_shortcodes( $content ); 743 744 return $content; 745 } 746 747 /** 748 * Strips a shortcode tag based on RegEx matches against post content. 749 * 750 * @since 3.3.0 751 * 752 * @param array $m RegEx matches against post content. 753 * @return string|false The content stripped of the tag, otherwise false. 754 */ 755 function strip_shortcode_tag( $m ) { 756 // Allow [[foo]] syntax for escaping a tag. 757 if ( '[' === $m[1] && ']' === $m[6] ) { 758 return substr( $m[0], 1, -1 ); 759 } 760 761 return $m[1] . $m[6]; 762 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Sat Apr 20 08:20:01 2024 | Cross-referenced by PHPXref |