setContentLang( 'qqx' ); $this->markerValue = 0; } private function getMarker() { $i = $this->markerValue++; return Parser::MARKER_PREFIX . '-blah-' . sprintf( '%08X', $i ) . Parser::MARKER_SUFFIX; } private static function getWarning( $message, $max = '' ) { return "($message: $max)"; } public function testAddNoWiki() { $ss = new StripState; $marker = $this->getMarker(); $ss->addNoWiki( $marker, '<>' ); $text = "x{$marker}y"; $text = $ss->unstripGeneral( $text ); $text = str_replace( '<', '', $text ); $text = $ss->unstripNoWiki( $text ); $this->assertSame( 'x<>y', $text ); } public function testAddGeneral() { $ss = new StripState; $marker = $this->getMarker(); $ss->addGeneral( $marker, '<>' ); $text = "x{$marker}y"; $text = $ss->unstripNoWiki( $text ); $text = str_replace( '<', '', $text ); $text = $ss->unstripGeneral( $text ); $this->assertSame( 'x<>y', $text ); } public function testUnstripBoth() { $ss = new StripState; $mk1 = $this->getMarker(); $mk2 = $this->getMarker(); $ss->addNoWiki( $mk1, '<1>' ); $ss->addGeneral( $mk2, '<2>' ); $text = "x{$mk1}{$mk2}y"; $text = str_replace( '<', '', $text ); $text = $ss->unstripBoth( $text ); $this->assertSame( 'x<1><2>y', $text ); } public static function provideUnstripRecursive() { return [ [ 0, 'text' ], [ 1, '=text=' ], [ 2, '==text==' ], [ 3, '==' . self::getWarning( 'unstrip-depth-warning', 2 ) . '==' ], ]; } /** @dataProvider provideUnstripRecursive */ public function testUnstripRecursive( $depth, $expected ) { $ss = new StripState( null, [ 'depthLimit' => 2 ] ); $text = 'text'; for ( $i = 0; $i < $depth; $i++ ) { $mk = $this->getMarker(); $ss->addNoWiki( $mk, "={$text}=" ); $text = $mk; } $text = $ss->unstripNoWiki( $text ); $this->assertSame( $expected, $text ); } public function testUnstripLoop() { $ss = new StripState( null, [ 'depthLimit' => 2 ] ); $mk = $this->getMarker(); $ss->addNoWiki( $mk, $mk ); $text = $ss->unstripNoWiki( $mk ); $this->assertSame( self::getWarning( 'parser-unstrip-loop-warning' ), $text ); } public static function provideUnstripSize() { return [ [ 0, 'x' ], [ 1, 'xx' ], [ 2, str_repeat( self::getWarning( 'unstrip-size-warning', 5 ), 2 ) ] ]; } /** @dataProvider provideUnstripSize */ public function testUnstripSize( $depth, $expected ) { $ss = new StripState( null, [ 'sizeLimit' => 5 ] ); $text = 'x'; for ( $i = 0; $i < $depth; $i++ ) { $mk = $this->getMarker(); $ss->addNoWiki( $mk, $text ); $text = "$mk$mk"; } $text = $ss->unstripNoWiki( $text ); $this->assertSame( $expected, $text ); } public static function provideGetLimitReport() { for ( $i = 1; $i < 4; $i++ ) { yield [ $i ]; } } /** @dataProvider provideGetLimitReport */ public function testGetLimitReport( $depth ) { $sizeLimit = 100000; $ss = new StripState( null, [ 'depthLimit' => 5, 'sizeLimit' => $sizeLimit ] ); $text = 'x'; for ( $i = 0; $i < $depth; $i++ ) { $mk = $this->getMarker(); $ss->addNoWiki( $mk, $text ); $text = "$mk$mk"; } $text = $ss->unstripNoWiki( $text ); $report = $ss->getLimitReport(); $messages = []; foreach ( $report as [ $msg, $params ] ) { $messages[$msg] = $params; } $this->assertSame( [ $depth - 1, 5 ], $messages['limitreport-unstrip-depth'] ); $this->assertSame( [ strlen( $this->getMarker() ) * 2 * ( pow( 2, $depth ) - 2 ) + pow( 2, $depth ), $sizeLimit ], $messages['limitreport-unstrip-size' ] ); } public function testReplaceNowikis() { $ss = new StripState(); // Note that unlike other uses of addNowiki, these add the original source // with the nowiki wrappers. When wikitext is being processed, the parser // uses strip markers in this fashion. $s1 = "[[Foo]]"; $nowikiS1 = "$s1"; $m1 = $this->getMarker(); $ss->addNoWiki( $m1, $nowikiS1 ); $s2 = "[[Foo]]"; $nowikiS2 = "$s2"; $m2 = $this->getMarker(); $ss->addNoWiki( $m2, $nowikiS2 ); $s3 = ""; $nowikiS3 = ""; $m3 = $this->getMarker(); $ss->addNoWiki( $m3, $nowikiS3 ); $text = "$s1; $s2; $s3"; $strippedText = "$m1; $m2; $m3"; $unstrippedText = "$nowikiS1; $nowikiS2; $nowikiS3"; $this->assertSame( $ss->unstripGeneral( $strippedText ), $strippedText ); $this->assertSame( $ss->unstripNoWiki( $strippedText ), $unstrippedText ); $out1 = $ss->replaceNoWikis( $strippedText, static function ( $s ) { return $s; } ); $this->assertSame( $out1, $unstrippedText ); // Simulate Scribunto lua modules use of unstripNowiki $out2 = $ss->replaceNoWikis( $strippedText, static function ( $s ) { return preg_replace( "#]*>#", '', $s ); } ); $this->assertSame( $out2, $text ); } public function testSplitSimple() { // "Raw HTML" nowiki strip marker $ss = new StripState(); $rawHtml = "foo"; $m1 = $this->getMarker(); $ss->addNoWiki( $m1, $rawHtml ); $expected = [ [ 'type' => 'string', 'content' => 'abc ' ], [ 'type' => 'nowiki', 'content' => $rawHtml, 'extra' => null, 'marker' => $m1 ], [ 'type' => 'string', 'content' => ' def' ], ]; $this->assertSame( $expected, $ss->split( "abc $m1 def" ) ); // "nowiki" nowiki strip marker $ss = new StripState(); $m2 = $this->getMarker(); $nowiki = "''foo''"; $ss->addNoWiki( $m2, $nowiki, 'nowiki' ); $text = "abc $m2 def"; $r2 = $ss->split( $text ); $expected = [ [ 'type' => 'string', 'content' => 'abc ' ], [ 'type' => 'nowiki', 'content' => $nowiki, 'extra' => 'nowiki', 'marker' => $m2 ], [ 'type' => 'string', 'content' => ' def' ], ]; $this->assertSame( $expected, $r2 ); // "nowiki" empty nowiki strip marker $ss = new StripState(); $m2 = $this->getMarker(); $nowiki = ""; $ss->addNoWiki( $m2, $nowiki, 'nowiki' ); $text = "abc $m2 def"; $r2 = $ss->split( $text ); $expected = [ [ 'type' => 'string', 'content' => 'abc ' ], [ 'type' => 'nowiki', 'content' => '', 'extra' => 'nowiki', 'marker' => $m2 ], [ 'type' => 'string', 'content' => ' def' ], ]; $this->assertSame( $expected, $r2 ); // exttag strip marker $ref = "foo"; $m3 = $this->getMarker(); $ss->addExtTag( $m3, $ref ); $text .= $m3; $r3 = $ss->split( $text ); $expected = array_merge( $expected, [ [ 'type' => 'string', 'content' => $ref ], [ 'type' => 'string', 'content' => '' ] ] ); $this->assertSame( $expected, $r3 ); } public function testSplitRecursive() { $ss = new StripState(); $ref = "foo"; $m1 = $this->getMarker(); $ss->addExtTag( $m1, $ref ); $poem = "foo $m1"; $m2 = $this->getMarker(); $ss->addExtTag( $m2, $poem ); $text = "abc $m2"; $expected = [ [ 'type' => 'string', 'content' => 'abc ' ], [ 'type' => 'string', 'content' => 'foo ' ], [ 'type' => 'string', 'content' => $ref ], [ 'type' => 'string', 'content' => '' ], [ 'type' => 'string', 'content' => '' ], ]; $result = $ss->split( $text ); $this->assertSame( $expected, $result ); } }