1<?php 2/** 3 * Abstract Syntax Component for the Ad-Hoc Tags Plugin 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Anika Henke <anika@selfthinker.org> 7 * @author Sascha Leib <sascha.leib(at)kolmio.com> 8 */ 9 10class syntax_plugin_adhoctags_abstract extends DokuWiki_Syntax_Plugin { 11 12 protected $tag = null; 13 protected $special_pattern = '<%t%\b[^>\r\n]*?/>'; 14 protected $entry_pattern = '<%t%\b[^>]*>(?=.*?</%t%>)'; 15 protected $exit_pattern = '</%t%>'; 16 protected $enabled = false; /* will be set by the constructors of instances */ 17 protected $output_tag = null; /* allows overriding the tag name for output */ 18 protected $configName = 'allowedElements'; 19 protected $pluginName = 'adhoctags'; 20 21 /* hook to override the registration process, if needed: */ 22 protected function registerTag() { 23 24 $arr = explode(',', $this->getConf($this->configName)); 25 26 return in_array($this->tag, $arr); 27 } 28 29 function getType(){ return 'formatting';} 30 function getAllowedTypes() { 31 return array('container', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs'); 32 } 33 function getPType(){ return 'stack';} 34 function getSort(){ return 195; } 35 // override default accepts() method to allow nesting - ie, to get the plugin accepts its own entry syntax 36 function accepts($mode) { 37 if ($mode == substr(get_class($this), 7)) { 38 return true; 39 } else { 40 return parent::accepts($mode); 41 } 42 } 43 44 /* allow additional attributes by overriding this function: */ 45 function allowAttribute(&$name, &$value) { 46 return false; 47 } 48 49 /** 50 * Connect pattern to lexer 51 */ 52 function connectTo($mode) { 53 54 if ($this->tag && $this->registerTag()) { 55 56 /* debug: 57 if ($mode == 'plugin_adhoctags_pre') 58 dbg('connectTo plugin_adhoctags_pre called for ' . $this->tag .', output = ' . $this->output_tag ); */ 59 60 if ($this->special_pattern !== '') { 61 $this->Lexer->addSpecialPattern(str_replace('%t%', $this->tag, $this->special_pattern),$mode,'plugin_' . $this->pluginName.'_'.$this->getPluginComponent()); 62 } 63 if ($this->entry_pattern !== '') { 64 $this->Lexer->addEntryPattern(str_replace('%t%', $this->tag, $this->entry_pattern),$mode,'plugin_' . $this->pluginName.'_'.$this->getPluginComponent()); 65 } 66 } 67 } 68 function postConnect() { 69 70 if ($this->tag && $this->registerTag()) { 71 if ($this->exit_pattern !== '') { 72 $this->Lexer->addExitPattern(str_replace('%t%', $this->tag, $this->exit_pattern), 'plugin_' . $this->pluginName.'_'.$this->getPluginComponent()); 73 } 74 } 75 } 76 77 /** 78 * Overrideable hooks for different handle states: 79 **/ 80 function handleEnterSpecial($match, $state, $pos, Doku_Handler $handler) { 81 82 //dbg('handleEnterSpecial: "' . $match ); 83 84 $data = trim(substr($match,strpos($match,' '),-1)," \t\n/"); 85 return array($state, $data); 86 } 87 88 function handleUnmatched($match, $state, $pos, Doku_Handler $handler) { 89 global $conf; 90 91 //dbg('handleUnmatched: "' . $match ); 92 93 if (substr($match, 0, 2) == '==') { // special case: it's a headline 94 $title = trim($match); 95 $level = max(7 - strspn($title,'='), 1); 96 $title = trim($title,'= '); 97 98 $handler->_addCall('header',array($title,$level,$pos), $pos); 99 // close the section edit the header could open 100 if ($title && $level <= $conf['maxseclevel']) { 101 $handler->addPluginCall('wrap_closesection', array(), DOKU_LEXER_SPECIAL, $pos, ''); 102 } 103 } else { 104 $handler->addCall('cdata', array($match), $pos); 105 } 106 return false; 107 } 108 109 function handleMatched($match, $state, $pos, Doku_Handler $handler) { 110 111 //dbg('DOKU_LEXER_MATCHED: ' . $match); 112 } 113 114 function handleExit($match, $state, $pos, Doku_Handler $handler) { 115 116 //dbg('handleExit: "' . $match ); 117 118 return array($state, ''); 119 120 } 121 122 /** 123 * Handle the match 124 */ 125 function handle($match, $state, $pos, Doku_Handler $handler){ 126 127 //dbg('handle: "' . $match ); 128 129 switch ($state) { 130 case DOKU_LEXER_ENTER: 131 case DOKU_LEXER_SPECIAL: 132 133 return $this->handleEnterSpecial($match, $state, $pos, $handler); 134 135 case DOKU_LEXER_UNMATCHED : 136 137 return $this->handleUnmatched($match, $state, $pos, $handler); 138 139 case DOKU_LEXER_MATCHED: 140 141 return $this->handleMatched($match, $state, $pos, $handler); 142 143 case DOKU_LEXER_EXIT : 144 145 return array($state, ''); 146 147 } 148 return false; 149 } 150 151 /** 152 * Create output 153 */ 154 function render($format, Doku_Renderer $renderer, $indata) { 155 static $type_stack = array (); 156 157 //dbg('render: format="' . $format .'", indata="' . implode(', ', $indata) . '"'); 158 159 if (empty($indata)) return false; 160 list($state, $data) = $indata; 161 162 // is there an overridden output tag? 163 $outTag = ($this->output_tag ? $this->output_tag : $this->tag); 164 165 if($format == 'xhtml'){ 166 switch ($state) { 167 case DOKU_LEXER_ENTER: 168 case DOKU_LEXER_SPECIAL: 169 $wrap = $this->loadHelper('adhoctags', true); 170 $attr = $wrap->buildAttributes($data, $this); 171 172 $renderer->doc .= '<'.$outTag . $attr.'>'; 173 if ($state == DOKU_LEXER_SPECIAL) $renderer->doc .= '</'.$outTag.'>'; 174 break; 175 176 case DOKU_LEXER_EXIT: 177 $renderer->doc .= '</'.$outTag.'>'; 178 break; 179 } 180 return true; 181 } 182 if($format == 'odt'){ 183 switch ($state) { 184 case DOKU_LEXER_ENTER: 185 array_push ($type_stack, $this->renderODTElementOpen($renderer, $outTag , $data)); 186 break; 187 188 case DOKU_LEXER_SPECIAL: 189 190 191 case DOKU_LEXER_EXIT: 192 $element = array_pop ($type_stack); 193 $this->renderODTElementClose ($renderer, $element); 194 break; 195 } 196 return true; 197 } 198 return false; 199 } 200 201 /** 202 * render ODT element, Open 203 * (get Attributes, select ODT element that fits, render it, return element name) 204 */ 205 function renderODTElementOpen($renderer, $HTMLelement, $data) { 206 //dbg('renderODTElementOpen: ' . $HTMLelement); 207 } 208 209 /** 210 * render ODT element, Close 211 */ 212 function renderODTElementClose($renderer, $element) { 213 //dbg('renderODTElementClose: ' . $element); 214 } 215 216}