wpseek.com
A WordPress-centric search engine for devs and theme authors



do_shortcodes_in_html_tags › WordPress Function

Since4.2.3
Deprecatedn/a
do_shortcodes_in_html_tags ( $content, $ignore_html, $tagnames )
Parameters: (3)
  • (string) $content Content to search for shortcodes.
    Required: Yes
  • (bool) $ignore_html When true, all square braces inside elements will be encoded.
    Required: Yes
  • (array) $tagnames List of shortcodes to find.
    Required: Yes
Returns:
  • (string) Content with shortcodes filtered out.
Defined at:
Codex:

Searches only inside HTML elements for shortcodes and process them.

Any [ or ] characters remaining inside elements will be HTML encoded to prevent interference with shortcodes that are outside the elements. Assumes $content processed by KSES already. Users with unfiltered_html capability may get unexpected output if angle braces are nested in tags.


Source

function do_shortcodes_in_html_tags( $content, $ignore_html, $tagnames ) {
	// Normalize entities in unfiltered HTML before adding placeholders.
	$trans   = array(
		'[' => '[',
		']' => ']',
	);
	$content = strtr( $content, $trans );
	$trans   = array(
		'[' => '[',
		']' => ']',
	);

	$pattern = get_shortcode_regex( $tagnames );
	$textarr = wp_html_split( $content );

	foreach ( $textarr as &$element ) {
		if ( '' === $element || '<' !== $element[0] ) {
			continue;
		}

		$noopen  = ! str_contains( $element, '[' );
		$noclose = ! str_contains( $element, ']' );
		if ( $noopen || $noclose ) {
			// This element does not contain shortcodes.
			if ( $noopen xor $noclose ) {
				// Need to encode stray '[' or ']' chars.
				$element = strtr( $element, $trans );
			}
			continue;
		}

		if ( $ignore_html || str_starts_with( $element, '<!--' ) || str_starts_with( $element, '<![CDATA[' ) ) {
			// Encode all '[' and ']' chars.
			$element = strtr( $element, $trans );
			continue;
		}

		$attributes = wp_kses_attr_parse( $element );
		if ( false === $attributes ) {
			// Some plugins are doing things like [name] <[email]>.
			if ( 1 === preg_match( '%^<\s*\[\[?[^\[\]]+\]%', $element ) ) {
				$element = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $element );
			}

			// Looks like we found some unexpected unfiltered HTML. Skipping it for confidence.
			$element = strtr( $element, $trans );
			continue;
		}

		// Get element name.
		$front   = array_shift( $attributes );
		$back    = array_pop( $attributes );
		$matches = array();
		preg_match( '%[a-zA-Z0-9]+%', $front, $matches );
		$elname = $matches[0];

		// Look for shortcodes in each attribute separately.
		foreach ( $attributes as &$attr ) {
			$open  = strpos( $attr, '[' );
			$close = strpos( $attr, ']' );
			if ( false === $open || false === $close ) {
				continue; // Go to next attribute. Square braces will be escaped at end of loop.
			}
			$double = strpos( $attr, '"' );
			$single = strpos( $attr, "'" );
			if ( ( false === $single || $open < $single ) && ( false === $double || $open < $double ) ) {
				/*
				 * $attr like '[shortcode]' or 'name = [shortcode]' implies unfiltered_html.
				 * In this specific situation we assume KSES did not run because the input
				 * was written by an administrator, so we should avoid changing the output
				 * and we do not need to run KSES here.
				 */
				$attr = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $attr );
			} else {
				/*
				 * $attr like 'name = "[shortcode]"' or "name = '[shortcode]'".
				 * We do not know if $content was unfiltered. Assume KSES ran before shortcodes.
				 */
				$count    = 0;
				$new_attr = preg_replace_callback( "/$pattern/", 'do_shortcode_tag', $attr, -1, $count );
				if ( $count > 0 ) {
					// Sanitize the shortcode output using KSES.
					$new_attr = wp_kses_one_attr( $new_attr, $elname );
					if ( '' !== trim( $new_attr ) ) {
						// The shortcode is safe to use now.
						$attr = $new_attr;
					}
				}
			}
		}
		$element = $front . implode( '', $attributes ) . $back;

		// Now encode any remaining '[' or ']' chars.
		$element = strtr( $element, $trans );
	}

	$content = implode( '', $textarr );

	return $content;
}