mOptions = ParserOptions::newFromUserAndLang( new User, $wgContLang );
$name = isset( $wgParserConf['preprocessorClass'] )
? $wgParserConf['preprocessorClass']
: 'Preprocessor_DOM';
$this->mPreprocessor = new $name( $this );
}
function getStripList() {
return [ 'gallery', 'display map' /* Used by Maps, see r80025 CR */, '/foo' ];
}
public static function provideCases() {
// @codingStandardsIgnoreStart Ignore Generic.Files.LineLength.TooLong
return [
[ "Foo", "Foo" ],
[ "", "<!-- Foo -->" ],
[ "", "<!-- Foo --><!-- Bar -->" ],
[ " ", "<!-- Foo --> <!-- Bar -->" ],
[ " \n ", "<!-- Foo --> \n <!-- Bar -->" ],
[ " \n \n", "<!-- Foo --> \n <!-- Bar -->\n" ],
[ " \n", "<!-- Foo --> <!-- Bar -->\n" ],
[ "Bar", "<!-->Bar" ],
[ "\n== Baz ==\n", "== Foo ==\n <!-- Bar -->\n== Baz ==\n" ],
[ "", "gallery" ],
[ "Foo Bar", "Foo gallery Bar" ],
[ "", "gallery</gallery>" ],
[ " ", "<foo> gallery</gallery>" ],
[ " ", "<foo> gallery<gallery></gallery>" ],
[ " Foo bar ", "<noinclude> Foo bar </noinclude>" ],
[ "\n{{Foo}}\n", "<noinclude>\nFoo\n</noinclude>" ],
[ "\n{{Foo}}\n\n", "<noinclude>\nFoo\n</noinclude>\n" ],
[ "foo bar", "galleryfoo bar" ],
[ "<{{foo}}>", "<foo>" ],
[ "<{{{foo}}}>", "<foo>" ],
[ "", "gallery</gallery</gallery>" ],
[ "=== Foo === ", "=== Foo === " ],
[ "=== Foo === ", "==<!-- -->= Foo === " ],
[ "=== Foo === ", "=== Foo ==<!-- -->= " ],
[ "=== Foo ===\n", "=== Foo ===<!-- -->\n" ],
[ "=== Foo === \n", "=== Foo ===<!-- --> <!-- -->\n" ],
[ "== Foo ==\n== Bar == \n", "== Foo ==\n== Bar == \n" ],
[ "===========", "===========" ],
[ "Foo\n=\n==\n=\n", "Foo\n=\n==\n=\n" ],
[ "{{Foo}}", "Foo" ],
[ "\n{{Foo}}", "\nFoo" ],
[ "{{Foo|bar}}", "Foobar" ],
[ "{{Foo|bar}}a", "Foobara" ],
[ "{{Foo|bar|baz}}", "Foobarbaz" ],
[ "{{Foo|1=bar}}", "Foo1=bar" ],
[ "{{Foo|=bar}}", "Foo=bar" ],
[ "{{Foo|bar=baz}}", "Foobar=baz" ],
[ "{{Foo|{{bar}}=baz}}", "Foobar=baz" ],
[ "{{Foo|1=bar|baz}}", "Foo1=barbaz" ],
[ "{{Foo|1=bar|2=baz}}", "Foo1=bar2=baz" ],
[ "{{Foo|bar|foo=baz}}", "Foobarfoo=baz" ],
[ "{{{1}}}", "1" ],
[ "{{{1|}}}", "1" ],
[ "{{{Foo}}}", "Foo" ],
[ "{{{Foo|}}}", "Foo" ],
[ "{{{Foo|bar|baz}}}", "Foobarbaz" ],
[ "{{Foo}}", "{<!-- -->{Foo}}" ],
[ "{{{{Foobar}}}}", "{Foobar}" ],
[ "{{{ {{Foo}} }}}", " Foo " ],
[ "{{ {{{Foo}}} }}", " Foo " ],
[ "{{{{{Foo}}}}}", "Foo" ],
[ "{{{{{Foo}} }}}", "Foo " ],
[ "{{{{{{Foo}}}}}}", "Foo" ],
[ "{{{{{{Foo}}}}}", "{Foo" ],
[ "[[[Foo]]", "[[[Foo]]" ],
[ "{{Foo|[[[[bar]]|baz]]}}", "Foo[[[[bar]]|baz]]" ], // This test is important, since it means the difference between having the [[ rule stacked or not
[ "{{Foo|[[[[bar]|baz]]}}", "{{Foo|[[[[bar]|baz]]}}" ],
[ "{{Foo|Foo [[[[bar]|baz]]}}", "{{Foo|Foo [[[[bar]|baz]]}}" ],
[ "Foo BarBaz", "Foo display mapBar</display map >Baz" ],
[ "Foo BarBaz", "Foo display map fooBar</display map >Baz" ],
[ "Foo ", "Foo gallery bar="baz" " ],
[ "Foo ", "Foo gallery bar="1" baz=2 " ],
[ "Foo/foo>", "/fooFoo<//foo>" ], # Worth blacklisting IMHO
[ "{{#ifexpr: ({{{1|1}}} = 2) | Foo | Bar }}", "#ifexpr: (11 = 2) Foo Bar " ],
[ "{{#if: {{{1|}}} | Foo | {{Bar}} }}", "#if: 1 Foo Bar " ],
[ "{{#if: {{{1|}}} | Foo | [[Bar]] }}", "#if: 1 Foo [[Bar]] " ],
[ "{{#if: {{{1|}}} | [[Foo]] | Bar }}", "#if: 1 [[Foo]] Bar " ],
[ "{{#if: {{{1|}}} | 1 | {{#if: {{{1|}}} | 2 | 3 }} }}", "#if: 1 1 #if: 1 2 3 " ],
[ "{{ {{Foo}}", "{{ Foo" ],
[ "{{Foobar {{Foo}} {{Bar}} {{Baz}} ", "{{Foobar Foo Bar Baz " ],
[ "[[Foo]] |", "[[Foo]] |" ],
[ "{{Foo|Bar|", "{{Foo|Bar|" ],
[ "[[Foo]", "[[Foo]" ],
[ "[[Foo|Bar]", "[[Foo|Bar]" ],
[ "{{Foo| [[Bar] }}", "{{Foo| [[Bar] }}" ],
[ "{{Foo| [[Bar|Baz] }}", "{{Foo| [[Bar|Baz] }}" ],
[ "{{Foo|bar=[[baz]}}", "{{Foo|bar=[[baz]}}" ],
[ "{{foo|", "{{foo|" ],
[ "{{foo|}", "{{foo|}" ],
[ "{{foo|} }}", "foo} " ],
[ "{{foo|bar=|}", "{{foo|bar=|}" ],
[ "{{Foo|} Bar=", "{{Foo|} Bar=" ],
[ "{{Foo|} Bar=}}", "Foo} Bar=" ],
/* [ file_get_contents( __DIR__ . '/QuoteQuran.txt' ], file_get_contents( __DIR__ . '/QuoteQuranExpanded.txt' ) ], */
];
// @codingStandardsIgnoreEnd
}
/**
* Get XML preprocessor tree from the preprocessor (which may not be the
* native XML-based one).
*
* @param string $wikiText
* @return string
*/
protected function preprocessToXml( $wikiText ) {
if ( method_exists( $this->mPreprocessor, 'preprocessToXml' ) ) {
return $this->normalizeXml( $this->mPreprocessor->preprocessToXml( $wikiText ) );
}
$dom = $this->mPreprocessor->preprocessToObj( $wikiText );
if ( is_callable( [ $dom, 'saveXML' ] ) ) {
return $dom->saveXML();
} else {
return $this->normalizeXml( $dom->__toString() );
}
}
/**
* Normalize XML string to the form that a DOMDocument saves out.
*
* @param string $xml
* @return string
*/
protected function normalizeXml( $xml ) {
return preg_replace( '!<([a-z]+)/>!', '<$1>$1>', str_replace( ' />', '/>', $xml ) );
}
/**
* @dataProvider provideCases
* @covers Preprocessor_DOM::preprocessToXml
*/
public function testPreprocessorOutput( $wikiText, $expectedXml ) {
$this->assertEquals( $this->normalizeXml( $expectedXml ), $this->preprocessToXml( $wikiText ) );
}
/**
* These are more complex test cases taken out of wiki articles.
*/
public static function provideFiles() {
// @codingStandardsIgnoreStart Ignore Generic.Files.LineLength.TooLong
return [
[ "QuoteQuran" ], # http://en.wikipedia.org/w/index.php?title=Template:QuoteQuran/sandbox&oldid=237348988 GFDL + CC BY-SA by Striver
[ "Factorial" ], # http://en.wikipedia.org/w/index.php?title=Template:Factorial&oldid=98548758 GFDL + CC BY-SA by Polonium
[ "All_system_messages" ], # http://tl.wiktionary.org/w/index.php?title=Suleras:All_system_messages&oldid=2765 GPL text generated by MediaWiki
[ "Fundraising" ], # http://tl.wiktionary.org/w/index.php?title=MediaWiki:Sitenotice&oldid=5716 GFDL + CC BY-SA, copied there by Sky Harbor.
[ "NestedTemplates" ], # bug 27936
];
// @codingStandardsIgnoreEnd
}
/**
* @dataProvider provideFiles
* @covers Preprocessor_DOM::preprocessToXml
*/
public function testPreprocessorOutputFiles( $filename ) {
$folder = __DIR__ . "/../../../parser/preprocess";
$wikiText = file_get_contents( "$folder/$filename.txt" );
$output = $this->preprocessToXml( $wikiText );
$expectedFilename = "$folder/$filename.expected";
if ( file_exists( $expectedFilename ) ) {
$expectedXml = $this->normalizeXml( file_get_contents( $expectedFilename ) );
$this->assertEquals( $expectedXml, $output );
} else {
$tempFilename = tempnam( $folder, "$filename." );
file_put_contents( $tempFilename, $output );
$this->markTestIncomplete( "File $expectedFilename missing. Output stored as $tempFilename" );
}
}
/**
* Tests from T30642 ยท https://phabricator.wikimedia.org/T30642
*/
public static function provideHeadings() {
// @codingStandardsIgnoreStart Ignore Generic.Files.LineLength.TooLong
return [ /* These should become headings: */
[ "== h ==", "== h ==<!--c1-->" ],
[ "== h == ", "== h == <!--c1-->" ],
[ "== h == ", "== h ==<!--c1--> " ],
[ "== h == ", "== h == <!--c1--> " ],
[ "== h ==", "== h ==<!--c1--><!--c2-->" ],
[ "== h == ", "== h == <!--c1--><!--c2-->" ],
[ "== h == ", "== h ==<!--c1--><!--c2--> " ],
[ "== h == ", "== h == <!--c1--><!--c2--> " ],
[ "== h == ", "== h == <!--c1--> <!--c2-->" ],
[ "== h == ", "== h ==<!--c1--> <!--c2--> " ],
[ "== h == ", "== h == <!--c1--> <!--c2--> " ],
[ "== h ==", "== h ==<!--c1--><!--c2--><!--c3-->" ],
[ "== h == ", "== h ==<!--c1--> <!--c2--><!--c3-->" ],
[ "== h == ", "== h ==<!--c1--><!--c2--> <!--c3-->" ],
[ "== h == ", "== h ==<!--c1--> <!--c2--> <!--c3-->" ],
[ "== h == ", "== h == <!--c1--><!--c2--><!--c3-->" ],
[ "== h == ", "== h == <!--c1--> <!--c2--><!--c3-->" ],
[ "== h == ", "== h == <!--c1--><!--c2--> <!--c3-->" ],
[ "== h == ", "== h == <!--c1--> <!--c2--> <!--c3-->" ],
[ "== h == ", "== h ==<!--c1--><!--c2--><!--c3--> " ],
[ "== h == ", "== h ==<!--c1--> <!--c2--><!--c3--> " ],
[ "== h == ", "== h ==<!--c1--><!--c2--> <!--c3--> " ],
[ "== h == ", "== h ==<!--c1--> <!--c2--> <!--c3--> " ],
[ "== h == ", "== h == <!--c1--><!--c2--><!--c3--> " ],
[ "== h == ", "== h == <!--c1--> <!--c2--><!--c3--> " ],
[ "== h == ", "== h == <!--c1--><!--c2--> <!--c3--> " ],
[ "== h == ", "== h == <!--c1--> <!--c2--> <!--c3--> " ],
[ "== h == ", "== h ==<!--c1--> <!--c2-->" ],
[ "== h == ", "== h == <!--c1--> <!--c2-->" ],
[ "== h == ", "== h ==<!--c1--> <!--c2--> " ],
/* These are not working: */
[ "== h == x ", "== h == x <!--c1--><!--c2--><!--c3--> " ],
[ "== h == x ", "== h ==<!--c1--> x <!--c2--><!--c3--> " ],
[ "== h == x ", "== h ==<!--c1--><!--c2--><!--c3--> x " ],
];
// @codingStandardsIgnoreEnd
}
/**
* @dataProvider provideHeadings
* @covers Preprocessor_DOM::preprocessToXml
*/
public function testHeadings( $wikiText, $expectedXml ) {
$this->assertEquals( $this->normalizeXml( $expectedXml ), $this->preprocessToXml( $wikiText ) );
}
}