1<?php
2/**
3 * DokuWiki Plugin htmlok (Syntax Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  saggi <saggi@gmx.de>
7 * @author  Elan Ruusamäe <glen@delfi.ee>
8 */
9
10namespace dokuwiki\plugin\htmlok;
11
12use Doku_Handler;
13use Doku_Renderer;
14
15abstract class BaseSyntaxPlugin extends \dokuwiki\Extension\SyntaxPlugin
16{
17    /** @var string */
18    protected $type = 'protected';
19    /** @var string */
20    protected $ptype;
21    /** @var int */
22    protected $sort;
23    /** @var string */
24    protected $tag;
25    /** @var string */
26    protected $mode;
27    /** @var string|null */
28    protected $class;
29
30    public function getType(): string
31    {
32        return $this->type;
33    }
34
35    public function getPType(): string
36    {
37        return $this->ptype;
38    }
39
40    public function getSort(): int
41    {
42        return $this->sort;
43    }
44
45    public function connectTo($mode)
46    {
47        $this->Lexer->addEntryPattern("<{$this->tag}>(?=.*?</{$this->tag}>)", $mode, $this->mode);
48    }
49
50    public function postConnect()
51    {
52        $this->Lexer->addExitPattern("</{$this->tag}>", $this->mode);
53    }
54
55    public function handle($match, $state, $pos, Doku_Handler $handler): array
56    {
57        switch ($state) {
58            case DOKU_LEXER_ENTER:
59                return [$state, $match];
60            case DOKU_LEXER_UNMATCHED:
61                return [$state, $match];
62            case DOKU_LEXER_EXIT:
63                return [$state, ''];
64        }
65
66        return [];
67    }
68
69    public function render($mode, Doku_Renderer $renderer, $data): bool
70    {
71        if ($mode !== 'xhtml') {
72            return false;
73        }
74
75        [$state, $match] = $data;
76        switch ($state) {
77            case DOKU_LEXER_ENTER:
78                if ($this->ptype === 'block') {
79                    $renderer->doc .= '<div class="' . $this->class . '">' . DOKU_LF;
80                }
81                break;
82            case DOKU_LEXER_UNMATCHED:
83                $renderer->doc .= $this->renderMatch($match);
84                break;
85            case DOKU_LEXER_EXIT:
86                if ($this->ptype === 'block') {
87                    $renderer->doc .= '</div>' . DOKU_LF;
88                }
89                break;
90        }
91
92        return true;
93    }
94
95    abstract protected function renderMatch(string $match): string;
96
97    /**
98     * Execute PHP code if allowed
99     *
100     * @param string $text PHP code that is either executed or printed
101     * @param string $wrapper html element to wrap result if $conf['phpok'] is okff
102     *
103     * @author Andreas Gohr <andi@splitbrain.org>
104     * @author Elan Ruusamäe <glen@delfi.ee>
105     */
106    protected function php(string $text, string $wrapper = 'code'): string
107    {
108        if ($this->getConf('phpok')) {
109            ob_start();
110            eval($text);
111            $contents= ob_get_contents();
112            ob_end_clean();
113            return $contents;
114        }
115
116        return p_xhtml_cached_geshi($text, 'php', $wrapper);
117    }
118
119    /**
120     * Output block level PHP code
121     *
122     * If 'phpok' is true this should evaluate the given code and append the result
123     * to document.
124     *
125     * @param string $text The PHP code
126     */
127    protected function phpblock(string $text): string
128    {
129        return $this->php($text, 'pre');
130    }
131
132    /**
133     * Insert HTML if allowed
134     *
135     * @param string $text html text
136     * @param string $wrapper html element to wrap result if 'htmlok' is ok.
137     *
138     * @author Andreas Gohr <andi@splitbrain.org>
139     * @author Elan Ruusamäe <glen@delfi.ee>
140     */
141    protected function html(string $text, string $wrapper = 'code'): string
142    {
143        if ($this->getConf('htmlok')) {
144            return $text;
145        }
146
147        return p_xhtml_cached_geshi($text, 'html4strict', $wrapper);
148    }
149
150    /**
151     * Output raw block-level HTML
152     *
153     * If $conf['htmlok'] is true this should add the code as is to $doc
154     *
155     * @param string $text The HTML
156     */
157    protected function htmlblock(string $text): string
158    {
159        return $this->html($text, 'pre');
160    }
161}
162