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 "; 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?>