xref: /plugin/combo/syntax/variable.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
1*04fd306cSNickeau<?php
2*04fd306cSNickeau
3*04fd306cSNickeauuse ComboStrap\ExceptionBadSyntax;
4*04fd306cSNickeauuse ComboStrap\ExecutionContext;
5*04fd306cSNickeauuse ComboStrap\MarkupPath;
6*04fd306cSNickeauuse ComboStrap\PipelineUtility;
7*04fd306cSNickeauuse ComboStrap\PluginUtility;
8*04fd306cSNickeauuse ComboStrap\SlotSystem;
9*04fd306cSNickeauuse ComboStrap\Template;
10*04fd306cSNickeau
11*04fd306cSNickeau
12*04fd306cSNickeau/**
13*04fd306cSNickeau *
14*04fd306cSNickeau * Variable
15*04fd306cSNickeau */
16*04fd306cSNickeauclass syntax_plugin_combo_variable extends DokuWiki_Syntax_Plugin
17*04fd306cSNickeau{
18*04fd306cSNickeau
19*04fd306cSNickeau
20*04fd306cSNickeau    const TAG = "variable";
21*04fd306cSNickeau
22*04fd306cSNickeau
23*04fd306cSNickeau    const CANONICAL = self::TAG;
24*04fd306cSNickeau    const EXPRESSION_ATTRIBUTE = "expression";
25*04fd306cSNickeau
26*04fd306cSNickeau    public static function isVariable($ref): bool
27*04fd306cSNickeau    {
28*04fd306cSNickeau        return substr($ref, 0, 1) === Template::DOLLAR_VARIABLE_PREFIX;
29*04fd306cSNickeau    }
30*04fd306cSNickeau
31*04fd306cSNickeau    /**
32*04fd306cSNickeau     * Template rendering will be context based
33*04fd306cSNickeau     * (first step to delete the template tag)
34*04fd306cSNickeau     * @param string $string
35*04fd306cSNickeau     * @param array|null $contextData
36*04fd306cSNickeau     * @return string
37*04fd306cSNickeau     */
38*04fd306cSNickeau    public static function replaceVariablesWithValuesFromContext(string $string, array $contextData = null): string
39*04fd306cSNickeau    {
40*04fd306cSNickeau        if ($contextData === null) {
41*04fd306cSNickeau            $executionContext = ExecutionContext::getActualOrCreateFromEnv();
42*04fd306cSNickeau            $contextData = $executionContext->getContextData();
43*04fd306cSNickeau        }
44*04fd306cSNickeau        return Template::create($string)->setProperties($contextData)->render();
45*04fd306cSNickeau    }
46*04fd306cSNickeau
47*04fd306cSNickeau
48*04fd306cSNickeau    public function getSort(): int
49*04fd306cSNickeau    {
50*04fd306cSNickeau        return 200;
51*04fd306cSNickeau    }
52*04fd306cSNickeau
53*04fd306cSNickeau    public function getType(): string
54*04fd306cSNickeau    {
55*04fd306cSNickeau        return 'substition';
56*04fd306cSNickeau    }
57*04fd306cSNickeau
58*04fd306cSNickeau
59*04fd306cSNickeau    /**
60*04fd306cSNickeau     *
61*04fd306cSNickeau     * How Dokuwiki will add P element
62*04fd306cSNickeau     *
63*04fd306cSNickeau     *  * 'normal' - The plugin can be used inside paragraphs (inline)
64*04fd306cSNickeau     *  * 'block'  - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs
65*04fd306cSNickeau     *  * 'stack'  - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs
66*04fd306cSNickeau     *
67*04fd306cSNickeau     * @see DokuWiki_Syntax_Plugin::getPType()
68*04fd306cSNickeau     *
69*04fd306cSNickeau     * This is the equivalent of inline or block for css
70*04fd306cSNickeau     */
71*04fd306cSNickeau    public function getPType(): string
72*04fd306cSNickeau    {
73*04fd306cSNickeau        return 'normal';
74*04fd306cSNickeau    }
75*04fd306cSNickeau
76*04fd306cSNickeau    /**
77*04fd306cSNickeau     * @return array
78*04fd306cSNickeau     * Allow which kind of plugin inside
79*04fd306cSNickeau     *
80*04fd306cSNickeau     * No one of array('baseonly','container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs')
81*04fd306cSNickeau     * because we manage self the content and we call self the parser
82*04fd306cSNickeau     *
83*04fd306cSNickeau     * Return an array of one or more of the mode types {@link $PARSER_MODES} in Parser.php
84*04fd306cSNickeau     */
85*04fd306cSNickeau    function getAllowedTypes(): array
86*04fd306cSNickeau    {
87*04fd306cSNickeau        return array();
88*04fd306cSNickeau    }
89*04fd306cSNickeau
90*04fd306cSNickeau
91*04fd306cSNickeau    public function connectTo($mode)
92*04fd306cSNickeau    {
93*04fd306cSNickeau
94*04fd306cSNickeau        $this->Lexer->addSpecialPattern(Template::CAPTURE_PATTERN_SHORT, $mode, PluginUtility::getModeFromTag($this->getPluginComponent()));
95*04fd306cSNickeau        $this->Lexer->addSpecialPattern(Template::CAPTURE_PATTERN_LONG, $mode, PluginUtility::getModeFromTag($this->getPluginComponent()));
96*04fd306cSNickeau
97*04fd306cSNickeau    }
98*04fd306cSNickeau
99*04fd306cSNickeau
100*04fd306cSNickeau    /**
101*04fd306cSNickeau     * Handle the syntax
102*04fd306cSNickeau     *
103*04fd306cSNickeau     * At the end of the parser, the `section_open` and `section_close` calls
104*04fd306cSNickeau     * are created in {@link action_plugin_combo_instructionspostprocessing}
105*04fd306cSNickeau     * and the text inside for the toc is captured
106*04fd306cSNickeau     *
107*04fd306cSNickeau     * @param string $match
108*04fd306cSNickeau     * @param int $state
109*04fd306cSNickeau     * @param int $pos
110*04fd306cSNickeau     * @param Doku_Handler $handler
111*04fd306cSNickeau     * @return array
112*04fd306cSNickeau     */
113*04fd306cSNickeau    public function handle($match, $state, $pos, Doku_Handler $handler): array
114*04fd306cSNickeau    {
115*04fd306cSNickeau        if ($state == DOKU_LEXER_SPECIAL) {
116*04fd306cSNickeau            $lengthLongPrefix = strlen(Template::LONG_PREFIX);
117*04fd306cSNickeau            /**
118*04fd306cSNickeau             * Recreating a pipeline expression
119*04fd306cSNickeau             */
120*04fd306cSNickeau            if (substr($match, 0, $lengthLongPrefix) === Template::LONG_PREFIX) {
121*04fd306cSNickeau                $expression = trim(substr($match, $lengthLongPrefix, -1));
122*04fd306cSNickeau                if (!in_array($expression[0], PipelineUtility::QUOTES_CHARACTERS)) {
123*04fd306cSNickeau                    $expression = "\${$expression}";
124*04fd306cSNickeau                }
125*04fd306cSNickeau            } else {
126*04fd306cSNickeau                $expression = "\"$match\"";
127*04fd306cSNickeau            }
128*04fd306cSNickeau            return [
129*04fd306cSNickeau                self::EXPRESSION_ATTRIBUTE => $expression,
130*04fd306cSNickeau                PluginUtility::STATE => $state
131*04fd306cSNickeau            ];
132*04fd306cSNickeau        }
133*04fd306cSNickeau        return array();
134*04fd306cSNickeau    }
135*04fd306cSNickeau
136*04fd306cSNickeau    public function render($format, $renderer, $data): bool
137*04fd306cSNickeau    {
138*04fd306cSNickeau
139*04fd306cSNickeau        switch ($format) {
140*04fd306cSNickeau            case "xhtml":
141*04fd306cSNickeau            {
142*04fd306cSNickeau                /**
143*04fd306cSNickeau                 * @var Doku_Renderer_xhtml $renderer
144*04fd306cSNickeau                 */
145*04fd306cSNickeau                $state = $data[PluginUtility::STATE];
146*04fd306cSNickeau                if ($state === DOKU_LEXER_SPECIAL) {
147*04fd306cSNickeau                    $expression = $data[self::EXPRESSION_ATTRIBUTE];
148*04fd306cSNickeau                    try {
149*04fd306cSNickeau                        $execute = PipelineUtility::execute($expression);
150*04fd306cSNickeau                    } catch (ExceptionBadSyntax $e) {
151*04fd306cSNickeau                        $renderer->doc .= $e->getMessage();
152*04fd306cSNickeau                        return false;
153*04fd306cSNickeau                    }
154*04fd306cSNickeau                    $renderer->doc .= $execute;
155*04fd306cSNickeau                    return true;
156*04fd306cSNickeau                }
157*04fd306cSNickeau                break;
158*04fd306cSNickeau            }
159*04fd306cSNickeau        }
160*04fd306cSNickeau        return false;
161*04fd306cSNickeau    }
162*04fd306cSNickeau
163*04fd306cSNickeau
164*04fd306cSNickeau}
165