MediaWiki  1.34.0
StripState.php
Go to the documentation of this file.
1 <?php
28 class StripState {
29  protected $data;
30  protected $regex;
31 
32  protected $parser;
33 
34  protected $circularRefGuard;
35  protected $depth = 0;
36  protected $highestDepth = 0;
37  protected $expandSize = 0;
38 
39  protected $depthLimit = 20;
40  protected $sizeLimit = 5000000;
41 
46  public function __construct( Parser $parser = null, $options = [] ) {
47  $this->data = [
48  'nowiki' => [],
49  'general' => []
50  ];
51  $this->regex = '/' . Parser::MARKER_PREFIX . "([^\x7f<>&'\"]+)" . Parser::MARKER_SUFFIX . '/';
52  $this->circularRefGuard = [];
53  $this->parser = $parser;
54 
55  if ( isset( $options['depthLimit'] ) ) {
56  $this->depthLimit = $options['depthLimit'];
57  }
58  if ( isset( $options['sizeLimit'] ) ) {
59  $this->sizeLimit = $options['sizeLimit'];
60  }
61  }
62 
68  public function addNoWiki( $marker, $value ) {
69  $this->addItem( 'nowiki', $marker, $value );
70  }
71 
76  public function addGeneral( $marker, $value ) {
77  $this->addItem( 'general', $marker, $value );
78  }
79 
86  protected function addItem( $type, $marker, $value ) {
87  if ( !preg_match( $this->regex, $marker, $m ) ) {
88  throw new MWException( "Invalid marker: $marker" );
89  }
90 
91  $this->data[$type][$m[1]] = $value;
92  }
93 
98  public function unstripGeneral( $text ) {
99  return $this->unstripType( 'general', $text );
100  }
101 
106  public function unstripNoWiki( $text ) {
107  return $this->unstripType( 'nowiki', $text );
108  }
109 
114  public function unstripBoth( $text ) {
115  $text = $this->unstripType( 'general', $text );
116  $text = $this->unstripType( 'nowiki', $text );
117  return $text;
118  }
119 
125  protected function unstripType( $type, $text ) {
126  // Shortcut
127  if ( !count( $this->data[$type] ) ) {
128  return $text;
129  }
130 
131  $callback = function ( $m ) use ( $type ) {
132  $marker = $m[1];
133  if ( isset( $this->data[$type][$marker] ) ) {
134  if ( isset( $this->circularRefGuard[$marker] ) ) {
135  return $this->getWarning( 'parser-unstrip-loop-warning' );
136  }
137 
138  if ( $this->depth > $this->highestDepth ) {
139  $this->highestDepth = $this->depth;
140  }
141  if ( $this->depth >= $this->depthLimit ) {
142  return $this->getLimitationWarning( 'unstrip-depth', $this->depthLimit );
143  }
144 
145  $value = $this->data[$type][$marker];
146  if ( $value instanceof Closure ) {
147  $value = $value();
148  }
149 
150  $this->expandSize += strlen( $value );
151  if ( $this->expandSize > $this->sizeLimit ) {
152  return $this->getLimitationWarning( 'unstrip-size', $this->sizeLimit );
153  }
154 
155  $this->circularRefGuard[$marker] = true;
156  $this->depth++;
157  $ret = $this->unstripType( $type, $value );
158  $this->depth--;
159  unset( $this->circularRefGuard[$marker] );
160 
161  return $ret;
162  } else {
163  return $m[0];
164  }
165  };
166 
167  $text = preg_replace_callback( $this->regex, $callback, $text );
168  return $text;
169  }
170 
178  private function getLimitationWarning( $type, $max = '' ) {
179  if ( $this->parser ) {
180  $this->parser->limitationWarn( $type, $max );
181  }
182  return $this->getWarning( "$type-warning", $max );
183  }
184 
192  private function getWarning( $message, $max = '' ) {
193  return '<span class="error">' .
194  wfMessage( $message )
195  ->numParams( $max )->inContentLanguage()->text() .
196  '</span>';
197  }
198 
205  public function getLimitReport() {
206  return [
207  [ 'limitreport-unstrip-depth',
208  [
211  ],
212  ],
213  [ 'limitreport-unstrip-size',
214  [
217  ],
218  ]
219  ];
220  }
221 
230  public function getSubState( $text ) {
231  wfDeprecated( __METHOD__, '1.31' );
232 
233  $subState = new StripState;
234  $pos = 0;
235  while ( true ) {
236  $startPos = strpos( $text, Parser::MARKER_PREFIX, $pos );
237  $endPos = strpos( $text, Parser::MARKER_SUFFIX, $pos );
238  if ( $startPos === false || $endPos === false ) {
239  break;
240  }
241 
242  $endPos += strlen( Parser::MARKER_SUFFIX );
243  $marker = substr( $text, $startPos, $endPos - $startPos );
244  if ( !preg_match( $this->regex, $marker, $m ) ) {
245  continue;
246  }
247 
248  $key = $m[1];
249  if ( isset( $this->data['nowiki'][$key] ) ) {
250  $subState->data['nowiki'][$key] = $this->data['nowiki'][$key];
251  } elseif ( isset( $this->data['general'][$key] ) ) {
252  $subState->data['general'][$key] = $this->data['general'][$key];
253  }
254  $pos = $endPos;
255  }
256  return $subState;
257  }
258 
269  public function merge( $otherState, $texts ) {
270  wfDeprecated( __METHOD__, '1.31' );
271 
272  $mergePrefix = wfRandomString( 16 );
273 
274  foreach ( $otherState->data as $type => $items ) {
275  foreach ( $items as $key => $value ) {
276  $this->data[$type]["$mergePrefix-$key"] = $value;
277  }
278  }
279 
280  $callback = function ( $m ) use ( $mergePrefix ) {
281  $key = $m[1];
282  return Parser::MARKER_PREFIX . $mergePrefix . '-' . $key . Parser::MARKER_SUFFIX;
283  };
284  $texts = preg_replace_callback( $otherState->regex, $callback, $texts );
285  return $texts;
286  }
287 
294  public function killMarkers( $text ) {
295  return preg_replace( $this->regex, '', $text );
296  }
297 }
StripState\merge
merge( $otherState, $texts)
Merge another StripState object into this one.
Definition: StripState.php:269
StripState\$depth
$depth
Definition: StripState.php:35
StripState\getSubState
getSubState( $text)
Get a StripState object which is sufficient to unstrip the given text.
Definition: StripState.php:230
StripState\unstripNoWiki
unstripNoWiki( $text)
Definition: StripState.php:106
StripState\unstripGeneral
unstripGeneral( $text)
Definition: StripState.php:98
StripState\$data
$data
Definition: StripState.php:29
StripState\getLimitationWarning
getLimitationWarning( $type, $max='')
Get warning HTML and register a limitation warning with the parser.
Definition: StripState.php:178
StripState\$highestDepth
$highestDepth
Definition: StripState.php:36
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1264
StripState\$depthLimit
$depthLimit
Definition: StripState.php:39
StripState\addNoWiki
addNoWiki( $marker, $value)
Add a nowiki strip item.
Definition: StripState.php:68
StripState
Definition: StripState.php:28
StripState\$expandSize
$expandSize
Definition: StripState.php:37
StripState\$sizeLimit
$sizeLimit
Definition: StripState.php:40
MWException
MediaWiki exception.
Definition: MWException.php:26
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
Definition: GlobalFunctions.php:1044
StripState\$circularRefGuard
$circularRefGuard
Definition: StripState.php:34
StripState\addGeneral
addGeneral( $marker, $value)
Definition: StripState.php:76
StripState\__construct
__construct(Parser $parser=null, $options=[])
Definition: StripState.php:46
StripState\getLimitReport
getLimitReport()
Get an array of parameters to pass to ParserOutput::setLimitReportData()
Definition: StripState.php:205
StripState\addItem
addItem( $type, $marker, $value)
Definition: StripState.php:86
StripState\unstripType
unstripType( $type, $text)
Definition: StripState.php:125
StripState\$regex
$regex
Definition: StripState.php:30
StripState\unstripBoth
unstripBoth( $text)
Definition: StripState.php:114
StripState\getWarning
getWarning( $message, $max='')
Get warning HTML.
Definition: StripState.php:192
StripState\$parser
$parser
Definition: StripState.php:32
StripState\killMarkers
killMarkers( $text)
Remove any strip markers found in the given text.
Definition: StripState.php:294
wfRandomString
wfRandomString( $length=32)
Get a random string containing a number of pseudo-random hex characters.
Definition: GlobalFunctions.php:274
$type
$type
Definition: testCompression.php:48