Merge "Use interwiki cache directly to resolve transwiki import sources"
[lhc/web/wiklou.git] / tests / phpunit / includes / page / WikiPageTest.php
1 <?php
2
3 /**
4 * @group ContentHandler
5 * @group Database
6 * ^--- important, causes temporary tables to be used instead of the real database
7 * @group medium
8 **/
9 class WikiPageTest extends MediaWikiLangTestCase {
10
11 protected $pages_to_delete;
12
13 function __construct( $name = null, array $data = array(), $dataName = '' ) {
14 parent::__construct( $name, $data, $dataName );
15
16 $this->tablesUsed = array_merge(
17 $this->tablesUsed,
18 array( 'page',
19 'revision',
20 'text',
21
22 'recentchanges',
23 'logging',
24
25 'page_props',
26 'pagelinks',
27 'categorylinks',
28 'langlinks',
29 'externallinks',
30 'imagelinks',
31 'templatelinks',
32 'iwlinks' ) );
33 }
34
35 protected function setUp() {
36 parent::setUp();
37 $this->pages_to_delete = array();
38
39 LinkCache::singleton()->clear(); # avoid cached redirect status, etc
40 }
41
42 protected function tearDown() {
43 foreach ( $this->pages_to_delete as $p ) {
44 /* @var $p WikiPage */
45
46 try {
47 if ( $p->exists() ) {
48 $p->doDeleteArticle( "testing done." );
49 }
50 } catch ( MWException $ex ) {
51 // fail silently
52 }
53 }
54 parent::tearDown();
55 }
56
57 /**
58 * @param Title|string $title
59 * @param string|null $model
60 * @return WikiPage
61 */
62 protected function newPage( $title, $model = null ) {
63 if ( is_string( $title ) ) {
64 $ns = $this->getDefaultWikitextNS();
65 $title = Title::newFromText( $title, $ns );
66 }
67
68 $p = new WikiPage( $title );
69
70 $this->pages_to_delete[] = $p;
71
72 return $p;
73 }
74
75 /**
76 * @param string|Title|WikiPage $page
77 * @param string $text
78 * @param int $model
79 *
80 * @return WikiPage
81 */
82 protected function createPage( $page, $text, $model = null ) {
83 if ( is_string( $page ) || $page instanceof Title ) {
84 $page = $this->newPage( $page, $model );
85 }
86
87 $content = ContentHandler::makeContent( $text, $page->getTitle(), $model );
88 $page->doEditContent( $content, "testing", EDIT_NEW );
89
90 return $page;
91 }
92
93 /**
94 * @covers WikiPage::doEditContent
95 */
96 public function testDoEditContent() {
97 $page = $this->newPage( "WikiPageTest_testDoEditContent" );
98 $title = $page->getTitle();
99
100 $content = ContentHandler::makeContent(
101 "[[Lorem ipsum]] dolor sit amet, consetetur sadipscing elitr, sed diam "
102 . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.",
103 $title,
104 CONTENT_MODEL_WIKITEXT
105 );
106
107 $page->doEditContent( $content, "[[testing]] 1" );
108
109 $this->assertTrue( $title->getArticleID() > 0, "Title object should have new page id" );
110 $this->assertTrue( $page->getId() > 0, "WikiPage should have new page id" );
111 $this->assertTrue( $title->exists(), "Title object should indicate that the page now exists" );
112 $this->assertTrue( $page->exists(), "WikiPage object should indicate that the page now exists" );
113
114 $id = $page->getId();
115
116 # ------------------------
117 $dbr = wfGetDB( DB_SLAVE );
118 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
119 $n = $res->numRows();
120 $res->free();
121
122 $this->assertEquals( 1, $n, 'pagelinks should contain one link from the page' );
123
124 # ------------------------
125 $page = new WikiPage( $title );
126
127 $retrieved = $page->getContent();
128 $this->assertTrue( $content->equals( $retrieved ), 'retrieved content doesn\'t equal original' );
129
130 # ------------------------
131 $content = ContentHandler::makeContent(
132 "At vero eos et accusam et justo duo [[dolores]] et ea rebum. "
133 . "Stet clita kasd [[gubergren]], no sea takimata sanctus est.",
134 $title,
135 CONTENT_MODEL_WIKITEXT
136 );
137
138 $page->doEditContent( $content, "testing 2" );
139
140 # ------------------------
141 $page = new WikiPage( $title );
142
143 $retrieved = $page->getContent();
144 $this->assertTrue( $content->equals( $retrieved ), 'retrieved content doesn\'t equal original' );
145
146 # ------------------------
147 $dbr = wfGetDB( DB_SLAVE );
148 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
149 $n = $res->numRows();
150 $res->free();
151
152 $this->assertEquals( 2, $n, 'pagelinks should contain two links from the page' );
153 }
154
155 /**
156 * @covers WikiPage::doEdit
157 */
158 public function testDoEdit() {
159 $this->hideDeprecated( "WikiPage::doEdit" );
160 $this->hideDeprecated( "WikiPage::getText" );
161 $this->hideDeprecated( "Revision::getText" );
162
163 // NOTE: assume help namespace will default to wikitext
164 $title = Title::newFromText( "Help:WikiPageTest_testDoEdit" );
165
166 $page = $this->newPage( $title );
167
168 $text = "[[Lorem ipsum]] dolor sit amet, consetetur sadipscing elitr, sed diam "
169 . " nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.";
170
171 $page->doEdit( $text, "[[testing]] 1" );
172
173 $this->assertTrue( $title->getArticleID() > 0, "Title object should have new page id" );
174 $this->assertTrue( $page->getId() > 0, "WikiPage should have new page id" );
175 $this->assertTrue( $title->exists(), "Title object should indicate that the page now exists" );
176 $this->assertTrue( $page->exists(), "WikiPage object should indicate that the page now exists" );
177
178 $id = $page->getId();
179
180 # ------------------------
181 $dbr = wfGetDB( DB_SLAVE );
182 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
183 $n = $res->numRows();
184 $res->free();
185
186 $this->assertEquals( 1, $n, 'pagelinks should contain one link from the page' );
187
188 # ------------------------
189 $page = new WikiPage( $title );
190
191 $retrieved = $page->getText();
192 $this->assertEquals( $text, $retrieved, 'retrieved text doesn\'t equal original' );
193
194 # ------------------------
195 $text = "At vero eos et accusam et justo duo [[dolores]] et ea rebum. "
196 . "Stet clita kasd [[gubergren]], no sea takimata sanctus est.";
197
198 $page->doEdit( $text, "testing 2" );
199
200 # ------------------------
201 $page = new WikiPage( $title );
202
203 $retrieved = $page->getText();
204 $this->assertEquals( $text, $retrieved, 'retrieved text doesn\'t equal original' );
205
206 # ------------------------
207 $dbr = wfGetDB( DB_SLAVE );
208 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
209 $n = $res->numRows();
210 $res->free();
211
212 $this->assertEquals( 2, $n, 'pagelinks should contain two links from the page' );
213 }
214
215 /**
216 * @covers WikiPage::doQuickEditContent
217 */
218 public function testDoQuickEditContent() {
219 global $wgUser;
220
221 $page = $this->createPage(
222 "WikiPageTest_testDoQuickEditContent",
223 "original text",
224 CONTENT_MODEL_WIKITEXT
225 );
226
227 $content = ContentHandler::makeContent(
228 "quick text",
229 $page->getTitle(),
230 CONTENT_MODEL_WIKITEXT
231 );
232 $page->doQuickEditContent( $content, $wgUser, "testing q" );
233
234 # ---------------------
235 $page = new WikiPage( $page->getTitle() );
236 $this->assertTrue( $content->equals( $page->getContent() ) );
237 }
238
239 /**
240 * @covers WikiPage::doDeleteArticle
241 */
242 public function testDoDeleteArticle() {
243 $page = $this->createPage(
244 "WikiPageTest_testDoDeleteArticle",
245 "[[original text]] foo",
246 CONTENT_MODEL_WIKITEXT
247 );
248 $id = $page->getId();
249
250 $page->doDeleteArticle( "testing deletion" );
251
252 $this->assertFalse(
253 $page->getTitle()->getArticleID() > 0,
254 "Title object should now have page id 0"
255 );
256 $this->assertFalse( $page->getId() > 0, "WikiPage should now have page id 0" );
257 $this->assertFalse(
258 $page->exists(),
259 "WikiPage::exists should return false after page was deleted"
260 );
261 $this->assertNull(
262 $page->getContent(),
263 "WikiPage::getContent should return null after page was deleted"
264 );
265 $this->assertFalse(
266 $page->getText(),
267 "WikiPage::getText should return false after page was deleted"
268 );
269
270 $t = Title::newFromText( $page->getTitle()->getPrefixedText() );
271 $this->assertFalse(
272 $t->exists(),
273 "Title::exists should return false after page was deleted"
274 );
275
276 // Run the job queue
277 JobQueueGroup::destroySingletons();
278 $jobs = new RunJobs;
279 $jobs->loadParamsAndArgs( null, array( 'quiet' => true ), null );
280 $jobs->execute();
281
282 # ------------------------
283 $dbr = wfGetDB( DB_SLAVE );
284 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
285 $n = $res->numRows();
286 $res->free();
287
288 $this->assertEquals( 0, $n, 'pagelinks should contain no more links from the page' );
289 }
290
291 /**
292 * @covers WikiPage::doDeleteUpdates
293 */
294 public function testDoDeleteUpdates() {
295 $page = $this->createPage(
296 "WikiPageTest_testDoDeleteArticle",
297 "[[original text]] foo",
298 CONTENT_MODEL_WIKITEXT
299 );
300 $id = $page->getId();
301
302 // Similar to MovePage logic
303 wfGetDB( DB_MASTER )->delete( 'page', array( 'page_id' => $id ), __METHOD__ );
304 $page->doDeleteUpdates( $id );
305
306 // Run the job queue
307 JobQueueGroup::destroySingletons();
308 $jobs = new RunJobs;
309 $jobs->loadParamsAndArgs( null, array( 'quiet' => true ), null );
310 $jobs->execute();
311
312 # ------------------------
313 $dbr = wfGetDB( DB_SLAVE );
314 $res = $dbr->select( 'pagelinks', '*', array( 'pl_from' => $id ) );
315 $n = $res->numRows();
316 $res->free();
317
318 $this->assertEquals( 0, $n, 'pagelinks should contain no more links from the page' );
319 }
320
321 /**
322 * @covers WikiPage::getRevision
323 */
324 public function testGetRevision() {
325 $page = $this->newPage( "WikiPageTest_testGetRevision" );
326
327 $rev = $page->getRevision();
328 $this->assertNull( $rev );
329
330 # -----------------
331 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
332
333 $rev = $page->getRevision();
334
335 $this->assertEquals( $page->getLatest(), $rev->getId() );
336 $this->assertEquals( "some text", $rev->getContent()->getNativeData() );
337 }
338
339 /**
340 * @covers WikiPage::getContent
341 */
342 public function testGetContent() {
343 $page = $this->newPage( "WikiPageTest_testGetContent" );
344
345 $content = $page->getContent();
346 $this->assertNull( $content );
347
348 # -----------------
349 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
350
351 $content = $page->getContent();
352 $this->assertEquals( "some text", $content->getNativeData() );
353 }
354
355 /**
356 * @covers WikiPage::getText
357 */
358 public function testGetText() {
359 $this->hideDeprecated( "WikiPage::getText" );
360
361 $page = $this->newPage( "WikiPageTest_testGetText" );
362
363 $text = $page->getText();
364 $this->assertFalse( $text );
365
366 # -----------------
367 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
368
369 $text = $page->getText();
370 $this->assertEquals( "some text", $text );
371 }
372
373 /**
374 * @covers WikiPage::getRawText
375 */
376 public function testGetRawText() {
377 $this->hideDeprecated( "WikiPage::getRawText" );
378
379 $page = $this->newPage( "WikiPageTest_testGetRawText" );
380
381 $text = $page->getRawText();
382 $this->assertFalse( $text );
383
384 # -----------------
385 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
386
387 $text = $page->getRawText();
388 $this->assertEquals( "some text", $text );
389 }
390
391 /**
392 * @covers WikiPage::getContentModel
393 */
394 public function testGetContentModel() {
395 global $wgContentHandlerUseDB;
396
397 if ( !$wgContentHandlerUseDB ) {
398 $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
399 }
400
401 $page = $this->createPage(
402 "WikiPageTest_testGetContentModel",
403 "some text",
404 CONTENT_MODEL_JAVASCRIPT
405 );
406
407 $page = new WikiPage( $page->getTitle() );
408 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $page->getContentModel() );
409 }
410
411 /**
412 * @covers WikiPage::getContentHandler
413 */
414 public function testGetContentHandler() {
415 global $wgContentHandlerUseDB;
416
417 if ( !$wgContentHandlerUseDB ) {
418 $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
419 }
420
421 $page = $this->createPage(
422 "WikiPageTest_testGetContentHandler",
423 "some text",
424 CONTENT_MODEL_JAVASCRIPT
425 );
426
427 $page = new WikiPage( $page->getTitle() );
428 $this->assertEquals( 'JavaScriptContentHandler', get_class( $page->getContentHandler() ) );
429 }
430
431 /**
432 * @covers WikiPage::exists
433 */
434 public function testExists() {
435 $page = $this->newPage( "WikiPageTest_testExists" );
436 $this->assertFalse( $page->exists() );
437
438 # -----------------
439 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
440 $this->assertTrue( $page->exists() );
441
442 $page = new WikiPage( $page->getTitle() );
443 $this->assertTrue( $page->exists() );
444
445 # -----------------
446 $page->doDeleteArticle( "done testing" );
447 $this->assertFalse( $page->exists() );
448
449 $page = new WikiPage( $page->getTitle() );
450 $this->assertFalse( $page->exists() );
451 }
452
453 public static function provideHasViewableContent() {
454 return array(
455 array( 'WikiPageTest_testHasViewableContent', false, true ),
456 array( 'Special:WikiPageTest_testHasViewableContent', false ),
457 array( 'MediaWiki:WikiPageTest_testHasViewableContent', false ),
458 array( 'Special:Userlogin', true ),
459 array( 'MediaWiki:help', true ),
460 );
461 }
462
463 /**
464 * @dataProvider provideHasViewableContent
465 * @covers WikiPage::hasViewableContent
466 */
467 public function testHasViewableContent( $title, $viewable, $create = false ) {
468 $page = $this->newPage( $title );
469 $this->assertEquals( $viewable, $page->hasViewableContent() );
470
471 if ( $create ) {
472 $this->createPage( $page, "some text", CONTENT_MODEL_WIKITEXT );
473 $this->assertTrue( $page->hasViewableContent() );
474
475 $page = new WikiPage( $page->getTitle() );
476 $this->assertTrue( $page->hasViewableContent() );
477 }
478 }
479
480 public static function provideGetRedirectTarget() {
481 return array(
482 array( 'WikiPageTest_testGetRedirectTarget_1', CONTENT_MODEL_WIKITEXT, "hello world", null ),
483 array(
484 'WikiPageTest_testGetRedirectTarget_2',
485 CONTENT_MODEL_WIKITEXT,
486 "#REDIRECT [[hello world]]",
487 "Hello world"
488 ),
489 );
490 }
491
492 /**
493 * @dataProvider provideGetRedirectTarget
494 * @covers WikiPage::getRedirectTarget
495 */
496 public function testGetRedirectTarget( $title, $model, $text, $target ) {
497 $this->setMwGlobals( array(
498 'wgCapitalLinks' => true,
499 ) );
500
501 $page = $this->createPage( $title, $text, $model );
502
503 # sanity check, because this test seems to fail for no reason for some people.
504 $c = $page->getContent();
505 $this->assertEquals( 'WikitextContent', get_class( $c ) );
506
507 # now, test the actual redirect
508 $t = $page->getRedirectTarget();
509 $this->assertEquals( $target, is_null( $t ) ? null : $t->getPrefixedText() );
510 }
511
512 /**
513 * @dataProvider provideGetRedirectTarget
514 * @covers WikiPage::isRedirect
515 */
516 public function testIsRedirect( $title, $model, $text, $target ) {
517 $page = $this->createPage( $title, $text, $model );
518 $this->assertEquals( !is_null( $target ), $page->isRedirect() );
519 }
520
521 public static function provideIsCountable() {
522 return array(
523
524 // any
525 array( 'WikiPageTest_testIsCountable',
526 CONTENT_MODEL_WIKITEXT,
527 '',
528 'any',
529 true
530 ),
531 array( 'WikiPageTest_testIsCountable',
532 CONTENT_MODEL_WIKITEXT,
533 'Foo',
534 'any',
535 true
536 ),
537
538 // comma
539 array( 'WikiPageTest_testIsCountable',
540 CONTENT_MODEL_WIKITEXT,
541 'Foo',
542 'comma',
543 false
544 ),
545 array( 'WikiPageTest_testIsCountable',
546 CONTENT_MODEL_WIKITEXT,
547 'Foo, bar',
548 'comma',
549 true
550 ),
551
552 // link
553 array( 'WikiPageTest_testIsCountable',
554 CONTENT_MODEL_WIKITEXT,
555 'Foo',
556 'link',
557 false
558 ),
559 array( 'WikiPageTest_testIsCountable',
560 CONTENT_MODEL_WIKITEXT,
561 'Foo [[bar]]',
562 'link',
563 true
564 ),
565
566 // redirects
567 array( 'WikiPageTest_testIsCountable',
568 CONTENT_MODEL_WIKITEXT,
569 '#REDIRECT [[bar]]',
570 'any',
571 false
572 ),
573 array( 'WikiPageTest_testIsCountable',
574 CONTENT_MODEL_WIKITEXT,
575 '#REDIRECT [[bar]]',
576 'comma',
577 false
578 ),
579 array( 'WikiPageTest_testIsCountable',
580 CONTENT_MODEL_WIKITEXT,
581 '#REDIRECT [[bar]]',
582 'link',
583 false
584 ),
585
586 // not a content namespace
587 array( 'Talk:WikiPageTest_testIsCountable',
588 CONTENT_MODEL_WIKITEXT,
589 'Foo',
590 'any',
591 false
592 ),
593 array( 'Talk:WikiPageTest_testIsCountable',
594 CONTENT_MODEL_WIKITEXT,
595 'Foo, bar',
596 'comma',
597 false
598 ),
599 array( 'Talk:WikiPageTest_testIsCountable',
600 CONTENT_MODEL_WIKITEXT,
601 'Foo [[bar]]',
602 'link',
603 false
604 ),
605
606 // not a content namespace, different model
607 array( 'MediaWiki:WikiPageTest_testIsCountable.js',
608 null,
609 'Foo',
610 'any',
611 false
612 ),
613 array( 'MediaWiki:WikiPageTest_testIsCountable.js',
614 null,
615 'Foo, bar',
616 'comma',
617 false
618 ),
619 array( 'MediaWiki:WikiPageTest_testIsCountable.js',
620 null,
621 'Foo [[bar]]',
622 'link',
623 false
624 ),
625 );
626 }
627
628 /**
629 * @dataProvider provideIsCountable
630 * @covers WikiPage::isCountable
631 */
632 public function testIsCountable( $title, $model, $text, $mode, $expected ) {
633 global $wgContentHandlerUseDB;
634
635 $this->setMwGlobals( 'wgArticleCountMethod', $mode );
636
637 $title = Title::newFromText( $title );
638
639 if ( !$wgContentHandlerUseDB
640 && $model
641 && ContentHandler::getDefaultModelFor( $title ) != $model
642 ) {
643 $this->markTestSkipped( "Can not use non-default content model $model for "
644 . $title->getPrefixedDBkey() . " with \$wgContentHandlerUseDB disabled." );
645 }
646
647 $page = $this->createPage( $title, $text, $model );
648
649 $editInfo = $page->prepareContentForEdit( $page->getContent() );
650
651 $v = $page->isCountable();
652 $w = $page->isCountable( $editInfo );
653
654 $this->assertEquals(
655 $expected,
656 $v,
657 "isCountable( null ) returned unexpected value " . var_export( $v, true )
658 . " instead of " . var_export( $expected, true )
659 . " in mode `$mode` for text \"$text\""
660 );
661
662 $this->assertEquals(
663 $expected,
664 $w,
665 "isCountable( \$editInfo ) returned unexpected value " . var_export( $v, true )
666 . " instead of " . var_export( $expected, true )
667 . " in mode `$mode` for text \"$text\""
668 );
669 }
670
671 public static function provideGetParserOutput() {
672 return array(
673 array( CONTENT_MODEL_WIKITEXT, "hello ''world''\n", "<p>hello <i>world</i></p>" ),
674 // @todo more...?
675 );
676 }
677
678 /**
679 * @dataProvider provideGetParserOutput
680 * @covers WikiPage::getParserOutput
681 */
682 public function testGetParserOutput( $model, $text, $expectedHtml ) {
683 $page = $this->createPage( 'WikiPageTest_testGetParserOutput', $text, $model );
684
685 $opt = $page->makeParserOptions( 'canonical' );
686 $po = $page->getParserOutput( $opt );
687 $text = $po->getText();
688
689 $text = trim( preg_replace( '/<!--.*?-->/sm', '', $text ) ); # strip injected comments
690 $text = preg_replace( '!\s*(</p>)!sm', '\1', $text ); # don't let tidy confuse us
691
692 $this->assertEquals( $expectedHtml, $text );
693
694 return $po;
695 }
696
697 /**
698 * @covers WikiPage::getParserOutput
699 */
700 public function testGetParserOutput_nonexisting() {
701 static $count = 0;
702 $count++;
703
704 $page = new WikiPage( new Title( "WikiPageTest_testGetParserOutput_nonexisting_$count" ) );
705
706 $opt = new ParserOptions();
707 $po = $page->getParserOutput( $opt );
708
709 $this->assertFalse( $po, "getParserOutput() shall return false for non-existing pages." );
710 }
711
712 /**
713 * @covers WikiPage::getParserOutput
714 */
715 public function testGetParserOutput_badrev() {
716 $page = $this->createPage( 'WikiPageTest_testGetParserOutput', "dummy", CONTENT_MODEL_WIKITEXT );
717
718 $opt = new ParserOptions();
719 $po = $page->getParserOutput( $opt, $page->getLatest() + 1234 );
720
721 // @todo would be neat to also test deleted revision
722
723 $this->assertFalse( $po, "getParserOutput() shall return false for non-existing revisions." );
724 }
725
726 public static $sections =
727
728 "Intro
729
730 == stuff ==
731 hello world
732
733 == test ==
734 just a test
735
736 == foo ==
737 more stuff
738 ";
739
740 public function dataReplaceSection() {
741 // NOTE: assume the Help namespace to contain wikitext
742 return array(
743 array( 'Help:WikiPageTest_testReplaceSection',
744 CONTENT_MODEL_WIKITEXT,
745 WikiPageTest::$sections,
746 "0",
747 "No more",
748 null,
749 trim( preg_replace( '/^Intro/sm', 'No more', WikiPageTest::$sections ) )
750 ),
751 array( 'Help:WikiPageTest_testReplaceSection',
752 CONTENT_MODEL_WIKITEXT,
753 WikiPageTest::$sections,
754 "",
755 "No more",
756 null,
757 "No more"
758 ),
759 array( 'Help:WikiPageTest_testReplaceSection',
760 CONTENT_MODEL_WIKITEXT,
761 WikiPageTest::$sections,
762 "2",
763 "== TEST ==\nmore fun",
764 null,
765 trim( preg_replace( '/^== test ==.*== foo ==/sm',
766 "== TEST ==\nmore fun\n\n== foo ==",
767 WikiPageTest::$sections ) )
768 ),
769 array( 'Help:WikiPageTest_testReplaceSection',
770 CONTENT_MODEL_WIKITEXT,
771 WikiPageTest::$sections,
772 "8",
773 "No more",
774 null,
775 trim( WikiPageTest::$sections )
776 ),
777 array( 'Help:WikiPageTest_testReplaceSection',
778 CONTENT_MODEL_WIKITEXT,
779 WikiPageTest::$sections,
780 "new",
781 "No more",
782 "New",
783 trim( WikiPageTest::$sections ) . "\n\n== New ==\n\nNo more"
784 ),
785 );
786 }
787
788 /**
789 * @dataProvider dataReplaceSection
790 * @covers WikiPage::replaceSection
791 */
792 public function testReplaceSection( $title, $model, $text, $section, $with,
793 $sectionTitle, $expected
794 ) {
795 $this->hideDeprecated( "WikiPage::replaceSection" );
796
797 $page = $this->createPage( $title, $text, $model );
798 $text = $page->replaceSection( $section, $with, $sectionTitle );
799 $text = trim( $text );
800
801 $this->assertEquals( $expected, $text );
802 }
803
804 /**
805 * @dataProvider dataReplaceSection
806 * @covers WikiPage::replaceSectionContent
807 */
808 public function testReplaceSectionContent( $title, $model, $text, $section,
809 $with, $sectionTitle, $expected
810 ) {
811 $page = $this->createPage( $title, $text, $model );
812
813 $content = ContentHandler::makeContent( $with, $page->getTitle(), $page->getContentModel() );
814 $c = $page->replaceSectionContent( $section, $content, $sectionTitle );
815
816 $this->assertEquals( $expected, is_null( $c ) ? null : trim( $c->getNativeData() ) );
817 }
818
819 /**
820 * @dataProvider dataReplaceSection
821 * @covers WikiPage::replaceSectionAtRev
822 */
823 public function testReplaceSectionAtRev( $title, $model, $text, $section,
824 $with, $sectionTitle, $expected
825 ) {
826 $page = $this->createPage( $title, $text, $model );
827 $baseRevId = $page->getLatest();
828
829 $content = ContentHandler::makeContent( $with, $page->getTitle(), $page->getContentModel() );
830 $c = $page->replaceSectionAtRev( $section, $content, $sectionTitle, $baseRevId );
831
832 $this->assertEquals( $expected, is_null( $c ) ? null : trim( $c->getNativeData() ) );
833 }
834
835 /* @todo FIXME: fix this!
836 public function testGetUndoText() {
837 $this->checkHasDiff3();
838
839 $text = "one";
840 $page = $this->createPage( "WikiPageTest_testGetUndoText", $text );
841 $rev1 = $page->getRevision();
842
843 $text .= "\n\ntwo";
844 $page->doEditContent(
845 ContentHandler::makeContent( $text, $page->getTitle() ),
846 "adding section two"
847 );
848 $rev2 = $page->getRevision();
849
850 $text .= "\n\nthree";
851 $page->doEditContent(
852 ContentHandler::makeContent( $text, $page->getTitle() ),
853 "adding section three"
854 );
855 $rev3 = $page->getRevision();
856
857 $text .= "\n\nfour";
858 $page->doEditContent(
859 ContentHandler::makeContent( $text, $page->getTitle() ),
860 "adding section four"
861 );
862 $rev4 = $page->getRevision();
863
864 $text .= "\n\nfive";
865 $page->doEditContent(
866 ContentHandler::makeContent( $text, $page->getTitle() ),
867 "adding section five"
868 );
869 $rev5 = $page->getRevision();
870
871 $text .= "\n\nsix";
872 $page->doEditContent(
873 ContentHandler::makeContent( $text, $page->getTitle() ),
874 "adding section six"
875 );
876 $rev6 = $page->getRevision();
877
878 $undo6 = $page->getUndoText( $rev6 );
879 if ( $undo6 === false ) $this->fail( "getUndoText failed for rev6" );
880 $this->assertEquals( "one\n\ntwo\n\nthree\n\nfour\n\nfive", $undo6 );
881
882 $undo3 = $page->getUndoText( $rev4, $rev2 );
883 if ( $undo3 === false ) $this->fail( "getUndoText failed for rev4..rev2" );
884 $this->assertEquals( "one\n\ntwo\n\nfive", $undo3 );
885
886 $undo2 = $page->getUndoText( $rev2 );
887 if ( $undo2 === false ) $this->fail( "getUndoText failed for rev2" );
888 $this->assertEquals( "one\n\nfive", $undo2 );
889 }
890 */
891
892 /**
893 * @todo FIXME: this is a better rollback test than the one below, but it
894 * keeps failing in jenkins for some reason.
895 */
896 public function broken_testDoRollback() {
897 $admin = new User();
898 $admin->setName( "Admin" );
899
900 $text = "one";
901 $page = $this->newPage( "WikiPageTest_testDoRollback" );
902 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
903 "section one", EDIT_NEW, false, $admin );
904
905 $user1 = new User();
906 $user1->setName( "127.0.1.11" );
907 $text .= "\n\ntwo";
908 $page = new WikiPage( $page->getTitle() );
909 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
910 "adding section two", 0, false, $user1 );
911
912 $user2 = new User();
913 $user2->setName( "127.0.2.13" );
914 $text .= "\n\nthree";
915 $page = new WikiPage( $page->getTitle() );
916 $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ),
917 "adding section three", 0, false, $user2 );
918
919 # we are having issues with doRollback spuriously failing. Apparently
920 # the last revision somehow goes missing or not committed under some
921 # circumstances. So, make sure the last revision has the right user name.
922 $dbr = wfGetDB( DB_SLAVE );
923 $this->assertEquals( 3, Revision::countByPageId( $dbr, $page->getId() ) );
924
925 $page = new WikiPage( $page->getTitle() );
926 $rev3 = $page->getRevision();
927 $this->assertEquals( '127.0.2.13', $rev3->getUserText() );
928
929 $rev2 = $rev3->getPrevious();
930 $this->assertEquals( '127.0.1.11', $rev2->getUserText() );
931
932 $rev1 = $rev2->getPrevious();
933 $this->assertEquals( 'Admin', $rev1->getUserText() );
934
935 # now, try the actual rollback
936 $admin->addGroup( "sysop" ); # XXX: make the test user a sysop...
937 $token = $admin->getEditToken(
938 array( $page->getTitle()->getPrefixedText(), $user2->getName() ),
939 null
940 );
941 $errors = $page->doRollback(
942 $user2->getName(),
943 "testing revert",
944 $token,
945 false,
946 $details,
947 $admin
948 );
949
950 if ( $errors ) {
951 $this->fail( "Rollback failed:\n" . print_r( $errors, true )
952 . ";\n" . print_r( $details, true ) );
953 }
954
955 $page = new WikiPage( $page->getTitle() );
956 $this->assertEquals( $rev2->getSha1(), $page->getRevision()->getSha1(),
957 "rollback did not revert to the correct revision" );
958 $this->assertEquals( "one\n\ntwo", $page->getContent()->getNativeData() );
959 }
960
961 /**
962 * @todo FIXME: the above rollback test is better, but it keeps failing in jenkins for some reason.
963 * @covers WikiPage::doRollback
964 */
965 public function testDoRollback() {
966 $admin = new User();
967 $admin->setName( "Admin" );
968
969 $text = "one";
970 $page = $this->newPage( "WikiPageTest_testDoRollback" );
971 $page->doEditContent(
972 ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
973 "section one",
974 EDIT_NEW,
975 false,
976 $admin
977 );
978 $rev1 = $page->getRevision();
979
980 $user1 = new User();
981 $user1->setName( "127.0.1.11" );
982 $text .= "\n\ntwo";
983 $page = new WikiPage( $page->getTitle() );
984 $page->doEditContent(
985 ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
986 "adding section two",
987 0,
988 false,
989 $user1
990 );
991
992 # now, try the rollback
993 $admin->addGroup( "sysop" ); # XXX: make the test user a sysop...
994 $token = $admin->getEditToken(
995 array( $page->getTitle()->getPrefixedText(), $user1->getName() ),
996 null
997 );
998 $errors = $page->doRollback(
999 $user1->getName(),
1000 "testing revert",
1001 $token,
1002 false,
1003 $details,
1004 $admin
1005 );
1006
1007 if ( $errors ) {
1008 $this->fail( "Rollback failed:\n" . print_r( $errors, true )
1009 . ";\n" . print_r( $details, true ) );
1010 }
1011
1012 $page = new WikiPage( $page->getTitle() );
1013 $this->assertEquals( $rev1->getSha1(), $page->getRevision()->getSha1(),
1014 "rollback did not revert to the correct revision" );
1015 $this->assertEquals( "one", $page->getContent()->getNativeData() );
1016 }
1017
1018 /**
1019 * @covers WikiPage::doRollback
1020 */
1021 public function testDoRollbackFailureSameContent() {
1022 $admin = new User();
1023 $admin->setName( "Admin" );
1024 $admin->addGroup( "sysop" ); # XXX: make the test user a sysop...
1025
1026 $text = "one";
1027 $page = $this->newPage( "WikiPageTest_testDoRollback" );
1028 $page->doEditContent(
1029 ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
1030 "section one",
1031 EDIT_NEW,
1032 false,
1033 $admin
1034 );
1035 $rev1 = $page->getRevision();
1036
1037 $user1 = new User();
1038 $user1->setName( "127.0.1.11" );
1039 $user1->addGroup( "sysop" ); # XXX: make the test user a sysop...
1040 $text .= "\n\ntwo";
1041 $page = new WikiPage( $page->getTitle() );
1042 $page->doEditContent(
1043 ContentHandler::makeContent( $text, $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
1044 "adding section two",
1045 0,
1046 false,
1047 $user1
1048 );
1049
1050 # now, do a the rollback from the same user was doing the edit before
1051 $resultDetails = array();
1052 $token = $user1->getEditToken(
1053 array( $page->getTitle()->getPrefixedText(), $user1->getName() ),
1054 null
1055 );
1056 $errors = $page->doRollback(
1057 $user1->getName(),
1058 "testing revert same user",
1059 $token,
1060 false,
1061 $resultDetails,
1062 $admin
1063 );
1064
1065 $this->assertEquals( array(), $errors, "Rollback failed same user" );
1066
1067 # now, try the rollback
1068 $resultDetails = array();
1069 $token = $admin->getEditToken(
1070 array( $page->getTitle()->getPrefixedText(), $user1->getName() ),
1071 null
1072 );
1073 $errors = $page->doRollback(
1074 $user1->getName(),
1075 "testing revert",
1076 $token,
1077 false,
1078 $resultDetails,
1079 $admin
1080 );
1081
1082 $this->assertEquals( array( array( 'alreadyrolled', 'WikiPageTest testDoRollback',
1083 '127.0.1.11', 'Admin' ) ), $errors, "Rollback not failed" );
1084
1085 $page = new WikiPage( $page->getTitle() );
1086 $this->assertEquals( $rev1->getSha1(), $page->getRevision()->getSha1(),
1087 "rollback did not revert to the correct revision" );
1088 $this->assertEquals( "one", $page->getContent()->getNativeData() );
1089 }
1090
1091 public static function provideGetAutosummary() {
1092 return array(
1093 array(
1094 'Hello there, world!',
1095 '#REDIRECT [[Foo]]',
1096 0,
1097 '/^Redirected page .*Foo/'
1098 ),
1099
1100 array(
1101 null,
1102 'Hello world!',
1103 EDIT_NEW,
1104 '/^Created page .*Hello/'
1105 ),
1106
1107 array(
1108 'Hello there, world!',
1109 '',
1110 0,
1111 '/^Blanked/'
1112 ),
1113
1114 array(
1115 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
1116 eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
1117 voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
1118 clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
1119 'Hello world!',
1120 0,
1121 '/^Replaced .*Hello/'
1122 ),
1123
1124 array(
1125 'foo',
1126 'bar',
1127 0,
1128 '/^$/'
1129 ),
1130 );
1131 }
1132
1133 /**
1134 * @dataProvider provideGetAutoSummary
1135 * @covers WikiPage::getAutosummary
1136 */
1137 public function testGetAutosummary( $old, $new, $flags, $expected ) {
1138 $this->hideDeprecated( "WikiPage::getAutosummary" );
1139
1140 $page = $this->newPage( "WikiPageTest_testGetAutosummary" );
1141
1142 $summary = $page->getAutosummary( $old, $new, $flags );
1143
1144 $this->assertTrue( (bool)preg_match( $expected, $summary ),
1145 "Autosummary didn't match expected pattern $expected: $summary" );
1146 }
1147
1148 public static function provideGetAutoDeleteReason() {
1149 return array(
1150 array(
1151 array(),
1152 false,
1153 false
1154 ),
1155
1156 array(
1157 array(
1158 array( "first edit", null ),
1159 ),
1160 "/first edit.*only contributor/",
1161 false
1162 ),
1163
1164 array(
1165 array(
1166 array( "first edit", null ),
1167 array( "second edit", null ),
1168 ),
1169 "/second edit.*only contributor/",
1170 true
1171 ),
1172
1173 array(
1174 array(
1175 array( "first edit", "127.0.2.22" ),
1176 array( "second edit", "127.0.3.33" ),
1177 ),
1178 "/second edit/",
1179 true
1180 ),
1181
1182 array(
1183 array(
1184 array(
1185 "first edit: "
1186 . "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam "
1187 . " nonumy eirmod tempor invidunt ut labore et dolore magna "
1188 . "aliquyam erat, sed diam voluptua. At vero eos et accusam "
1189 . "et justo duo dolores et ea rebum. Stet clita kasd gubergren, "
1190 . "no sea takimata sanctus est Lorem ipsum dolor sit amet.'",
1191 null
1192 ),
1193 ),
1194 '/first edit:.*\.\.\."/',
1195 false
1196 ),
1197
1198 array(
1199 array(
1200 array( "first edit", "127.0.2.22" ),
1201 array( "", "127.0.3.33" ),
1202 ),
1203 "/before blanking.*first edit/",
1204 true
1205 ),
1206
1207 );
1208 }
1209
1210 /**
1211 * @dataProvider provideGetAutoDeleteReason
1212 * @covers WikiPage::getAutoDeleteReason
1213 */
1214 public function testGetAutoDeleteReason( $edits, $expectedResult, $expectedHistory ) {
1215 global $wgUser;
1216
1217 // NOTE: assume Help namespace to contain wikitext
1218 $page = $this->newPage( "Help:WikiPageTest_testGetAutoDeleteReason" );
1219
1220 $c = 1;
1221
1222 foreach ( $edits as $edit ) {
1223 $user = new User();
1224
1225 if ( !empty( $edit[1] ) ) {
1226 $user->setName( $edit[1] );
1227 } else {
1228 $user = $wgUser;
1229 }
1230
1231 $content = ContentHandler::makeContent( $edit[0], $page->getTitle(), $page->getContentModel() );
1232
1233 $page->doEditContent( $content, "test edit $c", $c < 2 ? EDIT_NEW : 0, false, $user );
1234
1235 $c += 1;
1236 }
1237
1238 $reason = $page->getAutoDeleteReason( $hasHistory );
1239
1240 if ( is_bool( $expectedResult ) || is_null( $expectedResult ) ) {
1241 $this->assertEquals( $expectedResult, $reason );
1242 } else {
1243 $this->assertTrue( (bool)preg_match( $expectedResult, $reason ),
1244 "Autosummary didn't match expected pattern $expectedResult: $reason" );
1245 }
1246
1247 $this->assertEquals( $expectedHistory, $hasHistory,
1248 "expected \$hasHistory to be " . var_export( $expectedHistory, true ) );
1249
1250 $page->doDeleteArticle( "done" );
1251 }
1252
1253 public static function providePreSaveTransform() {
1254 return array(
1255 array( 'hello this is ~~~',
1256 "hello this is [[Special:Contributions/127.0.0.1|127.0.0.1]]",
1257 ),
1258 array( 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
1259 'hello \'\'this\'\' is <nowiki>~~~</nowiki>',
1260 ),
1261 );
1262 }
1263
1264 /**
1265 * @dataProvider providePreSaveTransform
1266 * @covers WikiPage::preSaveTransform
1267 */
1268 public function testPreSaveTransform( $text, $expected ) {
1269 $this->hideDeprecated( 'WikiPage::preSaveTransform' );
1270 $user = new User();
1271 $user->setName( "127.0.0.1" );
1272
1273 // NOTE: assume Help namespace to contain wikitext
1274 $page = $this->newPage( "Help:WikiPageTest_testPreloadTransform" );
1275 $text = $page->preSaveTransform( $text, $user );
1276
1277 $this->assertEquals( $expected, $text );
1278 }
1279
1280 /**
1281 * @covers WikiPage::factory
1282 */
1283 public function testWikiPageFactory() {
1284 $title = Title::makeTitle( NS_FILE, 'Someimage.png' );
1285 $page = WikiPage::factory( $title );
1286 $this->assertEquals( 'WikiFilePage', get_class( $page ) );
1287
1288 $title = Title::makeTitle( NS_CATEGORY, 'SomeCategory' );
1289 $page = WikiPage::factory( $title );
1290 $this->assertEquals( 'WikiCategoryPage', get_class( $page ) );
1291
1292 $title = Title::makeTitle( NS_MAIN, 'SomePage' );
1293 $page = WikiPage::factory( $title );
1294 $this->assertEquals( 'WikiPage', get_class( $page ) );
1295 }
1296 }