xref: /template/strap/ComboStrap/Call.php (revision 040d4aea0d11c3b622e8211f0048a4982159d6e2)
137748cd8SNickeau<?php
237748cd8SNickeau/**
337748cd8SNickeau * Copyright (c) 2021. ComboStrap, Inc. and its affiliates. All Rights Reserved.
437748cd8SNickeau *
537748cd8SNickeau * This source code is licensed under the GPL license found in the
637748cd8SNickeau * COPYING  file in the root directory of this source tree.
737748cd8SNickeau *
837748cd8SNickeau * @license  GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html)
937748cd8SNickeau * @author   ComboStrap <support@combostrap.com>
1037748cd8SNickeau *
1137748cd8SNickeau */
1237748cd8SNickeau
1337748cd8SNickeaunamespace ComboStrap;
1437748cd8SNickeau
1537748cd8SNickeauuse dokuwiki\Extension\SyntaxPlugin;
161fa8c418SNickeauuse syntax_plugin_combo_media;
1737748cd8SNickeau
1837748cd8SNickeau
1937748cd8SNickeau/**
2037748cd8SNickeau * Class Call
2137748cd8SNickeau * @package ComboStrap
2237748cd8SNickeau *
2337748cd8SNickeau * A wrapper around what's called a call
2437748cd8SNickeau * which is an array of information such
2537748cd8SNickeau * the mode, the data
2637748cd8SNickeau *
2737748cd8SNickeau * The {@link CallStack} is the only syntax representation that
2837748cd8SNickeau * is available in DokuWiki
2937748cd8SNickeau */
3037748cd8SNickeauclass Call
3137748cd8SNickeau{
3237748cd8SNickeau
3337748cd8SNickeau    const INLINE_DISPLAY = "inline";
3437748cd8SNickeau    const BlOCK_DISPLAY = "block";
3537748cd8SNickeau    /**
3637748cd8SNickeau     * List of inline components
3737748cd8SNickeau     * Used to manage white space before an unmatched string.
3837748cd8SNickeau     * The syntax tree of Dokuwiki (ie {@link \Doku_Handler::$calls})
3937748cd8SNickeau     * has only data and no class, for now, we create this
4037748cd8SNickeau     * lists manually because this is a hassle to retrieve this information from {@link \DokuWiki_Syntax_Plugin::getType()}
4137748cd8SNickeau     */
4237748cd8SNickeau    const INLINE_DOKUWIKI_COMPONENTS = array(
4337748cd8SNickeau        /**
4437748cd8SNickeau         * Formatting https://www.dokuwiki.org/devel:syntax_plugins#syntax_types
4537748cd8SNickeau         * Comes from the {@link \dokuwiki\Parsing\ParserMode\Formatting} class
4637748cd8SNickeau         */
4737748cd8SNickeau        "cdata",
4837748cd8SNickeau        "unformatted", // ie %% or nowiki
4937748cd8SNickeau        "doublequoteclosing", // https://www.dokuwiki.org/config:typography / https://www.dokuwiki.org/wiki:syntax#text_to_html_conversions
5037748cd8SNickeau        "doublequoteopening",
5137748cd8SNickeau        "singlequoteopening",
5237748cd8SNickeau        "singlequoteclosing",
5304fd306cSNickeau        "quote_open",
5404fd306cSNickeau        "quote_close",
5504fd306cSNickeau        "interwikilink",
5637748cd8SNickeau        "multiplyentity",
5737748cd8SNickeau        "apostrophe",
5804fd306cSNickeau        "deleted_open",
5904fd306cSNickeau        "deleted_close",
6004fd306cSNickeau        "emaillink",
6137748cd8SNickeau        "strong",
6237748cd8SNickeau        "emphasis",
6337748cd8SNickeau        "emphasis_open",
6437748cd8SNickeau        "emphasis_close",
6537748cd8SNickeau        "underline",
66e4026cd1Sgerardnico        "underline_close",
6704fd306cSNickeau        "underline_open",
6837748cd8SNickeau        "monospace",
6937748cd8SNickeau        "subscript",
7004fd306cSNickeau        "subscript_open",
7104fd306cSNickeau        "subscript_close",
7204fd306cSNickeau        "superscript_open",
7304fd306cSNickeau        "superscript_close",
7437748cd8SNickeau        "superscript",
7537748cd8SNickeau        "deleted",
7637748cd8SNickeau        "footnote",
7737748cd8SNickeau        /**
7837748cd8SNickeau         * Others
7937748cd8SNickeau         */
801fa8c418SNickeau        "acronym", // abbr
8137748cd8SNickeau        "strong_close",
8237748cd8SNickeau        "strong_open",
8337748cd8SNickeau        "monospace_open",
8437748cd8SNickeau        "monospace_close",
8537748cd8SNickeau        "doublequoteopening", // ie the character " in "The"
8637748cd8SNickeau        "entity", // for instance `...` are transformed in character
8737748cd8SNickeau        "linebreak",
8837748cd8SNickeau        "externallink",
8937748cd8SNickeau        "internallink",
9004fd306cSNickeau        "smiley",
9104fd306cSNickeau        MediaMarkup::INTERNAL_MEDIA_CALL_NAME,
9204fd306cSNickeau        MediaMarkup::EXTERNAL_MEDIA_CALL_NAME,
9337748cd8SNickeau        /**
9437748cd8SNickeau         * The inline of combo
9537748cd8SNickeau         */
9637748cd8SNickeau        \syntax_plugin_combo_link::TAG,
9704fd306cSNickeau        IconTag::TAG,
9804fd306cSNickeau        NoteTag::TAG_INOTE,
9904fd306cSNickeau        ButtonTag::MARKUP_LONG,
10037748cd8SNickeau        \syntax_plugin_combo_tooltip::TAG,
10104fd306cSNickeau        PipelineTag::TAG,
10204fd306cSNickeau        BreadcrumbTag::MARKUP_BLOCK, // only the typo is inline but yeah
10337748cd8SNickeau    );
10437748cd8SNickeau
10537748cd8SNickeau
10637748cd8SNickeau    const BLOCK_MARKUP_DOKUWIKI_COMPONENTS = array(
10737748cd8SNickeau        "listu_open", // ul
10837748cd8SNickeau        "listu_close",
10904fd306cSNickeau        "listo_open",
11004fd306cSNickeau        "listo_close",
11137748cd8SNickeau        "listitem_open", //li
11237748cd8SNickeau        "listitem_close",
11337748cd8SNickeau        "listcontent_open", // after li ???
11437748cd8SNickeau        "listcontent_close",
11537748cd8SNickeau        "table_open",
11637748cd8SNickeau        "table_close",
11704fd306cSNickeau        "p_open",
11804fd306cSNickeau        "p_close",
11904fd306cSNickeau        "nest", // seen as enclosing footnotes
12004fd306cSNickeau        "hr",
12104fd306cSNickeau        "rss"
12204fd306cSNickeau    );
12304fd306cSNickeau
12404fd306cSNickeau    /**
12504fd306cSNickeau     * Not inline, not block
12604fd306cSNickeau     */
12704fd306cSNickeau    const TABLE_MARKUP = array(
12804fd306cSNickeau        "tablethead_open",
12904fd306cSNickeau        "tablethead_close",
13004fd306cSNickeau        "tableheader_open",
13104fd306cSNickeau        "tableheader_close",
13204fd306cSNickeau        "tablerow_open",
13304fd306cSNickeau        "tablerow_close",
13404fd306cSNickeau        "tablecell_open",
13504fd306cSNickeau        "tablecell_close"
13637748cd8SNickeau    );
13737748cd8SNickeau
1381fa8c418SNickeau    /**
1391fa8c418SNickeau     * A media is not really an image
1401fa8c418SNickeau     * but it may contains one
1411fa8c418SNickeau     */
1421fa8c418SNickeau    const IMAGE_TAGS = [
1431fa8c418SNickeau        syntax_plugin_combo_media::TAG,
14404fd306cSNickeau        PageImageTag::MARKUP
1451fa8c418SNickeau    ];
1464cadd4f8SNickeau    const CANONICAL = "call";
14704fd306cSNickeau    const TABLE_DISPLAY = "table-display";
1481fa8c418SNickeau
14937748cd8SNickeau    private $call;
15037748cd8SNickeau
15137748cd8SNickeau    /**
15237748cd8SNickeau     * The key identifier in the {@link CallStack}
15337748cd8SNickeau     * @var mixed|string
15437748cd8SNickeau     */
15537748cd8SNickeau    private $key;
15637748cd8SNickeau
15737748cd8SNickeau    /**
15837748cd8SNickeau     * Call constructor.
15937748cd8SNickeau     * @param $call - the instruction array (ie called a call)
16037748cd8SNickeau     */
16137748cd8SNickeau    public function __construct(&$call, $key = "")
16237748cd8SNickeau    {
16337748cd8SNickeau        $this->call = &$call;
16437748cd8SNickeau        $this->key = $key;
16537748cd8SNickeau    }
16637748cd8SNickeau
16737748cd8SNickeau    /**
16837748cd8SNickeau     * Insert a tag above
16937748cd8SNickeau     * @param $tagName
17037748cd8SNickeau     * @param $state
17104fd306cSNickeau     * @param $syntaxComponentName - the name of the dokuwiki syntax component (ie plugin_name)
172c3437056SNickeau     * @param array $attribute
1734cadd4f8SNickeau     * @param string|null $rawContext
1744cadd4f8SNickeau     * @param string|null $content - the parsed content
175c3437056SNickeau     * @param string|null $payload - the payload after handler
176c3437056SNickeau     * @param int|null $position
17737748cd8SNickeau     * @return Call - a call
17837748cd8SNickeau     */
17904fd306cSNickeau    public static function createComboCall($tagName, $state, array $attribute = array(), string $rawContext = null, string $content = null, string $payload = null, int $position = null, string $syntaxComponentName = null): Call
18037748cd8SNickeau    {
18137748cd8SNickeau        $data = array(
18237748cd8SNickeau            PluginUtility::ATTRIBUTES => $attribute,
1834cadd4f8SNickeau            PluginUtility::CONTEXT => $rawContext,
184c3437056SNickeau            PluginUtility::STATE => $state,
18504fd306cSNickeau            PluginUtility::TAG => $tagName,
186c3437056SNickeau            PluginUtility::POSITION => $position
18737748cd8SNickeau        );
18804fd306cSNickeau        if ($payload !== null) {
18937748cd8SNickeau            $data[PluginUtility::PAYLOAD] = $payload;
19037748cd8SNickeau        }
191c3437056SNickeau        $positionInText = $position;
19237748cd8SNickeau
19304fd306cSNickeau        if ($syntaxComponentName !== null) {
19404fd306cSNickeau            $componentName = PluginUtility::getComponentName($syntaxComponentName);
19504fd306cSNickeau        } else {
19604fd306cSNickeau            $componentName = PluginUtility::getComponentName($tagName);
19704fd306cSNickeau        }
19804fd306cSNickeau        $obj = plugin_load('syntax', $componentName);
19904fd306cSNickeau        if ($obj === null) {
20004fd306cSNickeau            throw new ExceptionRuntimeInternal("The component tag ($componentName) does not exists");
20104fd306cSNickeau        }
20204fd306cSNickeau
20337748cd8SNickeau        $call = [
20437748cd8SNickeau            "plugin",
20537748cd8SNickeau            array(
20604fd306cSNickeau                $componentName,
20737748cd8SNickeau                $data,
20837748cd8SNickeau                $state,
20937748cd8SNickeau                $content
21037748cd8SNickeau            ),
21137748cd8SNickeau            $positionInText
21237748cd8SNickeau        ];
21337748cd8SNickeau        return new Call($call);
21437748cd8SNickeau    }
21537748cd8SNickeau
21637748cd8SNickeau    /**
21737748cd8SNickeau     * Insert a dokuwiki call
21837748cd8SNickeau     * @param $callName
21937748cd8SNickeau     * @param $array
22037748cd8SNickeau     * @param $positionInText
22137748cd8SNickeau     * @return Call
22237748cd8SNickeau     */
2234cadd4f8SNickeau    public static function createNativeCall($callName, $array = [], $positionInText = null): Call
22437748cd8SNickeau    {
22537748cd8SNickeau        $call = [
22637748cd8SNickeau            $callName,
22737748cd8SNickeau            $array,
22837748cd8SNickeau            $positionInText
22937748cd8SNickeau        ];
23037748cd8SNickeau        return new Call($call);
23137748cd8SNickeau    }
23237748cd8SNickeau
23304fd306cSNickeau    public static function createFromInstruction($instruction): Call
23437748cd8SNickeau    {
23537748cd8SNickeau        return new Call($instruction);
23637748cd8SNickeau    }
23737748cd8SNickeau
2384cadd4f8SNickeau    /**
2394cadd4f8SNickeau     * @param Call $call
2404cadd4f8SNickeau     * @return Call
2414cadd4f8SNickeau     */
2424cadd4f8SNickeau    public static function createFromCall(Call $call): Call
2434cadd4f8SNickeau    {
2444cadd4f8SNickeau        return self::createFromInstruction($call->toCallArray());
2454cadd4f8SNickeau    }
2464cadd4f8SNickeau
24737748cd8SNickeau
24837748cd8SNickeau    /**
24937748cd8SNickeau     *
25037748cd8SNickeau     * Return the tag name from a call array
25137748cd8SNickeau     *
25237748cd8SNickeau     * This is not the logical tag.
25337748cd8SNickeau     * This is much more what's called:
25437748cd8SNickeau     *   * the component name for a plugin
25537748cd8SNickeau     *   * or the handler name for dokuwiki
25637748cd8SNickeau     *
25737748cd8SNickeau     * For a plugin, this is equivalent
25837748cd8SNickeau     * to the {@link SyntaxPlugin::getPluginComponent()}
25937748cd8SNickeau     *
26037748cd8SNickeau     * This is not the fully qualified component name:
26137748cd8SNickeau     *   * with the plugin as prefix such as in {@link Call::getComponentName()}
26237748cd8SNickeau     *   * or with the `open` and `close` prefix such as `p_close` ...
26337748cd8SNickeau     *
26437748cd8SNickeau     * @return mixed|string
26537748cd8SNickeau     */
26637748cd8SNickeau    public function getTagName()
26737748cd8SNickeau    {
26804fd306cSNickeau
26937748cd8SNickeau        $mode = $this->call[0];
27037748cd8SNickeau        if ($mode != "plugin") {
27137748cd8SNickeau
27237748cd8SNickeau            /**
27337748cd8SNickeau             * This is a standard dokuwiki node
27437748cd8SNickeau             */
27537748cd8SNickeau            $dokuWikiNodeName = $this->call[0];
27637748cd8SNickeau
27737748cd8SNickeau            /**
27837748cd8SNickeau             * The dokwuiki node name has also the open and close notion
27937748cd8SNickeau             * We delete this is not in the doc and therefore not logical
28037748cd8SNickeau             */
28137748cd8SNickeau            $tagName = str_replace("_close", "", $dokuWikiNodeName);
28204fd306cSNickeau            return str_replace("_open", "", $tagName);
28304fd306cSNickeau        }
28437748cd8SNickeau
28537748cd8SNickeau        /**
28637748cd8SNickeau         * This is a plugin node
28737748cd8SNickeau         */
28837748cd8SNickeau        $pluginDokuData = $this->call[1];
28904fd306cSNickeau
29004fd306cSNickeau        /**
29104fd306cSNickeau         * If the tag is set
29204fd306cSNickeau         */
29304fd306cSNickeau        $pluginData = $pluginDokuData[1];
29404fd306cSNickeau        if (isset($pluginData[PluginUtility::TAG])) {
29504fd306cSNickeau            return $pluginData[PluginUtility::TAG];
29604fd306cSNickeau        }
29704fd306cSNickeau
29837748cd8SNickeau        $component = $pluginDokuData[0];
29937748cd8SNickeau        if (!is_array($component)) {
30037748cd8SNickeau            /**
30137748cd8SNickeau             * Tag name from class
30237748cd8SNickeau             */
30337748cd8SNickeau            $componentNames = explode("_", $component);
30437748cd8SNickeau            /**
30537748cd8SNickeau             * To take care of
30637748cd8SNickeau             * PHP Warning:  sizeof(): Parameter must be an array or an object that implements Countable
30737748cd8SNickeau             * in lib/plugins/combo/class/Tag.php on line 314
30837748cd8SNickeau             */
30937748cd8SNickeau            if (is_array($componentNames)) {
31037748cd8SNickeau                $tagName = $componentNames[sizeof($componentNames) - 1];
31137748cd8SNickeau            } else {
31237748cd8SNickeau                $tagName = $component;
31337748cd8SNickeau            }
31437748cd8SNickeau            return $tagName;
31504fd306cSNickeau        }
31604fd306cSNickeau
31704fd306cSNickeau        // To resolve: explode() expects parameter 2 to be string, array given
31804fd306cSNickeau        LogUtility::msg("The call (" . print_r($this->call, true) . ") has an array and not a string as component (" . print_r($component, true) . "). Page: " . MarkupPath::createFromRequestedPage(), LogUtility::LVL_MSG_ERROR);
31904fd306cSNickeau        return "";
32004fd306cSNickeau
32137748cd8SNickeau
32237748cd8SNickeau    }
32337748cd8SNickeau
32437748cd8SNickeau
32537748cd8SNickeau    /**
32637748cd8SNickeau     * The parser state
32737748cd8SNickeau     * @return mixed
32837748cd8SNickeau     * May be null (example eol, internallink, ...)
32937748cd8SNickeau     */
33004fd306cSNickeau    public
33104fd306cSNickeau    function getState()
33237748cd8SNickeau    {
33337748cd8SNickeau        $mode = $this->call[0];
3344cadd4f8SNickeau        if ($mode !== "plugin") {
33537748cd8SNickeau
33637748cd8SNickeau            /**
33737748cd8SNickeau             * There is no state because this is a standard
33837748cd8SNickeau             * dokuwiki syntax found in {@link \Doku_Renderer_xhtml}
33937748cd8SNickeau             * check if this is not a `...._close` or `...._open`
34037748cd8SNickeau             * to derive the state
34137748cd8SNickeau             */
34237748cd8SNickeau            $mode = $this->call[0];
34337748cd8SNickeau            $lastPositionSepName = strrpos($mode, "_");
34437748cd8SNickeau            $closeOrOpen = substr($mode, $lastPositionSepName + 1);
34537748cd8SNickeau            switch ($closeOrOpen) {
34637748cd8SNickeau                case "open":
34737748cd8SNickeau                    return DOKU_LEXER_ENTER;
34837748cd8SNickeau                case "close":
34937748cd8SNickeau                    return DOKU_LEXER_EXIT;
35037748cd8SNickeau                default:
35104fd306cSNickeau                    /**
35204fd306cSNickeau                     * Let op null, is used
35304fd306cSNickeau                     * in {@link CallStack::processEolToEndStack()}
35404fd306cSNickeau                     * and things can break
35504fd306cSNickeau                     */
35637748cd8SNickeau                    return null;
35737748cd8SNickeau            }
35837748cd8SNickeau
35937748cd8SNickeau        } else {
36037748cd8SNickeau            // Plugin
36137748cd8SNickeau            $returnedArray = $this->call[1];
36237748cd8SNickeau            if (array_key_exists(2, $returnedArray)) {
36337748cd8SNickeau                return $returnedArray[2];
36437748cd8SNickeau            } else {
36537748cd8SNickeau                return null;
36637748cd8SNickeau            }
36737748cd8SNickeau        }
36837748cd8SNickeau    }
36937748cd8SNickeau
37037748cd8SNickeau    /**
37137748cd8SNickeau     * @return mixed the data returned from the {@link DokuWiki_Syntax_Plugin::handle} (ie attributes, payload, ...)
372*040d4aeaSgerardnico     * It may be any type. Array, scalar
37337748cd8SNickeau     */
37404fd306cSNickeau    public
37504fd306cSNickeau    function &getPluginData($attribute = null)
37637748cd8SNickeau    {
3774cadd4f8SNickeau        $data = &$this->call[1][1];
3784cadd4f8SNickeau        if ($attribute === null) {
3794cadd4f8SNickeau            return $data;
3804cadd4f8SNickeau        }
3814cadd4f8SNickeau        return $data[$attribute];
3824cadd4f8SNickeau
38337748cd8SNickeau    }
38437748cd8SNickeau
38537748cd8SNickeau    /**
38637748cd8SNickeau     * @return mixed the matched content from the {@link DokuWiki_Syntax_Plugin::handle}
38737748cd8SNickeau     */
38804fd306cSNickeau    public
38904fd306cSNickeau    function getCapturedContent()
39037748cd8SNickeau    {
39137748cd8SNickeau        $caller = $this->call[0];
39237748cd8SNickeau        switch ($caller) {
39337748cd8SNickeau            case "plugin":
39437748cd8SNickeau                return $this->call[1][3];
39537748cd8SNickeau            case "internallink":
39637748cd8SNickeau                return '[[' . $this->call[1][0] . '|' . $this->call[1][1] . ']]';
39737748cd8SNickeau            case "eol":
39837748cd8SNickeau                return DOKU_LF;
39937748cd8SNickeau            case "header":
40037748cd8SNickeau            case "cdata":
40137748cd8SNickeau                return $this->call[1][0];
40237748cd8SNickeau            default:
40337748cd8SNickeau                if (isset($this->call[1][0]) && is_string($this->call[1][0])) {
40437748cd8SNickeau                    return $this->call[1][0];
40537748cd8SNickeau                } else {
40637748cd8SNickeau                    return "";
40737748cd8SNickeau                }
40837748cd8SNickeau        }
40937748cd8SNickeau    }
41037748cd8SNickeau
41137748cd8SNickeau
41204fd306cSNickeau    /**
413*040d4aeaSgerardnico     * Return the attributes of a call
41404fd306cSNickeau     */
41504fd306cSNickeau    public
416*040d4aeaSgerardnico    function &getAttributes(): array
41737748cd8SNickeau    {
41837748cd8SNickeau
41904fd306cSNickeau        $isPluginCall = $this->isPluginCall();
42004fd306cSNickeau        if (!$isPluginCall) {
42137748cd8SNickeau            return $this->call[1];
422*040d4aeaSgerardnico        }
423*040d4aeaSgerardnico
42404fd306cSNickeau        $data = &$this->getPluginData();
42504fd306cSNickeau        if (!is_array($data)) {
42604fd306cSNickeau            LogUtility::error("The handle data is not an array for the call ($this), correct the returned data from the handle syntax plugin function", self::CANONICAL);
427*040d4aeaSgerardnico            // We discard, it may be a third party plugin
428*040d4aeaSgerardnico            // The log will throw an error if it's on our hand
42904fd306cSNickeau            $data = [];
43004fd306cSNickeau            return $data;
4314cadd4f8SNickeau        }
43204fd306cSNickeau        if (!isset($data[PluginUtility::ATTRIBUTES])) {
43304fd306cSNickeau            $data[PluginUtility::ATTRIBUTES] = [];
43404fd306cSNickeau        }
43504fd306cSNickeau        $attributes = &$data[PluginUtility::ATTRIBUTES];
43604fd306cSNickeau        if (!is_array($attributes)) {
43704fd306cSNickeau            $message = "The attributes value are not an array for the call ($this), the value was wrapped in an array";
43804fd306cSNickeau            LogUtility::error($message, self::CANONICAL);
43904fd306cSNickeau            $attributes = [$attributes];
4404cadd4f8SNickeau        }
4414cadd4f8SNickeau        return $attributes;
44237748cd8SNickeau    }
44337748cd8SNickeau
44404fd306cSNickeau    public
44504fd306cSNickeau    function removeAttributes()
44637748cd8SNickeau    {
44737748cd8SNickeau
44837748cd8SNickeau        $data = &$this->getPluginData();
44937748cd8SNickeau        if (isset($data[PluginUtility::ATTRIBUTES])) {
45037748cd8SNickeau            unset($data[PluginUtility::ATTRIBUTES]);
45137748cd8SNickeau        }
45237748cd8SNickeau
45337748cd8SNickeau    }
45437748cd8SNickeau
45504fd306cSNickeau    public
45604fd306cSNickeau    function updateToPluginComponent($component, $state, $attributes = array())
45737748cd8SNickeau    {
45837748cd8SNickeau        if ($this->call[0] == "plugin") {
45937748cd8SNickeau            $match = $this->call[1][3];
46037748cd8SNickeau        } else {
46137748cd8SNickeau            $this->call[0] = "plugin";
46237748cd8SNickeau            $match = "";
46337748cd8SNickeau        }
46437748cd8SNickeau        $this->call[1] = array(
46537748cd8SNickeau            0 => $component,
46637748cd8SNickeau            1 => array(
46737748cd8SNickeau                PluginUtility::ATTRIBUTES => $attributes,
46837748cd8SNickeau                PluginUtility::STATE => $state,
46937748cd8SNickeau            ),
47037748cd8SNickeau            2 => $state,
47137748cd8SNickeau            3 => $match
47237748cd8SNickeau        );
47337748cd8SNickeau
47437748cd8SNickeau    }
47537748cd8SNickeau
4761fa8c418SNickeau    /**
4771fa8c418SNickeau     * Does the display has been set
4781fa8c418SNickeau     * to override the dokuwiki default
4791fa8c418SNickeau     * ({@link Syntax::getPType()}
4801fa8c418SNickeau     *
4811fa8c418SNickeau     * because an image is by default a inline component
4821fa8c418SNickeau     * but can be a block (ie top image of a card)
4831fa8c418SNickeau     * @return bool
4841fa8c418SNickeau     */
48504fd306cSNickeau    public
48604fd306cSNickeau    function isDisplaySet(): bool
4871fa8c418SNickeau    {
4881fa8c418SNickeau        return isset($this->call[1][1][PluginUtility::DISPLAY]);
4891fa8c418SNickeau    }
4901fa8c418SNickeau
49104fd306cSNickeau    /**
49204fd306cSNickeau     * @return string|null
49304fd306cSNickeau     * {@link Call::INLINE_DISPLAY} or {@link Call::BlOCK_DISPLAY}
49404fd306cSNickeau     */
49504fd306cSNickeau    public
49604fd306cSNickeau    function getDisplay(): ?string
49737748cd8SNickeau    {
4981fa8c418SNickeau        $mode = $this->getMode();
4991fa8c418SNickeau        if ($mode == "plugin") {
5001fa8c418SNickeau            if ($this->isDisplaySet()) {
5011fa8c418SNickeau                return $this->call[1][1][PluginUtility::DISPLAY];
5021fa8c418SNickeau            }
5031fa8c418SNickeau        }
5041fa8c418SNickeau
50537748cd8SNickeau        if ($this->getState() == DOKU_LEXER_UNMATCHED) {
50637748cd8SNickeau            /**
50737748cd8SNickeau             * Unmatched are content (ie text node in XML/HTML) and have
50837748cd8SNickeau             * no display
50937748cd8SNickeau             */
51037748cd8SNickeau            return Call::INLINE_DISPLAY;
51137748cd8SNickeau        } else {
51237748cd8SNickeau            $mode = $this->call[0];
51337748cd8SNickeau            if ($mode == "plugin") {
51437748cd8SNickeau                global $DOKU_PLUGINS;
51537748cd8SNickeau                $component = $this->getComponentName();
51637748cd8SNickeau                /**
51737748cd8SNickeau                 * @var SyntaxPlugin $syntaxPlugin
51837748cd8SNickeau                 */
51937748cd8SNickeau                $syntaxPlugin = $DOKU_PLUGINS['syntax'][$component];
52037748cd8SNickeau                $pType = $syntaxPlugin->getPType();
52137748cd8SNickeau                switch ($pType) {
52237748cd8SNickeau                    case "normal":
52337748cd8SNickeau                        return Call::INLINE_DISPLAY;
52437748cd8SNickeau                    case "block":
52537748cd8SNickeau                    case "stack":
52637748cd8SNickeau                        return Call::BlOCK_DISPLAY;
52737748cd8SNickeau                    default:
52837748cd8SNickeau                        LogUtility::msg("The ptype (" . $pType . ") is unknown.");
52937748cd8SNickeau                        return null;
53037748cd8SNickeau                }
53137748cd8SNickeau            } else {
53237748cd8SNickeau                if ($mode == "eol") {
53337748cd8SNickeau                    /**
53437748cd8SNickeau                     * Control character
53537748cd8SNickeau                     * We return it as it's used in the
53637748cd8SNickeau                     * {@link \syntax_plugin_combo_para::fromEolToParagraphUntilEndOfStack()}
53737748cd8SNickeau                     * to create the paragraph
53837748cd8SNickeau                     * This is not a block, nor an inline
53937748cd8SNickeau                     */
54037748cd8SNickeau                    return $mode;
54137748cd8SNickeau                }
54237748cd8SNickeau
54337748cd8SNickeau                if (in_array($mode, self::INLINE_DOKUWIKI_COMPONENTS)) {
54437748cd8SNickeau                    return Call::INLINE_DISPLAY;
54537748cd8SNickeau                }
54637748cd8SNickeau
54737748cd8SNickeau                if (in_array($mode, self::BLOCK_MARKUP_DOKUWIKI_COMPONENTS)) {
54837748cd8SNickeau                    return Call::BlOCK_DISPLAY;
54937748cd8SNickeau                }
55037748cd8SNickeau
55104fd306cSNickeau                if (in_array($mode, self::TABLE_MARKUP)) {
55204fd306cSNickeau                    return Call::TABLE_DISPLAY;
55304fd306cSNickeau                }
55404fd306cSNickeau
55504fd306cSNickeau                LogUtility::warning("The display of the call with the mode (" . $mode . ") is unknown");
55637748cd8SNickeau                return null;
55737748cd8SNickeau
55837748cd8SNickeau
55937748cd8SNickeau            }
56037748cd8SNickeau        }
56137748cd8SNickeau
56237748cd8SNickeau    }
56337748cd8SNickeau
56437748cd8SNickeau    /**
56537748cd8SNickeau     * Same as {@link Call::getTagName()}
56637748cd8SNickeau     * but fully qualified
56737748cd8SNickeau     * @return string
56837748cd8SNickeau     */
56904fd306cSNickeau    public
57004fd306cSNickeau    function getComponentName()
57137748cd8SNickeau    {
57237748cd8SNickeau        $mode = $this->call[0];
57337748cd8SNickeau        if ($mode == "plugin") {
57437748cd8SNickeau            $pluginDokuData = $this->call[1];
57537748cd8SNickeau            return $pluginDokuData[0];
57637748cd8SNickeau        } else {
57737748cd8SNickeau            return $mode;
57837748cd8SNickeau        }
57937748cd8SNickeau    }
58037748cd8SNickeau
58104fd306cSNickeau    public
58204fd306cSNickeau    function updateEolToSpace()
58337748cd8SNickeau    {
58437748cd8SNickeau        $mode = $this->call[0];
58537748cd8SNickeau        if ($mode != "eol") {
58637748cd8SNickeau            LogUtility::msg("You can't update a " . $mode . " to a space. It should be a eol", LogUtility::LVL_MSG_WARNING, "support");
58737748cd8SNickeau        } else {
58837748cd8SNickeau            $this->call[0] = "cdata";
58937748cd8SNickeau            $this->call[1] = array(
59037748cd8SNickeau                0 => " "
59137748cd8SNickeau            );
59237748cd8SNickeau        }
59337748cd8SNickeau
59437748cd8SNickeau    }
59537748cd8SNickeau
59604fd306cSNickeau    public
59704fd306cSNickeau    function &addAttribute($key, $value)
59837748cd8SNickeau    {
59937748cd8SNickeau        $mode = $this->call[0];
60037748cd8SNickeau        if ($mode == "plugin") {
60137748cd8SNickeau            $this->call[1][1][PluginUtility::ATTRIBUTES][$key] = $value;
60204fd306cSNickeau            // keep the new reference
60304fd306cSNickeau            return $this->call[1][1][PluginUtility::ATTRIBUTES][$key];
60437748cd8SNickeau        } else {
60537748cd8SNickeau            LogUtility::msg("You can't add an attribute to the non plugin call mode (" . $mode . ")", LogUtility::LVL_MSG_WARNING, "support");
60604fd306cSNickeau            $whatever = [];
60704fd306cSNickeau            return $whatever;
60837748cd8SNickeau        }
60937748cd8SNickeau    }
61037748cd8SNickeau
61104fd306cSNickeau    public
61204fd306cSNickeau    function getContext()
61337748cd8SNickeau    {
61437748cd8SNickeau        $mode = $this->call[0];
61504fd306cSNickeau        if ($mode === "plugin") {
61670bbd7f1Sgerardnico            return $this->call[1][1][PluginUtility::CONTEXT] ?? null;
61737748cd8SNickeau        } else {
61837748cd8SNickeau            LogUtility::msg("You can't ask for a context from a non plugin call mode (" . $mode . ")", LogUtility::LVL_MSG_WARNING, "support");
61937748cd8SNickeau            return null;
62037748cd8SNickeau        }
62137748cd8SNickeau    }
62237748cd8SNickeau
62337748cd8SNickeau    /**
62437748cd8SNickeau     *
62537748cd8SNickeau     * @return array
62637748cd8SNickeau     */
62704fd306cSNickeau    public
62804fd306cSNickeau    function toCallArray()
62937748cd8SNickeau    {
63037748cd8SNickeau        return $this->call;
63137748cd8SNickeau    }
63237748cd8SNickeau
63304fd306cSNickeau    public
63404fd306cSNickeau    function __toString()
63537748cd8SNickeau    {
63637748cd8SNickeau        $name = $this->key;
63737748cd8SNickeau        if (!empty($name)) {
63837748cd8SNickeau            $name .= " - ";
63937748cd8SNickeau        }
64037748cd8SNickeau        $name .= $this->getTagName();
64104fd306cSNickeau        $name .= " - {$this->getStateName()}";
64237748cd8SNickeau        return $name;
64337748cd8SNickeau    }
64437748cd8SNickeau
6454cadd4f8SNickeau    /**
6464cadd4f8SNickeau     * @return string|null
6474cadd4f8SNickeau     *
6484cadd4f8SNickeau     * If the type returned is a boolean attribute,
6494cadd4f8SNickeau     * it means you need to define the expected types
6504cadd4f8SNickeau     * in the function {@link TagAttributes::createFromTagMatch()}
6514cadd4f8SNickeau     * as third attribute
6524cadd4f8SNickeau     */
65304fd306cSNickeau    public
65404fd306cSNickeau    function getType(): ?string
65537748cd8SNickeau    {
65637748cd8SNickeau        if ($this->getState() == DOKU_LEXER_UNMATCHED) {
65737748cd8SNickeau            return null;
65837748cd8SNickeau        } else {
6594cadd4f8SNickeau            return $this->getAttribute(TagAttributes::TYPE_KEY);
66037748cd8SNickeau        }
66137748cd8SNickeau    }
66237748cd8SNickeau
66337748cd8SNickeau    /**
66437748cd8SNickeau     * @param $key
66537748cd8SNickeau     * @param null $default
6664cadd4f8SNickeau     * @return array|string|null
66737748cd8SNickeau     */
66804fd306cSNickeau    public
66904fd306cSNickeau    function &getAttribute($key, $default = null)
67037748cd8SNickeau    {
67104fd306cSNickeau        $attributes = &$this->getAttributes();
67237748cd8SNickeau        if (isset($attributes[$key])) {
67337748cd8SNickeau            return $attributes[$key];
6744cadd4f8SNickeau        }
67537748cd8SNickeau        return $default;
6764cadd4f8SNickeau
67737748cd8SNickeau    }
67837748cd8SNickeau
6794cadd4f8SNickeau    public
6804cadd4f8SNickeau    function getPayload()
68137748cd8SNickeau    {
68237748cd8SNickeau        $mode = $this->call[0];
68337748cd8SNickeau        if ($mode == "plugin") {
68437748cd8SNickeau            return $this->call[1][1][PluginUtility::PAYLOAD];
68537748cd8SNickeau        } else {
68637748cd8SNickeau            LogUtility::msg("You can't ask for a payload from a non plugin call mode (" . $mode . ").", LogUtility::LVL_MSG_WARNING, "support");
68737748cd8SNickeau            return null;
68837748cd8SNickeau        }
68937748cd8SNickeau    }
69037748cd8SNickeau
6914cadd4f8SNickeau    public
6924cadd4f8SNickeau    function setContext($value)
69337748cd8SNickeau    {
69437748cd8SNickeau        $this->call[1][1][PluginUtility::CONTEXT] = $value;
69537748cd8SNickeau        return $this;
69637748cd8SNickeau    }
69737748cd8SNickeau
6984cadd4f8SNickeau    public
6994cadd4f8SNickeau    function hasAttribute($attributeName): bool
70037748cd8SNickeau    {
70137748cd8SNickeau        $attributes = $this->getAttributes();
70237748cd8SNickeau        if (isset($attributes[$attributeName])) {
70337748cd8SNickeau            return true;
70437748cd8SNickeau        } else {
70537748cd8SNickeau            if ($this->getType() == $attributeName) {
70637748cd8SNickeau                return true;
70737748cd8SNickeau            } else {
70837748cd8SNickeau                return false;
70937748cd8SNickeau            }
71037748cd8SNickeau        }
71137748cd8SNickeau    }
71237748cd8SNickeau
7134cadd4f8SNickeau    public
7144cadd4f8SNickeau    function isPluginCall()
71537748cd8SNickeau    {
71637748cd8SNickeau        return $this->call[0] === "plugin";
71737748cd8SNickeau    }
71837748cd8SNickeau
71937748cd8SNickeau    /**
72037748cd8SNickeau     * @return mixed|string the position (ie key) in the array
72137748cd8SNickeau     */
7224cadd4f8SNickeau    public
7234cadd4f8SNickeau    function getKey()
72437748cd8SNickeau    {
72537748cd8SNickeau        return $this->key;
72637748cd8SNickeau    }
72737748cd8SNickeau
7284cadd4f8SNickeau    public
72904fd306cSNickeau    function &getInstructionCall()
73037748cd8SNickeau    {
73137748cd8SNickeau        return $this->call;
73237748cd8SNickeau    }
73337748cd8SNickeau
7344cadd4f8SNickeau    public
7354cadd4f8SNickeau    function setState($state)
73637748cd8SNickeau    {
73737748cd8SNickeau        if ($this->call[0] == "plugin") {
73837748cd8SNickeau            // for dokuwiki
73937748cd8SNickeau            $this->call[1][2] = $state;
74037748cd8SNickeau            // for the combo plugin if any
74137748cd8SNickeau            if (isset($this->call[1][1][PluginUtility::STATE])) {
74237748cd8SNickeau                $this->call[1][1][PluginUtility::STATE] = $state;
74337748cd8SNickeau            }
74437748cd8SNickeau        } else {
74537748cd8SNickeau            LogUtility::msg("This modification of state is not yet supported for a native call");
74637748cd8SNickeau        }
74737748cd8SNickeau    }
74837748cd8SNickeau
74937748cd8SNickeau
75037748cd8SNickeau    /**
75137748cd8SNickeau     * Return the position of the first matched character in the text file
75237748cd8SNickeau     * @return mixed
75337748cd8SNickeau     */
7544cadd4f8SNickeau    public
7554cadd4f8SNickeau    function getFirstMatchedCharacterPosition()
75637748cd8SNickeau    {
75737748cd8SNickeau
75837748cd8SNickeau        return $this->call[2];
75937748cd8SNickeau
76037748cd8SNickeau    }
76137748cd8SNickeau
76237748cd8SNickeau    /**
76337748cd8SNickeau     * Return the position of the last matched character in the text file
76437748cd8SNickeau     *
76537748cd8SNickeau     * This is the {@link Call::getFirstMatchedCharacterPosition()}
76637748cd8SNickeau     * plus the length of the {@link Call::getCapturedContent()}
76737748cd8SNickeau     * matched content
76837748cd8SNickeau     * @return int|mixed
76937748cd8SNickeau     */
7704cadd4f8SNickeau    public
7714cadd4f8SNickeau    function getLastMatchedCharacterPosition()
77237748cd8SNickeau    {
77370bbd7f1Sgerardnico        $captureContent = $this->getCapturedContent();
77470bbd7f1Sgerardnico        $length = 0;
77570bbd7f1Sgerardnico        if ($captureContent != null) {
77670bbd7f1Sgerardnico            $length = strlen($captureContent);
77770bbd7f1Sgerardnico        }
77870bbd7f1Sgerardnico        return $this->getFirstMatchedCharacterPosition() + $length;
77937748cd8SNickeau    }
78037748cd8SNickeau
78137748cd8SNickeau    /**
78237748cd8SNickeau     * @param $value string the class string to add
78337748cd8SNickeau     * @return Call
78437748cd8SNickeau     */
7854cadd4f8SNickeau    public
7864cadd4f8SNickeau    function addClassName(string $value): Call
78737748cd8SNickeau    {
78837748cd8SNickeau        $class = $this->getAttribute("class");
78937748cd8SNickeau        if ($class != null) {
79037748cd8SNickeau            $value = "$class $value";
79137748cd8SNickeau        }
79237748cd8SNickeau        $this->addAttribute("class", $value);
79337748cd8SNickeau        return $this;
79437748cd8SNickeau
79537748cd8SNickeau    }
79637748cd8SNickeau
79737748cd8SNickeau    /**
79837748cd8SNickeau     * @param $key
79937748cd8SNickeau     * @return mixed|null - the delete value of null if not found
80037748cd8SNickeau     */
8014cadd4f8SNickeau    public
8024cadd4f8SNickeau    function removeAttribute($key)
80337748cd8SNickeau    {
80437748cd8SNickeau
80537748cd8SNickeau        $data = &$this->getPluginData();
80637748cd8SNickeau        if (isset($data[PluginUtility::ATTRIBUTES][$key])) {
80737748cd8SNickeau            $value = $data[PluginUtility::ATTRIBUTES][$key];
80837748cd8SNickeau            unset($data[PluginUtility::ATTRIBUTES][$key]);
80937748cd8SNickeau            return $value;
81037748cd8SNickeau        } else {
81137748cd8SNickeau            // boolean attribute as first attribute
81237748cd8SNickeau            if ($this->getType() == $key) {
81337748cd8SNickeau                unset($data[PluginUtility::ATTRIBUTES][TagAttributes::TYPE_KEY]);
81437748cd8SNickeau                return true;
81537748cd8SNickeau            }
81637748cd8SNickeau            return null;
81737748cd8SNickeau        }
81837748cd8SNickeau
81937748cd8SNickeau    }
82037748cd8SNickeau
8214cadd4f8SNickeau    public
8224cadd4f8SNickeau    function setPayload($text)
82337748cd8SNickeau    {
82437748cd8SNickeau        if ($this->isPluginCall()) {
82537748cd8SNickeau            $this->call[1][1][PluginUtility::PAYLOAD] = $text;
82637748cd8SNickeau        } else {
82737748cd8SNickeau            LogUtility::msg("Setting the payload for a non-native call ($this) is not yet implemented");
82837748cd8SNickeau        }
82937748cd8SNickeau    }
83037748cd8SNickeau
83137748cd8SNickeau    /**
83237748cd8SNickeau     * @return bool true if the call is a text call (same as dom text node)
83337748cd8SNickeau     */
8344cadd4f8SNickeau    public
8354cadd4f8SNickeau    function isTextCall()
83637748cd8SNickeau    {
83737748cd8SNickeau        return (
83837748cd8SNickeau            $this->getState() == DOKU_LEXER_UNMATCHED ||
83937748cd8SNickeau            $this->getTagName() == "cdata" ||
84037748cd8SNickeau            $this->getTagName() == "acronym"
84137748cd8SNickeau        );
84237748cd8SNickeau    }
84337748cd8SNickeau
8444cadd4f8SNickeau    public
8454cadd4f8SNickeau    function setType($type)
84637748cd8SNickeau    {
84737748cd8SNickeau        if ($this->isPluginCall()) {
84837748cd8SNickeau            $this->call[1][1][PluginUtility::ATTRIBUTES][TagAttributes::TYPE_KEY] = $type;
84937748cd8SNickeau        } else {
85037748cd8SNickeau            LogUtility::msg("This is not a plugin call ($this), you can't set the type");
85137748cd8SNickeau        }
85237748cd8SNickeau    }
85337748cd8SNickeau
8544cadd4f8SNickeau    public
8554cadd4f8SNickeau    function addCssStyle($key, $value)
85637748cd8SNickeau    {
85737748cd8SNickeau        $style = $this->getAttribute("style");
85837748cd8SNickeau        $cssValue = "$key:$value";
8594cadd4f8SNickeau        if ($style !== null) {
86037748cd8SNickeau            $cssValue = "$style; $cssValue";
86137748cd8SNickeau        }
86237748cd8SNickeau        $this->addAttribute("style", $cssValue);
86337748cd8SNickeau    }
86437748cd8SNickeau
8654cadd4f8SNickeau    public
8664cadd4f8SNickeau    function setSyntaxComponentFromTag($tag)
86737748cd8SNickeau    {
86837748cd8SNickeau
86937748cd8SNickeau        if ($this->isPluginCall()) {
87037748cd8SNickeau            $this->call[1][0] = PluginUtility::getComponentName($tag);
87137748cd8SNickeau        } else {
87237748cd8SNickeau            LogUtility::msg("The call ($this) is a native call and we don't support yet the modification of the component to ($tag)");
87337748cd8SNickeau        }
87437748cd8SNickeau    }
87537748cd8SNickeau
87637748cd8SNickeau
8774cadd4f8SNickeau    public
8784cadd4f8SNickeau    function setCapturedContent($content)
87937748cd8SNickeau    {
88037748cd8SNickeau        $tagName = $this->getTagName();
88137748cd8SNickeau        switch ($tagName) {
88237748cd8SNickeau            case "cdata":
88337748cd8SNickeau                $this->call[1][0] = $content;
88437748cd8SNickeau                break;
88537748cd8SNickeau            default:
88637748cd8SNickeau                LogUtility::msg("Setting the captured content on a call for the tag ($tagName) is not yet implemented", LogUtility::LVL_MSG_ERROR);
88737748cd8SNickeau        }
88837748cd8SNickeau    }
88937748cd8SNickeau
8901fa8c418SNickeau    /**
8911fa8c418SNickeau     * Set the display to block or inline
8921fa8c418SNickeau     * One of `block` or `inline`
8931fa8c418SNickeau     */
8944cadd4f8SNickeau    public
8954cadd4f8SNickeau    function setDisplay($display): Call
8961fa8c418SNickeau    {
8971fa8c418SNickeau        $mode = $this->getMode();
8981fa8c418SNickeau        if ($mode == "plugin") {
8991fa8c418SNickeau            $this->call[1][1][PluginUtility::DISPLAY] = $display;
9001fa8c418SNickeau        } else {
9011fa8c418SNickeau            LogUtility::msg("You can't set a display on a non plugin call mode (" . $mode . ")", LogUtility::LVL_MSG_WARNING);
9021fa8c418SNickeau        }
9031fa8c418SNickeau        return $this;
9041fa8c418SNickeau
9051fa8c418SNickeau    }
9061fa8c418SNickeau
9071fa8c418SNickeau    /**
9081fa8c418SNickeau     * The plugin or not
9091fa8c418SNickeau     * @return mixed
9101fa8c418SNickeau     */
9114cadd4f8SNickeau    private
9124cadd4f8SNickeau    function getMode()
9131fa8c418SNickeau    {
9141fa8c418SNickeau        return $this->call[0];
9151fa8c418SNickeau    }
9161fa8c418SNickeau
9171fa8c418SNickeau    /**
9181fa8c418SNickeau     * Return if this an unmatched call with space
9191fa8c418SNickeau     * in captured content
9201fa8c418SNickeau     * @return bool
9211fa8c418SNickeau     */
9224cadd4f8SNickeau    public
9234cadd4f8SNickeau    function isUnMatchedEmptyCall(): bool
9241fa8c418SNickeau    {
9251fa8c418SNickeau        if ($this->getState() === DOKU_LEXER_UNMATCHED && trim($this->getCapturedContent()) === "") {
9261fa8c418SNickeau            return true;
9271fa8c418SNickeau        }
9281fa8c418SNickeau        return false;
9291fa8c418SNickeau    }
9301fa8c418SNickeau
9314cadd4f8SNickeau    public
9324cadd4f8SNickeau    function getExitCode()
9334cadd4f8SNickeau    {
9344cadd4f8SNickeau        $mode = $this->call[0];
9354cadd4f8SNickeau        if ($mode == "plugin") {
93670bbd7f1Sgerardnico            $value = $this->call[1][1][PluginUtility::EXIT_CODE] ?? null;
9374cadd4f8SNickeau            if ($value === null) {
9384cadd4f8SNickeau                return 0;
9394cadd4f8SNickeau            }
9404cadd4f8SNickeau            return $value;
9414cadd4f8SNickeau        } else {
9424cadd4f8SNickeau            LogUtility::msg("You can't ask for the exit code from a non plugin call mode (" . $mode . ").", LogUtility::LVL_MSG_WARNING, "support");
9434cadd4f8SNickeau            return 0;
9444cadd4f8SNickeau        }
9454cadd4f8SNickeau    }
9464cadd4f8SNickeau
94704fd306cSNickeau    public
94804fd306cSNickeau    function setAttribute(string $name, $value): Call
9494cadd4f8SNickeau    {
950*040d4aeaSgerardnico        $this->getAttributes()[$name] = $value;
9514cadd4f8SNickeau        return $this;
9524cadd4f8SNickeau    }
9534cadd4f8SNickeau
95404fd306cSNickeau    public
95504fd306cSNickeau    function setPluginData(string $name, $value): Call
9564cadd4f8SNickeau    {
9574cadd4f8SNickeau        $this->getPluginData()[$name] = $value;
9584cadd4f8SNickeau        return $this;
9594cadd4f8SNickeau    }
9604cadd4f8SNickeau
96104fd306cSNickeau    public
96204fd306cSNickeau    function getIdOrDefault()
96304fd306cSNickeau    {
96404fd306cSNickeau        $id = $this->getAttribute(TagAttributes::ID_KEY);
96504fd306cSNickeau        if ($id !== null) {
96604fd306cSNickeau            return $id;
96704fd306cSNickeau        }
96804fd306cSNickeau        return $this->getAttribute(TagAttributes::GENERATED_ID_KEY);
96904fd306cSNickeau    }
97004fd306cSNickeau
97104fd306cSNickeau    public
97204fd306cSNickeau    function getAttributeAndRemove(string $key)
97304fd306cSNickeau    {
97404fd306cSNickeau        $value = $this->getAttribute($key);
97504fd306cSNickeau        $this->removeAttribute($key);
97604fd306cSNickeau        return $value;
97704fd306cSNickeau    }
97804fd306cSNickeau
97904fd306cSNickeau    private function getStateName(): string
98004fd306cSNickeau    {
98104fd306cSNickeau        $state = $this->getState();
98204fd306cSNickeau        switch ($state) {
98304fd306cSNickeau            case DOKU_LEXER_ENTER:
98404fd306cSNickeau                return "enter";
98504fd306cSNickeau            case DOKU_LEXER_EXIT:
98604fd306cSNickeau                return "exit";
98704fd306cSNickeau            case DOKU_LEXER_SPECIAL:
98804fd306cSNickeau                return "empty";
98904fd306cSNickeau            case DOKU_LEXER_UNMATCHED:
99004fd306cSNickeau                return "text";
99104fd306cSNickeau            default:
99204fd306cSNickeau                return "unknown " . $state;
99304fd306cSNickeau        }
99404fd306cSNickeau    }
99504fd306cSNickeau
99637748cd8SNickeau
99737748cd8SNickeau}
998