do_shortcodes_in_html_tags() – Searches only inside HTML elements for shortcodes and process them.

You appear to be a bot. Output may be restricted

Description

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.

Usage

$string = do_shortcodes_in_html_tags( $content, $ignore_html, $tagnames );

Parameters

$content
( string ) required – Content to search for shortcodes.
$ignore_html
( bool ) required – When true, all square braces inside elements will be encoded.
$tagnames
( array ) required – List of shortcodes to find.

Returns

string Content with shortcodes filtered out.

Source

File name: wordpress/wp-includes/shortcodes.php
Lines:

1 to 100 of 100
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 crazy unfiltered HTML. Skipping it for sanity.
      $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;
}
 

 View on GitHub View on Trac