angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

shortcodes.php (21432B)


      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  * Clear all shortcodes.
    109  *
    110  * This function is simple, it clears all of the shortcode tags by replacing the
    111  * shortcodes global by a empty array. This is actually a very efficient method
    112  * for removing all shortcodes.
    113  *
    114  * @since 2.5.0
    115  *
    116  * @global array $shortcode_tags
    117  */
    118 function remove_all_shortcodes() {
    119 	global $shortcode_tags;
    120 
    121 	$shortcode_tags = array();
    122 }
    123 
    124 /**
    125  * Whether a registered shortcode exists named $tag
    126  *
    127  * @since 3.6.0
    128  *
    129  * @global array $shortcode_tags List of shortcode tags and their callback hooks.
    130  *
    131  * @param string $tag Shortcode tag to check.
    132  * @return bool Whether the given shortcode exists.
    133  */
    134 function shortcode_exists( $tag ) {
    135 	global $shortcode_tags;
    136 	return array_key_exists( $tag, $shortcode_tags );
    137 }
    138 
    139 /**
    140  * Whether the passed content contains the specified shortcode
    141  *
    142  * @since 3.6.0
    143  *
    144  * @global array $shortcode_tags
    145  *
    146  * @param string $content Content to search for shortcodes.
    147  * @param string $tag     Shortcode tag to check.
    148  * @return bool Whether the passed content contains the given shortcode.
    149  */
    150 function has_shortcode( $content, $tag ) {
    151 	if ( false === strpos( $content, '[' ) ) {
    152 		return false;
    153 	}
    154 
    155 	if ( shortcode_exists( $tag ) ) {
    156 		preg_match_all( '/' . get_shortcode_regex() . '/', $content, $matches, PREG_SET_ORDER );
    157 		if ( empty( $matches ) ) {
    158 			return false;
    159 		}
    160 
    161 		foreach ( $matches as $shortcode ) {
    162 			if ( $tag === $shortcode[2] ) {
    163 				return true;
    164 			} elseif ( ! empty( $shortcode[5] ) && has_shortcode( $shortcode[5], $tag ) ) {
    165 				return true;
    166 			}
    167 		}
    168 	}
    169 	return false;
    170 }
    171 
    172 /**
    173  * Search content for shortcodes and filter shortcodes through their hooks.
    174  *
    175  * This function is an alias for do_shortcode().
    176  *
    177  * @since 5.4.0
    178  *
    179  * @see do_shortcode()
    180  *
    181  * @param string $content     Content to search for shortcodes.
    182  * @param bool   $ignore_html When true, shortcodes inside HTML elements will be skipped.
    183  *                            Default false.
    184  * @return string Content with shortcodes filtered out.
    185  */
    186 function apply_shortcodes( $content, $ignore_html = false ) {
    187 	return do_shortcode( $content, $ignore_html );
    188 }
    189 
    190 /**
    191  * Search content for shortcodes and filter shortcodes through their hooks.
    192  *
    193  * If there are no shortcode tags defined, then the content will be returned
    194  * without any filtering. This might cause issues when plugins are disabled but
    195  * the shortcode will still show up in the post or content.
    196  *
    197  * @since 2.5.0
    198  *
    199  * @global array $shortcode_tags List of shortcode tags and their callback hooks.
    200  *
    201  * @param string $content     Content to search for shortcodes.
    202  * @param bool   $ignore_html When true, shortcodes inside HTML elements will be skipped.
    203  *                            Default false.
    204  * @return string Content with shortcodes filtered out.
    205  */
    206 function do_shortcode( $content, $ignore_html = false ) {
    207 	global $shortcode_tags;
    208 
    209 	if ( false === strpos( $content, '[' ) ) {
    210 		return $content;
    211 	}
    212 
    213 	if ( empty( $shortcode_tags ) || ! is_array( $shortcode_tags ) ) {
    214 		return $content;
    215 	}
    216 
    217 	// Find all registered tag names in $content.
    218 	preg_match_all( '@\[([^<>&/\[\]\x00-\x20=]++)@', $content, $matches );
    219 	$tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
    220 
    221 	if ( empty( $tagnames ) ) {
    222 		return $content;
    223 	}
    224 
    225 	$content = do_shortcodes_in_html_tags( $content, $ignore_html, $tagnames );
    226 
    227 	$pattern = get_shortcode_regex( $tagnames );
    228 	$content = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $content );
    229 
    230 	// Always restore square braces so we don't break things like <!--[if IE ]>.
    231 	$content = unescape_invalid_shortcodes( $content );
    232 
    233 	return $content;
    234 }
    235 
    236 /**
    237  * Retrieve the shortcode regular expression for searching.
    238  *
    239  * The regular expression combines the shortcode tags in the regular expression
    240  * in a regex class.
    241  *
    242  * The regular expression contains 6 different sub matches to help with parsing.
    243  *
    244  * 1 - An extra [ to allow for escaping shortcodes with double [[]]
    245  * 2 - The shortcode name
    246  * 3 - The shortcode argument list
    247  * 4 - The self closing /
    248  * 5 - The content of a shortcode when it wraps some content.
    249  * 6 - An extra ] to allow for escaping shortcodes with double [[]]
    250  *
    251  * @since 2.5.0
    252  * @since 4.4.0 Added the `$tagnames` parameter.
    253  *
    254  * @global array $shortcode_tags
    255  *
    256  * @param array $tagnames Optional. List of shortcodes to find. Defaults to all registered shortcodes.
    257  * @return string The shortcode search regular expression
    258  */
    259 function get_shortcode_regex( $tagnames = null ) {
    260 	global $shortcode_tags;
    261 
    262 	if ( empty( $tagnames ) ) {
    263 		$tagnames = array_keys( $shortcode_tags );
    264 	}
    265 	$tagregexp = implode( '|', array_map( 'preg_quote', $tagnames ) );
    266 
    267 	// WARNING! Do not change this regex without changing do_shortcode_tag() and strip_shortcode_tag().
    268 	// Also, see shortcode_unautop() and shortcode.js.
    269 
    270 	// phpcs:disable Squiz.Strings.ConcatenationSpacing.PaddingFound -- don't remove regex indentation
    271 	return '\\['                             // Opening bracket.
    272 		. '(\\[?)'                           // 1: Optional second opening bracket for escaping shortcodes: [[tag]].
    273 		. "($tagregexp)"                     // 2: Shortcode name.
    274 		. '(?![\\w-])'                       // Not followed by word character or hyphen.
    275 		. '('                                // 3: Unroll the loop: Inside the opening shortcode tag.
    276 		.     '[^\\]\\/]*'                   // Not a closing bracket or forward slash.
    277 		.     '(?:'
    278 		.         '\\/(?!\\])'               // A forward slash not followed by a closing bracket.
    279 		.         '[^\\]\\/]*'               // Not a closing bracket or forward slash.
    280 		.     ')*?'
    281 		. ')'
    282 		. '(?:'
    283 		.     '(\\/)'                        // 4: Self closing tag...
    284 		.     '\\]'                          // ...and closing bracket.
    285 		. '|'
    286 		.     '\\]'                          // Closing bracket.
    287 		.     '(?:'
    288 		.         '('                        // 5: Unroll the loop: Optionally, anything between the opening and closing shortcode tags.
    289 		.             '[^\\[]*+'             // Not an opening bracket.
    290 		.             '(?:'
    291 		.                 '\\[(?!\\/\\2\\])' // An opening bracket not followed by the closing shortcode tag.
    292 		.                 '[^\\[]*+'         // Not an opening bracket.
    293 		.             ')*+'
    294 		.         ')'
    295 		.         '\\[\\/\\2\\]'             // Closing shortcode tag.
    296 		.     ')?'
    297 		. ')'
    298 		. '(\\]?)';                          // 6: Optional second closing brocket for escaping shortcodes: [[tag]].
    299 	// phpcs:enable
    300 }
    301 
    302 /**
    303  * Regular Expression callable for do_shortcode() for calling shortcode hook.
    304  *
    305  * @see get_shortcode_regex() for details of the match array contents.
    306  *
    307  * @since 2.5.0
    308  * @access private
    309  *
    310  * @global array $shortcode_tags
    311  *
    312  * @param array $m Regular expression match array.
    313  * @return string|false Shortcode output on success, false on failure.
    314  */
    315 function do_shortcode_tag( $m ) {
    316 	global $shortcode_tags;
    317 
    318 	// Allow [[foo]] syntax for escaping a tag.
    319 	if ( '[' === $m[1] && ']' === $m[6] ) {
    320 		return substr( $m[0], 1, -1 );
    321 	}
    322 
    323 	$tag  = $m[2];
    324 	$attr = shortcode_parse_atts( $m[3] );
    325 
    326 	if ( ! is_callable( $shortcode_tags[ $tag ] ) ) {
    327 		_doing_it_wrong(
    328 			__FUNCTION__,
    329 			/* translators: %s: Shortcode tag. */
    330 			sprintf( __( 'Attempting to parse a shortcode without a valid callback: %s' ), $tag ),
    331 			'4.3.0'
    332 		);
    333 		return $m[0];
    334 	}
    335 
    336 	/**
    337 	 * Filters whether to call a shortcode callback.
    338 	 *
    339 	 * Returning a non-false value from filter will short-circuit the
    340 	 * shortcode generation process, returning that value instead.
    341 	 *
    342 	 * @since 4.7.0
    343 	 *
    344 	 * @param false|string $return      Short-circuit return value. Either false or the value to replace the shortcode with.
    345 	 * @param string       $tag         Shortcode name.
    346 	 * @param array|string $attr        Shortcode attributes array or empty string.
    347 	 * @param array        $m           Regular expression match array.
    348 	 */
    349 	$return = apply_filters( 'pre_do_shortcode_tag', false, $tag, $attr, $m );
    350 	if ( false !== $return ) {
    351 		return $return;
    352 	}
    353 
    354 	$content = isset( $m[5] ) ? $m[5] : null;
    355 
    356 	$output = $m[1] . call_user_func( $shortcode_tags[ $tag ], $attr, $content, $tag ) . $m[6];
    357 
    358 	/**
    359 	 * Filters the output created by a shortcode callback.
    360 	 *
    361 	 * @since 4.7.0
    362 	 *
    363 	 * @param string       $output Shortcode output.
    364 	 * @param string       $tag    Shortcode name.
    365 	 * @param array|string $attr   Shortcode attributes array or empty string.
    366 	 * @param array        $m      Regular expression match array.
    367 	 */
    368 	return apply_filters( 'do_shortcode_tag', $output, $tag, $attr, $m );
    369 }
    370 
    371 /**
    372  * Search only inside HTML elements for shortcodes and process them.
    373  *
    374  * Any [ or ] characters remaining inside elements will be HTML encoded
    375  * to prevent interference with shortcodes that are outside the elements.
    376  * Assumes $content processed by KSES already.  Users with unfiltered_html
    377  * capability may get unexpected output if angle braces are nested in tags.
    378  *
    379  * @since 4.2.3
    380  *
    381  * @param string $content     Content to search for shortcodes.
    382  * @param bool   $ignore_html When true, all square braces inside elements will be encoded.
    383  * @param array  $tagnames    List of shortcodes to find.
    384  * @return string Content with shortcodes filtered out.
    385  */
    386 function do_shortcodes_in_html_tags( $content, $ignore_html, $tagnames ) {
    387 	// Normalize entities in unfiltered HTML before adding placeholders.
    388 	$trans   = array(
    389 		'&#91;' => '&#091;',
    390 		'&#93;' => '&#093;',
    391 	);
    392 	$content = strtr( $content, $trans );
    393 	$trans   = array(
    394 		'[' => '&#91;',
    395 		']' => '&#93;',
    396 	);
    397 
    398 	$pattern = get_shortcode_regex( $tagnames );
    399 	$textarr = wp_html_split( $content );
    400 
    401 	foreach ( $textarr as &$element ) {
    402 		if ( '' === $element || '<' !== $element[0] ) {
    403 			continue;
    404 		}
    405 
    406 		$noopen  = false === strpos( $element, '[' );
    407 		$noclose = false === strpos( $element, ']' );
    408 		if ( $noopen || $noclose ) {
    409 			// This element does not contain shortcodes.
    410 			if ( $noopen xor $noclose ) {
    411 				// Need to encode stray '[' or ']' chars.
    412 				$element = strtr( $element, $trans );
    413 			}
    414 			continue;
    415 		}
    416 
    417 		if ( $ignore_html || '<!--' === substr( $element, 0, 4 ) || '<![CDATA[' === substr( $element, 0, 9 ) ) {
    418 			// Encode all '[' and ']' chars.
    419 			$element = strtr( $element, $trans );
    420 			continue;
    421 		}
    422 
    423 		$attributes = wp_kses_attr_parse( $element );
    424 		if ( false === $attributes ) {
    425 			// Some plugins are doing things like [name] <[email]>.
    426 			if ( 1 === preg_match( '%^<\s*\[\[?[^\[\]]+\]%', $element ) ) {
    427 				$element = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $element );
    428 			}
    429 
    430 			// Looks like we found some crazy unfiltered HTML. Skipping it for sanity.
    431 			$element = strtr( $element, $trans );
    432 			continue;
    433 		}
    434 
    435 		// Get element name.
    436 		$front   = array_shift( $attributes );
    437 		$back    = array_pop( $attributes );
    438 		$matches = array();
    439 		preg_match( '%[a-zA-Z0-9]+%', $front, $matches );
    440 		$elname = $matches[0];
    441 
    442 		// Look for shortcodes in each attribute separately.
    443 		foreach ( $attributes as &$attr ) {
    444 			$open  = strpos( $attr, '[' );
    445 			$close = strpos( $attr, ']' );
    446 			if ( false === $open || false === $close ) {
    447 				continue; // Go to next attribute. Square braces will be escaped at end of loop.
    448 			}
    449 			$double = strpos( $attr, '"' );
    450 			$single = strpos( $attr, "'" );
    451 			if ( ( false === $single || $open < $single ) && ( false === $double || $open < $double ) ) {
    452 				/*
    453 				 * $attr like '[shortcode]' or 'name = [shortcode]' implies unfiltered_html.
    454 				 * In this specific situation we assume KSES did not run because the input
    455 				 * was written by an administrator, so we should avoid changing the output
    456 				 * and we do not need to run KSES here.
    457 				 */
    458 				$attr = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $attr );
    459 			} else {
    460 				// $attr like 'name = "[shortcode]"' or "name = '[shortcode]'".
    461 				// We do not know if $content was unfiltered. Assume KSES ran before shortcodes.
    462 				$count    = 0;
    463 				$new_attr = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $attr, -1, $count );
    464 				if ( $count > 0 ) {
    465 					// Sanitize the shortcode output using KSES.
    466 					$new_attr = wp_kses_one_attr( $new_attr, $elname );
    467 					if ( '' !== trim( $new_attr ) ) {
    468 						// The shortcode is safe to use now.
    469 						$attr = $new_attr;
    470 					}
    471 				}
    472 			}
    473 		}
    474 		$element = $front . implode( '', $attributes ) . $back;
    475 
    476 		// Now encode any remaining '[' or ']' chars.
    477 		$element = strtr( $element, $trans );
    478 	}
    479 
    480 	$content = implode( '', $textarr );
    481 
    482 	return $content;
    483 }
    484 
    485 /**
    486  * Remove placeholders added by do_shortcodes_in_html_tags().
    487  *
    488  * @since 4.2.3
    489  *
    490  * @param string $content Content to search for placeholders.
    491  * @return string Content with placeholders removed.
    492  */
    493 function unescape_invalid_shortcodes( $content ) {
    494 	// Clean up entire string, avoids re-parsing HTML.
    495 	$trans = array(
    496 		'&#91;' => '[',
    497 		'&#93;' => ']',
    498 	);
    499 
    500 	$content = strtr( $content, $trans );
    501 
    502 	return $content;
    503 }
    504 
    505 /**
    506  * Retrieve the shortcode attributes regex.
    507  *
    508  * @since 4.4.0
    509  *
    510  * @return string The shortcode attribute regular expression
    511  */
    512 function get_shortcode_atts_regex() {
    513 	return '/([\w-]+)\s*=\s*"([^"]*)"(?:\s|$)|([\w-]+)\s*=\s*\'([^\']*)\'(?:\s|$)|([\w-]+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|\'([^\']*)\'(?:\s|$)|(\S+)(?:\s|$)/';
    514 }
    515 
    516 /**
    517  * Retrieve all attributes from the shortcodes tag.
    518  *
    519  * The attributes list has the attribute name as the key and the value of the
    520  * attribute as the value in the key/value pair. This allows for easier
    521  * retrieval of the attributes, since all attributes have to be known.
    522  *
    523  * @since 2.5.0
    524  *
    525  * @param string $text
    526  * @return array|string List of attribute values.
    527  *                      Returns empty array if '""' === trim( $text ).
    528  *                      Returns empty string if '' === trim( $text ).
    529  *                      All other matches are checked for not empty().
    530  */
    531 function shortcode_parse_atts( $text ) {
    532 	$atts    = array();
    533 	$pattern = get_shortcode_atts_regex();
    534 	$text    = preg_replace( "/[\x{00a0}\x{200b}]+/u", ' ', $text );
    535 	if ( preg_match_all( $pattern, $text, $match, PREG_SET_ORDER ) ) {
    536 		foreach ( $match as $m ) {
    537 			if ( ! empty( $m[1] ) ) {
    538 				$atts[ strtolower( $m[1] ) ] = stripcslashes( $m[2] );
    539 			} elseif ( ! empty( $m[3] ) ) {
    540 				$atts[ strtolower( $m[3] ) ] = stripcslashes( $m[4] );
    541 			} elseif ( ! empty( $m[5] ) ) {
    542 				$atts[ strtolower( $m[5] ) ] = stripcslashes( $m[6] );
    543 			} elseif ( isset( $m[7] ) && strlen( $m[7] ) ) {
    544 				$atts[] = stripcslashes( $m[7] );
    545 			} elseif ( isset( $m[8] ) && strlen( $m[8] ) ) {
    546 				$atts[] = stripcslashes( $m[8] );
    547 			} elseif ( isset( $m[9] ) ) {
    548 				$atts[] = stripcslashes( $m[9] );
    549 			}
    550 		}
    551 
    552 		// Reject any unclosed HTML elements.
    553 		foreach ( $atts as &$value ) {
    554 			if ( false !== strpos( $value, '<' ) ) {
    555 				if ( 1 !== preg_match( '/^[^<]*+(?:<[^>]*+>[^<]*+)*+$/', $value ) ) {
    556 					$value = '';
    557 				}
    558 			}
    559 		}
    560 	} else {
    561 		$atts = ltrim( $text );
    562 	}
    563 
    564 	return $atts;
    565 }
    566 
    567 /**
    568  * Combine user attributes with known attributes and fill in defaults when needed.
    569  *
    570  * The pairs should be considered to be all of the attributes which are
    571  * supported by the caller and given as a list. The returned attributes will
    572  * only contain the attributes in the $pairs list.
    573  *
    574  * If the $atts list has unsupported attributes, then they will be ignored and
    575  * removed from the final returned list.
    576  *
    577  * @since 2.5.0
    578  *
    579  * @param array  $pairs     Entire list of supported attributes and their defaults.
    580  * @param array  $atts      User defined attributes in shortcode tag.
    581  * @param string $shortcode Optional. The name of the shortcode, provided for context to enable filtering
    582  * @return array Combined and filtered attribute list.
    583  */
    584 function shortcode_atts( $pairs, $atts, $shortcode = '' ) {
    585 	$atts = (array) $atts;
    586 	$out  = array();
    587 	foreach ( $pairs as $name => $default ) {
    588 		if ( array_key_exists( $name, $atts ) ) {
    589 			$out[ $name ] = $atts[ $name ];
    590 		} else {
    591 			$out[ $name ] = $default;
    592 		}
    593 	}
    594 
    595 	if ( $shortcode ) {
    596 		/**
    597 		 * Filters shortcode attributes.
    598 		 *
    599 		 * If the third parameter of the shortcode_atts() function is present then this filter is available.
    600 		 * The third parameter, $shortcode, is the name of the shortcode.
    601 		 *
    602 		 * @since 3.6.0
    603 		 * @since 4.4.0 Added the `$shortcode` parameter.
    604 		 *
    605 		 * @param array  $out       The output array of shortcode attributes.
    606 		 * @param array  $pairs     The supported attributes and their defaults.
    607 		 * @param array  $atts      The user defined shortcode attributes.
    608 		 * @param string $shortcode The shortcode name.
    609 		 */
    610 		$out = apply_filters( "shortcode_atts_{$shortcode}", $out, $pairs, $atts, $shortcode );
    611 	}
    612 
    613 	return $out;
    614 }
    615 
    616 /**
    617  * Remove all shortcode tags from the given content.
    618  *
    619  * @since 2.5.0
    620  *
    621  * @global array $shortcode_tags
    622  *
    623  * @param string $content Content to remove shortcode tags.
    624  * @return string Content without shortcode tags.
    625  */
    626 function strip_shortcodes( $content ) {
    627 	global $shortcode_tags;
    628 
    629 	if ( false === strpos( $content, '[' ) ) {
    630 		return $content;
    631 	}
    632 
    633 	if ( empty( $shortcode_tags ) || ! is_array( $shortcode_tags ) ) {
    634 		return $content;
    635 	}
    636 
    637 	// Find all registered tag names in $content.
    638 	preg_match_all( '@\[([^<>&/\[\]\x00-\x20=]++)@', $content, $matches );
    639 
    640 	$tags_to_remove = array_keys( $shortcode_tags );
    641 
    642 	/**
    643 	 * Filters the list of shortcode tags to remove from the content.
    644 	 *
    645 	 * @since 4.7.0
    646 	 *
    647 	 * @param array  $tags_to_remove Array of shortcode tags to remove.
    648 	 * @param string $content        Content shortcodes are being removed from.
    649 	 */
    650 	$tags_to_remove = apply_filters( 'strip_shortcodes_tagnames', $tags_to_remove, $content );
    651 
    652 	$tagnames = array_intersect( $tags_to_remove, $matches[1] );
    653 
    654 	if ( empty( $tagnames ) ) {
    655 		return $content;
    656 	}
    657 
    658 	$content = do_shortcodes_in_html_tags( $content, true, $tagnames );
    659 
    660 	$pattern = get_shortcode_regex( $tagnames );
    661 	$content = preg_replace_callback( "/$pattern/", 'strip_shortcode_tag', $content );
    662 
    663 	// Always restore square braces so we don't break things like <!--[if IE ]>.
    664 	$content = unescape_invalid_shortcodes( $content );
    665 
    666 	return $content;
    667 }
    668 
    669 /**
    670  * Strips a shortcode tag based on RegEx matches against post content.
    671  *
    672  * @since 3.3.0
    673  *
    674  * @param array $m RegEx matches against post content.
    675  * @return string|false The content stripped of the tag, otherwise false.
    676  */
    677 function strip_shortcode_tag( $m ) {
    678 	// Allow [[foo]] syntax for escaping a tag.
    679 	if ( '[' === $m[1] && ']' === $m[6] ) {
    680 		return substr( $m[0], 1, -1 );
    681 	}
    682 
    683 	return $m[1] . $m[6];
    684 }