1<?php 2 3namespace dokuwiki\Parsing\ParserMode; 4 5use dokuwiki\Parsing\Handler; 6use dokuwiki\Parsing\Handler\Nest; 7use dokuwiki\Parsing\ModeRegistry; 8 9class Footnote extends AbstractMode 10{ 11 /** 12 * Footnote constructor. 13 */ 14 public function __construct() 15 { 16 $this->allowedModes = ModeRegistry::getInstance()->getModesForCategories([ 17 ModeRegistry::CATEGORY_CONTAINER, 18 ModeRegistry::CATEGORY_FORMATTING, 19 ModeRegistry::CATEGORY_SUBSTITION, 20 ModeRegistry::CATEGORY_PROTECTED, 21 ModeRegistry::CATEGORY_DISABLED, 22 ]); 23 24 unset($this->allowedModes[array_search('footnote', $this->allowedModes)]); 25 } 26 27 /** @inheritdoc */ 28 public function getSort() 29 { 30 return 150; 31 } 32 33 /** @inheritdoc */ 34 public function connectTo($mode) 35 { 36 $this->Lexer->addEntryPattern( 37 '\x28\x28(?=.*\x29\x29)', 38 $mode, 39 'footnote' 40 ); 41 } 42 43 /** @inheritdoc */ 44 public function postConnect() 45 { 46 $this->Lexer->addExitPattern( 47 '\x29\x29', 48 'footnote' 49 ); 50 } 51 52 /** @inheritdoc */ 53 public function handle($match, $state, $pos, Handler $handler) 54 { 55 switch ($state) { 56 case DOKU_LEXER_ENTER: 57 // footnotes can not be nested - however due to limitations in lexer it can't be prevented 58 // we will still enter a new footnote mode, we just do nothing 59 if ($handler->getStatus('footnote')) { 60 $handler->addCall('cdata', [$match], $pos); 61 break; 62 } 63 $handler->setStatus('footnote', true); 64 65 $handler->setCallWriter(new Nest($handler->getCallWriter(), 'footnote_close')); 66 $handler->addCall('footnote_open', [], $pos); 67 break; 68 case DOKU_LEXER_EXIT: 69 // check whether we have already exited the footnote mode, can happen if the modes were nested 70 if (!$handler->getStatus('footnote')) { 71 $handler->addCall('cdata', [$match], $pos); 72 break; 73 } 74 75 $handler->setStatus('footnote', false); 76 $handler->addCall('footnote_close', [], $pos); 77 78 /** @var Nest $reWriter */ 79 $reWriter = $handler->getCallWriter(); 80 $handler->setCallWriter($reWriter->process()); 81 break; 82 case DOKU_LEXER_UNMATCHED: 83 $handler->addCall('cdata', [$match], $pos); 84 break; 85 } 86 return true; 87 } 88} 89