Shortcode handler for [media].

@param array $atts Shortcode attributes.
@param string $content Shortcode content.
@param string $shortcode Shortcode name.

@return string
512245
public function mediaShortCodeHandler( $atts, $content, $shortcode ) {
		global $wp_embed;
		$atts = shortcode_atts(
			[
				'caption' => null,
				'src' => null,
			], $atts
		);
		$src = $atts['src'] ?? $content;
		if ( str_starts_with( $src, '“' ) || str_starts_with( $src, '”' ) || str_starts_with( $src, '‘' ) || str_starts_with( $src, '’' ) ) {
			$src = trim( $src, '“”‘’' ); // Trim fancy quotes, for MS-Word compatibility
		}
		$src = esc_url_raw( $src );
		if ( ! filter_var( $src, FILTER_VALIDATE_URL ) ) {
			return '';
		}
		// Can't use `do_shortcode_by_tags` because the default callback for 'embed' is `__return_false` - @see \WP_Embed::__construct
		$e = $wp_embed->run_shortcode( sprintf( '[embed src="%s"]', $src ) );
		if ( $atts['caption'] ) {
			return sprintf(
				'<figure class="embed">%1$s<figcaption>%2$s</figcaption></figure>',
				str_replace( [ '<p>', '</p>' ], '', $e ),
				$atts['caption']
			);
		} else {
			return $e;
		}
	}
14705
public function webShortcodeHandler( $atts, $content ) {

		global $id; // This is the Post ID, [@see WP_Query::setup_postdata, ...]

		$a = shortcode_atts(
			[
				'id' => '',
				'type' => '',
			], $atts
		);

		if ( ! empty( $content ) ) {
			// This is a tooltip
			if ( $a['id'] ) {
				if ( ! isset( $this->glossaryTerms[ $id ] ) ) {
					$this->glossaryTerms[ $id ] = [];
				}

				if ( ! isset( $this->glossaryTerms[ $id ][ $a['id'] ] ) ) {
					$this->glossaryTerms[ $id ][ $a['id'] ] = get_post_field( 'post_content', $a['id'] );
				}
				return $this->glossaryTooltip( $a['id'], $content );
			}
		} else {
			// This is a list of glossary terms
			return $this->glossaryTerms( $a['type'] );
		}

		return $content;
	}
890145
public static function unicodeToShortcode($content)
    {
        $replacement = '';
        $encoding = mb_detect_encoding($content);
        $codepoints = array_flip(self::getShortcodes());

        /* Break content along codepoint boundaries */
        $parts = preg_split(
            self::MB_REGEX,
            $content,
            -1,
            PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
        );

        /* Reconstruct content using shortcodes */
        $sequence = [];
        foreach ($parts as $offset => $part) {
            if (preg_match(self::MB_REGEX, $part)) {
                $part = mb_convert_encoding($part, 'UTF-32', $encoding);
                $words = unpack('N*', $part);
                $codepoint = sprintf('%X', reset($words));

                $sequence[] = $codepoint;

                if (isset($codepoints[$codepoint])) {
                    $replacement .= ":$codepoints[$codepoint]:";
                    $sequence = [];
                } else {
                    /* Check multi-codepoint sequence */
                    $multi = implode('-', $sequence);

                    if (isset($codepoints[$multi])) {
                        $replacement .= ":$codepoints[$multi]:";
                        $sequence = [];
                    }
                }
            } else {
                $replacement .= $part;
            }
        }

        return $replacement;
    }
809475
public static function stripTagsAndAtts($content, $allowedTags = '', $allowedAtts = '')
    {
        if (isset($allowedTags) && is_array($allowedTags)) {
            $content = strip_tags($content, implode($allowedTags));
        } else {
            $content = strip_tags($content);
        }

        //Strip attributes
        $atts = \Municipio\Helper\Html::getHtmlAttributes($content);

        if ($atts && !empty($atts)) {
            if (isset($allowedAtts) && is_array($allowedAtts)) {
                foreach ($allowedAtts as $attribute) {
                    unset($atts[$attribute]);
                }
            }

            foreach ($atts as $att) {
                $content = str_replace($att, "", $content);
            }
        }

        return $content;
    }
