1<?php
2/**
3 * The syntax plugin to handle <content> tags
4 *
5 */
6
7require_once(dirname(__FILE__).'/../conf.php');
8require_once(dirname(__FILE__).'/tools.php');
9require_once DOKU_PLUGIN . 'syntax.php';
10require_once DOKU_INC . 'inc/geshi.php';
11
12class CodeBlock extends DokuWiki_Syntax_Plugin {
13    private $pos = NULL;
14    private $text_pos = NULL;
15    private $text = NULL;
16    private $text_end = NULL;
17    private $end = NULL;
18    private $name = NULL;
19
20    /**
21     * return some info
22     */
23    function getInfo(){
24        return array(
25            'author' => 'Junling Ma',
26            'email'  => 'junlingm@gmail.com',
27            'url'    => 'http://www.math.uvic.ca/~jma'
28        );
29    }
30
31    function tag_name() { return NULL; }
32
33    function getType() {
34        return 'protected';
35    }
36
37    function getSort() {
38        return 8;
39    }
40
41    function syntax_mode() { return "plugin_projects_" . $this->tag_name(); }
42
43    function connectTo($mode) {
44        if ($this->tag_name() == NULL) return;
45        $tag = $this->tag_name();
46        $this->Lexer->addEntryPattern('<' . $tag . '.*?>(?=.*?</' .
47            $tag .'>)', $mode, $this->syntax_mode());
48    }
49
50    function postConnect() {
51        if ($this->tag_name() == NULL) return;
52        $tag = $this->tag_name();
53        $syntax_mode = "plugin_projects_$tag";
54        $this->Lexer->addExitPattern('</' . $tag . '>',
55            $this->syntax_mode());
56    }
57
58    /**
59     * Handle the match
60     */
61    function handle($match, $state, $pos, &$handler){
62        switch ($state) {
63            case DOKU_LEXER_ENTER :
64                $doc = $match . "</" . $this->tag_name() . ">";
65                $xml = DOMDocument::loadXML($doc);
66                $data = array();
67                foreach ($xml->firstChild->attributes as $name => $node)
68                    $data[$name] = $node->value;
69                $data["pos"] = $pos;
70                $data['text_pos'] = $pos + strlen($match);
71                return $data;
72            case DOKU_LEXER_EXIT :
73                return array("end" => $pos + strlen($match) - 1,
74                    'text_end' => $pos);
75            case DOKU_LEXER_UNMATCHED :
76                // skip the first blank line after the tag
77                $l = strlen($match);
78                $i = 0;
79                while ($match[$i] == ' ' || $match[$i] == "\t" || $match[$i] == "\r") {
80                    if ($i == $l) break;
81                    $i++;
82                }
83                if ($i < $l && $match[$i] == "\n") $i++;
84                $match = substr($match, $i);
85                $pos = $pos + $i;
86                // skip the trailing spaces and the last \n
87                $l = strlen($match) - 1;
88                if ($l >= 0 && $match[$l] == "\n") $l--;
89                $match = substr($match, 0, $l + 1);
90                  return array("code" => $match, 'pos' => $pos);
91        }
92        return NULL;
93    }
94
95    /**
96     * Create output
97     */
98
99    protected function add_content($file, $content) {}
100
101    function render($mode, &$renderer, $data) {
102        if (!is_array($data)) return;
103        if ($mode == 'metadata') {
104            if (!isset($data['code'])) return;
105            global $ID;
106            $file = $renderer->meta['ProjectFile'];
107            if ($file != NULL)
108                $this->add_content($file, $data['code']);
109            return;
110        }
111        if ($mode == 'xhtml') {
112            if (isset($data['highlight']))
113                $this->lang = $data['highlight'];
114            else if (!isset($this->lang) || !$this->lang) {
115                global $ID;
116                $this->lang = p_get_metadata($ID, 'ProjectFile:highlight', false);
117                if (!isset($this->lang) || !$this->lang) $this->lang = $this->language();
118                if (!isset($this->lang) || !$this->lang) $this->lang = "unspecified";
119            }
120            $this->render_xhtml($renderer, $data);
121        }
122    }
123
124    private function render_xhtml(&$renderer, $data) {
125        if (isset($data['text_pos'])) {
126            $this->text_pos = $data['text_pos'];
127            $this->name = $data['name'];
128            return;
129        }
130        if (isset($data['code'])) {
131            $this->text = $data['code'];
132            $this->text_pos = $data['pos'];
133            $this->text_end = $this->text_pos + strlen($this->text);
134            return;
135        }
136        if (isset($data['end'])) {
137            if ($this->text_end == NULL) $this->text_end = $data['text_end'];
138            $this->end = $data['end'];
139            // render
140            $renderer->doc .= "<div class=\"code_block\">";
141            $this->render_header($renderer, $data);
142            render_code($renderer, $this->text, $this->lang);
143            // end render
144            $renderer->doc .= "</div>";
145        }
146    }
147
148    function render_header(&$renderer, $data) {
149        $type = ucfirst($this->tag_name());
150        $name = $this->name;
151        // header
152        $renderer->doc .= "<div class=\"code_block_header\">";
153        // type
154        $renderer->doc .= "<div class=\"tag_header\">$type</div>";
155        // name
156        $renderer->doc .= "<div class=\"code_block_name\">$name&nbsp;";
157        $this->render_buttons($renderer, $this->end);
158        //end name
159        $renderer->doc .= "</div>";
160        //end header
161        $renderer->doc .= "</div>";
162    }
163
164    function render_buttons(&$renderer, $end) {
165        // edit button
166        global $ID;
167        if (auth_quickaclcheck($ID) <= AUTH_READ) return;
168        $renderer->doc .= "<div class=\"code_block_buttons\">";
169        include_once(DOKU_INC . 'inc/html.php');
170        $range = $this->text_pos . "-" . $this->text_end;
171        $tag = $this->tag_name();
172        $name = $this->name;
173        if ($name) {
174            $id = $tag . '_' . $name;
175            $name = $tag . ' ' . $name;
176        }
177        else {
178            $id = $tag;
179            $name = $tag;
180        }
181        $data = array(
182            "secid" => $id,
183            'target' => 'projects_wiki_file',
184            'name' => $name,
185            'range' => $range,
186            'lang' => $this->lang);
187        $renderer->doc .= trigger_event('HTML_SECEDIT_BUTTON', $data,
188            'html_secedit_get_button');
189        $renderer->doc .= "</div>";
190    }
191}
192?>