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