xref: /template/strap/ComboStrap/Call.php (revision 81f56eb90da55cece29ce129c7b54b0ac748dc2d)
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",
135*81f56eb9SNicolas GERARD        "tablecell_close",
136*81f56eb9SNicolas GERARD        "tableheader",
137*81f56eb9SNicolas GERARD        "table_align",
138*81f56eb9SNicolas GERARD        "table_row",
139*81f56eb9SNicolas GERARD        "tablecell",
140*81f56eb9SNicolas GERARD        "table_start",
141*81f56eb9SNicolas GERARD        "table_end"
14237748cd8SNickeau    );
14337748cd8SNickeau
1441fa8c418SNickeau    /**
1451fa8c418SNickeau     * A media is not really an image
1461fa8c418SNickeau     * but it may contains one
1471fa8c418SNickeau     */
1481fa8c418SNickeau    const IMAGE_TAGS = [
1491fa8c418SNickeau        syntax_plugin_combo_media::TAG,
15004fd306cSNickeau        PageImageTag::MARKUP
1511fa8c418SNickeau    ];
1524cadd4f8SNickeau    const CANONICAL = "call";
15304fd306cSNickeau    const TABLE_DISPLAY = "table-display";
1541fa8c418SNickeau
15537748cd8SNickeau    private $call;
15637748cd8SNickeau
15737748cd8SNickeau    /**
15837748cd8SNickeau     * The key identifier in the {@link CallStack}
15937748cd8SNickeau     * @var mixed|string
16037748cd8SNickeau     */
16137748cd8SNickeau    private $key;
16237748cd8SNickeau
16337748cd8SNickeau    /**
16437748cd8SNickeau     * Call constructor.
16537748cd8SNickeau     * @param $call - the instruction array (ie called a call)
16637748cd8SNickeau     */
16737748cd8SNickeau    public function __construct(&$call, $key = "")
16837748cd8SNickeau    {
16937748cd8SNickeau        $this->call = &$call;
17037748cd8SNickeau        $this->key = $key;
17137748cd8SNickeau    }
17237748cd8SNickeau
17337748cd8SNickeau    /**
17437748cd8SNickeau     * Insert a tag above
17537748cd8SNickeau     * @param $tagName
17637748cd8SNickeau     * @param $state
17704fd306cSNickeau     * @param $syntaxComponentName - the name of the dokuwiki syntax component (ie plugin_name)
178c3437056SNickeau     * @param array $attribute
1794cadd4f8SNickeau     * @param string|null $rawContext
1804cadd4f8SNickeau     * @param string|null $content - the parsed content
181c3437056SNickeau     * @param string|null $payload - the payload after handler
182c3437056SNickeau     * @param int|null $position
18337748cd8SNickeau     * @return Call - a call
18437748cd8SNickeau     */
18504fd306cSNickeau    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
18637748cd8SNickeau    {
18737748cd8SNickeau        $data = array(
18837748cd8SNickeau            PluginUtility::ATTRIBUTES => $attribute,
1894cadd4f8SNickeau            PluginUtility::CONTEXT => $rawContext,
190c3437056SNickeau            PluginUtility::STATE => $state,
19104fd306cSNickeau            PluginUtility::TAG => $tagName,
192c3437056SNickeau            PluginUtility::POSITION => $position
19337748cd8SNickeau        );
19404fd306cSNickeau        if ($payload !== null) {
19537748cd8SNickeau            $data[PluginUtility::PAYLOAD] = $payload;
19637748cd8SNickeau        }
197c3437056SNickeau        $positionInText = $position;
19837748cd8SNickeau
19904fd306cSNickeau        if ($syntaxComponentName !== null) {
20004fd306cSNickeau            $componentName = PluginUtility::getComponentName($syntaxComponentName);
20104fd306cSNickeau        } else {
20204fd306cSNickeau            $componentName = PluginUtility::getComponentName($tagName);
20304fd306cSNickeau        }
20404fd306cSNickeau        $obj = plugin_load('syntax', $componentName);
20504fd306cSNickeau        if ($obj === null) {
20604fd306cSNickeau            throw new ExceptionRuntimeInternal("The component tag ($componentName) does not exists");
20704fd306cSNickeau        }
20804fd306cSNickeau
20937748cd8SNickeau        $call = [
21037748cd8SNickeau            "plugin",
21137748cd8SNickeau            array(
21204fd306cSNickeau                $componentName,
21337748cd8SNickeau                $data,
21437748cd8SNickeau                $state,
21537748cd8SNickeau                $content
21637748cd8SNickeau            ),
21737748cd8SNickeau            $positionInText
21837748cd8SNickeau        ];
21937748cd8SNickeau        return new Call($call);
22037748cd8SNickeau    }
22137748cd8SNickeau
22237748cd8SNickeau    /**
22337748cd8SNickeau     * Insert a dokuwiki call
22437748cd8SNickeau     * @param $callName
22537748cd8SNickeau     * @param $array
22637748cd8SNickeau     * @param $positionInText
22737748cd8SNickeau     * @return Call
22837748cd8SNickeau     */
2294cadd4f8SNickeau    public static function createNativeCall($callName, $array = [], $positionInText = null): Call
23037748cd8SNickeau    {
23137748cd8SNickeau        $call = [
23237748cd8SNickeau            $callName,
23337748cd8SNickeau            $array,
23437748cd8SNickeau            $positionInText
23537748cd8SNickeau        ];
23637748cd8SNickeau        return new Call($call);
23737748cd8SNickeau    }
23837748cd8SNickeau
23904fd306cSNickeau    public static function createFromInstruction($instruction): Call
24037748cd8SNickeau    {
24137748cd8SNickeau        return new Call($instruction);
24237748cd8SNickeau    }
24337748cd8SNickeau
2444cadd4f8SNickeau    /**
2454cadd4f8SNickeau     * @param Call $call
2464cadd4f8SNickeau     * @return Call
2474cadd4f8SNickeau     */
2484cadd4f8SNickeau    public static function createFromCall(Call $call): Call
2494cadd4f8SNickeau    {
2504cadd4f8SNickeau        return self::createFromInstruction($call->toCallArray());
2514cadd4f8SNickeau    }
2524cadd4f8SNickeau
25337748cd8SNickeau
25437748cd8SNickeau    /**
25537748cd8SNickeau     *
25637748cd8SNickeau     * Return the tag name from a call array
25737748cd8SNickeau     *
25837748cd8SNickeau     * This is not the logical tag.
25937748cd8SNickeau     * This is much more what's called:
26037748cd8SNickeau     *   * the component name for a plugin
26137748cd8SNickeau     *   * or the handler name for dokuwiki
26237748cd8SNickeau     *
26337748cd8SNickeau     * For a plugin, this is equivalent
26437748cd8SNickeau     * to the {@link SyntaxPlugin::getPluginComponent()}
26537748cd8SNickeau     *
26637748cd8SNickeau     * This is not the fully qualified component name:
26737748cd8SNickeau     *   * with the plugin as prefix such as in {@link Call::getComponentName()}
26837748cd8SNickeau     *   * or with the `open` and `close` prefix such as `p_close` ...
26937748cd8SNickeau     *
27037748cd8SNickeau     * @return mixed|string
27137748cd8SNickeau     */
27237748cd8SNickeau    public function getTagName()
27337748cd8SNickeau    {
27404fd306cSNickeau
27537748cd8SNickeau        $mode = $this->call[0];
27637748cd8SNickeau        if ($mode != "plugin") {
27737748cd8SNickeau
27837748cd8SNickeau            /**
27937748cd8SNickeau             * This is a standard dokuwiki node
28037748cd8SNickeau             */
28137748cd8SNickeau            $dokuWikiNodeName = $this->call[0];
28237748cd8SNickeau
28337748cd8SNickeau            /**
28437748cd8SNickeau             * The dokwuiki node name has also the open and close notion
28537748cd8SNickeau             * We delete this is not in the doc and therefore not logical
28637748cd8SNickeau             */
28737748cd8SNickeau            $tagName = str_replace("_close", "", $dokuWikiNodeName);
28804fd306cSNickeau            return str_replace("_open", "", $tagName);
28904fd306cSNickeau        }
29037748cd8SNickeau
29137748cd8SNickeau        /**
29237748cd8SNickeau         * This is a plugin node
29337748cd8SNickeau         */
29437748cd8SNickeau        $pluginDokuData = $this->call[1];
29504fd306cSNickeau
29604fd306cSNickeau        /**
29704fd306cSNickeau         * If the tag is set
29804fd306cSNickeau         */
29904fd306cSNickeau        $pluginData = $pluginDokuData[1];
30004fd306cSNickeau        if (isset($pluginData[PluginUtility::TAG])) {
30104fd306cSNickeau            return $pluginData[PluginUtility::TAG];
30204fd306cSNickeau        }
30304fd306cSNickeau
30437748cd8SNickeau        $component = $pluginDokuData[0];
30537748cd8SNickeau        if (!is_array($component)) {
30637748cd8SNickeau            /**
30737748cd8SNickeau             * Tag name from class
30837748cd8SNickeau             */
30937748cd8SNickeau            $componentNames = explode("_", $component);
31037748cd8SNickeau            /**
31137748cd8SNickeau             * To take care of
31237748cd8SNickeau             * PHP Warning:  sizeof(): Parameter must be an array or an object that implements Countable
31337748cd8SNickeau             * in lib/plugins/combo/class/Tag.php on line 314
31437748cd8SNickeau             */
31537748cd8SNickeau            if (is_array($componentNames)) {
31637748cd8SNickeau                $tagName = $componentNames[sizeof($componentNames) - 1];
31737748cd8SNickeau            } else {
31837748cd8SNickeau                $tagName = $component;
31937748cd8SNickeau            }
32037748cd8SNickeau            return $tagName;
32104fd306cSNickeau        }
32204fd306cSNickeau
32304fd306cSNickeau        // To resolve: explode() expects parameter 2 to be string, array given
32404fd306cSNickeau        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);
32504fd306cSNickeau        return "";
32604fd306cSNickeau
32737748cd8SNickeau
32837748cd8SNickeau    }
32937748cd8SNickeau
33037748cd8SNickeau
33137748cd8SNickeau    /**
33237748cd8SNickeau     * The parser state
33337748cd8SNickeau     * @return mixed
33437748cd8SNickeau     * May be null (example eol, internallink, ...)
33537748cd8SNickeau     */
33604fd306cSNickeau    public
33704fd306cSNickeau    function getState()
33837748cd8SNickeau    {
33937748cd8SNickeau        $mode = $this->call[0];
3404cadd4f8SNickeau        if ($mode !== "plugin") {
34137748cd8SNickeau
34237748cd8SNickeau            /**
34337748cd8SNickeau             * There is no state because this is a standard
34437748cd8SNickeau             * dokuwiki syntax found in {@link \Doku_Renderer_xhtml}
34537748cd8SNickeau             * check if this is not a `...._close` or `...._open`
34637748cd8SNickeau             * to derive the state
34737748cd8SNickeau             */
34837748cd8SNickeau            $mode = $this->call[0];
34937748cd8SNickeau            $lastPositionSepName = strrpos($mode, "_");
35037748cd8SNickeau            $closeOrOpen = substr($mode, $lastPositionSepName + 1);
35137748cd8SNickeau            switch ($closeOrOpen) {
35237748cd8SNickeau                case "open":
35337748cd8SNickeau                    return DOKU_LEXER_ENTER;
35437748cd8SNickeau                case "close":
35537748cd8SNickeau                    return DOKU_LEXER_EXIT;
35637748cd8SNickeau                default:
35704fd306cSNickeau                    /**
35804fd306cSNickeau                     * Let op null, is used
35904fd306cSNickeau                     * in {@link CallStack::processEolToEndStack()}
36004fd306cSNickeau                     * and things can break
36104fd306cSNickeau                     */
36237748cd8SNickeau                    return null;
36337748cd8SNickeau            }
36437748cd8SNickeau
36537748cd8SNickeau        } else {
36637748cd8SNickeau            // Plugin
36737748cd8SNickeau            $returnedArray = $this->call[1];
36837748cd8SNickeau            if (array_key_exists(2, $returnedArray)) {
36937748cd8SNickeau                return $returnedArray[2];
37037748cd8SNickeau            } else {
37137748cd8SNickeau                return null;
37237748cd8SNickeau            }
37337748cd8SNickeau        }
37437748cd8SNickeau    }
37537748cd8SNickeau
37637748cd8SNickeau    /**
37737748cd8SNickeau     * @return mixed the data returned from the {@link DokuWiki_Syntax_Plugin::handle} (ie attributes, payload, ...)
378040d4aeaSgerardnico     * It may be any type. Array, scalar
37937748cd8SNickeau     */
38004fd306cSNickeau    public
38104fd306cSNickeau    function &getPluginData($attribute = null)
38237748cd8SNickeau    {
3834cadd4f8SNickeau        $data = &$this->call[1][1];
3844cadd4f8SNickeau        if ($attribute === null) {
3854cadd4f8SNickeau            return $data;
3864cadd4f8SNickeau        }
3874cadd4f8SNickeau        return $data[$attribute];
3884cadd4f8SNickeau
38937748cd8SNickeau    }
39037748cd8SNickeau
39137748cd8SNickeau    /**
39237748cd8SNickeau     * @return mixed the matched content from the {@link DokuWiki_Syntax_Plugin::handle}
39337748cd8SNickeau     */
39404fd306cSNickeau    public
39504fd306cSNickeau    function getCapturedContent()
39637748cd8SNickeau    {
39737748cd8SNickeau        $caller = $this->call[0];
39837748cd8SNickeau        switch ($caller) {
39937748cd8SNickeau            case "plugin":
40037748cd8SNickeau                return $this->call[1][3];
40137748cd8SNickeau            case "internallink":
40237748cd8SNickeau                return '[[' . $this->call[1][0] . '|' . $this->call[1][1] . ']]';
40337748cd8SNickeau            case "eol":
40437748cd8SNickeau                return DOKU_LF;
40537748cd8SNickeau            case "header":
40637748cd8SNickeau            case "cdata":
40737748cd8SNickeau                return $this->call[1][0];
40837748cd8SNickeau            default:
40937748cd8SNickeau                if (isset($this->call[1][0]) && is_string($this->call[1][0])) {
41037748cd8SNickeau                    return $this->call[1][0];
41137748cd8SNickeau                } else {
41237748cd8SNickeau                    return "";
41337748cd8SNickeau                }
41437748cd8SNickeau        }
41537748cd8SNickeau    }
41637748cd8SNickeau
41737748cd8SNickeau
41804fd306cSNickeau    /**
419040d4aeaSgerardnico     * Return the attributes of a call
42004fd306cSNickeau     */
42104fd306cSNickeau    public
422040d4aeaSgerardnico    function &getAttributes(): array
42337748cd8SNickeau    {
42437748cd8SNickeau
42504fd306cSNickeau        $isPluginCall = $this->isPluginCall();
42604fd306cSNickeau        if (!$isPluginCall) {
42737748cd8SNickeau            return $this->call[1];
428040d4aeaSgerardnico        }
429040d4aeaSgerardnico
43004fd306cSNickeau        $data = &$this->getPluginData();
43104fd306cSNickeau        if (!is_array($data)) {
43204fd306cSNickeau            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);
433040d4aeaSgerardnico            // We discard, it may be a third party plugin
434040d4aeaSgerardnico            // The log will throw an error if it's on our hand
43504fd306cSNickeau            $data = [];
43604fd306cSNickeau            return $data;
4374cadd4f8SNickeau        }
43804fd306cSNickeau        if (!isset($data[PluginUtility::ATTRIBUTES])) {
43904fd306cSNickeau            $data[PluginUtility::ATTRIBUTES] = [];
44004fd306cSNickeau        }
44104fd306cSNickeau        $attributes = &$data[PluginUtility::ATTRIBUTES];
44204fd306cSNickeau        if (!is_array($attributes)) {
44304fd306cSNickeau            $message = "The attributes value are not an array for the call ($this), the value was wrapped in an array";
44404fd306cSNickeau            LogUtility::error($message, self::CANONICAL);
44504fd306cSNickeau            $attributes = [$attributes];
4464cadd4f8SNickeau        }
4474cadd4f8SNickeau        return $attributes;
44837748cd8SNickeau    }
44937748cd8SNickeau
45004fd306cSNickeau    public
45104fd306cSNickeau    function removeAttributes()
45237748cd8SNickeau    {
45337748cd8SNickeau
45437748cd8SNickeau        $data = &$this->getPluginData();
45537748cd8SNickeau        if (isset($data[PluginUtility::ATTRIBUTES])) {
45637748cd8SNickeau            unset($data[PluginUtility::ATTRIBUTES]);
45737748cd8SNickeau        }
45837748cd8SNickeau
45937748cd8SNickeau    }
46037748cd8SNickeau
46104fd306cSNickeau    public
46204fd306cSNickeau    function updateToPluginComponent($component, $state, $attributes = array())
46337748cd8SNickeau    {
46437748cd8SNickeau        if ($this->call[0] == "plugin") {
46537748cd8SNickeau            $match = $this->call[1][3];
46637748cd8SNickeau        } else {
46737748cd8SNickeau            $this->call[0] = "plugin";
46837748cd8SNickeau            $match = "";
46937748cd8SNickeau        }
47037748cd8SNickeau        $this->call[1] = array(
47137748cd8SNickeau            0 => $component,
47237748cd8SNickeau            1 => array(
47337748cd8SNickeau                PluginUtility::ATTRIBUTES => $attributes,
47437748cd8SNickeau                PluginUtility::STATE => $state,
47537748cd8SNickeau            ),
47637748cd8SNickeau            2 => $state,
47737748cd8SNickeau            3 => $match
47837748cd8SNickeau        );
47937748cd8SNickeau
48037748cd8SNickeau    }
48137748cd8SNickeau
4821fa8c418SNickeau    /**
4831fa8c418SNickeau     * Does the display has been set
4841fa8c418SNickeau     * to override the dokuwiki default
4851fa8c418SNickeau     * ({@link Syntax::getPType()}
4861fa8c418SNickeau     *
4871fa8c418SNickeau     * because an image is by default a inline component
4881fa8c418SNickeau     * but can be a block (ie top image of a card)
4891fa8c418SNickeau     * @return bool
4901fa8c418SNickeau     */
49104fd306cSNickeau    public
49204fd306cSNickeau    function isDisplaySet(): bool
4931fa8c418SNickeau    {
4941fa8c418SNickeau        return isset($this->call[1][1][PluginUtility::DISPLAY]);
4951fa8c418SNickeau    }
4961fa8c418SNickeau
49704fd306cSNickeau    /**
49804fd306cSNickeau     * @return string|null
49904fd306cSNickeau     * {@link Call::INLINE_DISPLAY} or {@link Call::BlOCK_DISPLAY}
50004fd306cSNickeau     */
50104fd306cSNickeau    public
50204fd306cSNickeau    function getDisplay(): ?string
50337748cd8SNickeau    {
5041fa8c418SNickeau        $mode = $this->getMode();
5051fa8c418SNickeau        if ($mode == "plugin") {
5061fa8c418SNickeau            if ($this->isDisplaySet()) {
5071fa8c418SNickeau                return $this->call[1][1][PluginUtility::DISPLAY];
5081fa8c418SNickeau            }
5091fa8c418SNickeau        }
5101fa8c418SNickeau
51137748cd8SNickeau        if ($this->getState() == DOKU_LEXER_UNMATCHED) {
51237748cd8SNickeau            /**
51337748cd8SNickeau             * Unmatched are content (ie text node in XML/HTML) and have
51437748cd8SNickeau             * no display
51537748cd8SNickeau             */
51637748cd8SNickeau            return Call::INLINE_DISPLAY;
51737748cd8SNickeau        } else {
51837748cd8SNickeau            $mode = $this->call[0];
51937748cd8SNickeau            if ($mode == "plugin") {
52037748cd8SNickeau                global $DOKU_PLUGINS;
52137748cd8SNickeau                $component = $this->getComponentName();
52237748cd8SNickeau                /**
52337748cd8SNickeau                 * @var SyntaxPlugin $syntaxPlugin
52437748cd8SNickeau                 */
52537748cd8SNickeau                $syntaxPlugin = $DOKU_PLUGINS['syntax'][$component];
5267dbcdecdSNico                if ($syntaxPlugin === null) {
5277dbcdecdSNico                    // not a syntax plugin (ie frontmatter)
5287dbcdecdSNico                    return null;
5297dbcdecdSNico                }
53037748cd8SNickeau                $pType = $syntaxPlugin->getPType();
53137748cd8SNickeau                switch ($pType) {
532dff3a8c8SNico                    // https://www.dokuwiki.org/devel:syntax_plugins#syntax_types
533dff3a8c8SNico                    case "substition":
53437748cd8SNickeau                    case "normal":
53537748cd8SNickeau                        return Call::INLINE_DISPLAY;
53637748cd8SNickeau                    case "block":
53737748cd8SNickeau                    case "stack":
53837748cd8SNickeau                        return Call::BlOCK_DISPLAY;
53937748cd8SNickeau                    default:
54037748cd8SNickeau                        LogUtility::msg("The ptype (" . $pType . ") is unknown.");
54137748cd8SNickeau                        return null;
54237748cd8SNickeau                }
54337748cd8SNickeau            } else {
54437748cd8SNickeau                if ($mode == "eol") {
54537748cd8SNickeau                    /**
54637748cd8SNickeau                     * Control character
54737748cd8SNickeau                     * We return it as it's used in the
54837748cd8SNickeau                     * {@link \syntax_plugin_combo_para::fromEolToParagraphUntilEndOfStack()}
54937748cd8SNickeau                     * to create the paragraph
55037748cd8SNickeau                     * This is not a block, nor an inline
55137748cd8SNickeau                     */
55237748cd8SNickeau                    return $mode;
55337748cd8SNickeau                }
55437748cd8SNickeau
55537748cd8SNickeau                if (in_array($mode, self::INLINE_DOKUWIKI_COMPONENTS)) {
55637748cd8SNickeau                    return Call::INLINE_DISPLAY;
55737748cd8SNickeau                }
55837748cd8SNickeau
55937748cd8SNickeau                if (in_array($mode, self::BLOCK_MARKUP_DOKUWIKI_COMPONENTS)) {
56037748cd8SNickeau                    return Call::BlOCK_DISPLAY;
56137748cd8SNickeau                }
56237748cd8SNickeau
56304fd306cSNickeau                if (in_array($mode, self::TABLE_MARKUP)) {
56404fd306cSNickeau                    return Call::TABLE_DISPLAY;
56504fd306cSNickeau                }
56604fd306cSNickeau
56704fd306cSNickeau                LogUtility::warning("The display of the call with the mode (" . $mode . ") is unknown");
56837748cd8SNickeau                return null;
56937748cd8SNickeau
57037748cd8SNickeau
57137748cd8SNickeau            }
57237748cd8SNickeau        }
57337748cd8SNickeau
57437748cd8SNickeau    }
57537748cd8SNickeau
57637748cd8SNickeau    /**
57737748cd8SNickeau     * Same as {@link Call::getTagName()}
57837748cd8SNickeau     * but fully qualified
57937748cd8SNickeau     * @return string
58037748cd8SNickeau     */
58104fd306cSNickeau    public
58204fd306cSNickeau    function getComponentName()
58337748cd8SNickeau    {
58437748cd8SNickeau        $mode = $this->call[0];
58537748cd8SNickeau        if ($mode == "plugin") {
58637748cd8SNickeau            $pluginDokuData = $this->call[1];
58737748cd8SNickeau            return $pluginDokuData[0];
58837748cd8SNickeau        } else {
58937748cd8SNickeau            return $mode;
59037748cd8SNickeau        }
59137748cd8SNickeau    }
59237748cd8SNickeau
59304fd306cSNickeau    public
59404fd306cSNickeau    function updateEolToSpace()
59537748cd8SNickeau    {
59637748cd8SNickeau        $mode = $this->call[0];
59737748cd8SNickeau        if ($mode != "eol") {
59837748cd8SNickeau            LogUtility::msg("You can't update a " . $mode . " to a space. It should be a eol", LogUtility::LVL_MSG_WARNING, "support");
59937748cd8SNickeau        } else {
60037748cd8SNickeau            $this->call[0] = "cdata";
60137748cd8SNickeau            $this->call[1] = array(
60237748cd8SNickeau                0 => " "
60337748cd8SNickeau            );
60437748cd8SNickeau        }
60537748cd8SNickeau
60637748cd8SNickeau    }
60737748cd8SNickeau
60804fd306cSNickeau    public
60904fd306cSNickeau    function &addAttribute($key, $value)
61037748cd8SNickeau    {
61137748cd8SNickeau        $mode = $this->call[0];
61237748cd8SNickeau        if ($mode == "plugin") {
61337748cd8SNickeau            $this->call[1][1][PluginUtility::ATTRIBUTES][$key] = $value;
61404fd306cSNickeau            // keep the new reference
61504fd306cSNickeau            return $this->call[1][1][PluginUtility::ATTRIBUTES][$key];
61637748cd8SNickeau        } else {
61737748cd8SNickeau            LogUtility::msg("You can't add an attribute to the non plugin call mode (" . $mode . ")", LogUtility::LVL_MSG_WARNING, "support");
61804fd306cSNickeau            $whatever = [];
61904fd306cSNickeau            return $whatever;
62037748cd8SNickeau        }
62137748cd8SNickeau    }
62237748cd8SNickeau
62304fd306cSNickeau    public
62404fd306cSNickeau    function getContext()
62537748cd8SNickeau    {
62637748cd8SNickeau        $mode = $this->call[0];
62704fd306cSNickeau        if ($mode === "plugin") {
62870bbd7f1Sgerardnico            return $this->call[1][1][PluginUtility::CONTEXT] ?? null;
62937748cd8SNickeau        } else {
63037748cd8SNickeau            LogUtility::msg("You can't ask for a context from a non plugin call mode (" . $mode . ")", LogUtility::LVL_MSG_WARNING, "support");
63137748cd8SNickeau            return null;
63237748cd8SNickeau        }
63337748cd8SNickeau    }
63437748cd8SNickeau
63537748cd8SNickeau    /**
63637748cd8SNickeau     *
63737748cd8SNickeau     * @return array
63837748cd8SNickeau     */
63904fd306cSNickeau    public
64004fd306cSNickeau    function toCallArray()
64137748cd8SNickeau    {
64237748cd8SNickeau        return $this->call;
64337748cd8SNickeau    }
64437748cd8SNickeau
64504fd306cSNickeau    public
64604fd306cSNickeau    function __toString()
64737748cd8SNickeau    {
64837748cd8SNickeau        $name = $this->key;
64937748cd8SNickeau        if (!empty($name)) {
65037748cd8SNickeau            $name .= " - ";
65137748cd8SNickeau        }
65237748cd8SNickeau        $name .= $this->getTagName();
65304fd306cSNickeau        $name .= " - {$this->getStateName()}";
65437748cd8SNickeau        return $name;
65537748cd8SNickeau    }
65637748cd8SNickeau
6574cadd4f8SNickeau    /**
6584cadd4f8SNickeau     * @return string|null
6594cadd4f8SNickeau     *
6604cadd4f8SNickeau     * If the type returned is a boolean attribute,
6614cadd4f8SNickeau     * it means you need to define the expected types
6624cadd4f8SNickeau     * in the function {@link TagAttributes::createFromTagMatch()}
6634cadd4f8SNickeau     * as third attribute
6644cadd4f8SNickeau     */
66504fd306cSNickeau    public
66604fd306cSNickeau    function getType(): ?string
66737748cd8SNickeau    {
66837748cd8SNickeau        if ($this->getState() == DOKU_LEXER_UNMATCHED) {
66937748cd8SNickeau            return null;
67037748cd8SNickeau        } else {
6714cadd4f8SNickeau            return $this->getAttribute(TagAttributes::TYPE_KEY);
67237748cd8SNickeau        }
67337748cd8SNickeau    }
67437748cd8SNickeau
67537748cd8SNickeau    /**
67637748cd8SNickeau     * @param $key
67737748cd8SNickeau     * @param null $default
6784cadd4f8SNickeau     * @return array|string|null
67937748cd8SNickeau     */
68004fd306cSNickeau    public
68104fd306cSNickeau    function &getAttribute($key, $default = null)
68237748cd8SNickeau    {
68304fd306cSNickeau        $attributes = &$this->getAttributes();
68437748cd8SNickeau        if (isset($attributes[$key])) {
68537748cd8SNickeau            return $attributes[$key];
6864cadd4f8SNickeau        }
68737748cd8SNickeau        return $default;
6884cadd4f8SNickeau
68937748cd8SNickeau    }
69037748cd8SNickeau
6914cadd4f8SNickeau    public
6924cadd4f8SNickeau    function getPayload()
69337748cd8SNickeau    {
69437748cd8SNickeau        $mode = $this->call[0];
69537748cd8SNickeau        if ($mode == "plugin") {
69637748cd8SNickeau            return $this->call[1][1][PluginUtility::PAYLOAD];
69737748cd8SNickeau        } else {
69837748cd8SNickeau            LogUtility::msg("You can't ask for a payload from a non plugin call mode (" . $mode . ").", LogUtility::LVL_MSG_WARNING, "support");
69937748cd8SNickeau            return null;
70037748cd8SNickeau        }
70137748cd8SNickeau    }
70237748cd8SNickeau
7034cadd4f8SNickeau    public
7044cadd4f8SNickeau    function setContext($value)
70537748cd8SNickeau    {
70637748cd8SNickeau        $this->call[1][1][PluginUtility::CONTEXT] = $value;
70737748cd8SNickeau        return $this;
70837748cd8SNickeau    }
70937748cd8SNickeau
7104cadd4f8SNickeau    public
7114cadd4f8SNickeau    function hasAttribute($attributeName): bool
71237748cd8SNickeau    {
71337748cd8SNickeau        $attributes = $this->getAttributes();
71437748cd8SNickeau        if (isset($attributes[$attributeName])) {
71537748cd8SNickeau            return true;
71637748cd8SNickeau        } else {
71737748cd8SNickeau            if ($this->getType() == $attributeName) {
71837748cd8SNickeau                return true;
71937748cd8SNickeau            } else {
72037748cd8SNickeau                return false;
72137748cd8SNickeau            }
72237748cd8SNickeau        }
72337748cd8SNickeau    }
72437748cd8SNickeau
7254cadd4f8SNickeau    public
7264cadd4f8SNickeau    function isPluginCall()
72737748cd8SNickeau    {
72837748cd8SNickeau        return $this->call[0] === "plugin";
72937748cd8SNickeau    }
73037748cd8SNickeau
73137748cd8SNickeau    /**
73237748cd8SNickeau     * @return mixed|string the position (ie key) in the array
73337748cd8SNickeau     */
7344cadd4f8SNickeau    public
7354cadd4f8SNickeau    function getKey()
73637748cd8SNickeau    {
73737748cd8SNickeau        return $this->key;
73837748cd8SNickeau    }
73937748cd8SNickeau
7404cadd4f8SNickeau    public
74104fd306cSNickeau    function &getInstructionCall()
74237748cd8SNickeau    {
74337748cd8SNickeau        return $this->call;
74437748cd8SNickeau    }
74537748cd8SNickeau
7464cadd4f8SNickeau    public
7474cadd4f8SNickeau    function setState($state)
74837748cd8SNickeau    {
74937748cd8SNickeau        if ($this->call[0] == "plugin") {
75037748cd8SNickeau            // for dokuwiki
75137748cd8SNickeau            $this->call[1][2] = $state;
75237748cd8SNickeau            // for the combo plugin if any
75337748cd8SNickeau            if (isset($this->call[1][1][PluginUtility::STATE])) {
75437748cd8SNickeau                $this->call[1][1][PluginUtility::STATE] = $state;
75537748cd8SNickeau            }
75637748cd8SNickeau        } else {
75737748cd8SNickeau            LogUtility::msg("This modification of state is not yet supported for a native call");
75837748cd8SNickeau        }
75937748cd8SNickeau    }
76037748cd8SNickeau
76137748cd8SNickeau
76237748cd8SNickeau    /**
76337748cd8SNickeau     * Return the position of the first matched character in the text file
76437748cd8SNickeau     * @return mixed
76537748cd8SNickeau     */
7664cadd4f8SNickeau    public
7674cadd4f8SNickeau    function getFirstMatchedCharacterPosition()
76837748cd8SNickeau    {
76937748cd8SNickeau
77037748cd8SNickeau        return $this->call[2];
77137748cd8SNickeau
77237748cd8SNickeau    }
77337748cd8SNickeau
77437748cd8SNickeau    /**
77537748cd8SNickeau     * Return the position of the last matched character in the text file
77637748cd8SNickeau     *
77737748cd8SNickeau     * This is the {@link Call::getFirstMatchedCharacterPosition()}
77837748cd8SNickeau     * plus the length of the {@link Call::getCapturedContent()}
77937748cd8SNickeau     * matched content
78037748cd8SNickeau     * @return int|mixed
78137748cd8SNickeau     */
7824cadd4f8SNickeau    public
7834cadd4f8SNickeau    function getLastMatchedCharacterPosition()
78437748cd8SNickeau    {
78570bbd7f1Sgerardnico        $captureContent = $this->getCapturedContent();
78670bbd7f1Sgerardnico        $length = 0;
78770bbd7f1Sgerardnico        if ($captureContent != null) {
78870bbd7f1Sgerardnico            $length = strlen($captureContent);
78970bbd7f1Sgerardnico        }
79070bbd7f1Sgerardnico        return $this->getFirstMatchedCharacterPosition() + $length;
79137748cd8SNickeau    }
79237748cd8SNickeau
79337748cd8SNickeau    /**
79437748cd8SNickeau     * @param $value string the class string to add
79537748cd8SNickeau     * @return Call
79637748cd8SNickeau     */
7974cadd4f8SNickeau    public
7984cadd4f8SNickeau    function addClassName(string $value): Call
79937748cd8SNickeau    {
80037748cd8SNickeau        $class = $this->getAttribute("class");
80137748cd8SNickeau        if ($class != null) {
80237748cd8SNickeau            $value = "$class $value";
80337748cd8SNickeau        }
80437748cd8SNickeau        $this->addAttribute("class", $value);
80537748cd8SNickeau        return $this;
80637748cd8SNickeau
80737748cd8SNickeau    }
80837748cd8SNickeau
80937748cd8SNickeau    /**
81037748cd8SNickeau     * @param $key
81137748cd8SNickeau     * @return mixed|null - the delete value of null if not found
81237748cd8SNickeau     */
8134cadd4f8SNickeau    public
8144cadd4f8SNickeau    function removeAttribute($key)
81537748cd8SNickeau    {
81637748cd8SNickeau
81737748cd8SNickeau        $data = &$this->getPluginData();
81837748cd8SNickeau        if (isset($data[PluginUtility::ATTRIBUTES][$key])) {
81937748cd8SNickeau            $value = $data[PluginUtility::ATTRIBUTES][$key];
82037748cd8SNickeau            unset($data[PluginUtility::ATTRIBUTES][$key]);
82137748cd8SNickeau            return $value;
82237748cd8SNickeau        } else {
82337748cd8SNickeau            // boolean attribute as first attribute
82437748cd8SNickeau            if ($this->getType() == $key) {
82537748cd8SNickeau                unset($data[PluginUtility::ATTRIBUTES][TagAttributes::TYPE_KEY]);
82637748cd8SNickeau                return true;
82737748cd8SNickeau            }
82837748cd8SNickeau            return null;
82937748cd8SNickeau        }
83037748cd8SNickeau
83137748cd8SNickeau    }
83237748cd8SNickeau
8334cadd4f8SNickeau    public
8344cadd4f8SNickeau    function setPayload($text)
83537748cd8SNickeau    {
83637748cd8SNickeau        if ($this->isPluginCall()) {
83737748cd8SNickeau            $this->call[1][1][PluginUtility::PAYLOAD] = $text;
83837748cd8SNickeau        } else {
83937748cd8SNickeau            LogUtility::msg("Setting the payload for a non-native call ($this) is not yet implemented");
84037748cd8SNickeau        }
84137748cd8SNickeau    }
84237748cd8SNickeau
84337748cd8SNickeau    /**
84437748cd8SNickeau     * @return bool true if the call is a text call (same as dom text node)
84537748cd8SNickeau     */
8464cadd4f8SNickeau    public
8474cadd4f8SNickeau    function isTextCall()
84837748cd8SNickeau    {
84937748cd8SNickeau        return (
85037748cd8SNickeau            $this->getState() == DOKU_LEXER_UNMATCHED ||
85137748cd8SNickeau            $this->getTagName() == "cdata" ||
85237748cd8SNickeau            $this->getTagName() == "acronym"
85337748cd8SNickeau        );
85437748cd8SNickeau    }
85537748cd8SNickeau
8564cadd4f8SNickeau    public
8574cadd4f8SNickeau    function setType($type)
85837748cd8SNickeau    {
85937748cd8SNickeau        if ($this->isPluginCall()) {
86037748cd8SNickeau            $this->call[1][1][PluginUtility::ATTRIBUTES][TagAttributes::TYPE_KEY] = $type;
86137748cd8SNickeau        } else {
86237748cd8SNickeau            LogUtility::msg("This is not a plugin call ($this), you can't set the type");
86337748cd8SNickeau        }
86437748cd8SNickeau    }
86537748cd8SNickeau
8664cadd4f8SNickeau    public
8674cadd4f8SNickeau    function addCssStyle($key, $value)
86837748cd8SNickeau    {
86937748cd8SNickeau        $style = $this->getAttribute("style");
87037748cd8SNickeau        $cssValue = "$key:$value";
8714cadd4f8SNickeau        if ($style !== null) {
87237748cd8SNickeau            $cssValue = "$style; $cssValue";
87337748cd8SNickeau        }
87437748cd8SNickeau        $this->addAttribute("style", $cssValue);
87537748cd8SNickeau    }
87637748cd8SNickeau
8774cadd4f8SNickeau    public
8784cadd4f8SNickeau    function setSyntaxComponentFromTag($tag)
87937748cd8SNickeau    {
88037748cd8SNickeau
88137748cd8SNickeau        if ($this->isPluginCall()) {
88237748cd8SNickeau            $this->call[1][0] = PluginUtility::getComponentName($tag);
88337748cd8SNickeau        } else {
88437748cd8SNickeau            LogUtility::msg("The call ($this) is a native call and we don't support yet the modification of the component to ($tag)");
88537748cd8SNickeau        }
88637748cd8SNickeau    }
88737748cd8SNickeau
88837748cd8SNickeau
8894cadd4f8SNickeau    public
8904cadd4f8SNickeau    function setCapturedContent($content)
89137748cd8SNickeau    {
89237748cd8SNickeau        $tagName = $this->getTagName();
89337748cd8SNickeau        switch ($tagName) {
89437748cd8SNickeau            case "cdata":
89537748cd8SNickeau                $this->call[1][0] = $content;
89637748cd8SNickeau                break;
89737748cd8SNickeau            default:
89837748cd8SNickeau                LogUtility::msg("Setting the captured content on a call for the tag ($tagName) is not yet implemented", LogUtility::LVL_MSG_ERROR);
89937748cd8SNickeau        }
90037748cd8SNickeau    }
90137748cd8SNickeau
9021fa8c418SNickeau    /**
9031fa8c418SNickeau     * Set the display to block or inline
9041fa8c418SNickeau     * One of `block` or `inline`
9051fa8c418SNickeau     */
9064cadd4f8SNickeau    public
9074cadd4f8SNickeau    function setDisplay($display): Call
9081fa8c418SNickeau    {
9091fa8c418SNickeau        $mode = $this->getMode();
9101fa8c418SNickeau        if ($mode == "plugin") {
9111fa8c418SNickeau            $this->call[1][1][PluginUtility::DISPLAY] = $display;
9121fa8c418SNickeau        } else {
9131fa8c418SNickeau            LogUtility::msg("You can't set a display on a non plugin call mode (" . $mode . ")", LogUtility::LVL_MSG_WARNING);
9141fa8c418SNickeau        }
9151fa8c418SNickeau        return $this;
9161fa8c418SNickeau
9171fa8c418SNickeau    }
9181fa8c418SNickeau
9191fa8c418SNickeau    /**
9201fa8c418SNickeau     * The plugin or not
9211fa8c418SNickeau     * @return mixed
9221fa8c418SNickeau     */
9234cadd4f8SNickeau    private
9244cadd4f8SNickeau    function getMode()
9251fa8c418SNickeau    {
9261fa8c418SNickeau        return $this->call[0];
9271fa8c418SNickeau    }
9281fa8c418SNickeau
9291fa8c418SNickeau    /**
9301fa8c418SNickeau     * Return if this an unmatched call with space
9311fa8c418SNickeau     * in captured content
9321fa8c418SNickeau     * @return bool
9331fa8c418SNickeau     */
9344cadd4f8SNickeau    public
9354cadd4f8SNickeau    function isUnMatchedEmptyCall(): bool
9361fa8c418SNickeau    {
9371fa8c418SNickeau        if ($this->getState() === DOKU_LEXER_UNMATCHED && trim($this->getCapturedContent()) === "") {
9381fa8c418SNickeau            return true;
9391fa8c418SNickeau        }
9401fa8c418SNickeau        return false;
9411fa8c418SNickeau    }
9421fa8c418SNickeau
9434cadd4f8SNickeau    public
9444cadd4f8SNickeau    function getExitCode()
9454cadd4f8SNickeau    {
9464cadd4f8SNickeau        $mode = $this->call[0];
9474cadd4f8SNickeau        if ($mode == "plugin") {
94870bbd7f1Sgerardnico            $value = $this->call[1][1][PluginUtility::EXIT_CODE] ?? null;
9494cadd4f8SNickeau            if ($value === null) {
9504cadd4f8SNickeau                return 0;
9514cadd4f8SNickeau            }
9524cadd4f8SNickeau            return $value;
9534cadd4f8SNickeau        } else {
9544cadd4f8SNickeau            LogUtility::msg("You can't ask for the exit code from a non plugin call mode (" . $mode . ").", LogUtility::LVL_MSG_WARNING, "support");
9554cadd4f8SNickeau            return 0;
9564cadd4f8SNickeau        }
9574cadd4f8SNickeau    }
9584cadd4f8SNickeau
95904fd306cSNickeau    public
96004fd306cSNickeau    function setAttribute(string $name, $value): Call
9614cadd4f8SNickeau    {
962040d4aeaSgerardnico        $this->getAttributes()[$name] = $value;
9634cadd4f8SNickeau        return $this;
9644cadd4f8SNickeau    }
9654cadd4f8SNickeau
96604fd306cSNickeau    public
96704fd306cSNickeau    function setPluginData(string $name, $value): Call
9684cadd4f8SNickeau    {
9694cadd4f8SNickeau        $this->getPluginData()[$name] = $value;
9704cadd4f8SNickeau        return $this;
9714cadd4f8SNickeau    }
9724cadd4f8SNickeau
97304fd306cSNickeau    public
97404fd306cSNickeau    function getIdOrDefault()
97504fd306cSNickeau    {
97604fd306cSNickeau        $id = $this->getAttribute(TagAttributes::ID_KEY);
97704fd306cSNickeau        if ($id !== null) {
97804fd306cSNickeau            return $id;
97904fd306cSNickeau        }
98004fd306cSNickeau        return $this->getAttribute(TagAttributes::GENERATED_ID_KEY);
98104fd306cSNickeau    }
98204fd306cSNickeau
98304fd306cSNickeau    public
98404fd306cSNickeau    function getAttributeAndRemove(string $key)
98504fd306cSNickeau    {
98604fd306cSNickeau        $value = $this->getAttribute($key);
98704fd306cSNickeau        $this->removeAttribute($key);
98804fd306cSNickeau        return $value;
98904fd306cSNickeau    }
99004fd306cSNickeau
99104fd306cSNickeau    private function getStateName(): string
99204fd306cSNickeau    {
99304fd306cSNickeau        $state = $this->getState();
99404fd306cSNickeau        switch ($state) {
99504fd306cSNickeau            case DOKU_LEXER_ENTER:
99604fd306cSNickeau                return "enter";
99704fd306cSNickeau            case DOKU_LEXER_EXIT:
99804fd306cSNickeau                return "exit";
99904fd306cSNickeau            case DOKU_LEXER_SPECIAL:
100004fd306cSNickeau                return "empty";
100104fd306cSNickeau            case DOKU_LEXER_UNMATCHED:
100204fd306cSNickeau                return "text";
100304fd306cSNickeau            default:
100404fd306cSNickeau                return "unknown " . $state;
100504fd306cSNickeau        }
100604fd306cSNickeau    }
100704fd306cSNickeau
100837748cd8SNickeau
100937748cd8SNickeau}
1010