xref: /plugin/combo/ComboStrap/Call.php (revision 7dbcdecd15b9c1485d6e26d96fd967e18985d6c4)
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, ...)
372040d4aeaSgerardnico     * 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    /**
413040d4aeaSgerardnico     * Return the attributes of a call
41404fd306cSNickeau     */
41504fd306cSNickeau    public
416040d4aeaSgerardnico    function &getAttributes(): array
41737748cd8SNickeau    {
41837748cd8SNickeau
41904fd306cSNickeau        $isPluginCall = $this->isPluginCall();
42004fd306cSNickeau        if (!$isPluginCall) {
42137748cd8SNickeau            return $this->call[1];
422040d4aeaSgerardnico        }
423040d4aeaSgerardnico
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);
427040d4aeaSgerardnico            // We discard, it may be a third party plugin
428040d4aeaSgerardnico            // 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];
520*7dbcdecdSNico                if ($syntaxPlugin === null) {
521*7dbcdecdSNico                    // not a syntax plugin (ie frontmatter)
522*7dbcdecdSNico                    return null;
523*7dbcdecdSNico                }
52437748cd8SNickeau                $pType = $syntaxPlugin->getPType();
52537748cd8SNickeau                switch ($pType) {
52637748cd8SNickeau                    case "normal":
52737748cd8SNickeau                        return Call::INLINE_DISPLAY;
52837748cd8SNickeau                    case "block":
52937748cd8SNickeau                    case "stack":
53037748cd8SNickeau                        return Call::BlOCK_DISPLAY;
53137748cd8SNickeau                    default:
53237748cd8SNickeau                        LogUtility::msg("The ptype (" . $pType . ") is unknown.");
53337748cd8SNickeau                        return null;
53437748cd8SNickeau                }
53537748cd8SNickeau            } else {
53637748cd8SNickeau                if ($mode == "eol") {
53737748cd8SNickeau                    /**
53837748cd8SNickeau                     * Control character
53937748cd8SNickeau                     * We return it as it's used in the
54037748cd8SNickeau                     * {@link \syntax_plugin_combo_para::fromEolToParagraphUntilEndOfStack()}
54137748cd8SNickeau                     * to create the paragraph
54237748cd8SNickeau                     * This is not a block, nor an inline
54337748cd8SNickeau                     */
54437748cd8SNickeau                    return $mode;
54537748cd8SNickeau                }
54637748cd8SNickeau
54737748cd8SNickeau                if (in_array($mode, self::INLINE_DOKUWIKI_COMPONENTS)) {
54837748cd8SNickeau                    return Call::INLINE_DISPLAY;
54937748cd8SNickeau                }
55037748cd8SNickeau
55137748cd8SNickeau                if (in_array($mode, self::BLOCK_MARKUP_DOKUWIKI_COMPONENTS)) {
55237748cd8SNickeau                    return Call::BlOCK_DISPLAY;
55337748cd8SNickeau                }
55437748cd8SNickeau
55504fd306cSNickeau                if (in_array($mode, self::TABLE_MARKUP)) {
55604fd306cSNickeau                    return Call::TABLE_DISPLAY;
55704fd306cSNickeau                }
55804fd306cSNickeau
55904fd306cSNickeau                LogUtility::warning("The display of the call with the mode (" . $mode . ") is unknown");
56037748cd8SNickeau                return null;
56137748cd8SNickeau
56237748cd8SNickeau
56337748cd8SNickeau            }
56437748cd8SNickeau        }
56537748cd8SNickeau
56637748cd8SNickeau    }
56737748cd8SNickeau
56837748cd8SNickeau    /**
56937748cd8SNickeau     * Same as {@link Call::getTagName()}
57037748cd8SNickeau     * but fully qualified
57137748cd8SNickeau     * @return string
57237748cd8SNickeau     */
57304fd306cSNickeau    public
57404fd306cSNickeau    function getComponentName()
57537748cd8SNickeau    {
57637748cd8SNickeau        $mode = $this->call[0];
57737748cd8SNickeau        if ($mode == "plugin") {
57837748cd8SNickeau            $pluginDokuData = $this->call[1];
57937748cd8SNickeau            return $pluginDokuData[0];
58037748cd8SNickeau        } else {
58137748cd8SNickeau            return $mode;
58237748cd8SNickeau        }
58337748cd8SNickeau    }
58437748cd8SNickeau
58504fd306cSNickeau    public
58604fd306cSNickeau    function updateEolToSpace()
58737748cd8SNickeau    {
58837748cd8SNickeau        $mode = $this->call[0];
58937748cd8SNickeau        if ($mode != "eol") {
59037748cd8SNickeau            LogUtility::msg("You can't update a " . $mode . " to a space. It should be a eol", LogUtility::LVL_MSG_WARNING, "support");
59137748cd8SNickeau        } else {
59237748cd8SNickeau            $this->call[0] = "cdata";
59337748cd8SNickeau            $this->call[1] = array(
59437748cd8SNickeau                0 => " "
59537748cd8SNickeau            );
59637748cd8SNickeau        }
59737748cd8SNickeau
59837748cd8SNickeau    }
59937748cd8SNickeau
60004fd306cSNickeau    public
60104fd306cSNickeau    function &addAttribute($key, $value)
60237748cd8SNickeau    {
60337748cd8SNickeau        $mode = $this->call[0];
60437748cd8SNickeau        if ($mode == "plugin") {
60537748cd8SNickeau            $this->call[1][1][PluginUtility::ATTRIBUTES][$key] = $value;
60604fd306cSNickeau            // keep the new reference
60704fd306cSNickeau            return $this->call[1][1][PluginUtility::ATTRIBUTES][$key];
60837748cd8SNickeau        } else {
60937748cd8SNickeau            LogUtility::msg("You can't add an attribute to the non plugin call mode (" . $mode . ")", LogUtility::LVL_MSG_WARNING, "support");
61004fd306cSNickeau            $whatever = [];
61104fd306cSNickeau            return $whatever;
61237748cd8SNickeau        }
61337748cd8SNickeau    }
61437748cd8SNickeau
61504fd306cSNickeau    public
61604fd306cSNickeau    function getContext()
61737748cd8SNickeau    {
61837748cd8SNickeau        $mode = $this->call[0];
61904fd306cSNickeau        if ($mode === "plugin") {
62070bbd7f1Sgerardnico            return $this->call[1][1][PluginUtility::CONTEXT] ?? null;
62137748cd8SNickeau        } else {
62237748cd8SNickeau            LogUtility::msg("You can't ask for a context from a non plugin call mode (" . $mode . ")", LogUtility::LVL_MSG_WARNING, "support");
62337748cd8SNickeau            return null;
62437748cd8SNickeau        }
62537748cd8SNickeau    }
62637748cd8SNickeau
62737748cd8SNickeau    /**
62837748cd8SNickeau     *
62937748cd8SNickeau     * @return array
63037748cd8SNickeau     */
63104fd306cSNickeau    public
63204fd306cSNickeau    function toCallArray()
63337748cd8SNickeau    {
63437748cd8SNickeau        return $this->call;
63537748cd8SNickeau    }
63637748cd8SNickeau
63704fd306cSNickeau    public
63804fd306cSNickeau    function __toString()
63937748cd8SNickeau    {
64037748cd8SNickeau        $name = $this->key;
64137748cd8SNickeau        if (!empty($name)) {
64237748cd8SNickeau            $name .= " - ";
64337748cd8SNickeau        }
64437748cd8SNickeau        $name .= $this->getTagName();
64504fd306cSNickeau        $name .= " - {$this->getStateName()}";
64637748cd8SNickeau        return $name;
64737748cd8SNickeau    }
64837748cd8SNickeau
6494cadd4f8SNickeau    /**
6504cadd4f8SNickeau     * @return string|null
6514cadd4f8SNickeau     *
6524cadd4f8SNickeau     * If the type returned is a boolean attribute,
6534cadd4f8SNickeau     * it means you need to define the expected types
6544cadd4f8SNickeau     * in the function {@link TagAttributes::createFromTagMatch()}
6554cadd4f8SNickeau     * as third attribute
6564cadd4f8SNickeau     */
65704fd306cSNickeau    public
65804fd306cSNickeau    function getType(): ?string
65937748cd8SNickeau    {
66037748cd8SNickeau        if ($this->getState() == DOKU_LEXER_UNMATCHED) {
66137748cd8SNickeau            return null;
66237748cd8SNickeau        } else {
6634cadd4f8SNickeau            return $this->getAttribute(TagAttributes::TYPE_KEY);
66437748cd8SNickeau        }
66537748cd8SNickeau    }
66637748cd8SNickeau
66737748cd8SNickeau    /**
66837748cd8SNickeau     * @param $key
66937748cd8SNickeau     * @param null $default
6704cadd4f8SNickeau     * @return array|string|null
67137748cd8SNickeau     */
67204fd306cSNickeau    public
67304fd306cSNickeau    function &getAttribute($key, $default = null)
67437748cd8SNickeau    {
67504fd306cSNickeau        $attributes = &$this->getAttributes();
67637748cd8SNickeau        if (isset($attributes[$key])) {
67737748cd8SNickeau            return $attributes[$key];
6784cadd4f8SNickeau        }
67937748cd8SNickeau        return $default;
6804cadd4f8SNickeau
68137748cd8SNickeau    }
68237748cd8SNickeau
6834cadd4f8SNickeau    public
6844cadd4f8SNickeau    function getPayload()
68537748cd8SNickeau    {
68637748cd8SNickeau        $mode = $this->call[0];
68737748cd8SNickeau        if ($mode == "plugin") {
68837748cd8SNickeau            return $this->call[1][1][PluginUtility::PAYLOAD];
68937748cd8SNickeau        } else {
69037748cd8SNickeau            LogUtility::msg("You can't ask for a payload from a non plugin call mode (" . $mode . ").", LogUtility::LVL_MSG_WARNING, "support");
69137748cd8SNickeau            return null;
69237748cd8SNickeau        }
69337748cd8SNickeau    }
69437748cd8SNickeau
6954cadd4f8SNickeau    public
6964cadd4f8SNickeau    function setContext($value)
69737748cd8SNickeau    {
69837748cd8SNickeau        $this->call[1][1][PluginUtility::CONTEXT] = $value;
69937748cd8SNickeau        return $this;
70037748cd8SNickeau    }
70137748cd8SNickeau
7024cadd4f8SNickeau    public
7034cadd4f8SNickeau    function hasAttribute($attributeName): bool
70437748cd8SNickeau    {
70537748cd8SNickeau        $attributes = $this->getAttributes();
70637748cd8SNickeau        if (isset($attributes[$attributeName])) {
70737748cd8SNickeau            return true;
70837748cd8SNickeau        } else {
70937748cd8SNickeau            if ($this->getType() == $attributeName) {
71037748cd8SNickeau                return true;
71137748cd8SNickeau            } else {
71237748cd8SNickeau                return false;
71337748cd8SNickeau            }
71437748cd8SNickeau        }
71537748cd8SNickeau    }
71637748cd8SNickeau
7174cadd4f8SNickeau    public
7184cadd4f8SNickeau    function isPluginCall()
71937748cd8SNickeau    {
72037748cd8SNickeau        return $this->call[0] === "plugin";
72137748cd8SNickeau    }
72237748cd8SNickeau
72337748cd8SNickeau    /**
72437748cd8SNickeau     * @return mixed|string the position (ie key) in the array
72537748cd8SNickeau     */
7264cadd4f8SNickeau    public
7274cadd4f8SNickeau    function getKey()
72837748cd8SNickeau    {
72937748cd8SNickeau        return $this->key;
73037748cd8SNickeau    }
73137748cd8SNickeau
7324cadd4f8SNickeau    public
73304fd306cSNickeau    function &getInstructionCall()
73437748cd8SNickeau    {
73537748cd8SNickeau        return $this->call;
73637748cd8SNickeau    }
73737748cd8SNickeau
7384cadd4f8SNickeau    public
7394cadd4f8SNickeau    function setState($state)
74037748cd8SNickeau    {
74137748cd8SNickeau        if ($this->call[0] == "plugin") {
74237748cd8SNickeau            // for dokuwiki
74337748cd8SNickeau            $this->call[1][2] = $state;
74437748cd8SNickeau            // for the combo plugin if any
74537748cd8SNickeau            if (isset($this->call[1][1][PluginUtility::STATE])) {
74637748cd8SNickeau                $this->call[1][1][PluginUtility::STATE] = $state;
74737748cd8SNickeau            }
74837748cd8SNickeau        } else {
74937748cd8SNickeau            LogUtility::msg("This modification of state is not yet supported for a native call");
75037748cd8SNickeau        }
75137748cd8SNickeau    }
75237748cd8SNickeau
75337748cd8SNickeau
75437748cd8SNickeau    /**
75537748cd8SNickeau     * Return the position of the first matched character in the text file
75637748cd8SNickeau     * @return mixed
75737748cd8SNickeau     */
7584cadd4f8SNickeau    public
7594cadd4f8SNickeau    function getFirstMatchedCharacterPosition()
76037748cd8SNickeau    {
76137748cd8SNickeau
76237748cd8SNickeau        return $this->call[2];
76337748cd8SNickeau
76437748cd8SNickeau    }
76537748cd8SNickeau
76637748cd8SNickeau    /**
76737748cd8SNickeau     * Return the position of the last matched character in the text file
76837748cd8SNickeau     *
76937748cd8SNickeau     * This is the {@link Call::getFirstMatchedCharacterPosition()}
77037748cd8SNickeau     * plus the length of the {@link Call::getCapturedContent()}
77137748cd8SNickeau     * matched content
77237748cd8SNickeau     * @return int|mixed
77337748cd8SNickeau     */
7744cadd4f8SNickeau    public
7754cadd4f8SNickeau    function getLastMatchedCharacterPosition()
77637748cd8SNickeau    {
77770bbd7f1Sgerardnico        $captureContent = $this->getCapturedContent();
77870bbd7f1Sgerardnico        $length = 0;
77970bbd7f1Sgerardnico        if ($captureContent != null) {
78070bbd7f1Sgerardnico            $length = strlen($captureContent);
78170bbd7f1Sgerardnico        }
78270bbd7f1Sgerardnico        return $this->getFirstMatchedCharacterPosition() + $length;
78337748cd8SNickeau    }
78437748cd8SNickeau
78537748cd8SNickeau    /**
78637748cd8SNickeau     * @param $value string the class string to add
78737748cd8SNickeau     * @return Call
78837748cd8SNickeau     */
7894cadd4f8SNickeau    public
7904cadd4f8SNickeau    function addClassName(string $value): Call
79137748cd8SNickeau    {
79237748cd8SNickeau        $class = $this->getAttribute("class");
79337748cd8SNickeau        if ($class != null) {
79437748cd8SNickeau            $value = "$class $value";
79537748cd8SNickeau        }
79637748cd8SNickeau        $this->addAttribute("class", $value);
79737748cd8SNickeau        return $this;
79837748cd8SNickeau
79937748cd8SNickeau    }
80037748cd8SNickeau
80137748cd8SNickeau    /**
80237748cd8SNickeau     * @param $key
80337748cd8SNickeau     * @return mixed|null - the delete value of null if not found
80437748cd8SNickeau     */
8054cadd4f8SNickeau    public
8064cadd4f8SNickeau    function removeAttribute($key)
80737748cd8SNickeau    {
80837748cd8SNickeau
80937748cd8SNickeau        $data = &$this->getPluginData();
81037748cd8SNickeau        if (isset($data[PluginUtility::ATTRIBUTES][$key])) {
81137748cd8SNickeau            $value = $data[PluginUtility::ATTRIBUTES][$key];
81237748cd8SNickeau            unset($data[PluginUtility::ATTRIBUTES][$key]);
81337748cd8SNickeau            return $value;
81437748cd8SNickeau        } else {
81537748cd8SNickeau            // boolean attribute as first attribute
81637748cd8SNickeau            if ($this->getType() == $key) {
81737748cd8SNickeau                unset($data[PluginUtility::ATTRIBUTES][TagAttributes::TYPE_KEY]);
81837748cd8SNickeau                return true;
81937748cd8SNickeau            }
82037748cd8SNickeau            return null;
82137748cd8SNickeau        }
82237748cd8SNickeau
82337748cd8SNickeau    }
82437748cd8SNickeau
8254cadd4f8SNickeau    public
8264cadd4f8SNickeau    function setPayload($text)
82737748cd8SNickeau    {
82837748cd8SNickeau        if ($this->isPluginCall()) {
82937748cd8SNickeau            $this->call[1][1][PluginUtility::PAYLOAD] = $text;
83037748cd8SNickeau        } else {
83137748cd8SNickeau            LogUtility::msg("Setting the payload for a non-native call ($this) is not yet implemented");
83237748cd8SNickeau        }
83337748cd8SNickeau    }
83437748cd8SNickeau
83537748cd8SNickeau    /**
83637748cd8SNickeau     * @return bool true if the call is a text call (same as dom text node)
83737748cd8SNickeau     */
8384cadd4f8SNickeau    public
8394cadd4f8SNickeau    function isTextCall()
84037748cd8SNickeau    {
84137748cd8SNickeau        return (
84237748cd8SNickeau            $this->getState() == DOKU_LEXER_UNMATCHED ||
84337748cd8SNickeau            $this->getTagName() == "cdata" ||
84437748cd8SNickeau            $this->getTagName() == "acronym"
84537748cd8SNickeau        );
84637748cd8SNickeau    }
84737748cd8SNickeau
8484cadd4f8SNickeau    public
8494cadd4f8SNickeau    function setType($type)
85037748cd8SNickeau    {
85137748cd8SNickeau        if ($this->isPluginCall()) {
85237748cd8SNickeau            $this->call[1][1][PluginUtility::ATTRIBUTES][TagAttributes::TYPE_KEY] = $type;
85337748cd8SNickeau        } else {
85437748cd8SNickeau            LogUtility::msg("This is not a plugin call ($this), you can't set the type");
85537748cd8SNickeau        }
85637748cd8SNickeau    }
85737748cd8SNickeau
8584cadd4f8SNickeau    public
8594cadd4f8SNickeau    function addCssStyle($key, $value)
86037748cd8SNickeau    {
86137748cd8SNickeau        $style = $this->getAttribute("style");
86237748cd8SNickeau        $cssValue = "$key:$value";
8634cadd4f8SNickeau        if ($style !== null) {
86437748cd8SNickeau            $cssValue = "$style; $cssValue";
86537748cd8SNickeau        }
86637748cd8SNickeau        $this->addAttribute("style", $cssValue);
86737748cd8SNickeau    }
86837748cd8SNickeau
8694cadd4f8SNickeau    public
8704cadd4f8SNickeau    function setSyntaxComponentFromTag($tag)
87137748cd8SNickeau    {
87237748cd8SNickeau
87337748cd8SNickeau        if ($this->isPluginCall()) {
87437748cd8SNickeau            $this->call[1][0] = PluginUtility::getComponentName($tag);
87537748cd8SNickeau        } else {
87637748cd8SNickeau            LogUtility::msg("The call ($this) is a native call and we don't support yet the modification of the component to ($tag)");
87737748cd8SNickeau        }
87837748cd8SNickeau    }
87937748cd8SNickeau
88037748cd8SNickeau
8814cadd4f8SNickeau    public
8824cadd4f8SNickeau    function setCapturedContent($content)
88337748cd8SNickeau    {
88437748cd8SNickeau        $tagName = $this->getTagName();
88537748cd8SNickeau        switch ($tagName) {
88637748cd8SNickeau            case "cdata":
88737748cd8SNickeau                $this->call[1][0] = $content;
88837748cd8SNickeau                break;
88937748cd8SNickeau            default:
89037748cd8SNickeau                LogUtility::msg("Setting the captured content on a call for the tag ($tagName) is not yet implemented", LogUtility::LVL_MSG_ERROR);
89137748cd8SNickeau        }
89237748cd8SNickeau    }
89337748cd8SNickeau
8941fa8c418SNickeau    /**
8951fa8c418SNickeau     * Set the display to block or inline
8961fa8c418SNickeau     * One of `block` or `inline`
8971fa8c418SNickeau     */
8984cadd4f8SNickeau    public
8994cadd4f8SNickeau    function setDisplay($display): Call
9001fa8c418SNickeau    {
9011fa8c418SNickeau        $mode = $this->getMode();
9021fa8c418SNickeau        if ($mode == "plugin") {
9031fa8c418SNickeau            $this->call[1][1][PluginUtility::DISPLAY] = $display;
9041fa8c418SNickeau        } else {
9051fa8c418SNickeau            LogUtility::msg("You can't set a display on a non plugin call mode (" . $mode . ")", LogUtility::LVL_MSG_WARNING);
9061fa8c418SNickeau        }
9071fa8c418SNickeau        return $this;
9081fa8c418SNickeau
9091fa8c418SNickeau    }
9101fa8c418SNickeau
9111fa8c418SNickeau    /**
9121fa8c418SNickeau     * The plugin or not
9131fa8c418SNickeau     * @return mixed
9141fa8c418SNickeau     */
9154cadd4f8SNickeau    private
9164cadd4f8SNickeau    function getMode()
9171fa8c418SNickeau    {
9181fa8c418SNickeau        return $this->call[0];
9191fa8c418SNickeau    }
9201fa8c418SNickeau
9211fa8c418SNickeau    /**
9221fa8c418SNickeau     * Return if this an unmatched call with space
9231fa8c418SNickeau     * in captured content
9241fa8c418SNickeau     * @return bool
9251fa8c418SNickeau     */
9264cadd4f8SNickeau    public
9274cadd4f8SNickeau    function isUnMatchedEmptyCall(): bool
9281fa8c418SNickeau    {
9291fa8c418SNickeau        if ($this->getState() === DOKU_LEXER_UNMATCHED && trim($this->getCapturedContent()) === "") {
9301fa8c418SNickeau            return true;
9311fa8c418SNickeau        }
9321fa8c418SNickeau        return false;
9331fa8c418SNickeau    }
9341fa8c418SNickeau
9354cadd4f8SNickeau    public
9364cadd4f8SNickeau    function getExitCode()
9374cadd4f8SNickeau    {
9384cadd4f8SNickeau        $mode = $this->call[0];
9394cadd4f8SNickeau        if ($mode == "plugin") {
94070bbd7f1Sgerardnico            $value = $this->call[1][1][PluginUtility::EXIT_CODE] ?? null;
9414cadd4f8SNickeau            if ($value === null) {
9424cadd4f8SNickeau                return 0;
9434cadd4f8SNickeau            }
9444cadd4f8SNickeau            return $value;
9454cadd4f8SNickeau        } else {
9464cadd4f8SNickeau            LogUtility::msg("You can't ask for the exit code from a non plugin call mode (" . $mode . ").", LogUtility::LVL_MSG_WARNING, "support");
9474cadd4f8SNickeau            return 0;
9484cadd4f8SNickeau        }
9494cadd4f8SNickeau    }
9504cadd4f8SNickeau
95104fd306cSNickeau    public
95204fd306cSNickeau    function setAttribute(string $name, $value): Call
9534cadd4f8SNickeau    {
954040d4aeaSgerardnico        $this->getAttributes()[$name] = $value;
9554cadd4f8SNickeau        return $this;
9564cadd4f8SNickeau    }
9574cadd4f8SNickeau
95804fd306cSNickeau    public
95904fd306cSNickeau    function setPluginData(string $name, $value): Call
9604cadd4f8SNickeau    {
9614cadd4f8SNickeau        $this->getPluginData()[$name] = $value;
9624cadd4f8SNickeau        return $this;
9634cadd4f8SNickeau    }
9644cadd4f8SNickeau
96504fd306cSNickeau    public
96604fd306cSNickeau    function getIdOrDefault()
96704fd306cSNickeau    {
96804fd306cSNickeau        $id = $this->getAttribute(TagAttributes::ID_KEY);
96904fd306cSNickeau        if ($id !== null) {
97004fd306cSNickeau            return $id;
97104fd306cSNickeau        }
97204fd306cSNickeau        return $this->getAttribute(TagAttributes::GENERATED_ID_KEY);
97304fd306cSNickeau    }
97404fd306cSNickeau
97504fd306cSNickeau    public
97604fd306cSNickeau    function getAttributeAndRemove(string $key)
97704fd306cSNickeau    {
97804fd306cSNickeau        $value = $this->getAttribute($key);
97904fd306cSNickeau        $this->removeAttribute($key);
98004fd306cSNickeau        return $value;
98104fd306cSNickeau    }
98204fd306cSNickeau
98304fd306cSNickeau    private function getStateName(): string
98404fd306cSNickeau    {
98504fd306cSNickeau        $state = $this->getState();
98604fd306cSNickeau        switch ($state) {
98704fd306cSNickeau            case DOKU_LEXER_ENTER:
98804fd306cSNickeau                return "enter";
98904fd306cSNickeau            case DOKU_LEXER_EXIT:
99004fd306cSNickeau                return "exit";
99104fd306cSNickeau            case DOKU_LEXER_SPECIAL:
99204fd306cSNickeau                return "empty";
99304fd306cSNickeau            case DOKU_LEXER_UNMATCHED:
99404fd306cSNickeau                return "text";
99504fd306cSNickeau            default:
99604fd306cSNickeau                return "unknown " . $state;
99704fd306cSNickeau        }
99804fd306cSNickeau    }
99904fd306cSNickeau
100037748cd8SNickeau
100137748cd8SNickeau}
1002