1<?php 2/** 3 * DokuWiki Plugin variants (Syntax Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Michael Hamann <michael@content-space.de> 7 */ 8 9// must be run within Dokuwiki 10if (!defined('DOKU_INC')) die(); 11 12/** 13 * The variants syntax class, defines the if/else syntax 14 */ 15class syntax_plugin_variants_variants extends DokuWiki_Syntax_Plugin { 16 /** 17 * @return string The plugin type 18 */ 19 public function getType() { 20 return 'container'; 21 } 22 23 /** 24 * @return string The paragraph type 25 */ 26 public function getPType() { 27 return 'block'; 28 } 29 30 /** 31 * @return int The sort number 32 */ 33 public function getSort() { 34 return 200; 35 } 36 37 /** 38 * @return array The allowed types that may be used inside the plugin 39 */ 40 public function getAllowedTypes() { 41 return array('container', 'baseonly', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs'); 42 } 43 44 /** 45 * @param string $mode The mode that shall be tested 46 * @return bool If the mode is accepted inside the plugin 47 */ 48 public function accepts($mode) { 49 // allow nesting! 50 if ($mode == substr(get_class($this), 7)) return true; 51 return parent::accepts($mode); 52 } 53 54 /** 55 * Add the patterns 56 * 57 * @param int $mode The current mode 58 */ 59 public function connectTo($mode) { 60 $this->Lexer->addEntryPattern('<ifvar [^=>]+=[^>]+>',$mode,'plugin_variants_variants'); 61 $this->Lexer->addPattern('<else>', 'plugin_variants_variants'); 62 } 63 64 /** 65 * Add the exit patterns 66 */ 67 public function postConnect() { 68 $this->Lexer->addExitPattern('</ifvar>','plugin_variants_variants'); 69 } 70 71 /** 72 * handle a syntax match 73 * 74 * @param string $match The match 75 * @param int $state The current handler state 76 * @param int $pos The position in the page 77 * @param Doku_Handler $handler The handler object 78 * @return bool False, this plugin doesn't need to be added by the handler 79 */ 80 public function handle($match, $state, $pos, Doku_Handler $handler){ 81 switch ($state) { 82 case DOKU_LEXER_ENTER: 83 // setup call writer 84 $condition = substr($match, 7, -1); 85 $CallWriter = new syntax_plugin_variants_callwriter($handler->CallWriter, $condition, $pos); 86 $handler->CallWriter =& $CallWriter; 87 88 break; 89 case DOKU_LEXER_MATCHED: 90 // start else branch 91 $handler->CallWriter->startElse(); 92 // else 93 break; 94 case DOKU_LEXER_UNMATCHED: 95 // store cdata 96 $handler->_addCall('cdata', array($match), $pos); 97 break; 98 case DOKU_LEXER_EXIT: 99 // end call writer 100 $handler->CallWriter->process(); 101 $ReWriter = & $handler->CallWriter; 102 $handler->CallWriter = & $ReWriter->CallWriter; 103 break; 104 } 105 return false; 106 } 107 108 /** 109 * Render the output of the variants plugin 110 * 111 * @param string $mode The output mode 112 * @param Doku_Renderer $renderer The renderer 113 * @param array $data The data from the handler 114 * @return bool If anything has been rendered 115 */ 116 public function render($mode, Doku_Renderer $renderer, $data) { 117 $renderer->nocache(); 118 /** @var Input $INPUT */ 119 global $INPUT; 120 list($condition, $ifcalls, $elsecalls) = $data; 121 122 list($key, $value) = explode('=', $condition, 2); 123 124 $condresult = true; 125 if (substr($key, -1) == '!') { 126 $key = substr($key, 0, -1); 127 $condresult = false; 128 } 129 130 trim($key); trim($value); 131 132 if ($INPUT->has($key) && ($INPUT->str($key) == $value) == $condresult) { 133 $renderer->nest($ifcalls); 134 } else { 135 $renderer->nest($elsecalls); 136 } 137 138 return true; 139 } 140} 141 142/** 143 * Call writer for the variants plugins 144 */ 145class syntax_plugin_variants_callwriter { 146 private $ifcalls = array(); 147 private $elsecalls = array(); 148 private $condition; 149 private $in_else = false; 150 private $startpos; 151 /** @var Doku_Handler_CallWriter $CallWriter */ 152 var $CallWriter; 153 154 /** 155 * Construct a new syntax plugin variants callwriter 156 * 157 * @param Doku_Handler_CallWriter $CallWriter The parent handler 158 * @param string $condition The condition 159 * @param int $startpos The position of the start of the syntax 160 */ 161 function __construct(& $CallWriter, $condition, $startpos) { 162 $this->CallWriter = & $CallWriter; 163 $this->condition = $condition; 164 $this->startpos = $startpos; 165 } 166 167 function startElse() { 168 $this->in_else = true; 169 } 170 171 /** 172 * Adds a single call 173 * 174 * @param array $call The call that shall be written 175 */ 176 function writeCall($call) { 177 if ($this->in_else) { 178 $this->elsecalls[] = $call; 179 } else { 180 $this->ifcalls[] = $call; 181 } 182 } 183 184 /** 185 * Adds an array of calls 186 * 187 * @param array $calls The calls that shall be written 188 */ 189 function writeCalls($calls) { 190 if ($this->in_else) { 191 $this->elsecalls = array_merge($this->elsecalls, $calls); 192 } else { 193 $this->ifcalls = array_merge($this->ifcalls, $calls); 194 } 195 } 196 197 function finalise() { 198 $this->process(); 199 $this->CallWriter->finalise(); 200 unset($this->CallWriter); 201 } 202 203 function process() { 204 // process blocks 205 $B = new Doku_Handler_Block(); 206 $this->ifcalls = $B->process($this->ifcalls); 207 $B = new Doku_Handler_Block(); 208 $this->elsecalls = $B->process($this->elsecalls); 209 210 $this->CallWriter->writeCall(array('plugin',array('variants_variants', array($this->condition, $this->ifcalls, $this->elsecalls), DOKU_LEXER_SPECIAL, ''), $this->startpos)); 211 $this->ifcalls = array(); 212 $this->elsecalls = array(); 213 } 214} 215 216// vim:ts=4:sw=4:et: 217