MediaWiki
REL1_22
|
00001 <?php 00028 class StripState { 00029 protected $prefix; 00030 protected $data; 00031 protected $regex; 00032 00033 protected $tempType, $tempMergePrefix; 00034 protected $circularRefGuard; 00035 protected $recursionLevel = 0; 00036 00037 const UNSTRIP_RECURSION_LIMIT = 20; 00038 00042 function __construct( $prefix ) { 00043 $this->prefix = $prefix; 00044 $this->data = array( 00045 'nowiki' => array(), 00046 'general' => array() 00047 ); 00048 $this->regex = "/{$this->prefix}([^\x7f]+)" . Parser::MARKER_SUFFIX . '/'; 00049 $this->circularRefGuard = array(); 00050 } 00051 00057 function addNoWiki( $marker, $value ) { 00058 $this->addItem( 'nowiki', $marker, $value ); 00059 } 00060 00065 function addGeneral( $marker, $value ) { 00066 $this->addItem( 'general', $marker, $value ); 00067 } 00068 00075 protected function addItem( $type, $marker, $value ) { 00076 if ( !preg_match( $this->regex, $marker, $m ) ) { 00077 throw new MWException( "Invalid marker: $marker" ); 00078 } 00079 00080 $this->data[$type][$m[1]] = $value; 00081 } 00082 00087 function unstripGeneral( $text ) { 00088 return $this->unstripType( 'general', $text ); 00089 } 00090 00095 function unstripNoWiki( $text ) { 00096 return $this->unstripType( 'nowiki', $text ); 00097 } 00098 00103 function unstripBoth( $text ) { 00104 $text = $this->unstripType( 'general', $text ); 00105 $text = $this->unstripType( 'nowiki', $text ); 00106 return $text; 00107 } 00108 00114 protected function unstripType( $type, $text ) { 00115 // Shortcut 00116 if ( !count( $this->data[$type] ) ) { 00117 return $text; 00118 } 00119 00120 wfProfileIn( __METHOD__ ); 00121 $oldType = $this->tempType; 00122 $this->tempType = $type; 00123 $text = preg_replace_callback( $this->regex, array( $this, 'unstripCallback' ), $text ); 00124 $this->tempType = $oldType; 00125 wfProfileOut( __METHOD__ ); 00126 return $text; 00127 } 00128 00133 protected function unstripCallback( $m ) { 00134 $marker = $m[1]; 00135 if ( isset( $this->data[$this->tempType][$marker] ) ) { 00136 if ( isset( $this->circularRefGuard[$marker] ) ) { 00137 return '<span class="error">' 00138 . wfMessage( 'parser-unstrip-loop-warning' )->inContentLanguage()->text() 00139 . '</span>'; 00140 } 00141 if ( $this->recursionLevel >= self::UNSTRIP_RECURSION_LIMIT ) { 00142 return '<span class="error">' . 00143 wfMessage( 'parser-unstrip-recursion-limit' ) 00144 ->numParams( self::UNSTRIP_RECURSION_LIMIT )->inContentLanguage()->text() . 00145 '</span>'; 00146 } 00147 $this->circularRefGuard[$marker] = true; 00148 $this->recursionLevel++; 00149 $ret = $this->unstripType( $this->tempType, $this->data[$this->tempType][$marker] ); 00150 $this->recursionLevel--; 00151 unset( $this->circularRefGuard[$marker] ); 00152 return $ret; 00153 } else { 00154 return $m[0]; 00155 } 00156 } 00157 00166 function getSubState( $text ) { 00167 $subState = new StripState( $this->prefix ); 00168 $pos = 0; 00169 while ( true ) { 00170 $startPos = strpos( $text, $this->prefix, $pos ); 00171 $endPos = strpos( $text, Parser::MARKER_SUFFIX, $pos ); 00172 if ( $startPos === false || $endPos === false ) { 00173 break; 00174 } 00175 00176 $endPos += strlen( Parser::MARKER_SUFFIX ); 00177 $marker = substr( $text, $startPos, $endPos - $startPos ); 00178 if ( !preg_match( $this->regex, $marker, $m ) ) { 00179 continue; 00180 } 00181 00182 $key = $m[1]; 00183 if ( isset( $this->data['nowiki'][$key] ) ) { 00184 $subState->data['nowiki'][$key] = $this->data['nowiki'][$key]; 00185 } elseif ( isset( $this->data['general'][$key] ) ) { 00186 $subState->data['general'][$key] = $this->data['general'][$key]; 00187 } 00188 $pos = $endPos; 00189 } 00190 return $subState; 00191 } 00192 00202 function merge( $otherState, $texts ) { 00203 $mergePrefix = Parser::getRandomString(); 00204 00205 foreach ( $otherState->data as $type => $items ) { 00206 foreach ( $items as $key => $value ) { 00207 $this->data[$type]["$mergePrefix-$key"] = $value; 00208 } 00209 } 00210 00211 $this->tempMergePrefix = $mergePrefix; 00212 $texts = preg_replace_callback( $otherState->regex, array( $this, 'mergeCallback' ), $texts ); 00213 $this->tempMergePrefix = null; 00214 return $texts; 00215 } 00216 00221 protected function mergeCallback( $m ) { 00222 $key = $m[1]; 00223 return "{$this->prefix}{$this->tempMergePrefix}-$key" . Parser::MARKER_SUFFIX; 00224 } 00225 00232 function killMarkers( $text ) { 00233 return preg_replace( $this->regex, '', $text ); 00234 } 00235 }