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