1<?php
2
3/**
4 * Plugin QnA: Block syntax
5 *
6 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
7 * @author     Mykola Ostrovskyy <dwpforge@gmail.com>
8 */
9
10class syntax_plugin_qna_block extends DokuWiki_Syntax_Plugin {
11
12    private $mode;
13    private $questionId;
14    private $maxIdLength;
15
16    /**
17     * Constructor
18     */
19    public function __construct() {
20        $this->mode = substr(get_class($this), 7);
21        $this->questionId = array();
22        $this->maxIdLength = 30;
23    }
24
25    /**
26     * What kind of syntax are we?
27     */
28    public function getType() {
29        return 'container';
30    }
31
32    public function getPType() {
33        return 'block';
34    }
35
36    /**
37     * Where to sort in?
38     */
39    public function getSort() {
40        return 55;
41    }
42
43    /**
44     *
45     */
46    public function connectTo($mode) {
47        $this->Lexer->addSpecialPattern('\n\?{3}.*?(?=\n)', $mode, $this->mode);
48        $this->Lexer->addSpecialPattern('\n!{3}', $mode, $this->mode);
49    }
50
51    /**
52     *
53     */
54    public function handle($match, $state, $pos, Doku_Handler $handler) {
55        if ($state == DOKU_LEXER_SPECIAL) {
56            if ($match[1] == '?') {
57                $question = trim(substr($match, 4));
58
59                if ($question != '') {
60                    $identifier = $this->questionToIdentifier($question);
61
62                    $data = array('open_question', $question, $identifier);
63                }
64                else {
65                    $data = array('close_block');
66                }
67            }
68            else {
69                $data = array('open_answer');
70            }
71        }
72        else {
73            $data = false;
74        }
75
76        return $data;
77    }
78
79    /**
80     *
81     */
82    public function render($mode, Doku_Renderer $renderer, $data) {
83        if ($mode == 'xhtml') {
84            list($tag, $style) = explode('_', $data[0]);
85
86            if ($tag == 'open') {
87                $renderer->doc .= '<div class="qna-' . $style . '">' . DOKU_LF;
88
89                if ($style == 'question') {
90                    $renderer->doc .= '<div class="qna-title">';
91                    $renderer->doc .= '<a name="' . $data[2] . '">';
92                    $renderer->doc .= $data[1] . '</a></div>' . DOKU_LF;
93                }
94            }
95            else {
96                $renderer->doc .= '</div>' . DOKU_LF;
97            }
98
99            return true;
100        }
101        elseif ($mode == 'metadata') {
102            if ($data[0] == 'open_question') {
103                $meta['title'] = $data[1];
104                $meta['id'] = $data[2];
105                $meta['level'] = $data[3];
106                $meta['class'] = 'question';
107
108                $renderer->meta['description']['tableofquestions'][] = $meta;
109            }
110
111            return true;
112        }
113
114        return false;
115    }
116
117    /**
118     * Convert a question title to unique identifier
119     */
120    private function questionToIdentifier($title) {
121        $identifier = str_replace(':', '', cleanID($title));
122        $identifier = ltrim($identifier, '0123456789._-');
123
124        if (\dokuwiki\Utf8\PhpString::strlen($identifier) > $this->maxIdLength) {
125            $identifier = \dokuwiki\Utf8\PhpString::substr($identifier, 0, $this->maxIdLength);
126        }
127
128        $identifier = rtrim($identifier, '_');
129
130        if (isset($this->questionId[$identifier])) {
131            $identifier .= '_' . ++$this->questionId[$identifier];
132        }
133        else {
134            $this->questionId[$identifier] = 1;
135        }
136
137        return $identifier;
138    }
139}
140