MediaWiki  REL1_22
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 }