1319025
public function doShortcode(string $content, $tags = [], bool $deep = false): string
    {
        $tags = $this->preProcessTags($tags);
        $handler = function (string $tag, ?string $content = null, array $atts = []) {
            $shortcode = $this[$tag];

            if ($shortcode instanceof AttributeInterface) {
                $atts = array_merge($shortcode->getAttributes(), $atts);

                return $shortcode->handle($content, $atts);
            }

            return $shortcode->handle($content);
        };

        $result = (string) $this->parser->parseShortcode($content, $tags, $handler);

        if ($deep && $this->hasShortcode($result, $tags)) {
            return $this->doShortcode($result, $tags, $deep);
        }

        return $result;
    }
70459
public function hasShortcode($content, $tag)
    {
        if (false === strpos($content, '[')) {
            return false;
        }

        if ($this->existsShortcode($tag)) {
            return true;
        }

        preg_match_all($this->shortcodeRegex(), $content, $matches, PREG_SET_ORDER);

        if (empty($matches)) {
            return false;
        }

        foreach ($matches as $shortcode) {
            if ($tag === $shortcode[2]) {
                return true;
            }
        }

        return false;
    }
1198366
public static function ol(
        string $content = null, 
        array $attributes = []
    ) : string
    {
        return self::tag("ol", $content, $attributes);
    }
89507
public function parse($content)
    {
        $this->extend('onBeforeParse', $content);

        $continue = true;

        // If no shortcodes defined, don't try and parse any
        if (!$this->shortcodes) {
            $continue = false;
        } elseif (!trim($content)) {
            // If no content, don't try and parse it
            $continue = false;
        } elseif (strpos($content, '[') === false) {
            // If no shortcode tag, don't try and parse it
            $continue = false;
        }

        if ($continue) {
            // First we operate in text mode, replacing any shortcodes with marker elements so that later we can
            // use a proper DOM
            list($content, $tags) = $this->replaceElementTagsWithMarkers($content);

        /** @var HTMLValue $htmlvalue */
            $htmlvalue = Injector::inst()->create('HTMLValue', $content);

            // Now parse the result into a DOM
            if (!$htmlvalue->isValid()) {
                if (self::$error_behavior == self::ERROR) {
                    user_error('Couldn\'t decode HTML when processing short codes', E_USER_ERROR);
                } else {
                    $continue = false;
                }
            }
        }

        if ($continue) {
            // First, replace any shortcodes that are in attributes
            $this->replaceAttributeTagsWithContent($htmlvalue);

            // Find all the element scoped shortcode markers
            $shortcodes = $htmlvalue->query('//img[@class="' . self::$marker_class . '"]');

            // Find the parents. Do this before DOM modification, since SPLIT might cause parents to move otherwise
            $parents = $this->findParentsForMarkers($shortcodes);

        /** @var DOMElement $shortcode */
            foreach ($shortcodes as $shortcode) {
                $tag = $tags[$shortcode->getAttribute('data-tagid')];
                $parent = $parents[$shortcode->getAttribute('data-parentid')];

                $class = null;
                if (!empty($tag['attrs']['location'])) {
                    $class = $tag['attrs']['location'];
                } elseif (!empty($tag['attrs']['class'])) {
                    $class = $tag['attrs']['class'];
                }

                $location = self::INLINE;
                if ($class == 'left' || $class == 'right') {
                    $location = self::BEFORE;
                }
                /**
                 * Below code disabled due to https://github.com/silverstripe/silverstripe-framework/issues/5987
                if ($class == 'center' || $class == 'leftAlone') {
                    $location = self::SPLIT;
                }
                 */

                if (!$parent) {
                    if ($location !== self::INLINE) {
                        user_error(
                            "Parent block for shortcode couldn't be found, but location wasn't INLINE",
                            E_USER_ERROR
                        );
                    }
                } else {
                    $this->moveMarkerToCompliantHome($shortcode, $parent, $location);
                }

                $this->replaceMarkerWithContent($shortcode, $tag);
            }

            $content = $htmlvalue->getContent();

            // Clean up any marker classes left over, for example, those injected into <script> tags
            $parser = $this;
            $content = preg_replace_callback(
                // Not a general-case parser; assumes that the HTML generated in replaceElementTagsWithMarkers()
                // hasn't been heavily modified
                '/<img[^>]+class="' . preg_quote(self::$marker_class) . '"[^>]+data-tagid="([^"]+)"[^>]*>/i',
                function ($matches) use ($tags, $parser) {
                    $tag = $tags[$matches[1]];
                    return $parser->getShortcodeReplacementText($tag);
                },
                $content
            );
        }

        $this->extend('onAfterParse', $content);

        return $content;
    }
