1<?php
2/**
3 * DokuWiki Plugin embeddedphp (Syntax Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  fiwswe <dwplugin@fwml.de>
7 */
8class syntax_plugin_embeddedphp_phpinline extends \dokuwiki\Extension\SyntaxPlugin
9{
10    /**
11     * Return the tag this plugin instance reacts to
12     *
13     * @return string
14     */
15    public function GetTag(): string
16    {
17    	return 'php';
18    }
19
20    /** @inheritDoc */
21    public function getType()
22    {
23        return 'formatting';
24    }
25
26    /** @inheritDoc */
27    public function getPType()
28    {
29        return 'normal';
30    }
31
32    /** @inheritDoc */
33    public function getSort()
34    {
35        // The default <php>/<PHP> handler up to "Igor" has priority 180. By setting a
36        // lower priority we override the built-in functionality.
37        return 179;
38    }
39
40    /*
41     * Return the plugin Lexer mode
42     *
43     * @return string
44     */
45    public function getPluginModeName(): string
46    {
47        return 'plugin_'.$this->getPluginName().'_'.$this->getPluginComponent();
48    }
49
50    /** @inheritDoc */
51    public function connectTo($mode)
52    {
53        $p = '<'.$this->GetTag().'>(?=.*?</'.$this->GetTag().'>)';
54        $m = $this->getPluginModeName();
55        $this->Lexer->addEntryPattern($p, $mode, $m);
56    }
57
58    /** @inheritDoc */
59    public function postConnect()
60    {
61        $p = '</'.$this->GetTag().'>';
62        $m = $this->getPluginModeName();
63        $this->Lexer->addExitPattern($p, $m);
64    }
65
66    /** @inheritDoc */
67    public function handle($match, $state, $pos, Doku_Handler $handler)
68    {
69        // If we are parsing a submitted comment. Executing embedded PHP in comments is
70        // not a good idea!
71        if (isset($_REQUEST['comment'])) {
72            return false;
73        }
74
75        switch($state) {
76            case DOKU_LEXER_UNMATCHED :
77                // Return the data needed in $this->render() as an array:
78                return [$state, $match];
79        }
80
81        return false;
82    }
83
84    /** @inheritDoc */
85    public function render($mode, Doku_Renderer $renderer, $data)
86    {
87        if ($mode === 'xhtml') {
88            if (is_array($data) && (count($data) > 1)) {
89                $this->php($data[1], $renderer);
90
91                return true;
92            }
93        }
94
95        return false;
96    }
97
98    /**
99     * Determine whether embedding PHP code is allowed
100     *
101     * @return  bool    true if executing embedded PHP code is allowed
102     */
103    public function allowEmbedding(): bool
104    {
105        $allow = ($this->getConf('embedphpok') == 1) &&
106        		 ($this->getConf('privatewiki') == 1);
107
108        return $allow;
109    }
110
111    /**
112     * Execute PHP code if allowed
113     *
114     * @param  string $text              PHP code that is either executed or printed
115     * @param  Doku_Renderer $renderer   Renderer used for output
116     * @param  string $wrapper           html element to wrap result if executing embedded PHP code is not allowed
117     */
118    public function php($text, Doku_Renderer $renderer, $wrapper = 'code'): void {
119        if($this->allowEmbedding()) {
120            ob_start();
121            eval($text);
122            $o = ob_get_contents();
123            if (!empty($o)) {
124                if ($this->isBlockElement()) {
125                    $renderer->doc .= '<div class="embeddedphp">'.$o.'</div>';
126                } else {
127                    $renderer->doc .= '<span class="embeddedphp">'.$o.'</span>';
128                }
129            }
130            ob_end_clean();
131        } else {
132            $renderer->doc .= /*'###.get_class($this)'.*/p_xhtml_cached_geshi($text, 'php', $wrapper);
133        }
134    }
135
136    /**
137     * Generic test to differentiate between inline and block modes
138     *
139     * @return bool true if this generates a block element, false otherwise.
140     */
141    public function isBlockElement(): bool
142    {
143    	return false;
144    }
145}
146
147