1 <?php
2 /**
3  * The syntax plugin to handle <content> tags
4  *
5  */
6 
7 require_once(dirname(__FILE__).'/../conf.php');
8 require_once(dirname(__FILE__).'/tools.php');
9 require_once DOKU_PLUGIN . 'syntax.php';
10 require_once DOKU_INC . 'inc/geshi.php';
11 
12 class 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 ?>