[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/parser/ -> handler.php (source)

   1  <?php
   2  if(!defined('DOKU_INC')) define('DOKU_INC',fullpath(dirname(__FILE__).'/../../').'/');
   3  
   4  if (!defined('DOKU_PARSER_EOL')) define('DOKU_PARSER_EOL',"\n");   // add this to make handling test cases simpler
   5  
   6  class Doku_Handler {
   7  
   8      var $Renderer = NULL;
   9  
  10      var $CallWriter = NULL;
  11  
  12      var $calls = array();
  13  
  14      var $status = array(
  15          'section' => false,
  16          'section_edit_start' => -1,
  17          'section_edit_level' => 1,
  18          'section_edit_title' => ''
  19      );
  20  
  21      var $rewriteBlocks = true;
  22  
  23      function Doku_Handler() {
  24          $this->CallWriter = & new Doku_Handler_CallWriter($this);
  25      }
  26  
  27      function _addCall($handler, $args, $pos) {
  28          $call = array($handler,$args, $pos);
  29          $this->CallWriter->writeCall($call);
  30      }
  31  
  32      function addPluginCall($plugin, $args, $state, $pos, $match) {
  33          $call = array('plugin',array($plugin, $args, $state, $match), $pos);
  34          $this->CallWriter->writeCall($call);
  35      }
  36  
  37      function _finalize(){
  38  
  39          $this->CallWriter->finalise();
  40  
  41          if ( $this->status['section'] ) {
  42             $last_call = end($this->calls);
  43             array_push($this->calls,array('section_close',array(), $last_call[2]));
  44             if ($this->status['section_edit_start']>1) {
  45                 // ignore last edit section if there is only one header
  46                 array_push($this->calls,array('section_edit',array($this->status['section_edit_start'], 0, $this->status['section_edit_level'], $this->status['section_edit_title']), $last_call[2]));
  47             }
  48          }
  49  
  50          if ( $this->rewriteBlocks ) {
  51              $B = & new Doku_Handler_Block();
  52              $this->calls = $B->process($this->calls);
  53          }
  54  
  55          trigger_event('PARSER_HANDLER_DONE',$this);
  56  
  57          array_unshift($this->calls,array('document_start',array(),0));
  58          $last_call = end($this->calls);
  59          array_push($this->calls,array('document_end',array(),$last_call[2]));
  60      }
  61  
  62      function fetch() {
  63          $call = each($this->calls);
  64          if ( $call ) {
  65              return $call['value'];
  66          }
  67          return false;
  68      }
  69  
  70  
  71      /**
  72       * Special plugin handler
  73       *
  74       * This handler is called for all modes starting with 'plugin_'.
  75       * An additional parameter with the plugin name is passed
  76       *
  77       * @author Andreas Gohr <andi@splitbrain.org>
  78       */
  79      function plugin($match, $state, $pos, $pluginname){
  80          $data = array($match);
  81          $plugin =& plugin_load('syntax',$pluginname);
  82          if($plugin != null){
  83              $data = $plugin->handle($match, $state, $pos, $this);
  84          }
  85          if ($data !== false) {
  86            $this->addPluginCall($pluginname,$data,$state,$pos,$match);
  87          }
  88          return true;
  89      }
  90  
  91      function base($match, $state, $pos) {
  92          switch ( $state ) {
  93              case DOKU_LEXER_UNMATCHED:
  94                  $this->_addCall('cdata',array($match), $pos);
  95                  return true;
  96              break;
  97          }
  98      }
  99  
 100      function header($match, $state, $pos) {
 101          global $conf;
 102  
 103          // get level and title
 104          $title = trim($match);
 105          $level = 7 - strspn($title,'=');
 106          if($level < 1) $level = 1;
 107          $title = trim($title,'=');
 108          $title = trim($title);
 109  
 110          if ($this->status['section']) $this->_addCall('section_close',array(),$pos);
 111  
 112          if ($level<=$conf['maxseclevel']) {
 113              $this->_addCall('section_edit',array($this->status['section_edit_start'], $pos-1, $this->status['section_edit_level'], $this->status['section_edit_title']), $pos);
 114              $this->status['section_edit_start'] = $pos;
 115              $this->status['section_edit_level'] = $level;
 116              $this->status['section_edit_title'] = $title;
 117          }
 118  
 119          $this->_addCall('header',array($title,$level,$pos), $pos);
 120  
 121          $this->_addCall('section_open',array($level),$pos);
 122          $this->status['section'] = true;
 123          return true;
 124      }
 125  
 126      function notoc($match, $state, $pos) {
 127          $this->_addCall('notoc',array(),$pos);
 128          return true;
 129      }
 130  
 131      function nocache($match, $state, $pos) {
 132          $this->_addCall('nocache',array(),$pos);
 133          return true;
 134      }
 135  
 136      function linebreak($match, $state, $pos) {
 137          $this->_addCall('linebreak',array(),$pos);
 138          return true;
 139      }
 140  
 141      function eol($match, $state, $pos) {
 142          $this->_addCall('eol',array(),$pos);
 143          return true;
 144      }
 145  
 146      function hr($match, $state, $pos) {
 147          $this->_addCall('hr',array(),$pos);
 148          return true;
 149      }
 150  
 151      function _nestingTag($match, $state, $pos, $name) {
 152          switch ( $state ) {
 153              case DOKU_LEXER_ENTER:
 154                  $this->_addCall($name.'_open', array(), $pos);
 155              break;
 156              case DOKU_LEXER_EXIT:
 157                  $this->_addCall($name.'_close', array(), $pos);
 158              break;
 159              case DOKU_LEXER_UNMATCHED:
 160                  $this->_addCall('cdata',array($match), $pos);
 161              break;
 162          }
 163      }
 164  
 165      function strong($match, $state, $pos) {
 166          $this->_nestingTag($match, $state, $pos, 'strong');
 167          return true;
 168      }
 169  
 170      function emphasis($match, $state, $pos) {
 171          $this->_nestingTag($match, $state, $pos, 'emphasis');
 172          return true;
 173      }
 174  
 175      function underline($match, $state, $pos) {
 176          $this->_nestingTag($match, $state, $pos, 'underline');
 177          return true;
 178      }
 179  
 180      function monospace($match, $state, $pos) {
 181          $this->_nestingTag($match, $state, $pos, 'monospace');
 182          return true;
 183      }
 184  
 185      function subscript($match, $state, $pos) {
 186          $this->_nestingTag($match, $state, $pos, 'subscript');
 187          return true;
 188      }
 189  
 190      function superscript($match, $state, $pos) {
 191          $this->_nestingTag($match, $state, $pos, 'superscript');
 192          return true;
 193      }
 194  
 195      function deleted($match, $state, $pos) {
 196          $this->_nestingTag($match, $state, $pos, 'deleted');
 197          return true;
 198      }
 199  
 200  
 201      function footnote($match, $state, $pos) {
 202  //        $this->_nestingTag($match, $state, $pos, 'footnote');
 203          if (!isset($this->_footnote)) $this->_footnote = false;
 204  
 205          switch ( $state ) {
 206              case DOKU_LEXER_ENTER:
 207                  // footnotes can not be nested - however due to limitations in lexer it can't be prevented
 208                  // we will still enter a new footnote mode, we just do nothing
 209                  if ($this->_footnote) {
 210                    $this->_addCall('cdata',array($match), $pos);
 211                    break;
 212                  }
 213  
 214                  $this->_footnote = true;
 215  
 216                  $ReWriter = & new Doku_Handler_Nest($this->CallWriter,'footnote_close');
 217                  $this->CallWriter = & $ReWriter;
 218                  $this->_addCall('footnote_open', array(), $pos);
 219              break;
 220              case DOKU_LEXER_EXIT:
 221                  // check whether we have already exitted the footnote mode, can happen if the modes were nested
 222                  if (!$this->_footnote) {
 223                    $this->_addCall('cdata',array($match), $pos);
 224                    break;
 225                  }
 226  
 227                  $this->_footnote = false;
 228  
 229                  $this->_addCall('footnote_close', array(), $pos);
 230                  $this->CallWriter->process();
 231                  $ReWriter = & $this->CallWriter;
 232                  $this->CallWriter = & $ReWriter->CallWriter;
 233              break;
 234              case DOKU_LEXER_UNMATCHED:
 235                  $this->_addCall('cdata', array($match), $pos);
 236              break;
 237          }
 238          return true;
 239      }
 240  
 241      function listblock($match, $state, $pos) {
 242          switch ( $state ) {
 243              case DOKU_LEXER_ENTER:
 244                  $ReWriter = & new Doku_Handler_List($this->CallWriter);
 245                  $this->CallWriter = & $ReWriter;
 246                  $this->_addCall('list_open', array($match), $pos);
 247              break;
 248              case DOKU_LEXER_EXIT:
 249                  $this->_addCall('list_close', array(), $pos);
 250                  $this->CallWriter->process();
 251                  $ReWriter = & $this->CallWriter;
 252                  $this->CallWriter = & $ReWriter->CallWriter;
 253              break;
 254              case DOKU_LEXER_MATCHED:
 255                  $this->_addCall('list_item', array($match), $pos);
 256              break;
 257              case DOKU_LEXER_UNMATCHED:
 258                  $this->_addCall('cdata', array($match), $pos);
 259              break;
 260          }
 261          return true;
 262      }
 263  
 264      function unformatted($match, $state, $pos) {
 265          if ( $state == DOKU_LEXER_UNMATCHED ) {
 266              $this->_addCall('unformatted',array($match), $pos);
 267          }
 268          return true;
 269      }
 270  
 271      function php($match, $state, $pos) {
 272          global $conf;
 273          if ( $state == DOKU_LEXER_UNMATCHED ) {
 274              $this->_addCall('php',array($match), $pos);
 275          }
 276          return true;
 277      }
 278  
 279      function phpblock($match, $state, $pos) {
 280          global $conf;
 281          if ( $state == DOKU_LEXER_UNMATCHED ) {
 282              $this->_addCall('phpblock',array($match), $pos);
 283          }
 284          return true;
 285      }
 286  
 287      function html($match, $state, $pos) {
 288          global $conf;
 289          if ( $state == DOKU_LEXER_UNMATCHED ) {
 290              $this->_addCall('html',array($match), $pos);
 291          }
 292          return true;
 293      }
 294  
 295      function htmlblock($match, $state, $pos) {
 296          global $conf;
 297          if ( $state == DOKU_LEXER_UNMATCHED ) {
 298              $this->_addCall('htmlblock',array($match), $pos);
 299          }
 300          return true;
 301      }
 302  
 303      function preformatted($match, $state, $pos) {
 304          switch ( $state ) {
 305              case DOKU_LEXER_ENTER:
 306                  $ReWriter = & new Doku_Handler_Preformatted($this->CallWriter);
 307                  $this->CallWriter = & $ReWriter;
 308                  $this->_addCall('preformatted_start',array(), $pos);
 309              break;
 310              case DOKU_LEXER_EXIT:
 311                  $this->_addCall('preformatted_end',array(), $pos);
 312                  $this->CallWriter->process();
 313                  $ReWriter = & $this->CallWriter;
 314                  $this->CallWriter = & $ReWriter->CallWriter;
 315              break;
 316              case DOKU_LEXER_MATCHED:
 317                  $this->_addCall('preformatted_newline',array(), $pos);
 318              break;
 319              case DOKU_LEXER_UNMATCHED:
 320                  $this->_addCall('preformatted_content',array($match), $pos);
 321              break;
 322          }
 323  
 324          return true;
 325      }
 326  
 327      function file($match, $state, $pos) {
 328          if ( $state == DOKU_LEXER_UNMATCHED ) {
 329              $this->_addCall('file',array($match), $pos);
 330          }
 331          return true;
 332      }
 333  
 334      function quote($match, $state, $pos) {
 335  
 336          switch ( $state ) {
 337  
 338              case DOKU_LEXER_ENTER:
 339                  $ReWriter = & new Doku_Handler_Quote($this->CallWriter);
 340                  $this->CallWriter = & $ReWriter;
 341                  $this->_addCall('quote_start',array($match), $pos);
 342              break;
 343  
 344              case DOKU_LEXER_EXIT:
 345                  $this->_addCall('quote_end',array(), $pos);
 346                  $this->CallWriter->process();
 347                  $ReWriter = & $this->CallWriter;
 348                  $this->CallWriter = & $ReWriter->CallWriter;
 349              break;
 350  
 351              case DOKU_LEXER_MATCHED:
 352                  $this->_addCall('quote_newline',array($match), $pos);
 353              break;
 354  
 355              case DOKU_LEXER_UNMATCHED:
 356                  $this->_addCall('cdata',array($match), $pos);
 357              break;
 358  
 359          }
 360  
 361          return true;
 362      }
 363  
 364      function code($match, $state, $pos) {
 365          switch ( $state ) {
 366              case DOKU_LEXER_UNMATCHED:
 367                  $matches = preg_split('/>/u',$match,2);
 368                  $matches[0] = trim($matches[0]);
 369                  if ( trim($matches[0]) == '' ) {
 370                      $matches[0] = NULL;
 371                  }
 372                  # $matches[0] contains name of programming language
 373                  # if available, We shortcut html here.
 374                  if($matches[0] == 'html') $matches[0] = 'html4strict';
 375                  $this->_addCall(
 376                          'code',
 377                          array($matches[1],$matches[0]),
 378                          $pos
 379                      );
 380              break;
 381          }
 382          return true;
 383      }
 384  
 385      function acronym($match, $state, $pos) {
 386          $this->_addCall('acronym',array($match), $pos);
 387          return true;
 388      }
 389  
 390      function smiley($match, $state, $pos) {
 391          $this->_addCall('smiley',array($match), $pos);
 392          return true;
 393      }
 394  
 395      function wordblock($match, $state, $pos) {
 396          $this->_addCall('wordblock',array($match), $pos);
 397          return true;
 398      }
 399  
 400      function entity($match, $state, $pos) {
 401          $this->_addCall('entity',array($match), $pos);
 402          return true;
 403      }
 404  
 405      function multiplyentity($match, $state, $pos) {
 406          preg_match_all('/\d+/',$match,$matches);
 407          $this->_addCall('multiplyentity',array($matches[0][0],$matches[0][1]), $pos);
 408          return true;
 409      }
 410  
 411      function singlequoteopening($match, $state, $pos) {
 412          $this->_addCall('singlequoteopening',array(), $pos);
 413          return true;
 414      }
 415  
 416      function singlequoteclosing($match, $state, $pos) {
 417          $this->_addCall('singlequoteclosing',array(), $pos);
 418          return true;
 419      }
 420  
 421      function apostrophe($match, $state, $pos) {
 422