src/View/Parsers/ShortcodeParser.php
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;
    }
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;
    }
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 ; }
Parse a string, and replace any registered shortcodes within it with the result of the mapped callback.

@param string $content
@return string
Parse a string and replace any registered shortcodes within it with the result of the mapped callback .