1<?php 2 3namespace dokuwiki\Parsing\ParserMode; 4 5use dokuwiki\Parsing\Handler; 6use dokuwiki\Parsing\ModeRegistry; 7 8/** 9 * Base class for inline formatting modes (bold, italic, underline, etc.) 10 * 11 * Each concrete subclass defines its entry/exit patterns, mode name, and sort order. 12 */ 13abstract class AbstractFormatting extends AbstractMode 14{ 15 /** 16 * Constructor. Sets up allowed modes for this formatting type. 17 * 18 * Formatting modes accept other formatting, substitutions, and disabled modes, 19 * but exclude themselves to prevent self-nesting (e.g. bold inside bold). 20 */ 21 public function __construct() 22 { 23 $self = $this->getModeName(); 24 $this->allowedModes = array_filter( 25 ModeRegistry::getInstance()->getModesForCategories([ 26 ModeRegistry::CATEGORY_FORMATTING, 27 ModeRegistry::CATEGORY_SUBSTITION, 28 ModeRegistry::CATEGORY_DISABLED, 29 ]), 30 static fn($mode) => $mode !== $self 31 ); 32 } 33 34 /** @inheritdoc */ 35 public function connectTo($mode) 36 { 37 // Can't nest formatting in itself 38 if ($mode === $this->getModeName()) { 39 return; 40 } 41 42 $this->Lexer->addEntryPattern( 43 $this->getEntryPattern(), 44 $mode, 45 $this->getModeName() 46 ); 47 } 48 49 /** 50 * @return string The regex pattern that starts this formatting 51 */ 52 abstract protected function getEntryPattern(): string; 53 54 /** 55 * @return string The regex pattern that ends this formatting 56 */ 57 abstract protected function getExitPattern(): string; 58 59 /** 60 * @return string The mode name used for lexer registration 61 */ 62 abstract protected function getModeName(): string; 63 64 /** @inheritdoc */ 65 public function postConnect() 66 { 67 $this->Lexer->addExitPattern( 68 $this->getExitPattern(), 69 $this->getModeName() 70 ); 71 } 72 73 /** @inheritdoc */ 74 public function handle($match, $state, $pos, Handler $handler) 75 { 76 $name = $this->getModeName(); 77 match ($state) { 78 DOKU_LEXER_ENTER => $handler->addCall($name . '_open', [], $pos), 79 DOKU_LEXER_EXIT => $handler->addCall($name . '_close', [], $pos), 80 DOKU_LEXER_UNMATCHED => $handler->addCall('cdata', [$match], $pos), 81 default => true, 82 }; 83 return true; 84 } 85} 86