1032035
public function strip($content)
    {
        $handlers = new HandlerContainer();
        $handlers->setDefault(function(ShortcodeInterface $s) { return $s->getContent(); });
        $processor = new Processor(new RegexParser(), $handlers);

        return $processor->process($content);
    }
715568
public static function shortcodeToEntities($content) {
        $replacements = self::getShortcodeEntities();
        return str_replace(array_keys($replacements), $replacements, $content);
    }
582807
function shortcodeHandler( $atts, $content = '' ) {

		global $id; // This is the Post ID, [@see WP_Query::setup_postdata, ...]

		$a = shortcode_atts(
			[
				'numbered' => 'yes',
				'symbol' => '*',
				'suptext' => ' ',
			], $atts
		);

		if ( ! $content ) {
			return '';
		}

		if ( ! isset( $this->footnotes[ $id ] ) ) {
			$this->footnotes[ $id ] = [];
			if ( 'no' === $a['numbered'] ) {
				$this->numbered[ $id ] = false;
			} else {
				$this->numbered[ $id ] = true;
			}
		}

		$this->footnotes[ $id ][] = $content;
		$footnotes = $this->footnotes[ $id ];
		$num = count( $footnotes );
		$numlabel = "$id-$num";

		$retval = '<a class="footnote" title="' . \Pressbooks\Sanitize\sanitize_xml_attribute( wp_strip_all_tags( $content ) ) . '" id="return-footnote-' . $numlabel . '" href="#footnote-' . $numlabel . '"><sup class="footnote">[';

		if ( $this->numbered[ $id ] ) {
			$retval .= $num;
		} else {
			$retval .= $a['symbol'];
		}

		if ( trim( $a['suptext'] ) ) {
			if ( $this->numbered[ $id ] ) {
				$retval .= '. ';
			}

			$retval .= $a['suptext'];
		}
		$retval .= ']</sup></a>';

		return $retval;
	}
789142
public function tag($tag, $content, array $attributes = [])
    {
        return $this->htmlBuilder->tag($tag, $content, $attributes);
    }
1009426
protected function _renderTag($attribs = array(), $content = null)
    {
        unset($attribs['content']);
        unset($attribs['separator']);

        $attribs = $this->buildAttributes($attribs);

        if($this->getConfig()->escape) {
            $content = $this->getTemplate()->escape($content);
        }

        $html = '<title '.$attribs.'>'.$content.'</title>'."\n";
        return $html;
    }
781367
public static function td(
        string $content = null, 
        array $attributes = []
    ) : string
    {
        return self::tag("td", $content, $attributes);
    }
911806
public function parseShortcode(string $content, array $tags, Closure $callback = null)
    {
        if (strpos($content, '[') === false && empty($tags)) {
            return is_null($callback) ? [] : $content;
        }

        $regex = $this->getRegex($tags);

        preg_match_all("/$regex/", $content, $matches, PREG_SET_ORDER);

        if (is_null($callback)) {
            return iterator_to_array($this->generateResults($matches));
        }

        return preg_replace_callback("/$regex/", $this->generateCallback($callback), $content);
    }
670619
public static function shortcodeToUnicode($content)
    {
        $replacements = self::getShortcodeCodepoints();
        return str_replace(array_keys($replacements), $replacements, $content);
    }
1051268
protected function parseContent($content)
    {
        $content = preg_replace_callback($this->shortcodeRegex(), [$this, 'doShortcodeTag'], $content);
        if (!$this->isFinishedParse()) {
            $content = $this->parseContent($content);
        }
        return $content;
    }