MediaWiki  REL1_20
StripState.php
Go to the documentation of this file.
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 }
00236