MediaWiki REL1_33
RenderedRevisionTest.php
Go to the documentation of this file.
1<?php
2
4
20use PHPUnit\Framework\MockObject\MockObject;
22use User;
23use Wikimedia\TestingAccessWrapper;
25
30
33
34 public function setUp() {
35 parent::setUp();
36
37 $this->combinerCallback = function ( RenderedRevision $rr, array $hints = [] ) {
38 return $this->combineOutput( $rr, $hints );
39 };
40 }
41
42 private function combineOutput( RenderedRevision $rrev, array $hints = [] ) {
43 // NOTE: the is a slightly simplified version of RevisionRenderer::combineSlotOutput
44
45 $withHtml = $hints['generate-html'] ?? true;
46
47 $revision = $rrev->getRevision();
48 $slots = $revision->getSlots()->getSlots();
49
50 $combinedOutput = new ParserOutput( null );
51 $slotOutput = [];
52 foreach ( $slots as $role => $slot ) {
53 $out = $rrev->getSlotParserOutput( $role, $hints );
54 $slotOutput[$role] = $out;
55
56 $combinedOutput->mergeInternalMetaDataFrom( $out );
57 $combinedOutput->mergeTrackingMetaDataFrom( $out );
58 }
59
60 if ( $withHtml ) {
61 $html = '';
63 foreach ( $slotOutput as $role => $out ) {
64
65 if ( $html !== '' ) {
66 // skip header for the first slot
67 $html .= "(($role))";
68 }
69
70 $html .= $out->getRawText();
71 $combinedOutput->mergeHtmlMetaDataFrom( $out );
72 }
73
74 $combinedOutput->setText( $html );
75 }
76
77 return $combinedOutput;
78 }
79
85 private function getMockTitle( $articleId, $revisionId ) {
87 $mock = $this->getMockBuilder( Title::class )
88 ->disableOriginalConstructor()
89 ->getMock();
90 $mock->expects( $this->any() )
91 ->method( 'getNamespace' )
92 ->will( $this->returnValue( NS_MAIN ) );
93 $mock->expects( $this->any() )
94 ->method( 'getText' )
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' )
110 ->will( $this->returnValue( CONTENT_MODEL_WIKITEXT ) );
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() )
118 ->method( 'equals' )
119 ->willReturnCallback( function ( Title $other ) use ( $mock ) {
120 return $mock->getPrefixedText() === $other->getPrefixedText();
121 } );
122 $mock->expects( $this->any() )
123 ->method( 'userCan' )
124 ->willReturnCallback( function ( $perm, User $user ) use ( $mock ) {
125 return $user->isAllowed( $perm );
126 } );
127
128 return $mock;
129 }
130
138 private function getMockRevision(
139 $class,
140 $title,
141 $id = null,
142 $visibility = 0,
143 array $content = null
144 ) {
145 $frank = new UserIdentityValue( 9, 'Frank', 0 );
146
147 if ( !$content ) {
148 $text = "";
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";
154
155 $content = [ 'main' => new WikitextContent( $text ) ];
156 }
157
159 $mock = $this->getMockBuilder( $class )
160 ->disableOriginalConstructor()
161 ->setMethods( [
162 'getId',
163 'getPageId',
164 'getPageAsLinkTarget',
165 'getUser',
166 'getVisibility',
167 'getTimestamp',
168 ] )->getMock();
169
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' );
176
178 $mockAccess = TestingAccessWrapper::newFromObject( $mock );
179 $mockAccess->mSlots = new MutableRevisionSlots();
180
181 foreach ( $content as $role => $cnt ) {
182 $mockAccess->mSlots->setContent( $role, $cnt );
183 }
184
185 return $mock;
186 }
187
189 $title = $this->getMockTitle( 0, 21 );
190 $rev = $this->getMockRevision( RevisionStoreRecord::class, $title );
191
192 $options = ParserOptions::newCanonical( 'canonical' );
193 $rr = new RenderedRevision( $title, $rev, $options, $this->combinerCallback );
194
195 $this->assertFalse( $rr->isContentDeleted(), 'isContentDeleted' );
196
197 $this->assertSame( $rev, $rr->getRevision() );
198 $this->assertSame( $options, $rr->getOptions() );
199
200 $html = $rr->getRevisionParserOutput()->getText();
201
202 $this->assertContains( 'page:RenderTestPage!', $html );
203 $this->assertContains( 'user:Frank!', $html );
204 $this->assertContains( 'time:20180101000003!', $html );
205 }
206
208 $title = $this->getMockTitle( 0, 21 );
209 $name = $title->getPrefixedText();
210
211 $text = "(ONE)<includeonly>(TWO)</includeonly><noinclude>#{{:$name}}#</noinclude>";
212
213 $content = [
214 'main' => new WikitextContent( $text )
215 ];
216
217 $rev = $this->getMockRevision( RevisionStoreRecord::class, $title, null, 0, $content );
218
219 $options = ParserOptions::newCanonical( 'canonical' );
220 $rr = new RenderedRevision( $title, $rev, $options, $this->combinerCallback );
221
222 $html = $rr->getRevisionParserOutput()->getText();
223 $this->assertContains( '(ONE)#(ONE)(TWO)#', $html );
224 }
225
227 $title = $this->getMockTitle( 7, 21 );
228 $rev = $this->getMockRevision( RevisionStoreRecord::class, $title, 21 );
229
230 $options = ParserOptions::newCanonical( 'canonical' );
231 $rr = new RenderedRevision( $title, $rev, $options, $this->combinerCallback );
232
233 $this->assertFalse( $rr->isContentDeleted(), 'isContentDeleted' );
234
235 $this->assertSame( $rev, $rr->getRevision() );
236 $this->assertSame( $options, $rr->getOptions() );
237
238 $html = $rr->getRevisionParserOutput()->getText();
239
240 $this->assertContains( 'page:RenderTestPage!', $html );
241 $this->assertContains( 'rev:21!', $html );
242 $this->assertContains( 'user:Frank!', $html );
243 $this->assertContains( 'time:20180101000003!', $html );
244
245 $this->assertSame( $html, $rr->getSlotParserOutput( SlotRecord::MAIN )->getText() );
246 }
247
249 $title = $this->getMockTitle( 7, 21 );
250 $rev = $this->getMockRevision( RevisionStoreRecord::class, $title, 11 );
251
252 $options = ParserOptions::newCanonical( 'canonical' );
253 $rr = new RenderedRevision( $title, $rev, $options, $this->combinerCallback );
254
255 $this->assertFalse( $rr->isContentDeleted(), 'isContentDeleted' );
256
257 $this->assertSame( $rev, $rr->getRevision() );
258 $this->assertSame( $options, $rr->getOptions() );
259
260 $html = $rr->getRevisionParserOutput()->getText();
261
262 $this->assertContains( 'page:RenderTestPage!', $html );
263 $this->assertContains( 'rev:11!', $html );
264 $this->assertContains( 'user:Frank!', $html );
265 $this->assertContains( 'time:20180101000003!', $html );
266
267 $this->assertSame( $html, $rr->getSlotParserOutput( SlotRecord::MAIN )->getText() );
268 }
269
271 $title = $this->getMockTitle( 7, 21 );
272 $rev = $this->getMockRevision( RevisionArchiveRecord::class, $title, 11 );
273
274 $options = ParserOptions::newCanonical( 'canonical' );
275 $rr = new RenderedRevision( $title, $rev, $options, $this->combinerCallback );
276
277 $this->assertFalse( $rr->isContentDeleted(), 'isContentDeleted' );
278
279 $this->assertSame( $rev, $rr->getRevision() );
280 $this->assertSame( $options, $rr->getOptions() );
281
282 $html = $rr->getRevisionParserOutput()->getText();
283
284 $this->assertContains( 'page:RenderTestPage!', $html );
285 $this->assertContains( 'rev:11!', $html );
286 $this->assertContains( 'user:Frank!', $html );
287 $this->assertContains( 'time:20180101000003!', $html );
288
289 $this->assertSame( $html, $rr->getSlotParserOutput( SlotRecord::MAIN )->getText() );
290 }
291
293 $title = $this->getMockTitle( 7, 21 );
294 $rev = $this->getMockRevision(
295 RevisionStoreRecord::class,
296 $title,
297 11,
298 RevisionRecord::DELETED_TEXT
299 );
300
301 $options = ParserOptions::newCanonical( 'canonical' );
302 $rr = new RenderedRevision( $title, $rev, $options, $this->combinerCallback );
303
304 $this->setExpectedException( SuppressedDataException::class );
305 $rr->getRevisionParserOutput();
306 }
307
309 $title = $this->getMockTitle( 7, 21 );
310 $rev = $this->getMockRevision(
311 RevisionStoreRecord::class,
312 $title,
313 11,
314 RevisionRecord::DELETED_TEXT
315 );
316
317 $options = ParserOptions::newCanonical( 'canonical' );
318 $sysop = $this->getTestUser( [ 'sysop' ] )->getUser(); // privileged!
319 $rr = new RenderedRevision(
320 $title,
321 $rev,
322 $options,
323 $this->combinerCallback,
324 RevisionRecord::FOR_THIS_USER,
325 $sysop
326 );
327
328 $this->assertTrue( $rr->isContentDeleted(), 'isContentDeleted' );
329
330 $this->assertSame( $rev, $rr->getRevision() );
331 $this->assertSame( $options, $rr->getOptions() );
332
333 $html = $rr->getRevisionParserOutput()->getText();
334
335 // Suppressed content should be visible for sysops
336 $this->assertContains( 'page:RenderTestPage!', $html );
337 $this->assertContains( 'rev:11!', $html );
338 $this->assertContains( 'user:Frank!', $html );
339 $this->assertContains( 'time:20180101000003!', $html );
340
341 $this->assertSame( $html, $rr->getSlotParserOutput( SlotRecord::MAIN )->getText() );
342 }
343
345 $title = $this->getMockTitle( 7, 21 );
346 $rev = $this->getMockRevision(
347 RevisionStoreRecord::class,
348 $title,
349 11,
350 RevisionRecord::DELETED_TEXT
351 );
352
353 $options = ParserOptions::newCanonical( 'canonical' );
354 $rr = new RenderedRevision(
355 $title,
356 $rev,
357 $options,
358 $this->combinerCallback,
359 RevisionRecord::RAW
360 );
361
362 $this->assertTrue( $rr->isContentDeleted(), 'isContentDeleted' );
363
364 $this->assertSame( $rev, $rr->getRevision() );
365 $this->assertSame( $options, $rr->getOptions() );
366
367 $html = $rr->getRevisionParserOutput()->getText();
368
369 // Suppressed content should be visible for sysops
370 $this->assertContains( 'page:RenderTestPage!', $html );
371 $this->assertContains( 'rev:11!', $html );
372 $this->assertContains( 'user:Frank!', $html );
373 $this->assertContains( 'time:20180101000003!', $html );
374
375 $this->assertSame( $html, $rr->getSlotParserOutput( SlotRecord::MAIN )->getText() );
376 }
377
379 $content = [
380 'main' => new WikitextContent( '[[Kittens]]' ),
381 'aux' => new WikitextContent( '[[Goats]]' ),
382 ];
383
384 $title = $this->getMockTitle( 7, 21 );
385 $rev = $this->getMockRevision( RevisionStoreRecord::class, $title, 11, 0, $content );
386
387 $options = ParserOptions::newCanonical( 'canonical' );
388 $rr = new RenderedRevision( $title, $rev, $options, $this->combinerCallback );
389
390 $combinedOutput = $rr->getRevisionParserOutput();
391 $mainOutput = $rr->getSlotParserOutput( SlotRecord::MAIN );
392 $auxOutput = $rr->getSlotParserOutput( 'aux' );
393
394 $combinedHtml = $combinedOutput->getText();
395 $mainHtml = $mainOutput->getText();
396 $auxHtml = $auxOutput->getText();
397
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' );
405
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' );
413 }
414
416 $title = $this->getMockTitle( 7, 21 );
417
419
420 $text = "";
421 $text .= "* page:{{PAGENAME}}!\n";
422 $text .= "* rev:{{REVISIONID}}!\n";
423 $text .= "* user:{{REVISIONUSER}}!\n";
424 $text .= "* time:{{REVISIONTIMESTAMP}}!\n";
425
426 $rev->setContent( SlotRecord::MAIN, new WikitextContent( $text ) );
427
428 $options = ParserOptions::newCanonical( 'canonical' );
429 $rr = new RenderedRevision( $title, $rev, $options, $this->combinerCallback );
430
431 // MutableRevisionRecord without ID should be used by the parser.
432 // USeful for fake
433 $html = $rr->getRevisionParserOutput()->getText();
434
435 $this->assertContains( 'page:RenderTestPage!', $html );
436 $this->assertContains( 'rev:!', $html );
437 $this->assertContains( 'user:!', $html );
438 $this->assertContains( 'time:!', $html );
439 }
440
442 $title = $this->getMockTitle( 7, 21 );
443
445 $rev->setId( 21 );
446
447 $text = "";
448 $text .= "* page:{{PAGENAME}}!\n";
449 $text .= "* rev:{{REVISIONID}}!\n";
450 $text .= "* user:{{REVISIONUSER}}!\n";
451 $text .= "* time:{{REVISIONTIMESTAMP}}!\n";
452
453 $rev->setContent( SlotRecord::MAIN, new WikitextContent( $text ) );
454
455 $actualRevision = $this->getMockRevision(
456 RevisionStoreRecord::class,
457 $title,
458 21,
459 RevisionRecord::DELETED_TEXT
460 );
461
462 $options = ParserOptions::newCanonical( 'canonical' );
463 $rr = new RenderedRevision( $title, $rev, $options, $this->combinerCallback );
464
465 // MutableRevisionRecord with ID should not be used by the parser,
466 // revision should be loaded instead!
467 $revisionStore = $this->getMockBuilder( RevisionStore::class )
468 ->disableOriginalConstructor()
469 ->getMock();
470
471 $revisionStore->expects( $this->once() )
472 ->method( 'getKnownCurrentRevision' )
473 ->with( $title, 0 )
474 ->willReturn( $actualRevision );
475
476 $this->setService( 'RevisionStore', $revisionStore );
477
478 $html = $rr->getRevisionParserOutput()->getText();
479
480 $this->assertContains( 'page:RenderTestPage!', $html );
481 $this->assertContains( 'rev:21!', $html );
482 $this->assertContains( 'user:Frank!', $html );
483 $this->assertContains( 'time:20180101000003!', $html );
484 }
485
486 public function testSetRevisionParserOutput() {
487 $title = $this->getMockTitle( 3, 21 );
488 $rev = $this->getMockRevision( RevisionStoreRecord::class, $title );
489
490 $options = ParserOptions::newCanonical( 'canonical' );
491 $rr = new RenderedRevision( $title, $rev, $options, $this->combinerCallback );
492
493 $output = new ParserOutput( 'Kittens' );
494 $rr->setRevisionParserOutput( $output );
495
496 $this->assertSame( $output, $rr->getRevisionParserOutput() );
497 $this->assertSame( 'Kittens', $rr->getRevisionParserOutput()->getText() );
498
499 $this->assertSame( $output, $rr->getSlotParserOutput( SlotRecord::MAIN ) );
500 $this->assertSame( 'Kittens', $rr->getSlotParserOutput( SlotRecord::MAIN )->getText() );
501 }
502
503 public function testNoHtml() {
505 $mockContent = $this->getMockBuilder( WikitextContent::class )
506 ->setMethods( [ 'getParserOutput' ] )
507 ->setConstructorArgs( [ 'Whatever' ] )
508 ->getMock();
509 $mockContent->method( 'getParserOutput' )
510 ->willReturnCallback( function ( Title $title, $revId = null,
511 ParserOptions $options = null, $generateHtml = true
512 ) {
513 if ( !$generateHtml ) {
514 return new ParserOutput( null );
515 } else {
516 $this->fail( 'Should not be called with $generateHtml == true' );
517 return null; // never happens, make analyzer happy
518 }
519 } );
520
521 $title = $this->getMockTitle( 7, 21 );
522
524 $rev->setContent( SlotRecord::MAIN, $mockContent );
525 $rev->setContent( 'aux', $mockContent );
526
527 $options = ParserOptions::newCanonical( 'canonical' );
528 $rr = new RenderedRevision( $title, $rev, $options, $this->combinerCallback );
529
530 $output = $rr->getSlotParserOutput( SlotRecord::MAIN, [ 'generate-html' => false ] );
531 $this->assertFalse( $output->hasText(), 'hasText' );
532
533 $output = $rr->getRevisionParserOutput( [ 'generate-html' => false ] );
534 $this->assertFalse( $output->hasText(), 'hasText' );
535 }
536
537 public function testUpdateRevision() {
538 $title = $this->getMockTitle( 7, 21 );
539
541
542 $text = "";
543 $text .= "* page:{{PAGENAME}}!\n";
544 $text .= "* rev:{{REVISIONID}}!\n";
545 $text .= "* user:{{REVISIONUSER}}!\n";
546 $text .= "* time:{{REVISIONTIMESTAMP}}!\n";
547
548 $rev->setContent( SlotRecord::MAIN, new WikitextContent( $text ) );
549 $rev->setContent( 'aux', new WikitextContent( '[[Goats]]' ) );
550
551 $options = ParserOptions::newCanonical( 'canonical' );
552 $rr = new RenderedRevision( $title, $rev, $options, $this->combinerCallback );
553
554 $firstOutput = $rr->getRevisionParserOutput();
555 $mainOutput = $rr->getSlotParserOutput( SlotRecord::MAIN );
556 $auxOutput = $rr->getSlotParserOutput( 'aux' );
557
558 // emulate a saved revision
559 $savedRev = new MutableRevisionRecord( $title );
560 $savedRev->setContent( SlotRecord::MAIN, new WikitextContent( $text ) );
561 $savedRev->setContent( 'aux', new WikitextContent( '[[Goats]]' ) );
562 $savedRev->setId( 23 ); // saved, new
563 $savedRev->setUser( new UserIdentityValue( 9, 'Frank', 0 ) );
564 $savedRev->setTimestamp( '20180101000003' );
565
566 $rr->updateRevision( $savedRev );
567
568 $this->assertNotSame( $mainOutput, $rr->getSlotParserOutput( SlotRecord::MAIN ), 'Reset main' );
569 $this->assertSame( $auxOutput, $rr->getSlotParserOutput( 'aux' ), 'Keep aux' );
570
571 $updatedOutput = $rr->getRevisionParserOutput();
572 $html = $updatedOutput->getText();
573
574 $this->assertNotSame( $firstOutput, $updatedOutput, 'Reset merged' );
575 $this->assertContains( 'page:RenderTestPage!', $html );
576 $this->assertContains( 'rev:23!', $html );
577 $this->assertContains( 'user:Frank!', $html );
578 $this->assertContains( 'time:20180101000003!', $html );
579 $this->assertContains( 'Goats', $html );
580
581 $rr->updateRevision( $savedRev ); // should do nothing
582 $this->assertSame( $updatedOutput, $rr->getRevisionParserOutput(), 'no more reset needed' );
583 }
584
585}
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
Internationalisation code.
Definition Language.php:36
setService( $name, $object)
Sets a service, maintaining a stashed version of the previous service to be restored in tearDown.
static getTestUser( $groups=[])
Convenience method for getting an immutable test user.
Mutable RevisionRecord implementation, for building new revision entries programmatically.
Mutable version of RevisionSlots, for constructing a new revision.
RenderedRevision represents the rendered representation of a revision.
getSlotParserOutput( $role, array $hints=[])
A RevisionRecord representing a revision of a deleted page persisted in the archive table.
Page revision base class.
A RevisionRecord representing an existing revision persisted in the revision table.
Service for looking up page revisions.
Value object representing a content slot associated with a page revision.
Exception raised in response to an audience check when attempting to access suppressed information wi...
getMockRevision( $class, $title, $id=null, $visibility=0, array $content=null)
combineOutput(RenderedRevision $rrev, array $hints=[])
Value object representing a user's identity.
Set options of the Parser.
Represents a title within MediaWiki.
Definition Title.php:40
getPrefixedText()
Get the prefixed title with spaces.
Definition Title.php:1660
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition User.php:48
Content object for wiki text pages.
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
const NS_MAIN
Definition Defines.php:73
const CONTENT_MODEL_WIKITEXT
Definition Defines.php:244
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that When $user is not it can be in the form of< username >< more info > e g for bot passwords intended to be added to log contexts Fields it might only if the login was with a bot password 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
Definition hooks.txt:855
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
Definition hooks.txt:1999
namespace and then decline to actually register it file or subcat img or subcat $title
Definition hooks.txt:955
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
Definition hooks.txt:2011
Allows to change the fields on the form that will be generated $name
Definition hooks.txt:271
return true to allow those checks to and false if checking is done & $user
Definition hooks.txt:1510
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
Definition hooks.txt:2272
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
Definition hooks.txt:1779
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition injection.txt:37
Base interface for content objects.
Definition Content.php:34
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))
$content