1<?php
2/**
3 * DokuWiki Plugin ifauthex (Syntax Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Pietro Saccardi <lizardm4@gmail.com>
7 */
8
9// must be run within Dokuwiki
10if (!defined('DOKU_INC')) {
11    die();
12}
13
14require_once(__DIR__ . '/lib/grammar.php');
15
16class syntax_plugin_ifauthex extends DokuWiki_Syntax_Plugin
17{
18    /** @inheritDoc */
19    public function getType()
20    {
21        return 'formatting';
22    }
23
24    /** @inheritDoc */
25    function getAllowedTypes()
26    {
27        return array('container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs', 'baseonly');
28    }
29
30    /** @inheritDoc */
31    function getPType()
32    {
33        return 'stack';
34    }
35
36    /** @inheritDoc */
37    public function getSort()
38    {
39        return 195;
40    }
41
42    /** @inheritDoc */
43    public function connectTo($mode)
44    {
45        $this->Lexer->addEntryPattern('<ifauth\b.*?>(?=.*?</ifauth>)', $mode, 'plugin_ifauthex');
46    }
47
48    /** @inheritDoc */
49    public function postConnect()
50    {
51        $this->Lexer->addExitPattern('</ifauth>', 'plugin_ifauthex');
52    }
53
54    /** @inheritDoc */
55    public function handle($match, $state, $pos, Doku_Handler $handler)
56    {
57        global $conf;
58        switch ($state) {
59            case DOKU_LEXER_ENTER:
60                $matches = null;
61                preg_match('/^<ifauth\b(.*?)>$/', $match, $matches);
62                if (is_array($matches) && count($matches) > 0) {
63                    // The last group contains the expression.
64                    // Can't already pre-parse because DokuWiki serializes the
65                    // objects that are returned, but it doesn't know about our
66                    // custom classes at this point.
67                    return array($state, $matches[count($matches) - 1]);
68                }
69                return array($state, null);
70            case DOKU_LEXER_MATCHED:
71                break;
72            case DOKU_LEXER_UNMATCHED:
73                return array($state, $match);
74            case DOKU_LEXER_EXIT:
75                return array($state, null);
76        }
77        return false;
78    }
79
80    /** @inheritDoc */
81    public function render($mode, Doku_Renderer $renderer, $data)
82    {
83        list($state, $exprOrMatch) = $data;
84
85        // never cache
86        $renderer->nocache();
87
88        switch ($state) {
89            case DOKU_LEXER_ENTER:
90                if ($exprOrMatch === null) {
91                    // something went wrong
92                    return false;
93                }
94                try {
95                    // check if current user should see the content
96                    $exprOrMatch = auth_expr_parse($exprOrMatch);
97                    $shouldRender = (bool) $exprOrMatch->evaluate();
98                    if(!$shouldRender) {
99                        // point the renderer's doc to something else, remembering the old one
100                        $renderer->meta['ifauthex.originalDoc'] = &$renderer->doc;
101                        $ignoredDoc = is_array($renderer->doc) ? [] : '';
102                        $renderer->doc = &$ignoredDoc;
103
104                        // do the same for the toc list
105                        $renderer->meta['ifauthex.originalToc'] = &$renderer->toc;
106                        $ignoredToc = [];
107                        $renderer->toc = &$ignoredToc;
108
109                        $renderer->meta['ifauthex.isDiverted'] = true;
110
111                    }
112                } catch (Exception $e) {
113                    // something went wrong parsing the expression
114                    msg(hsc($e->getMessage()), -1);
115                    return false;
116                }
117                break;
118            case DOKU_LEXER_UNMATCHED:
119                $renderer->cdata($exprOrMatch);
120                break;
121            case DOKU_LEXER_EXIT:
122                // point the renderer's doc and toc back to the original
123                if($renderer->meta['ifauthex.isDiverted']) {
124                    $renderer->doc = &$renderer->meta['ifauthex.originalDoc'];
125                    $renderer->toc = &$renderer->meta['ifauthex.originalToc'];
126                    $renderer->meta['ifauthex.isDiverted'] = false;
127                }
128                break;
129        }
130
131        return true;
132    }
133}
134
135