20use PHPUnit\Framework\MockObject\MockObject;
23use Wikimedia\TestingAccessWrapper;
45 $withHtml = $hints[
'generate-html'] ??
true;
47 $revision = $rrev->getRevision();
48 $slots = $revision->getSlots()->getSlots();
52 foreach ( $slots as $role => $slot ) {
53 $out = $rrev->getSlotParserOutput( $role, $hints );
54 $slotOutput[$role] =
$out;
56 $combinedOutput->mergeInternalMetaDataFrom(
$out );
57 $combinedOutput->mergeTrackingMetaDataFrom(
$out );
63 foreach ( $slotOutput as $role =>
$out ) {
71 $combinedOutput->mergeHtmlMetaDataFrom(
$out );
74 $combinedOutput->setText(
$html );
77 return $combinedOutput;
87 $mock = $this->getMockBuilder( Title::class )
88 ->disableOriginalConstructor()
90 $mock->expects( $this->
any() )
91 ->method(
'getNamespace' )
92 ->will( $this->returnValue(
NS_MAIN ) );
93 $mock->expects( $this->
any() )
95 ->will( $this->returnValue(
'RenderTestPage' ) );
96 $mock->expects( $this->
any() )
97 ->method(
'getPrefixedText' )
98 ->will( $this->returnValue(
'RenderTestPage' ) );
99 $mock->expects( $this->
any() )
100 ->method(
'getDBkey' )
101 ->will( $this->returnValue(
'RenderTestPage' ) );
102 $mock->expects( $this->
any() )
103 ->method(
'getArticleID' )
104 ->will( $this->returnValue( $articleId ) );
105 $mock->expects( $this->
any() )
106 ->method(
'getLatestRevId' )
107 ->will( $this->returnValue( $revisionId ) );
108 $mock->expects( $this->
any() )
109 ->method(
'getContentModel' )
111 $mock->expects( $this->
any() )
112 ->method(
'getPageLanguage' )
113 ->will( $this->returnValue( Language::factory(
'en' ) ) );
114 $mock->expects( $this->
any() )
115 ->method(
'isContentPage' )
116 ->will( $this->returnValue(
true ) );
117 $mock->expects( $this->
any() )
119 ->willReturnCallback(
function ( Title $other ) use ( $mock ) {
120 return $mock->getPrefixedText() === $other->getPrefixedText();
122 $mock->expects( $this->
any() )
123 ->method(
'userCan' )
124 ->willReturnCallback(
function ( $perm,
User $user )
use ( $mock ) {
125 return $user->isAllowed( $perm );
149 $text .=
"* page:{{PAGENAME}}!\n";
150 $text .=
"* rev:{{REVISIONID}}!\n";
151 $text .=
"* user:{{REVISIONUSER}}!\n";
152 $text .=
"* time:{{REVISIONTIMESTAMP}}!\n";
153 $text .=
"* [[Link It]]\n";
159 $mock = $this->getMockBuilder( $class )
160 ->disableOriginalConstructor()
164 'getPageAsLinkTarget',
170 $mock->method(
'getId' )->willReturn( $id );
171 $mock->method(
'getPageId' )->willReturn( $title->getArticleID() );
172 $mock->method(
'getPageAsLinkTarget' )->willReturn( $title );
173 $mock->method(
'getUser' )->willReturn( $frank );
174 $mock->method(
'getVisibility' )->willReturn( $visibility );
175 $mock->method(
'getTimestamp' )->willReturn(
'20180101000003' );
178 $mockAccess = TestingAccessWrapper::newFromObject( $mock );
181 foreach (
$content as $role => $cnt ) {
182 $mockAccess->mSlots->setContent( $role, $cnt );
192 $options = ParserOptions::newCanonical(
'canonical' );
195 $this->assertFalse( $rr->isContentDeleted(),
'isContentDeleted' );
197 $this->assertSame(
$rev, $rr->getRevision() );
198 $this->assertSame(
$options, $rr->getOptions() );
200 $html = $rr->getRevisionParserOutput()->getText();
202 $this->assertContains(
'page:RenderTestPage!',
$html );
203 $this->assertContains(
'user:Frank!',
$html );
204 $this->assertContains(
'time:20180101000003!',
$html );
209 $name = $title->getPrefixedText();
211 $text =
"(ONE)<includeonly>(TWO)</includeonly><noinclude>#{{:$name}}#</noinclude>";
219 $options = ParserOptions::newCanonical(
'canonical' );
222 $html = $rr->getRevisionParserOutput()->getText();
223 $this->assertContains(
'(ONE)#(ONE)(TWO)#',
$html );
230 $options = ParserOptions::newCanonical(
'canonical' );
233 $this->assertFalse( $rr->isContentDeleted(),
'isContentDeleted' );
235 $this->assertSame(
$rev, $rr->getRevision() );
236 $this->assertSame(
$options, $rr->getOptions() );
238 $html = $rr->getRevisionParserOutput()->getText();
240 $this->assertContains(
'page:RenderTestPage!',
$html );
241 $this->assertContains(
'rev:21!',
$html );
242 $this->assertContains(
'user:Frank!',
$html );
243 $this->assertContains(
'time:20180101000003!',
$html );
245 $this->assertSame(
$html, $rr->getSlotParserOutput( SlotRecord::MAIN )->getText() );
252 $options = ParserOptions::newCanonical(
'canonical' );
255 $this->assertFalse( $rr->isContentDeleted(),
'isContentDeleted' );
257 $this->assertSame(
$rev, $rr->getRevision() );
258 $this->assertSame(
$options, $rr->getOptions() );
260 $html = $rr->getRevisionParserOutput()->getText();
262 $this->assertContains(
'page:RenderTestPage!',
$html );
263 $this->assertContains(
'rev:11!',
$html );
264 $this->assertContains(
'user:Frank!',
$html );
265 $this->assertContains(
'time:20180101000003!',
$html );
267 $this->assertSame(
$html, $rr->getSlotParserOutput( SlotRecord::MAIN )->getText() );
274 $options = ParserOptions::newCanonical(
'canonical' );
277 $this->assertFalse( $rr->isContentDeleted(),
'isContentDeleted' );
279 $this->assertSame(
$rev, $rr->getRevision() );
280 $this->assertSame(
$options, $rr->getOptions() );
282 $html = $rr->getRevisionParserOutput()->getText();
284 $this->assertContains(
'page:RenderTestPage!',
$html );
285 $this->assertContains(
'rev:11!',
$html );
286 $this->assertContains(
'user:Frank!',
$html );
287 $this->assertContains(
'time:20180101000003!',
$html );
289 $this->assertSame(
$html, $rr->getSlotParserOutput( SlotRecord::MAIN )->getText() );
295 RevisionStoreRecord::class,
298 RevisionRecord::DELETED_TEXT
301 $options = ParserOptions::newCanonical(
'canonical' );
304 $this->setExpectedException( SuppressedDataException::class );
305 $rr->getRevisionParserOutput();
311 RevisionStoreRecord::class,
314 RevisionRecord::DELETED_TEXT
317 $options = ParserOptions::newCanonical(
'canonical' );
318 $sysop = $this->
getTestUser( [
'sysop' ] )->getUser();
323 $this->combinerCallback,
324 RevisionRecord::FOR_THIS_USER,
328 $this->assertTrue( $rr->isContentDeleted(),
'isContentDeleted' );
330 $this->assertSame(
$rev, $rr->getRevision() );
331 $this->assertSame(
$options, $rr->getOptions() );
333 $html = $rr->getRevisionParserOutput()->getText();
336 $this->assertContains(
'page:RenderTestPage!',
$html );
337 $this->assertContains(
'rev:11!',
$html );
338 $this->assertContains(
'user:Frank!',
$html );
339 $this->assertContains(
'time:20180101000003!',
$html );
341 $this->assertSame(
$html, $rr->getSlotParserOutput( SlotRecord::MAIN )->getText() );
347 RevisionStoreRecord::class,
350 RevisionRecord::DELETED_TEXT
353 $options = ParserOptions::newCanonical(
'canonical' );
358 $this->combinerCallback,
362 $this->assertTrue( $rr->isContentDeleted(),
'isContentDeleted' );
364 $this->assertSame(
$rev, $rr->getRevision() );
365 $this->assertSame(
$options, $rr->getOptions() );
367 $html = $rr->getRevisionParserOutput()->getText();
370 $this->assertContains(
'page:RenderTestPage!',
$html );
371 $this->assertContains(
'rev:11!',
$html );
372 $this->assertContains(
'user:Frank!',
$html );
373 $this->assertContains(
'time:20180101000003!',
$html );
375 $this->assertSame(
$html, $rr->getSlotParserOutput( SlotRecord::MAIN )->getText() );
387 $options = ParserOptions::newCanonical(
'canonical' );
390 $combinedOutput = $rr->getRevisionParserOutput();
391 $mainOutput = $rr->getSlotParserOutput( SlotRecord::MAIN );
392 $auxOutput = $rr->getSlotParserOutput(
'aux' );
394 $combinedHtml = $combinedOutput->getText();
395 $mainHtml = $mainOutput->getText();
396 $auxHtml = $auxOutput->getText();
398 $this->assertContains(
'Kittens', $mainHtml );
399 $this->assertContains(
'Goats', $auxHtml );
400 $this->assertNotContains(
'Goats', $mainHtml );
401 $this->assertNotContains(
'Kittens', $auxHtml );
402 $this->assertContains(
'Kittens', $combinedHtml );
403 $this->assertContains(
'Goats', $combinedHtml );
404 $this->assertContains(
'aux', $combinedHtml,
'slot section header' );
406 $combinedLinks = $combinedOutput->getLinks();
407 $mainLinks = $mainOutput->getLinks();
408 $auxLinks = $auxOutput->getLinks();
409 $this->assertTrue( isset( $combinedLinks[
NS_MAIN][
'Kittens'] ),
'links from main slot' );
410 $this->assertTrue( isset( $combinedLinks[
NS_MAIN][
'Goats'] ),
'links from aux slot' );
411 $this->assertFalse( isset( $mainLinks[
NS_MAIN][
'Goats'] ),
'no aux links in main' );
412 $this->assertFalse( isset( $auxLinks[
NS_MAIN][
'Kittens'] ),
'no main links in aux' );
421 $text .=
"* page:{{PAGENAME}}!\n";
422 $text .=
"* rev:{{REVISIONID}}!\n";
423 $text .=
"* user:{{REVISIONUSER}}!\n";
424 $text .=
"* time:{{REVISIONTIMESTAMP}}!\n";
428 $options = ParserOptions::newCanonical(
'canonical' );
433 $html = $rr->getRevisionParserOutput()->getText();
435 $this->assertContains(
'page:RenderTestPage!',
$html );
436 $this->assertContains(
'rev:!',
$html );
437 $this->assertContains(
'user:!',
$html );
438 $this->assertContains(
'time:!',
$html );
448 $text .=
"* page:{{PAGENAME}}!\n";
449 $text .=
"* rev:{{REVISIONID}}!\n";
450 $text .=
"* user:{{REVISIONUSER}}!\n";
451 $text .=
"* time:{{REVISIONTIMESTAMP}}!\n";
456 RevisionStoreRecord::class,
459 RevisionRecord::DELETED_TEXT
462 $options = ParserOptions::newCanonical(
'canonical' );
467 $revisionStore = $this->getMockBuilder( RevisionStore::class )
468 ->disableOriginalConstructor()
471 $revisionStore->expects( $this->once() )
472 ->method(
'getKnownCurrentRevision' )
474 ->willReturn( $actualRevision );
476 $this->
setService(
'RevisionStore', $revisionStore );
478 $html = $rr->getRevisionParserOutput()->getText();
480 $this->assertContains(
'page:RenderTestPage!',
$html );
481 $this->assertContains(
'rev:21!',
$html );
482 $this->assertContains(
'user:Frank!',
$html );
483 $this->assertContains(
'time:20180101000003!',
$html );
488 $mockContent = $this->getMockBuilder( WikitextContent::class )
489 ->setMethods( [
'getParserOutput' ] )
490 ->setConstructorArgs( [
'Whatever' ] )
492 $mockContent->method(
'getParserOutput' )
493 ->willReturnCallback(
function (
Title $title, $revId =
null,
496 if ( !$generateHtml ) {
499 $this->fail(
'Should not be called with $generateHtml == true' );
507 $rev->setContent( SlotRecord::MAIN, $mockContent );
508 $rev->setContent(
'aux', $mockContent );
510 $options = ParserOptions::newCanonical(
'canonical' );
513 $output = $rr->getSlotParserOutput( SlotRecord::MAIN, [
'generate-html' =>
false ] );
514 $this->assertFalse(
$output->hasText(),
'hasText' );
516 $output = $rr->getRevisionParserOutput( [
'generate-html' =>
false ] );
517 $this->assertFalse(
$output->hasText(),
'hasText' );
526 $text .=
"* page:{{PAGENAME}}!\n";
527 $text .=
"* rev:{{REVISIONID}}!\n";
528 $text .=
"* user:{{REVISIONUSER}}!\n";
529 $text .=
"* time:{{REVISIONTIMESTAMP}}!\n";
534 $options = ParserOptions::newCanonical(
'canonical' );
537 $firstOutput = $rr->getRevisionParserOutput();
538 $mainOutput = $rr->getSlotParserOutput( SlotRecord::MAIN );
539 $auxOutput = $rr->getSlotParserOutput(
'aux' );
543 $savedRev->setContent( SlotRecord::MAIN,
new WikitextContent( $text ) );
545 $savedRev->setId( 23 );
547 $savedRev->setTimestamp(
'20180101000003' );
549 $rr->updateRevision( $savedRev );
551 $this->assertNotSame( $mainOutput, $rr->getSlotParserOutput( SlotRecord::MAIN ),
'Reset main' );
552 $this->assertSame( $auxOutput, $rr->getSlotParserOutput(
'aux' ),
'Keep aux' );
554 $updatedOutput = $rr->getRevisionParserOutput();
555 $html = $updatedOutput->getText();
557 $this->assertNotSame( $firstOutput, $updatedOutput,
'Reset merged' );
558 $this->assertContains(
'page:RenderTestPage!',
$html );
559 $this->assertContains(
'rev:23!',
$html );
560 $this->assertContains(
'user:Frank!',
$html );
561 $this->assertContains(
'time:20180101000003!',
$html );
562 $this->assertContains(
'Goats',
$html );
564 $rr->updateRevision( $savedRev );
565 $this->assertSame( $updatedOutput, $rr->getRevisionParserOutput(),
'no more reset needed' );
they could even be mouse clicks or menu items whatever suits your program You should also get your if any
Internationalisation code.
Set options of the Parser.
Represents a title within MediaWiki.
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Content object for wiki text pages.
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output $out
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses & $html
static configuration should be added through ResourceLoaderGetConfigVars instead can be used to get the real title e g db for database replication lag or jobqueue for job queue size converted to pseudo seconds It is possible to add more fields and they will be returned to the user in the API response after the basic globals have been set but before ordinary actions take place $output
presenting them properly to the user as errors is done by the caller return true use this to change the list i e etc $rev
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
const CONTENT_MODEL_WIKITEXT
Base interface for content objects.
The wiki should then use memcached to cache various data To use multiple just add more items to the array To increase the weight of a make its entry a array("192.168.0.1:11211", 2))