[ 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 * @since 6.5.0 The `$attr` parameter is always an array. 421 * 422 * @param false|string $output Short-circuit return value. Either false or the value to replace the shortcode with. 423 * @param string $tag Shortcode name. 424 * @param array $attr Shortcode attributes array, can be empty if the original arguments string cannot be parsed. 425 * @param array $m Regular expression match array. 426 */ 427 $return = apply_filters( 'pre_do_shortcode_tag', false, $tag, $attr, $m ); 428 if ( false !== $return ) { 429 return $return; 430 } 431 432 $content = isset( $m[5] ) ? $m[5] : null; 433 434 $output = $m[1] . call_user_func( $shortcode_tags[ $tag ], $attr, $content, $tag ) . $m[6]; 435 436 /** 437 * Filters the output created by a shortcode callback. 438 * 439 * @since 4.7.0 440 * @since 6.5.0 The `$attr` parameter is always an array. 441 * 442 * @param string $output Shortcode output. 443 * @param string $tag Shortcode name. 444 * @param array $attr Shortcode attributes array, can be empty if the original arguments string cannot be parsed. 445 * @param array $m Regular expression match array. 446 */ 447 return apply_filters( 'do_shortcode_tag', $output, $tag, $attr, $m ); 448 } 449 450 /** 451 * Searches only inside HTML elements for shortcodes and process them. 452 * 453 * Any [ or ] characters remaining inside elements will be HTML encoded 454 * to prevent interference with shortcodes that are outside the elements. 455 * Assumes $content processed by KSES already. Users with unfiltered_html 456 * capability may get unexpected output if angle braces are nested in tags. 457 * 458 * @since 4.2.3 459 * 460 * @param string $content Content to search for shortcodes. 461 * @param bool $ignore_html When true, all square braces inside elements will be encoded. 462 * @param array $tagnames List of shortcodes to find. 463 * @return string Content with shortcodes filtered out. 464 */ 465 function do_shortcodes_in_html_tags( $content, $ignore_html, $tagnames ) { 466 // Normalize entities in unfiltered HTML before adding placeholders. 467 $trans = array( 468 '[' => '[', 469 ']' => ']', 470 ); 471 $content = strtr( $content, $trans ); 472 $trans = array( 473 '[' => '[', 474 ']' => ']', 475 ); 476 477 $pattern = get_shortcode_regex( $tagnames ); 478 $textarr = wp_html_split( $content ); 479 480 foreach ( $textarr as &$element ) { 481 if ( '' === $element || '<' !== $element[0] ) { 482 continue; 483 } 484 485 $noopen = ! str_contains( $element, '[' ); 486 $noclose = ! str_contains( $element, ']' ); 487 if ( $noopen || $noclose ) { 488 // This element does not contain shortcodes. 489 if ( $noopen xor $noclose ) { 490 // Need to encode stray '[' or ']' chars. 491 $element = strtr( $element, $trans ); 492 } 493 continue; 494 } 495 496 if ( $ignore_html || str_starts_with( $element, '<!--' ) || str_starts_with( $element, '<![CDATA[' ) ) { 497 // Encode all '[' and ']' chars. 498 $element = strtr( $element, $trans ); 499 continue; 500 } 501 502 $attributes = wp_kses_attr_parse( $element ); 503 if ( false === $attributes ) { 504 // Some plugins are doing things like [name] <[email]>. 505 if ( 1 === preg_match( '%^<\s*\[\[?[^\[\]]+\]%', $element ) ) { 506 $element = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $element ); 507 } 508 509 // Looks like we found some unexpected unfiltered HTML. Skipping it for confidence. 510 $element = strtr( $element, $trans ); 511 continue; 512 } 513 514 // Get element name. 515 $front = array_shift( $attributes ); 516 $back = array_pop( $attributes ); 517 $matches = array(); 518 preg_match( '%[a-zA-Z0-9]+%', $front, $matches ); 519 $elname = $matches[0]; 520 521 // Look for shortcodes in each attribute separately. 522 foreach ( $attributes as &$attr ) { 523 $open = strpos( $attr, '[' ); 524 $close = strpos( $attr, ']' ); 525 if ( false === $open || false === $close ) { 526 continue; // Go to next attribute. Square braces will be escaped at end of loop. 527 } 528 $double = strpos( $attr, '"' ); 529 $single = strpos( $attr, "'" ); 530 if ( ( false === $single || $open < $single ) && ( false === $double || $open < $double ) ) { 531 /* 532 * $attr like '[shortcode]' or 'name = [shortcode]' implies unfiltered_html. 533 * In this specific situation we assume KSES did not run because the input 534 * was written by an administrator, so we should avoid changing the output 535 * and we do not need to run KSES here. 536 */ 537 $attr = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $attr ); 538 } else { 539 /* 540 * $attr like 'name = "[shortcode]"' or "name = '[shortcode]'". 541 * We do not know if $content was unfiltered. Assume KSES ran before shortcodes. 542 */ 543 $count = 0; 544 $new_attr = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $attr, -1, $count ); 545 if ( $count > 0 ) { 546 // Sanitize the shortcode output using KSES. 547 $new_attr = wp_kses_one_attr( $new_attr, $elname ); 548 if ( '' !== trim( $new_attr ) ) { 549 // The shortcode is safe to use now. 550 $attr = $new_attr; 551 } 552 } 553 } 554 } 555 $element = $front . implode( '', $attributes ) . $back; 556 557 // Now encode any remaining '[' or ']' chars. 558 $element = strtr( $element, $trans ); 559 } 560 561 $content = implode( '', $textarr ); 562 563 return $content; 564 } 565 566 /** 567 * Removes placeholders added by do_shortcodes_in_html_tags(). 568 * 569 * @since 4.2.3 570 * 571 * @param string $content Content to search for placeholders. 572 * @return string Content with placeholders removed. 573 */ 574 function unescape_invalid_shortcodes( $content ) { 575 // Clean up entire string, avoids re-parsing HTML. 576 $trans = array( 577 '[' => '[', 578 ']' => ']', 579 ); 580 581 $content = strtr( $content, $trans ); 582 583 return $content; 584 } 585 586 /** 587 * Retrieves the shortcode attributes regex. 588 * 589 * @since 4.4.0 590 * 591 * @return string The shortcode attribute regular expression. 592 */ 593 function get_shortcode_atts_regex() { 594 return '/([\w-]+)\s*=\s*"([^"]*)"(?:\s|$)|([\w-]+)\s*=\s*\'([^\']*)\'(?:\s|$)|([\w-]+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|\'([^\']*)\'(?:\s|$)|(\S+)(?:\s|$)/'; 595 } 596 597 /** 598 * Retrieves all attributes from the shortcodes tag. 599 * 600 * The attributes list has the attribute name as the key and the value of the 601 * attribute as the value in the key/value pair. This allows for easier 602 * retrieval of the attributes, since all attributes have to be known. 603 * 604 * @since 2.5.0 605 * @since 6.5.0 The function now always returns an array, 606 * even if the original arguments string cannot be parsed or is empty. 607 * 608 * @param string $text Shortcode arguments list. 609 * @return array Array of attribute values keyed by attribute name. 610 * Returns empty array if there are no attributes 611 * or if the original arguments string cannot be parsed. 612 */ 613 function shortcode_parse_atts( $text ) { 614 $atts = array(); 615 $pattern = get_shortcode_atts_regex(); 616 $text = preg_replace( "/[\x{00a0}\x{200b}]+/u", ' ', $text ); 617 if ( preg_match_all( $pattern, $text, $match, PREG_SET_ORDER ) ) { 618 foreach ( $match as $m ) { 619 if ( ! empty( $m[1] ) ) { 620 $atts[ strtolower( $m[1] ) ] = stripcslashes( $m[2] ); 621 } elseif ( ! empty( $m[3] ) ) { 622 $atts[ strtolower( $m[3] ) ] = stripcslashes( $m[4] ); 623 } elseif ( ! empty( $m[5] ) ) { 624 $atts[ strtolower( $m[5] ) ] = stripcslashes( $m[6] ); 625 } elseif ( isset( $m[7] ) && strlen( $m[7] ) ) { 626 $atts[] = stripcslashes( $m[7] ); 627 } elseif ( isset( $m[8] ) && strlen( $m[8] ) ) { 628 $atts[] = stripcslashes( $m[8] ); 629 } elseif ( isset( $m[9] ) ) { 630 $atts[] = stripcslashes( $m[9] ); 631 } 632 } 633 634 // Reject any unclosed HTML elements. 635 foreach ( $atts as &$value ) { 636 if ( str_contains( $value, '<' ) ) { 637 if ( 1 !== preg_match( '/^[^<]*+(?:<[^>]*+>[^<]*+)*+$/', $value ) ) { 638 $value = ''; 639 } 640 } 641 } 642 } 643 644 return $atts; 645 } 646 647 /** 648 * Combines user attributes with known attributes and fill in defaults when needed. 649 * 650 * The pairs should be considered to be all of the attributes which are 651 * supported by the caller and given as a list. The returned attributes will 652 * only contain the attributes in the $pairs list. 653 * 654 * If the $atts list has unsupported attributes, then they will be ignored and 655 * removed from the final returned list. 656 * 657 * @since 2.5.0 658 * 659 * @param array $pairs Entire list of supported attributes and their defaults. 660 * @param array $atts User defined attributes in shortcode tag. 661 * @param string $shortcode Optional. The name of the shortcode, provided for context to enable filtering 662 * @return array Combined and filtered attribute list. 663 */ 664 function shortcode_atts( $pairs, $atts, $shortcode = '' ) { 665 $atts = (array) $atts; 666 $out = array(); 667 foreach ( $pairs as $name => $default ) { 668 if ( array_key_exists( $name, $atts ) ) { 669 $out[ $name ] = $atts[ $name ]; 670 } else { 671 $out[ $name ] = $default; 672 } 673 } 674 675 if ( $shortcode ) { 676 /** 677 * Filters shortcode attributes. 678 * 679 * If the third parameter of the shortcode_atts() function is present then this filter is available. 680 * The third parameter, $shortcode, is the name of the shortcode. 681 * 682 * @since 3.6.0 683 * @since 4.4.0 Added the `$shortcode` parameter. 684 * 685 * @param array $out The output array of shortcode attributes. 686 * @param array $pairs The supported attributes and their defaults. 687 * @param array $atts The user defined shortcode attributes. 688 * @param string $shortcode The shortcode name. 689 */ 690 $out = apply_filters( "shortcode_atts_{$shortcode}", $out, $pairs, $atts, $shortcode ); 691 } 692 693 return $out; 694 } 695 696 /** 697 * Removes all shortcode tags from the given content. 698 * 699 * @since 2.5.0 700 * 701 * @global array $shortcode_tags 702 * 703 * @param string $content Content to remove shortcode tags. 704 * @return string Content without shortcode tags. 705 */ 706 function strip_shortcodes( $content ) { 707 global $shortcode_tags; 708 709 if ( ! str_contains( $content, '[' ) ) { 710 return $content; 711 } 712 713 if ( empty( $shortcode_tags ) || ! is_array( $shortcode_tags ) ) { 714 return $content; 715 } 716 717 // Find all registered tag names in $content. 718 preg_match_all( '@\[([^<>&/\[\]\x00-\x20=]++)@', $content, $matches ); 719 720 $tags_to_remove = array_keys( $shortcode_tags ); 721 722 /** 723 * Filters the list of shortcode tags to remove from the content. 724 * 725 * @since 4.7.0 726 * 727 * @param array $tags_to_remove Array of shortcode tags to remove. 728 * @param string $content Content shortcodes are being removed from. 729 */ 730 $tags_to_remove = apply_filters( 'strip_shortcodes_tagnames', $tags_to_remove, $content ); 731 732 $tagnames = array_intersect( $tags_to_remove, $matches[1] ); 733 734 if ( empty( $tagnames ) ) { 735 return $content; 736 } 737 738 $content = do_shortcodes_in_html_tags( $content, true, $tagnames ); 739 740 $pattern = get_shortcode_regex( $tagnames ); 741 $content = preg_replace_callback( "/$pattern/", 'strip_shortcode_tag', $content ); 742 743 // Always restore square braces so we don't break things like <!--[if IE ]>. 744 $content = unescape_invalid_shortcodes( $content ); 745 746 return $content; 747 } 748 749 /** 750 * Strips a shortcode tag based on RegEx matches against post content. 751 * 752 * @since 3.3.0 753 * 754 * @param array $m RegEx matches against post content. 755 * @return string|false The content stripped of the tag, otherwise false. 756 */ 757 function strip_shortcode_tag( $m ) { 758 // Allow [[foo]] syntax for escaping a tag. 759 if ( '[' === $m[1] && ']' === $m[6] ) { 760 return substr( $m[0], 1, -1 ); 761 } 762 763 return $m[1] . $m[6]; 764 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Thu Nov 21 08:20:01 2024 | Cross-referenced by PHPXref |